allow adding Altair test blocks (#2872)
testblockutil currently fails to add test blocks to Altair state because it assumes phase0 blocks in various places. This patch corrects this limitation by using forked types internally. Note that existing clients so far solely operate on phase0 blocks and should eventually be updated.
This commit is contained in:
parent
aaf1ccde14
commit
ddbbbae3c8
|
@ -97,7 +97,7 @@ cli do(slots = SLOTS_PER_EPOCH * 5,
|
|||
withTimer(timers[t]):
|
||||
signedBlock = addTestBlock(
|
||||
state[], latest_block_root, cache, attestations = blockAttestations,
|
||||
flags = flags)
|
||||
flags = flags).phase0Block
|
||||
latest_block_root = withTimerRet(timers[tHashBlock]):
|
||||
hash_tree_root(signedBlock.message)
|
||||
signedBlock.root = latest_block_root
|
||||
|
|
|
@ -113,7 +113,7 @@ suite "Attestation pool processing" & preset():
|
|||
let
|
||||
root1 = addTestBlock(
|
||||
state.data, state.blck.root,
|
||||
cache, attestations = attestations, nextSlot = false).root
|
||||
cache, attestations = attestations, nextSlot = false).phase0Block.root
|
||||
bc1 = get_beacon_committee(
|
||||
state[].data, getStateField(state.data, slot), 0.CommitteeIndex, cache)
|
||||
att1 = makeAttestation(state[].data, root1, bc1[0], cache)
|
||||
|
@ -377,7 +377,7 @@ suite "Attestation pool processing" & preset():
|
|||
test "Fork choice returns latest block with no attestations":
|
||||
var cache = StateCache()
|
||||
let
|
||||
b1 = addTestBlock(state.data, dag.tail.root, cache)
|
||||
b1 = addTestBlock(state.data, dag.tail.root, cache).phase0Block
|
||||
b1Add = dag.addRawBlock(quarantine, b1) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
|
@ -390,7 +390,7 @@ suite "Attestation pool processing" & preset():
|
|||
head == b1Add[]
|
||||
|
||||
let
|
||||
b2 = addTestBlock(state.data, b1.root, cache)
|
||||
b2 = addTestBlock(state.data, b1.root, cache).phase0Block
|
||||
b2Add = dag.addRawBlock(quarantine, b2) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
|
@ -405,7 +405,7 @@ suite "Attestation pool processing" & preset():
|
|||
test "Fork choice returns block with attestation":
|
||||
var cache = StateCache()
|
||||
let
|
||||
b10 = makeTestBlock(state.data, dag.tail.root, cache)
|
||||
b10 = makeTestBlock(state.data, dag.tail.root, cache).phase0Block
|
||||
b10Add = dag.addRawBlock(quarantine, b10) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
|
@ -420,7 +420,7 @@ suite "Attestation pool processing" & preset():
|
|||
let
|
||||
b11 = makeTestBlock(state.data, dag.tail.root, cache,
|
||||
graffiti = GraffitiBytes [1'u8, 0, 0, 0 ,0 ,0 ,0 ,0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
)
|
||||
).phase0Block
|
||||
b11Add = dag.addRawBlock(quarantine, b11) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
|
@ -466,7 +466,7 @@ suite "Attestation pool processing" & preset():
|
|||
test "Trying to add a block twice tags the second as an error":
|
||||
var cache = StateCache()
|
||||
let
|
||||
b10 = makeTestBlock(state.data, dag.tail.root, cache)
|
||||
b10 = makeTestBlock(state.data, dag.tail.root, cache).phase0Block
|
||||
b10Add = dag.addRawBlock(quarantine, b10) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
|
@ -495,7 +495,7 @@ suite "Attestation pool processing" & preset():
|
|||
dag.updateFlags.incl {skipBLSValidation}
|
||||
var cache = StateCache()
|
||||
let
|
||||
b10 = addTestBlock(state.data, dag.tail.root, cache)
|
||||
b10 = addTestBlock(state.data, dag.tail.root, cache).phase0Block
|
||||
b10Add = dag.addRawBlock(quarantine, b10) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
|
@ -521,7 +521,7 @@ suite "Attestation pool processing" & preset():
|
|||
get_committee_count_per_slot(state[].data, Epoch epoch, cache)
|
||||
for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH:
|
||||
let new_block = addTestBlock(
|
||||
state.data, block_root, cache, attestations = attestations)
|
||||
state.data, block_root, cache, attestations = attestations).phase0Block
|
||||
|
||||
block_root = new_block.root
|
||||
let blockRef = dag.addRawBlock(quarantine, new_block) do (
|
||||
|
|
|
@ -127,8 +127,8 @@ suite "Block pool processing" & preset():
|
|||
cache = StateCache()
|
||||
rewards = RewardInfo()
|
||||
att0 = makeFullAttestations(state[], dag.tail.root, 0.Slot, cache)
|
||||
b1 = addTestBlock(state[], dag.tail.root, cache, attestations = att0)
|
||||
b2 = addTestBlock(state[], b1.root, cache)
|
||||
b1 = addTestBlock(state[], dag.tail.root, cache, attestations = att0).phase0Block
|
||||
b2 = addTestBlock(state[], b1.root, cache).phase0Block
|
||||
test "getRef returns nil for missing blocks":
|
||||
check:
|
||||
dag.getRef(default Eth2Digest) == nil
|
||||
|
@ -181,7 +181,7 @@ suite "Block pool processing" & preset():
|
|||
rewards, {})
|
||||
|
||||
let
|
||||
b4 = addTestBlock(state[], b2.root, cache)
|
||||
b4 = addTestBlock(state[], b2.root, cache).phase0Block
|
||||
b4Add = dag.addRawBlock(quarantine, b4, nilPhase0Callback)
|
||||
|
||||
check:
|
||||
|
@ -357,7 +357,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
test "prune heads on finalization" & preset():
|
||||
# Create a fork that will not be taken
|
||||
var
|
||||
blck = makeTestBlock(dag.headState.data, dag.head.root, cache)
|
||||
blck = makeTestBlock(dag.headState.data, dag.head.root, cache).phase0Block
|
||||
tmpState = assignClone(dag.headState.data)
|
||||
check:
|
||||
process_slots(
|
||||
|
@ -365,7 +365,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
getStateField(tmpState[], slot) + (5 * SLOTS_PER_EPOCH).uint64,
|
||||
cache, rewards, {})
|
||||
|
||||
let lateBlock = addTestBlock(tmpState[], dag.head.root, cache)
|
||||
let lateBlock = addTestBlock(tmpState[], dag.head.root, cache).phase0Block
|
||||
block:
|
||||
let status = dag.addRawBlock(quarantine, blck, nilPhase0Callback)
|
||||
check: status.isOk()
|
||||
|
@ -381,7 +381,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
blck = addTestBlock(
|
||||
tmpState[], dag.head.root, cache,
|
||||
attestations = makeFullAttestations(
|
||||
tmpState[], dag.head.root, getStateField(tmpState[], slot), cache, {}))
|
||||
tmpState[], dag.head.root, getStateField(tmpState[], slot), cache, {})).phase0Block
|
||||
let added = dag.addRawBlock(quarantine, blck, nilPhase0Callback)
|
||||
check: added.isOk()
|
||||
dag.updateHead(added[], quarantine)
|
||||
|
@ -452,7 +452,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
if i == SLOTS_PER_EPOCH - 1:
|
||||
assign(prestate[], dag.headState.data)
|
||||
|
||||
let blck = makeTestBlock(dag.headState.data, dag.head.root, cache)
|
||||
let blck = makeTestBlock(dag.headState.data, dag.head.root, cache).phase0Block
|
||||
let added = dag.addRawBlock(quarantine, blck, nilPhase0Callback)
|
||||
check: added.isOk()
|
||||
dag.updateHead(added[], quarantine)
|
||||
|
@ -469,7 +469,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
cache, rewards, {})
|
||||
|
||||
# create another block, orphaning the head
|
||||
let blck = makeTestBlock(prestate[], dag.head.parent.root, cache)
|
||||
let blck = makeTestBlock(prestate[], dag.head.parent.root, cache).phase0Block
|
||||
|
||||
# Add block, but don't update head
|
||||
let added = dag.addRawBlock(quarantine, blck, nilPhase0Callback)
|
||||
|
@ -486,7 +486,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
for blck in makeTestBlocks(
|
||||
dag.headState.data, dag.head.root, cache, int(SLOTS_PER_EPOCH * 6 - 2),
|
||||
true):
|
||||
let added = dag.addRawBlock(quarantine, blck, nilPhase0Callback)
|
||||
let added = dag.addRawBlock(quarantine, blck.phase0Block, nilPhase0Callback)
|
||||
check: added.isOk()
|
||||
dag.updateHead(added[], quarantine)
|
||||
dag.pruneAtFinalization()
|
||||
|
@ -501,7 +501,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
dag.headState.data, dag.head.root, cache,
|
||||
attestations = makeFullAttestations(
|
||||
dag.headState.data, dag.head.root, getStateField(dag.headState.data, slot),
|
||||
cache, {}))
|
||||
cache, {})).phase0Block
|
||||
|
||||
let added = dag.addRawBlock(quarantine, blck, nilPhase0Callback)
|
||||
check: added.isOk()
|
||||
|
@ -563,7 +563,7 @@ suite "Old database versions" & preset():
|
|||
state = newClone(dag.headState.data)
|
||||
cache = StateCache()
|
||||
att0 = makeFullAttestations(state[], dag.tail.root, 0.Slot, cache)
|
||||
b1 = addTestBlock(state[], dag.tail.root, cache, attestations = att0)
|
||||
b1 = addTestBlock(state[], dag.tail.root, cache, attestations = att0).phase0Block
|
||||
b1Add = dag.addRawBlock(quarantine, b1, nilPhase0Callback)
|
||||
|
||||
check:
|
||||
|
@ -600,7 +600,7 @@ suite "Diverging hardforks":
|
|||
# Because the first block is after the Altair transition, the only block in
|
||||
# common is the tail block
|
||||
var
|
||||
b1 = addTestBlock(tmpState[], dag.tail.root, cache)
|
||||
b1 = addTestBlock(tmpState[], dag.tail.root, cache).phase0Block
|
||||
b1Add = dag.addRawBlock(quarantine, b1, nilPhase0Callback)
|
||||
|
||||
check b1Add.isOk()
|
||||
|
@ -618,7 +618,7 @@ suite "Diverging hardforks":
|
|||
|
||||
# There's a block in the shared-correct phase0 hardfork, before epoch 2
|
||||
var
|
||||
b1 = addTestBlock(tmpState[], dag.tail.root, cache)
|
||||
b1 = addTestBlock(tmpState[], dag.tail.root, cache).phase0Block
|
||||
b1Add = dag.addRawBlock(quarantine, b1, nilPhase0Callback)
|
||||
|
||||
check:
|
||||
|
@ -629,7 +629,7 @@ suite "Diverging hardforks":
|
|||
cache, rewards, {})
|
||||
|
||||
var
|
||||
b2 = addTestBlock(tmpState[], b1.root, cache)
|
||||
b2 = addTestBlock(tmpState[], b1.root, cache).phase0Block
|
||||
b2Add = dag.addRawBlock(quarantine, b2, nilPhase0Callback)
|
||||
|
||||
check b2Add.isOk()
|
||||
|
|
|
@ -74,7 +74,7 @@ suite "Gossip validation " & preset():
|
|||
for blck in makeTestBlocks(
|
||||
dag.headState.data, dag.head.root, cache,
|
||||
int(SLOTS_PER_EPOCH * 5), false):
|
||||
let added = dag.addRawBlock(quarantine, blck) do (
|
||||
let added = dag.addRawBlock(quarantine, blck.phase0Block) do (
|
||||
blckRef: BlockRef, signedBlock: phase0.TrustedSignedBeaconBlock,
|
||||
epochRef: EpochRef):
|
||||
# Callback add to fork choice if valid
|
||||
|
|
|
@ -10,7 +10,7 @@ import
|
|||
options, stew/endians2,
|
||||
../beacon_chain/[beacon_node_types],
|
||||
../beacon_chain/validators/validator_pool,
|
||||
../beacon_chain/spec/datatypes/[phase0, altair, merge],
|
||||
../beacon_chain/spec/datatypes/merge,
|
||||
../beacon_chain/spec/[helpers, signatures, state_transition, forks],
|
||||
../beacon_chain/consensus_object_pools/attestation_pool
|
||||
|
||||
|
@ -60,19 +60,18 @@ func makeInitialDeposits*(
|
|||
result.add makeDeposit(i, flags)
|
||||
|
||||
func signBlock(
|
||||
fork: Fork, genesis_validators_root: Eth2Digest, blck: phase0.BeaconBlock,
|
||||
privKey: ValidatorPrivKey, flags: UpdateFlags = {}): phase0.SignedBeaconBlock =
|
||||
let root = hash_tree_root(blck)
|
||||
phase0.SignedBeaconBlock(
|
||||
message: blck,
|
||||
root: root,
|
||||
signature:
|
||||
fork: Fork, genesis_validators_root: Eth2Digest, forked: ForkedBeaconBlock,
|
||||
privKey: ValidatorPrivKey, flags: UpdateFlags = {}): ForkedSignedBeaconBlock =
|
||||
let
|
||||
slot = withBlck(forked): blck.slot
|
||||
root = hash_tree_root(forked)
|
||||
signature =
|
||||
if skipBlsValidation notin flags:
|
||||
get_block_signature(
|
||||
fork, genesis_validators_root, blck.slot, root, privKey).toValidatorSig()
|
||||
fork, genesis_validators_root, slot, root, privKey).toValidatorSig()
|
||||
else:
|
||||
ValidatorSig()
|
||||
)
|
||||
ForkedSignedBeaconBlock.init(forked, root, signature)
|
||||
|
||||
proc addTestBlock*(
|
||||
state: var ForkedHashedBeaconState,
|
||||
|
@ -83,7 +82,7 @@ proc addTestBlock*(
|
|||
deposits = newSeq[Deposit](),
|
||||
graffiti = default(GraffitiBytes),
|
||||
flags: set[UpdateFlag] = {},
|
||||
nextSlot = true): phase0.SignedBeaconBlock =
|
||||
nextSlot = true): ForkedSignedBeaconBlock =
|
||||
# Create and add a block to state - state will advance by one slot!
|
||||
if nextSlot:
|
||||
var rewards: RewardInfo
|
||||
|
@ -104,34 +103,61 @@ proc addTestBlock*(
|
|||
else:
|
||||
ValidatorSig()
|
||||
|
||||
let
|
||||
message = makeBeaconBlock(
|
||||
defaultRuntimeConfig,
|
||||
state.hbsPhase0,
|
||||
proposer_index.get(),
|
||||
parent_root,
|
||||
randao_reveal,
|
||||
# Keep deposit counts internally consistent.
|
||||
Eth1Data(
|
||||
deposit_root: eth1_data.deposit_root,
|
||||
deposit_count: getStateField(state, eth1_deposit_index) + deposits.lenu64,
|
||||
block_hash: eth1_data.block_hash),
|
||||
graffiti,
|
||||
attestations,
|
||||
deposits,
|
||||
@[],
|
||||
@[],
|
||||
@[],
|
||||
default(ExecutionPayload),
|
||||
noRollback,
|
||||
cache)
|
||||
|
||||
doAssert message.isOk(), "Should have created a valid block!"
|
||||
let message =
|
||||
case state.beaconStateFork
|
||||
of forkPhase0:
|
||||
let res = makeBeaconBlock(
|
||||
defaultRuntimeConfig,
|
||||
state.hbsPhase0,
|
||||
proposer_index.get(),
|
||||
parent_root,
|
||||
randao_reveal,
|
||||
# Keep deposit counts internally consistent.
|
||||
Eth1Data(
|
||||
deposit_root: eth1_data.deposit_root,
|
||||
deposit_count: getStateField(state, eth1_deposit_index) + deposits.lenu64,
|
||||
block_hash: eth1_data.block_hash),
|
||||
graffiti,
|
||||
attestations,
|
||||
deposits,
|
||||
@[],
|
||||
@[],
|
||||
@[],
|
||||
default(ExecutionPayload),
|
||||
noRollback,
|
||||
cache)
|
||||
doAssert res.isOk(), "Should have created a valid block!"
|
||||
ForkedBeaconBlock.init(res.get())
|
||||
of forkAltair:
|
||||
let res = makeBeaconBlock(
|
||||
defaultRuntimeConfig,
|
||||
state.hbsAltair,
|
||||
proposer_index.get(),
|
||||
parent_root,
|
||||
randao_reveal,
|
||||
# Keep deposit counts internally consistent.
|
||||
Eth1Data(
|
||||
deposit_root: eth1_data.deposit_root,
|
||||
deposit_count: getStateField(state, eth1_deposit_index) + deposits.lenu64,
|
||||
block_hash: eth1_data.block_hash),
|
||||
graffiti,
|
||||
attestations,
|
||||
deposits,
|
||||
@[],
|
||||
@[],
|
||||
@[],
|
||||
SyncAggregate(
|
||||
sync_committee_signature: ValidatorSig.infinity),
|
||||
default(ExecutionPayload),
|
||||
noRollback,
|
||||
cache)
|
||||
doAssert res.isOk(), "Should have created a valid block!"
|
||||
ForkedBeaconBlock.init(res.get())
|
||||
|
||||
let
|
||||
new_block = signBlock(
|
||||
getStateField(state, fork),
|
||||
getStateField(state, genesis_validators_root), message.get(), privKey,
|
||||
getStateField(state, genesis_validators_root), message, privKey,
|
||||
flags)
|
||||
|
||||
new_block
|
||||
|
@ -143,7 +169,7 @@ proc makeTestBlock*(
|
|||
eth1_data = Eth1Data(),
|
||||
attestations = newSeq[Attestation](),
|
||||
deposits = newSeq[Deposit](),
|
||||
graffiti = default(GraffitiBytes)): phase0.SignedBeaconBlock =
|
||||
graffiti = default(GraffitiBytes)): ForkedSignedBeaconBlock =
|
||||
# Create a block for `state.slot + 1` - like a block proposer would do!
|
||||
# It's a bit awkward - in order to produce a block for N+1, we need to
|
||||
# calculate what the state will look like after that block has been applied,
|
||||
|
@ -284,33 +310,26 @@ func makeFullAttestations*(
|
|||
attestation.signature = agg.finish().toValidatorSig()
|
||||
result.add attestation
|
||||
|
||||
iterator makeTestBlocks(
|
||||
state: phase0.HashedBeaconState,
|
||||
iterator makeTestBlocks*(
|
||||
state: ForkedHashedBeaconState,
|
||||
parent_root: Eth2Digest,
|
||||
cache: var StateCache,
|
||||
blocks: int,
|
||||
attested: bool): phase0.SignedBeaconBlock =
|
||||
attested: bool): ForkedSignedBeaconBlock =
|
||||
var
|
||||
# TODO replace wrapper with more native usage
|
||||
state = (ref ForkedHashedBeaconState)(
|
||||
hbsPhase0: state, beaconStateFork: forkPhase0)
|
||||
state = assignClone(state)[]
|
||||
parent_root = parent_root
|
||||
for _ in 0..<blocks:
|
||||
let attestations = if attested:
|
||||
makeFullAttestations(state[], parent_root, getStateField(state[], slot), cache)
|
||||
makeFullAttestations(state, parent_root, getStateField(state, slot), cache)
|
||||
else:
|
||||
@[]
|
||||
|
||||
let blck = addTestBlock(
|
||||
state[], parent_root, cache, attestations = attestations)
|
||||
state, parent_root, cache, attestations = attestations)
|
||||
yield blck
|
||||
parent_root = blck.root
|
||||
|
||||
iterator makeTestBlocks*(state: ForkedHashedBeaconState; parent_root: Eth2Digest;
|
||||
cache: var StateCache; blocks: int; attested: bool): phase0.SignedBeaconBlock =
|
||||
for blck in makeTestBlocks(state.hbsPhase0, parent_root, cache, blocks, attested):
|
||||
yield blck
|
||||
|
||||
proc getAttestationsForTestBlock*(
|
||||
pool: var AttestationPool, stateData: StateData, cache: var StateCache):
|
||||
seq[Attestation] =
|
||||
|
|
Loading…
Reference in New Issue