9.6 KiB
Fork choice tests
The aim of the fork choice tests is to provide test coverage of the various components of the fork choice.
Table of contents
- Test case format
- Condition
Test case format
meta.yaml
description: string -- Optional. Description of test case, purely for debugging purposes.
bls_setting: int -- see general test-format spec.
anchor_state.ssz_snappy
An SSZ-snappy encoded BeaconState
, the state to initialize store with get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock)
helper.
anchor_block.ssz_snappy
An SSZ-snappy encoded BeaconBlock
, the block to initialize store with get_forkchoice_store(anchor_state: BeaconState, anchor_block: BeaconBlock)
helper.
steps.yaml
The steps to execute in sequence. There may be multiple items of the following types:
on_tick
execution step
The parameter that is required for executing on_tick(store, time)
.
{
tick: int -- to execute `on_tick(store, time)`.
valid: bool -- optional, default to `true`.
If it's `false`, this execution step is expected to be invalid.
}
After this step, the store
object may have been updated.
on_attestation
execution step
The parameter that is required for executing on_attestation(store, attestation)
.
{
attestation: string -- the name of the `attestation_<32-byte-root>.ssz_snappy` file.
To execute `on_attestation(store, attestation)` with the given attestation.
valid: bool -- optional, default to `true`.
If it's `false`, this execution step is expected to be invalid.
}
The file is located in the same folder (see below).
After this step, the store
object may have been updated.
on_block
execution step
The parameter that is required for executing on_block(store, block)
.
{
block: string -- the name of the `block_<32-byte-root>.ssz_snappy` file.
To execute `on_block(store, block)` with the given attestation.
blobs: string -- optional, the name of the `blobs_<32-byte-root>.ssz_snappy` file.
The blobs file content is a `List[Blob, MAX_BLOBS_PER_BLOCK]` SSZ object.
proofs: array of byte48 hex string -- optional, the proofs of blob commitments.
valid: bool -- optional, default to `true`.
If it's `false`, this execution step is expected to be invalid.
}
The file is located in the same folder (see below).
blobs
and proofs
are new fields from Deneb EIP-4844. These fields indicate the expected values from retrieve_blobs_and_proofs()
helper inside is_data_available()
helper. If these two fields are not provided, retrieve_blobs_and_proofs()
returns empty lists.
After this step, the store
object may have been updated.
on_merge_block
execution step
Adds PowBlock
data which is required for executing on_block(store, block)
.
{
pow_block: string -- the name of the `pow_block_<32-byte-root>.ssz_snappy` file.
To be used in `get_pow_block` lookup
}
The file is located in the same folder (see below).
PowBlocks should be used as return values for get_pow_block(hash: Hash32) -> PowBlock
function if hashes match.
on_attester_slashing
execution step
The parameter that is required for executing on_attester_slashing(store, attester_slashing)
.
{
attester_slashing: string -- the name of the `attester_slashing_<32-byte-root>.ssz_snappy` file.
To execute `on_attester_slashing(store, attester_slashing)` with the given attester slashing.
valid: bool -- optional, default to `true`.
If it's `false`, this execution step is expected to be invalid.
}
The file is located in the same folder (see below).
After this step, the store
object may have been updated.
on_payload_info
execution step
Optional step for optimistic sync tests.
{
block_hash: string, -- Encoded 32-byte value of payload's block hash.
payload_status: {
status: string, -- Enum, "VALID" | "INVALID" | "SYNCING" | "ACCEPTED" | "INVALID_BLOCK_HASH".
latest_valid_hash: string, -- Encoded 32-byte value of the latest valid block hash, may be `null`.
validation_error: string, -- Message providing additional details on the validation error, may be `null`.
}
}
This step sets the payloadStatus
value that Execution Layer client mock returns in responses to the following Engine API calls:
engine_newPayloadV1(payload)
ifpayload.blockHash == payload_info.block_hash
engine_forkchoiceUpdatedV1(forkchoiceState, ...)
ifforkchoiceState.headBlockHash == payload_info.block_hash
Note: Status of a payload must be initialized via on_payload_info
before the corresponding on_block
execution step.
Note: Status of the same payload may be updated for several times throughout the test.
Checks step
The checks to verify the current status of store
.
checks: {<store_attibute>: value} -- the assertions.
<store_attibute>
is the field member or property of Store
object that maintained by client implementation. The fields include:
head: {
slot: int,
root: string, -- Encoded 32-byte value from get_head(store)
}
time: int -- store.time
genesis_time: int -- store.genesis_time
justified_checkpoint: {
epoch: int, -- Integer value from store.justified_checkpoint.epoch
root: string, -- Encoded 32-byte value from store.justified_checkpoint.root
}
finalized_checkpoint: {
epoch: int, -- Integer value from store.finalized_checkpoint.epoch
root: string, -- Encoded 32-byte value from store.finalized_checkpoint.root
}
proposer_boost_root: string -- Encoded 32-byte value from store.proposer_boost_root
Additionally, these fields if get_proposer_head
and should_override_forkchoice_update
features are implemented:
get_proposer_head: string -- Encoded 32-byte value from get_proposer_head(store)
should_override_forkchoice_update: { -- [New in Bellatrix]
validator_is_connected: bool, -- The mocking result of `validator_is_connected(proposer_index)` in this call
result: bool, -- The result of `should_override_forkchoice_update(store, head_root)`, where head_root is the result value from get_head(store)
}
For example:
- checks:
time: 192
head: {slot: 32, root: '0xdaa1d49d57594ced0c35688a6da133abb086d191a2ebdfd736fad95299325aeb'}
justified_checkpoint: {epoch: 3, root: '0xc25faab4acab38d3560864ca01e4d5cc4dc2cd473da053fbc03c2669143a2de4'}
finalized_checkpoint: {epoch: 2, root: '0x40d32d6283ec11c53317a46808bc88f55657d93b95a1af920403187accf48f4f'}
proposer_boost_root: '0xdaa1d49d57594ced0c35688a6da133abb086d191a2ebdfd736fad95299325aeb'
get_proposer_head: '0xdaa1d49d57594ced0c35688a6da133abb086d191a2ebdfd736fad95299325aeb'
should_override_forkchoice_update: {validator_is_connected: false, result: false}
Note: Each checks
step may include one or multiple items. Each item has to be checked against the current store.
attestation_<32-byte-root>.ssz_snappy
<32-byte-root>
is the hash tree root of the given attestation.
Each file is an SSZ-snappy encoded Attestation
.
block_<32-byte-root>.ssz_snappy
<32-byte-root>
is the hash tree root of the given block.
Each file is an SSZ-snappy encoded SignedBeaconBlock
.
Condition
- Deserialize
anchor_state.ssz_snappy
andanchor_block.ssz_snappy
to initialize the local store object by withget_forkchoice_store(anchor_state, anchor_block)
helper. - Iterate sequentially through
steps.yaml
- For each execution, look up the corresponding ssz_snappy file. Execute the corresponding helper function on the current store.
- For the
on_block
execution step: iflen(block.message.body.attestations) > 0
, execute each attestation withon_attestation(store, attestation)
after executingon_block(store, block)
.
- For the
- For each
checks
step, the assertions on the current store must be satisfied.
- For each execution, look up the corresponding ssz_snappy file. Execute the corresponding helper function on the current store.