extend `makeTestBlocks` for sync aggregates
This extends the `makeTestBlocks` function used in tests with a new parameter `syncCommitteeRatio` to control whether the produced blocks should be signed by the validators assigned to the sync committee. A similar parameter already exists to configure whether attestations for the test blocks should be produced.
This commit is contained in:
parent
40a9da385d
commit
5e9625c1be
|
@ -6,8 +6,10 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
|
random,
|
||||||
chronicles,
|
chronicles,
|
||||||
options, stew/endians2,
|
options, stew/endians2,
|
||||||
|
../beacon_chain/consensus_object_pools/sync_committee_msg_pool,
|
||||||
../beacon_chain/validators/validator_pool,
|
../beacon_chain/validators/validator_pool,
|
||||||
../beacon_chain/spec/datatypes/merge,
|
../beacon_chain/spec/datatypes/merge,
|
||||||
../beacon_chain/spec/[
|
../beacon_chain/spec/[
|
||||||
|
@ -78,6 +80,7 @@ proc addTestBlock*(
|
||||||
eth1_data = Eth1Data(),
|
eth1_data = Eth1Data(),
|
||||||
attestations = newSeq[Attestation](),
|
attestations = newSeq[Attestation](),
|
||||||
deposits = newSeq[Deposit](),
|
deposits = newSeq[Deposit](),
|
||||||
|
sync_aggregate = SyncAggregate.init(),
|
||||||
graffiti = default(GraffitiBytes),
|
graffiti = default(GraffitiBytes),
|
||||||
flags: set[UpdateFlag] = {},
|
flags: set[UpdateFlag] = {},
|
||||||
nextSlot = true,
|
nextSlot = true,
|
||||||
|
@ -116,7 +119,7 @@ proc addTestBlock*(
|
||||||
attestations,
|
attestations,
|
||||||
deposits,
|
deposits,
|
||||||
BeaconBlockExits(),
|
BeaconBlockExits(),
|
||||||
SyncAggregate.init(),
|
sync_aggregate,
|
||||||
default(ExecutionPayload),
|
default(ExecutionPayload),
|
||||||
noRollback,
|
noRollback,
|
||||||
cache)
|
cache)
|
||||||
|
@ -137,6 +140,7 @@ proc makeTestBlock*(
|
||||||
eth1_data = Eth1Data(),
|
eth1_data = Eth1Data(),
|
||||||
attestations = newSeq[Attestation](),
|
attestations = newSeq[Attestation](),
|
||||||
deposits = newSeq[Deposit](),
|
deposits = newSeq[Deposit](),
|
||||||
|
sync_aggregate = SyncAggregate.init(),
|
||||||
graffiti = default(GraffitiBytes),
|
graffiti = default(GraffitiBytes),
|
||||||
cfg = defaultRuntimeConfig): ForkedSignedBeaconBlock =
|
cfg = defaultRuntimeConfig): ForkedSignedBeaconBlock =
|
||||||
# Create a block for `state.slot + 1` - like a block proposer would do!
|
# Create a block for `state.slot + 1` - like a block proposer would do!
|
||||||
|
@ -145,7 +149,8 @@ proc makeTestBlock*(
|
||||||
# because the block includes the state root.
|
# because the block includes the state root.
|
||||||
var tmpState = assignClone(state)
|
var tmpState = assignClone(state)
|
||||||
addTestBlock(
|
addTestBlock(
|
||||||
tmpState[], cache, eth1_data, attestations, deposits, graffiti, cfg = cfg)
|
tmpState[], cache, eth1_data,
|
||||||
|
attestations, deposits, sync_aggregate, graffiti, cfg = cfg)
|
||||||
|
|
||||||
func makeAttestationData*(
|
func makeAttestationData*(
|
||||||
state: ForkyBeaconState, slot: Slot, committee_index: CommitteeIndex,
|
state: ForkyBeaconState, slot: Slot, committee_index: CommitteeIndex,
|
||||||
|
@ -283,19 +288,120 @@ func makeFullAttestations*(
|
||||||
attestation.signature = agg.finish().toValidatorSig()
|
attestation.signature = agg.finish().toValidatorSig()
|
||||||
result.add attestation
|
result.add attestation
|
||||||
|
|
||||||
|
proc makeSyncAggregate(
|
||||||
|
state: ForkedHashedBeaconState,
|
||||||
|
syncCommitteeRatio: float,
|
||||||
|
cfg: RuntimeConfig): SyncAggregate =
|
||||||
|
if syncCommitteeRatio <= 0.0:
|
||||||
|
return SyncAggregate.init()
|
||||||
|
let
|
||||||
|
syncCommittee =
|
||||||
|
withState(state):
|
||||||
|
when stateFork >= BeaconStateFork.Altair:
|
||||||
|
const SLOTS_PER_PERIOD =
|
||||||
|
EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH
|
||||||
|
if (state.data.slot + 1) mod SLOTS_PER_PERIOD == 0:
|
||||||
|
state.data.next_sync_committee
|
||||||
|
else:
|
||||||
|
state.data.current_sync_committee
|
||||||
|
else:
|
||||||
|
return SyncAggregate.init()
|
||||||
|
fork =
|
||||||
|
getStateField(state, fork)
|
||||||
|
genesis_validators_root =
|
||||||
|
getStateField(state, genesis_validators_root)
|
||||||
|
slot =
|
||||||
|
getStateField(state, slot)
|
||||||
|
latest_block_root =
|
||||||
|
withState(state): state.latest_block_root
|
||||||
|
syncCommitteePool = newClone(SyncCommitteeMsgPool.init())
|
||||||
|
type
|
||||||
|
Aggregator = object
|
||||||
|
subcommitteeIdx: SyncSubcommitteeIndex
|
||||||
|
validatorIdx: ValidatorIndex
|
||||||
|
selectionProof: ValidatorSig
|
||||||
|
var aggregators: seq[Aggregator]
|
||||||
|
for subcommitteeIdx in allSyncSubcommittees():
|
||||||
|
let
|
||||||
|
firstKeyIdx = subcommitteeIdx.int * SYNC_SUBCOMMITTEE_SIZE
|
||||||
|
lastKeyIdx = firstKeyIdx + SYNC_SUBCOMMITTEE_SIZE - 1
|
||||||
|
var processedKeys = initHashSet[ValidatorPubKey]()
|
||||||
|
for idx, validatorKey in syncCommittee.pubkeys[firstKeyIdx .. lastKeyIdx]:
|
||||||
|
if validatorKey in processedKeys: continue
|
||||||
|
processedKeys.incl validatorKey
|
||||||
|
if rand(1.0) > syncCommitteeRatio: continue
|
||||||
|
var positions: seq[uint64]
|
||||||
|
for pos, key in syncCommittee.pubkeys[firstKeyIdx + idx .. lastKeyIdx]:
|
||||||
|
if key == validatorKey:
|
||||||
|
positions.add (idx + pos).uint64
|
||||||
|
let
|
||||||
|
validatorIdx =
|
||||||
|
block:
|
||||||
|
var res = 0
|
||||||
|
for i, validator in getStateField(state, validators):
|
||||||
|
if validator.pubkey == validatorKey:
|
||||||
|
res = i
|
||||||
|
break
|
||||||
|
res.ValidatorIndex
|
||||||
|
signature = get_sync_committee_message_signature(
|
||||||
|
fork, genesis_validators_root,
|
||||||
|
slot, latest_block_root,
|
||||||
|
MockPrivKeys[validatorIdx])
|
||||||
|
selectionProofSig = get_sync_aggregator_selection_data_signature(
|
||||||
|
fork, genesis_validators_root,
|
||||||
|
slot, subcommitteeIdx.uint64,
|
||||||
|
MockPrivKeys[validatorIdx])
|
||||||
|
syncCommitteePool[].addSyncCommitteeMessage(
|
||||||
|
slot,
|
||||||
|
latest_block_root,
|
||||||
|
uint64 validatorIdx,
|
||||||
|
signature,
|
||||||
|
subcommitteeIdx,
|
||||||
|
positions)
|
||||||
|
if is_sync_committee_aggregator(selectionProofSig.toValidatorSig):
|
||||||
|
aggregators.add Aggregator(
|
||||||
|
subcommitteeIdx: subcommitteeIdx,
|
||||||
|
validatorIdx: validatorIdx,
|
||||||
|
selectionProof: selectionProofSig.toValidatorSig)
|
||||||
|
for aggregator in aggregators:
|
||||||
|
var contribution: SyncCommitteeContribution
|
||||||
|
if syncCommitteePool[].produceContribution(
|
||||||
|
slot, latest_block_root, aggregator.subcommitteeIdx, contribution):
|
||||||
|
let
|
||||||
|
contributionAndProof = ContributionAndProof(
|
||||||
|
aggregator_index: uint64 aggregator.validatorIdx,
|
||||||
|
contribution: contribution,
|
||||||
|
selection_proof: aggregator.selectionProof)
|
||||||
|
contributionSig = get_sync_committee_contribution_and_proof_signature(
|
||||||
|
fork, genesis_validators_root,
|
||||||
|
contributionAndProof,
|
||||||
|
MockPrivKeys[aggregator.validatorIdx])
|
||||||
|
signedContributionAndProof = SignedContributionAndProof(
|
||||||
|
message: contributionAndProof,
|
||||||
|
signature: contributionSig.toValidatorSig)
|
||||||
|
syncCommitteePool[].addContribution(
|
||||||
|
signedContributionAndProof, contribution.signature.load.get)
|
||||||
|
syncCommitteePool[].produceSyncAggregate(latest_block_root)
|
||||||
|
|
||||||
iterator makeTestBlocks*(
|
iterator makeTestBlocks*(
|
||||||
state: ForkedHashedBeaconState,
|
state: ForkedHashedBeaconState,
|
||||||
cache: var StateCache,
|
cache: var StateCache,
|
||||||
blocks: int,
|
blocks: int,
|
||||||
attested: bool,
|
attested: bool,
|
||||||
|
syncCommitteeRatio = 0.0,
|
||||||
cfg = defaultRuntimeConfig): ForkedSignedBeaconBlock =
|
cfg = defaultRuntimeConfig): ForkedSignedBeaconBlock =
|
||||||
var
|
var
|
||||||
state = assignClone(state)
|
state = assignClone(state)
|
||||||
for _ in 0..<blocks:
|
for _ in 0..<blocks:
|
||||||
let parent_root = withState(state[]): state.latest_block_root()
|
let
|
||||||
let attestations = if attested:
|
parent_root = withState(state[]): state.latest_block_root()
|
||||||
makeFullAttestations(state[], parent_root, getStateField(state[], slot), cache)
|
attestations =
|
||||||
else:
|
if attested:
|
||||||
@[]
|
makeFullAttestations(
|
||||||
|
state[], parent_root, getStateField(state[], slot), cache)
|
||||||
|
else:
|
||||||
|
@[]
|
||||||
|
sync_aggregate = makeSyncAggregate(state[], syncCommitteeRatio, cfg)
|
||||||
|
|
||||||
yield addTestBlock(state[], cache, attestations = attestations, cfg = cfg)
|
yield addTestBlock(state[], cache,
|
||||||
|
attestations = attestations, sync_aggregate = sync_aggregate, cfg = cfg)
|
||||||
|
|
Loading…
Reference in New Issue