add sync committee types and some helpers (#2829)
This commit is contained in:
parent
6d47d96c84
commit
eeba2869fc
|
@ -98,9 +98,10 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
OK: 4/4 Fail: 0/4 Skip: 0/4
|
OK: 4/4 Fail: 0/4 Skip: 0/4
|
||||||
## Gossip validation [Preset: mainnet]
|
## Gossip validation [Preset: mainnet]
|
||||||
```diff
|
```diff
|
||||||
|
+ Any committee index is valid OK
|
||||||
+ Validation sanity OK
|
+ Validation sanity OK
|
||||||
```
|
```
|
||||||
OK: 1/1 Fail: 0/1 Skip: 0/1
|
OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||||
## Honest validator
|
## Honest validator
|
||||||
```diff
|
```diff
|
||||||
+ General pubsub topics OK
|
+ 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
|
OK: 36/48 Fail: 0/48 Skip: 12/48
|
||||||
|
|
||||||
---TOTAL---
|
---TOTAL---
|
||||||
OK: 185/197 Fail: 0/197 Skip: 12/197
|
OK: 186/198 Fail: 0/198 Skip: 12/198
|
||||||
|
|
|
@ -75,6 +75,33 @@ type
|
||||||
nextAttestationEpoch*: seq[tuple[subnet: Epoch, aggregate: Epoch]] ## \
|
nextAttestationEpoch*: seq[tuple[subnet: Epoch, aggregate: Epoch]] ## \
|
||||||
## sequence based on validator indices
|
## 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
|
ExitPool* = object
|
||||||
## The exit pool tracks attester slashings, proposer slashings, and
|
## The exit pool tracks attester slashings, proposer slashings, and
|
||||||
## voluntary exits that could be added to a proposed block.
|
## voluntary exits that could be added to a proposed block.
|
||||||
|
@ -153,3 +180,6 @@ type
|
||||||
lastCalculatedEpoch*: Epoch
|
lastCalculatedEpoch*: Epoch
|
||||||
|
|
||||||
func shortLog*(v: AttachedValidator): string = shortLog(v.pubKey)
|
func shortLog*(v: AttachedValidator): string = shortLog(v.pubKey)
|
||||||
|
|
||||||
|
func hash*(x: SyncCommitteeMsgKey): Hash =
|
||||||
|
hashData(unsafeAddr x, sizeof(x))
|
||||||
|
|
|
@ -2096,3 +2096,13 @@ proc broadcastBeaconBlock*(node: Eth2Node, forked: ForkedSignedBeaconBlock) =
|
||||||
of BeaconBlockFork.Altair:
|
of BeaconBlockFork.Altair:
|
||||||
let topic = getBeaconBlocksTopic(node.forkDigests.altair)
|
let topic = getBeaconBlocksTopic(node.forkDigests.altair)
|
||||||
node.broadcast(topic, forked.altairBlock)
|
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)
|
||||||
|
|
|
@ -464,5 +464,8 @@ func init*(T: typedesc[ValidatorSig], data: array[RawSigSize, byte]): T {.noInit
|
||||||
raise (ref ValueError)(msg: $v.error)
|
raise (ref ValueError)(msg: $v.error)
|
||||||
v[]
|
v[]
|
||||||
|
|
||||||
|
func infinity*(T: type ValidatorSig): T =
|
||||||
|
result.blob[0] = byte 0xC0
|
||||||
|
|
||||||
proc burnMem*(key: var ValidatorPrivKey) =
|
proc burnMem*(key: var ValidatorPrivKey) =
|
||||||
ncrutils.burnMem(addr key, sizeof(ValidatorPrivKey))
|
ncrutils.burnMem(addr key, sizeof(ValidatorPrivKey))
|
||||||
|
|
|
@ -442,6 +442,24 @@ when false:
|
||||||
chronicles.formatIt BeaconBlock: it.shortLog
|
chronicles.formatIt BeaconBlock: it.shortLog
|
||||||
chronicles.formatIt SyncCommitteeIndex: uint8(it)
|
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)
|
template asUInt8*(x: SyncCommitteeIndex): uint8 = uint8(x)
|
||||||
|
|
||||||
Json.useCustomSerialization(BeaconState.justification_bits):
|
Json.useCustomSerialization(BeaconState.justification_bits):
|
||||||
|
|
|
@ -47,12 +47,18 @@ template epoch*(slot: Slot): Epoch =
|
||||||
template isEpoch*(slot: Slot): bool =
|
template isEpoch*(slot: Slot): bool =
|
||||||
(slot mod SLOTS_PER_EPOCH) == 0
|
(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 =
|
template syncCommitteePeriod*(epoch: Epoch): uint64 =
|
||||||
epoch div EPOCHS_PER_SYNC_COMMITTEE_PERIOD
|
epoch div EPOCHS_PER_SYNC_COMMITTEE_PERIOD
|
||||||
|
|
||||||
template syncCommitteePeriod*(slot: Slot): uint64 =
|
template syncCommitteePeriod*(slot: Slot): uint64 =
|
||||||
epoch(slot) div EPOCHS_PER_SYNC_COMMITTEE_PERIOD
|
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
|
# 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 =
|
func compute_start_slot_at_epoch*(epoch: Epoch): Slot =
|
||||||
## Return the start slot of ``epoch``.
|
## Return the start slot of ``epoch``.
|
||||||
|
|
|
@ -171,6 +171,12 @@ func get_committee_count_per_slot*(state: SomeBeaconState,
|
||||||
# Otherwise, get_beacon_committee(...) cannot access some committees.
|
# Otherwise, get_beacon_committee(...) cannot access some committees.
|
||||||
doAssert (SLOTS_PER_EPOCH * MAX_COMMITTEES_PER_SLOT) >= uint64(result)
|
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,
|
func get_committee_count_per_slot*(state: SomeBeaconState,
|
||||||
slot: Slot,
|
slot: Slot,
|
||||||
cache: var StateCache): uint64 =
|
cache: var StateCache): uint64 =
|
||||||
|
@ -194,11 +200,14 @@ func compute_committee_slice*(
|
||||||
active_validators, index, count: uint64): Slice[int] =
|
active_validators, index, count: uint64): Slice[int] =
|
||||||
doAssert active_validators <= ValidatorIndex.high.uint64
|
doAssert active_validators <= ValidatorIndex.high.uint64
|
||||||
|
|
||||||
let
|
if index < count:
|
||||||
start = (active_validators * index) div count
|
let
|
||||||
endIdx = (active_validators * (index + 1)) div count
|
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],
|
iterator compute_committee*(shuffled_indices: seq[ValidatorIndex],
|
||||||
index: uint64, count: uint64): ValidatorIndex =
|
index: uint64, count: uint64): ValidatorIndex =
|
||||||
|
|
|
@ -45,6 +45,25 @@ suite "Gossip validation " & preset():
|
||||||
defaultRuntimeConfig, state.data, getStateField(state.data, slot) + 1,
|
defaultRuntimeConfig, state.data, getStateField(state.data, slot) + 1,
|
||||||
cache, rewards, {})
|
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":
|
test "Validation sanity":
|
||||||
# TODO: refactor tests to avoid skipping BLS validation
|
# TODO: refactor tests to avoid skipping BLS validation
|
||||||
dag.updateFlags.incl {skipBLSValidation}
|
dag.updateFlags.incl {skipBLSValidation}
|
||||||
|
|
Loading…
Reference in New Issue