add sync committee types and some helpers (#2829)

This commit is contained in:
tersec 2021-08-28 09:00:00 +00:00 committed by GitHub
parent 6d47d96c84
commit eeba2869fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 102 additions and 6 deletions

View File

@ -98,9 +98,10 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
OK: 4/4 Fail: 0/4 Skip: 0/4
## Gossip validation [Preset: mainnet]
```diff
+ Any committee index is valid OK
+ Validation sanity OK
```
OK: 1/1 Fail: 0/1 Skip: 0/1
OK: 2/2 Fail: 0/2 Skip: 0/2
## Honest validator
```diff
+ General pubsub topics OK
@ -339,4 +340,4 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
OK: 36/48 Fail: 0/48 Skip: 12/48
---TOTAL---
OK: 185/197 Fail: 0/197 Skip: 12/197
OK: 186/198 Fail: 0/198 Skip: 12/198

View File

@ -75,6 +75,33 @@ type
nextAttestationEpoch*: seq[tuple[subnet: Epoch, aggregate: Epoch]] ## \
## sequence based on validator indices
SyncCommitteeMsgKey* = object
originator*: ValidatorIndex
slot*: Slot
committeeIdx*: SyncCommitteeIndex
TrustedSyncCommitteeMsg* = object
slot*: Slot
committeeIdx*: SyncCommitteeIndex
positionInCommittee*: uint64
signature*: CookedSig
BestSyncSubcommitteeContribution* = object
totalParticipants*: int
participationBits*: SyncCommitteeAggregationBits
signature*: CookedSig
BestSyncSubcommitteeContributions* = array[SYNC_COMMITTEE_SUBNET_COUNT,
BestSyncSubcommitteeContribution]
SyncCommitteeMsgPool* = object
seenByAuthor*: HashSet[SyncCommitteeMsgKey]
seenAggregateByAuthor*: HashSet[SyncCommitteeMsgKey]
blockVotes*: Table[Eth2Digest, seq[TrustedSyncCommitteeMsg]]
bestAggregates*: Table[Eth2Digest, BestSyncSubcommitteeContributions]
SyncCommitteeMsgPoolRef* = ref SyncCommitteeMsgPool
ExitPool* = object
## The exit pool tracks attester slashings, proposer slashings, and
## voluntary exits that could be added to a proposed block.
@ -153,3 +180,6 @@ type
lastCalculatedEpoch*: Epoch
func shortLog*(v: AttachedValidator): string = shortLog(v.pubKey)
func hash*(x: SyncCommitteeMsgKey): Hash =
hashData(unsafeAddr x, sizeof(x))

View File

@ -2096,3 +2096,13 @@ proc broadcastBeaconBlock*(node: Eth2Node, forked: ForkedSignedBeaconBlock) =
of BeaconBlockFork.Altair:
let topic = getBeaconBlocksTopic(node.forkDigests.altair)
node.broadcast(topic, forked.altairBlock)
proc broadcastSyncCommitteeMessage*(
node: Eth2Node, msg: SyncCommitteeMessage, committeeIdx: SyncCommitteeIndex) =
let topic = getSyncCommitteeTopic(node.forkDigests.altair, committeeIdx)
node.broadcast(topic, msg)
proc broadcastSignedContributionAndProof*(
node: Eth2Node, msg: SignedContributionAndProof) =
let topic = getSyncCommitteeContributionAndProofTopic(node.forkDigests.altair)
node.broadcast(topic, msg)

View File

@ -464,5 +464,8 @@ func init*(T: typedesc[ValidatorSig], data: array[RawSigSize, byte]): T {.noInit
raise (ref ValueError)(msg: $v.error)
v[]
func infinity*(T: type ValidatorSig): T =
result.blob[0] = byte 0xC0
proc burnMem*(key: var ValidatorPrivKey) =
ncrutils.burnMem(addr key, sizeof(ValidatorPrivKey))

View File

@ -442,6 +442,24 @@ when false:
chronicles.formatIt BeaconBlock: it.shortLog
chronicles.formatIt SyncCommitteeIndex: uint8(it)
template asInt*(x: SyncCommitteeIndex): int = int(x)
template asUInt8*(x: SyncCommitteeIndex): uint8 = uint8(x)
template asUInt64*(x: SyncCommitteeIndex): uint64 = uint64(x)
template `==`*(x, y: SyncCommitteeIndex): bool =
distinctBase(x) == distinctBase(y)
iterator allSyncCommittees*: SyncCommitteeIndex =
for committeeIdx in 0 ..< SYNC_COMMITTEE_SUBNET_COUNT:
yield SyncCommitteeIndex(committeeIdx)
template validateSyncCommitteeIndexOr*(networkValParam: uint64, elseBody: untyped) =
let networkVal = networkValParam
if networkVal < SYNC_COMMITTEE_SUBNET_COUNT:
SyncCommitteeIndex(networkVal)
else:
elseBody
template asUInt8*(x: SyncCommitteeIndex): uint8 = uint8(x)
Json.useCustomSerialization(BeaconState.justification_bits):

View File

@ -47,12 +47,18 @@ template epoch*(slot: Slot): Epoch =
template isEpoch*(slot: Slot): bool =
(slot mod SLOTS_PER_EPOCH) == 0
const SLOTS_PER_SYNC_COMMITTEE_PERIOD* =
EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH
template syncCommitteePeriod*(epoch: Epoch): uint64 =
epoch div EPOCHS_PER_SYNC_COMMITTEE_PERIOD
template syncCommitteePeriod*(slot: Slot): uint64 =
epoch(slot) div EPOCHS_PER_SYNC_COMMITTEE_PERIOD
func syncCommitteePeriodStartSlot*(period: uint64): Slot =
Slot(period * EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH)
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_start_slot_at_epoch
func compute_start_slot_at_epoch*(epoch: Epoch): Slot =
## Return the start slot of ``epoch``.

View File

@ -171,6 +171,12 @@ func get_committee_count_per_slot*(state: SomeBeaconState,
# Otherwise, get_beacon_committee(...) cannot access some committees.
doAssert (SLOTS_PER_EPOCH * MAX_COMMITTEES_PER_SLOT) >= uint64(result)
iterator committee_indices_per_slot*(state: SomeBeaconState,
epoch: Epoch,
cache: var StateCache): CommitteeIndex =
for idx in 0'u64 ..< get_committee_count_per_slot(state, epoch, cache):
yield CommitteeIndex.verifiedValue(idx)
func get_committee_count_per_slot*(state: SomeBeaconState,
slot: Slot,
cache: var StateCache): uint64 =
@ -194,11 +200,14 @@ func compute_committee_slice*(
active_validators, index, count: uint64): Slice[int] =
doAssert active_validators <= ValidatorIndex.high.uint64
let
start = (active_validators * index) div count
endIdx = (active_validators * (index + 1)) div count
if index < count:
let
start = (active_validators * index) div count
endIdx = (active_validators * (index + 1)) div count
start.int..(endIdx.int - 1)
start.int..(endIdx.int - 1)
else:
0 .. -1
iterator compute_committee*(shuffled_indices: seq[ValidatorIndex],
index: uint64, count: uint64): ValidatorIndex =

View File

@ -45,6 +45,25 @@ suite "Gossip validation " & preset():
defaultRuntimeConfig, state.data, getStateField(state.data, slot) + 1,
cache, rewards, {})
test "Any committee index is valid":
template committee(idx: uint64): untyped =
get_beacon_committee(
dag.headState.data, dag.head.slot, idx.CommitteeIndex, cache)
template committeeLen(idx: uint64): untyped =
get_beacon_committee_len(
dag.headState.data, dag.head.slot, idx.CommitteeIndex, cache)
check:
committee(0).len > 0
committee(10000).len == 0
committee(uint64.high).len == 0
check:
committeeLen(2) > 0
committeeLen(10000) == 0
committeeLen(uint64.high) == 0
test "Validation sanity":
# TODO: refactor tests to avoid skipping BLS validation
dag.updateFlags.incl {skipBLSValidation}