diff --git a/pyproject.toml b/pyproject.toml index 2b15aa6eb1..7c829bab77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ dependencies = [ [project.optional-dependencies] test = [ + "deepdiff==8.5.0", "pytest-cov==6.2.1", "pytest-xdist==3.7.0", "pytest==8.4.1", diff --git a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py index 4b5cdbc1ce..57ce36e878 100644 --- a/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/deneb/fork_choice/test_on_block.py @@ -4,20 +4,12 @@ spec_state_test, with_all_phases_from_except, ) -from eth2spec.test.helpers.blob import ( - get_sample_blob_tx, -) -from eth2spec.test.helpers.block import ( - build_empty_block_for_next_slot, -) +from eth2spec.test.helpers.blob import get_block_with_blob from eth2spec.test.helpers.constants import ( DENEB, EIP7732, FULU, ) -from eth2spec.test.helpers.execution_payload import ( - compute_el_block_hash, -) from eth2spec.test.helpers.fork_choice import ( BlobData, get_genesis_forkchoice_store_and_block, @@ -29,19 +21,6 @@ ) -def get_block_with_blob(spec, state, rng=None): - block = build_empty_block_for_next_slot(spec, state) - opaque_tx, blobs, blob_kzg_commitments, blob_kzg_proofs = get_sample_blob_tx( - spec, blob_count=1, rng=rng - ) - block.body.execution_payload.transactions = [opaque_tx] - block.body.execution_payload.block_hash = compute_el_block_hash( - spec, block.body.execution_payload, state - ) - block.body.blob_kzg_commitments = blob_kzg_commitments - return block, blobs, blob_kzg_proofs - - # TODO(jtraglia): Use with_all_phases_from_to_except after EIP7732 is based on Fulu. # This applies to every other test in this file too. @with_all_phases_from_except(DENEB, [FULU, EIP7732]) diff --git a/tests/core/pyspec/eth2spec/test/fulu/fork_choice/test_on_block.py b/tests/core/pyspec/eth2spec/test/fulu/fork_choice/test_on_block.py index fdead7e728..c2430720d4 100644 --- a/tests/core/pyspec/eth2spec/test/fulu/fork_choice/test_on_block.py +++ b/tests/core/pyspec/eth2spec/test/fulu/fork_choice/test_on_block.py @@ -1 +1,337 @@ -# TODO: add new data availability tests. +from random import Random + +from eth2spec.test.context import ( + spec_state_test, + with_fulu_and_later, +) +from eth2spec.test.helpers.blob import get_block_with_blob_and_sidecars +from eth2spec.test.helpers.fork_choice import ( + BlobData, + get_genesis_forkchoice_store_and_block, + on_tick_and_append_step, + tick_and_add_block_with_data, +) + + +def flip_one_bit_in_bytes(data: bytes, index: int = 0) -> bytes: + """ + Flip one bit in a bytes object at the given index. + """ + constr = data.__class__ + byte_index = index // 8 + bit_index = 7 - (index % 8) + byte = data[byte_index] + flipped_byte = byte ^ (1 << bit_index) + + return constr(bytes(data[:byte_index]) + bytes([flipped_byte]) + bytes(data[byte_index + 1 :])) + + +def get_alt_sidecars(spec, state): + """ + Get alternative sidecars for negative test cases. + """ + rng = Random(4321) + _, _, _, _, alt_sidecars = get_block_with_blob_and_sidecars(spec, state, rng=rng, blob_count=2) + return alt_sidecars + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__ok(spec, state): + """ + Similar to test_simple_blob_data, but in PeerDAS version that is from Fulu onwards. + It covers code related to the blob sidecars because on_block calls `is_data_available` + and we are calling `get_data_column_sidecars_from_block` in the test itself. + """ + rng = Random(1234) + + test_steps = [] + # Initialization + store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) + yield "anchor_state", state + yield "anchor_block", anchor_block + current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time + on_tick_and_append_step(spec, store, current_time, test_steps) + assert store.time == current_time + + # On receiving a block of `GENESIS_SLOT + 1` slot + _, blobs, blob_kzg_proofs, signed_block, sidecars = get_block_with_blob_and_sidecars( + spec, state, rng=rng, blob_count=2 + ) + blob_data = BlobData(blobs, blob_kzg_proofs, sidecars) + + yield from tick_and_add_block_with_data(spec, store, signed_block, test_steps, blob_data) + + assert spec.get_head(store) == signed_block.message.hash_tree_root() + + # On receiving a block of next epoch + _, blobs, blob_kzg_proofs, signed_block, sidecars = get_block_with_blob_and_sidecars( + spec, state, rng=rng, blob_count=2 + ) + blob_data = BlobData(blobs, blob_kzg_proofs, sidecars) + + yield from tick_and_add_block_with_data(spec, store, signed_block, test_steps, blob_data) + + assert spec.get_head(store) == signed_block.message.hash_tree_root() + + yield "steps", test_steps + + +def run_on_block_peerdas_invalid_test(spec, state, fn): + """ + Run a invalid PeerDAS on_block test with a sidecars mutation function. + """ + rng = Random(1234) + + test_steps = [] + + # Initialization + store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) + yield "anchor_state", state + yield "anchor_block", anchor_block + current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time + on_tick_and_append_step(spec, store, current_time, test_steps) + assert store.time == current_time + + _, blobs, blob_kzg_proofs, signed_block, sidecars = get_block_with_blob_and_sidecars( + spec, state, rng=rng, blob_count=2 + ) + sidecars = fn(sidecars) + blob_data = BlobData(blobs, blob_kzg_proofs, []) + + yield from tick_and_add_block_with_data( + spec, store, signed_block, test_steps, blob_data, valid=False + ) + assert spec.get_head(store) != signed_block.message.hash_tree_root() + + yield "steps", test_steps + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__not_available(spec, state): + """ + Test is_data_available throws an exception when not enough columns are sampled. + """ + yield from run_on_block_peerdas_invalid_test( + spec, + state, + # Empty sidecars will trigger the simulation of not enough columns being sampled + lambda _: [], + ) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_zero_blobs(spec, state): + """ + Test is_data_available returns false when there are no blobs in the sidecars. + """ + + def invalid_zero_blobs(sidecars): + sidecars[0].column = [] + sidecars[0].kzg_commitments = [] + sidecars[0].kzg_proofs = [] + return sidecars + + yield from run_on_block_peerdas_invalid_test(spec, state, invalid_zero_blobs) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_index_1(spec, state): + """ + Test invalid index in sidecars for negative PeerDAS on_block test. + """ + + def invalid_index(sidecars): + sidecars[0].index = 128 # Invalid index + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_index) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_index_2(spec, state): + """ + Test invalid index in sidecars for negative PeerDAS on_block test. + """ + + def invalid_index(sidecars): + sidecars[0].index = 256 # Invalid index + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_index) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_mismatch_len_column_1(spec, state): + """ + Test mismatch length in column for negative PeerDAS on_block test. + """ + + def invalid_mismatch_len_column(sidecars): + sidecars[0].column = sidecars[0].column[1:] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_mismatch_len_column) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_mismatch_len_column_2(spec, state): + """ + Test mismatch length in column for negative PeerDAS on_block test. + """ + + def invalid_mismatch_len_column(sidecars): + sidecars[1].column = sidecars[1].column[1:] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_mismatch_len_column) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_mismatch_len_kzg_commitments_1(spec, state): + """ + Test mismatch length in kzg_commitments for negative PeerDAS on_block test. + """ + + def invalid_mismatch_len_kzg_commitments(sidecars): + sidecars[0].kzg_commitments = sidecars[0].kzg_commitments[1:] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_mismatch_len_kzg_commitments) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_mismatch_len_kzg_commitments_2(spec, state): + """ + Test mismatch length in kzg_commitments for negative PeerDAS on_block test. + """ + + def invalid_mismatch_len_kzg_commitments(sidecars): + sidecars[1].kzg_commitments = sidecars[1].kzg_commitments[1:] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_mismatch_len_kzg_commitments) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_mismatch_len_kzg_proofs_1(spec, state): + """ + Test mismatch length in kzg_proofs for negative PeerDAS on_block test. + """ + + def invalid_mismatch_len_kzg_proofs(sidecars): + sidecars[0].kzg_proofs = sidecars[0].kzg_proofs[1:] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_mismatch_len_kzg_proofs) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_mismatch_len_kzg_proofs_2(spec, state): + """ + Test mismatch length in kzg_proofs for negative PeerDAS on_block test. + """ + + def invalid_mismatch_len_kzg_proofs(sidecars): + sidecars[1].kzg_proofs = sidecars[1].kzg_proofs[1:] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_mismatch_len_kzg_proofs) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_wrong_column_1(spec, state): + """ + Test wrong column for negative PeerDAS on_block test. + """ + + def invalid_wrong_column(sidecars): + sidecars[0].column[0] = flip_one_bit_in_bytes(sidecars[0].column[0], 80) + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_wrong_column) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_wrong_column_2(spec, state): + """ + Test wrong column for negative PeerDAS on_block test. + """ + + def invalid_wrong_column(sidecars): + sidecars[1].column[1] = flip_one_bit_in_bytes(sidecars[1].column[1], 20) + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_wrong_column) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_wrong_commitment_1(spec, state): + """ + Test wrong commitment for negative PeerDAS on_block test. + """ + alt_sidecars = get_alt_sidecars(spec, state) + + def invalid_wrong_commitment(sidecars): + sidecars[0].kzg_commitments[0] = alt_sidecars[0].kzg_commitments[0] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_wrong_commitment) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_wrong_commitment_2(spec, state): + """ + Test wrong commitment for negative PeerDAS on_block test. + """ + alt_sidecars = get_alt_sidecars(spec, state) + + def invalid_wrong_commitment(sidecars): + sidecars[1].kzg_commitments[1] = alt_sidecars[1].kzg_commitments[1] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_wrong_commitment) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_wrong_proof_1(spec, state): + """ + Test wrong proof for negative PeerDAS on_block test. + """ + alt_sidecars = get_alt_sidecars(spec, state) + + def invalid_wrong_proof(sidecars): + sidecars[0].kzg_proofs[0] = alt_sidecars[0].kzg_proofs[0] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_wrong_proof) + + +@with_fulu_and_later +@spec_state_test +def test_on_block_peerdas__invalid_wrong_proof_2(spec, state): + """ + Test wrong proof for negative PeerDAS on_block test. + """ + alt_sidecars = get_alt_sidecars(spec, state) + + def invalid_wrong_proof(sidecars): + sidecars[1].kzg_proofs[1] = alt_sidecars[1].kzg_proofs[1] + return sidecars + + run_on_block_peerdas_invalid_test(spec, state, invalid_wrong_proof) diff --git a/tests/core/pyspec/eth2spec/test/fulu/unittests/das/test_das.py b/tests/core/pyspec/eth2spec/test/fulu/unittests/das/test_das.py index 767b4cd275..6b12586196 100644 --- a/tests/core/pyspec/eth2spec/test/fulu/unittests/das/test_das.py +++ b/tests/core/pyspec/eth2spec/test/fulu/unittests/das/test_das.py @@ -1,13 +1,18 @@ import random +from deepdiff import DeepDiff + from eth2spec.test.context import ( single_phase, + spec_state_test, spec_test, with_fulu_and_later, ) from eth2spec.test.helpers.blob import ( + get_block_with_blob_and_sidecars, get_sample_blob, ) +from eth2spec.test.helpers.fork_choice import BlobData, with_blob_data def chunks(lst, n): @@ -65,3 +70,62 @@ def test_recover_matrix(spec): # Ensure that the recovered matrix matches the original matrix assert recovered_matrix == matrix + + +def run_is_data_available_peerdas_test(spec, blob_data): + def callback(): + yield spec.is_data_available(spec.Root(b"\x00" * 32)) + + return next(with_blob_data(spec, blob_data, callback)) + + +@with_fulu_and_later +@spec_state_test +def test_is_data_available_peerdas(spec, state): + rng = random.Random(1234) + _, blobs, blob_kzg_proofs, _, sidecars = get_block_with_blob_and_sidecars( + spec, state, rng=rng, blob_count=2 + ) + blob_data = BlobData(blobs, blob_kzg_proofs, sidecars) + + result = run_is_data_available_peerdas_test(spec, blob_data) + + assert result is True, "Data should be available for the block with blob data" + + +@with_fulu_and_later +@spec_state_test +def test_get_data_column_sidecars(spec, state): + rng = random.Random(1234) + _, blobs, _, signed_block, sidecars = get_block_with_blob_and_sidecars( + spec, state, rng=rng, blob_count=2 + ) + + sidecars_result = spec.get_data_column_sidecars( + signed_block_header=spec.compute_signed_block_header(signed_block), + kzg_commitments=sidecars[0].kzg_commitments, + kzg_commitments_inclusion_proof=sidecars[0].kzg_commitments_inclusion_proof, + cells_and_kzg_proofs=[spec.compute_cells_and_kzg_proofs(blob) for blob in blobs], + ) + + assert len(sidecars_result) == len(sidecars), ( + "Should return the same number of sidecars as input" + ) + assert DeepDiff(sidecars, sidecars_result) == {}, "Sidecars should match the expected sidecars" + + +@with_fulu_and_later +@spec_state_test +def test_get_data_column_sidecars_from_column_sidecar(spec, state): + rng = random.Random(1234) + _, blobs, _, _, sidecars = get_block_with_blob_and_sidecars(spec, state, rng=rng, blob_count=2) + + sidecars_result = spec.get_data_column_sidecars_from_column_sidecar( + sidecar=sidecars[0], + cells_and_kzg_proofs=[spec.compute_cells_and_kzg_proofs(blob) for blob in blobs], + ) + + assert len(sidecars_result) == len(sidecars), ( + "Should return the same number of sidecars as input" + ) + assert DeepDiff(sidecars, sidecars_result) == {}, "Sidecars should match the expected sidecars" diff --git a/tests/core/pyspec/eth2spec/test/helpers/blob.py b/tests/core/pyspec/eth2spec/test/helpers/blob.py index 2cb37af643..910db36e90 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/blob.py +++ b/tests/core/pyspec/eth2spec/test/helpers/blob.py @@ -1,12 +1,17 @@ import random +from functools import cache +from random import Random from rlp import encode, Serializable from rlp.sedes import big_endian_int, Binary, binary, CountableList, List as RLPList +from eth2spec.test.helpers.block import build_empty_block_for_next_slot +from eth2spec.test.helpers.execution_payload import compute_el_block_hash from eth2spec.test.helpers.forks import ( is_post_electra, is_post_fulu, ) +from eth2spec.test.helpers.state import state_transition_and_sign_block class Eip4844RlpTransaction(Serializable): @@ -126,3 +131,32 @@ def get_max_blob_count(spec, state): return spec.config.MAX_BLOBS_PER_BLOCK_ELECTRA else: return spec.config.MAX_BLOBS_PER_BLOCK + + +def get_block_with_blob(spec, state, rng: Random | None = None, blob_count=1): + block = build_empty_block_for_next_slot(spec, state) + opaque_tx, blobs, blob_kzg_commitments, blob_kzg_proofs = get_sample_blob_tx( + spec, blob_count=blob_count, rng=rng or random.Random(5566) + ) + block.body.execution_payload.transactions = [opaque_tx] + block.body.execution_payload.block_hash = compute_el_block_hash( + spec, block.body.execution_payload, state + ) + block.body.blob_kzg_commitments = blob_kzg_commitments + return block, blobs, blob_kzg_proofs + + +def get_block_with_blob_and_sidecars(spec, state, rng=None, blob_count=1): + block, blobs, blob_kzg_proofs = get_block_with_blob(spec, state, rng=rng, blob_count=blob_count) + cells_and_kzg_proofs = [_cached_compute_cells_and_kzg_proofs(spec, blob) for blob in blobs] + + # We need a signed block to call `get_data_column_sidecars_from_block` + signed_block = state_transition_and_sign_block(spec, state, block) + + sidecars = spec.get_data_column_sidecars_from_block(signed_block, cells_and_kzg_proofs) + return block, blobs, blob_kzg_proofs, signed_block, sidecars + + +@cache +def _cached_compute_cells_and_kzg_proofs(spec, blob): + return spec.compute_cells_and_kzg_proofs(blob) diff --git a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py index 21951d9f8b..1a5efe4615 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py +++ b/tests/core/pyspec/eth2spec/test/helpers/fork_choice.py @@ -3,13 +3,14 @@ from eth_utils import encode_hex +from eth2spec.fulu.mainnet import DataColumnSidecar from eth2spec.test.exceptions import BlockNotFoundException from eth2spec.test.helpers.attestations import ( next_epoch_with_attestations, next_slots_with_attestations, state_transition_with_full_block, ) -from eth2spec.test.helpers.forks import is_post_eip7732 +from eth2spec.test.helpers.forks import is_post_eip7732, is_post_fulu from eth2spec.test.helpers.state import ( payload_state_transition, payload_state_transition_no_store, @@ -30,16 +31,29 @@ class BlobData(NamedTuple): """ blobs: Sequence[Any] - proofs: Sequence[bytes] + proofs: Sequence[bytes] | None = None + sidecars: Sequence[DataColumnSidecar] | None = None -def with_blob_data(spec, blob_data, func): +def with_blob_data(spec, blob_data: BlobData, func): + if not is_post_fulu(spec): + if blob_data.proofs is None: + raise ValueError("blob_data.proofs must be provided when pre FULU fork") + yield from with_blob_data_deneb(spec, blob_data, func) + else: + if blob_data.sidecars is None: + raise ValueError("blob_data.sidecars must be provided when post FULU fork") + yield from with_blob_data_fulu(spec, blob_data, func) + + +def with_blob_data_deneb(spec, blob_data: BlobData, func): """ This helper runs the given ``func`` with monkeypatched ``retrieve_blobs_and_proofs`` that returns ``blob_data.blobs, blob_data.proofs``. """ - def retrieve_blobs_and_proofs(beacon_block_root): + def retrieve_blobs_and_proofs(_): + assert blob_data.proofs is not None, "blob_data.proofs must be provided" return blob_data.blobs, blob_data.proofs retrieve_blobs_and_proofs_backup = spec.retrieve_blobs_and_proofs @@ -61,6 +75,37 @@ def wrap(flag: AtomicBoolean): assert is_called.value +def with_blob_data_fulu(spec, blob_data: BlobData, func): + """ + This helper runs the given ``func`` with monkeypatched ``retrieve_column_sidecars`` + that returns ``blob_data``. + """ + + def retrieve_column_sidecars(_): + assert blob_data.sidecars is not None, "blob_data.sidecars must be provided" + if len(blob_data.sidecars) == 0: + assert False, "Simulation: not all required columns have been sampled" + return blob_data.sidecars + + retrieve_column_sidecars_backup = spec.retrieve_column_sidecars + spec.retrieve_column_sidecars = retrieve_column_sidecars + + class AtomicBoolean: + value = False + + is_called = AtomicBoolean() + + def wrap(flag: AtomicBoolean): + yield from func() + flag.value = True + + try: + yield from wrap(is_called) + finally: + spec.retrieve_column_sidecars = retrieve_column_sidecars_backup + assert is_called.value + + def get_anchor_root(spec, state): anchor_block_header = state.latest_block_header.copy() if anchor_block_header.state_root == spec.Bytes32(): @@ -77,7 +122,7 @@ def tick_and_add_block( merge_block=False, block_not_found=False, is_optimistic=False, - blob_data=None, + blob_data: BlobData | None = None, ): pre_state = get_store_full_state(spec, store, signed_block.message.parent_root) if merge_block: @@ -189,6 +234,20 @@ def get_blobs_file_name(blobs=None, blobs_root=None): return f"blobs_{encode_hex(blobs_root)}" +def get_sidecars_file_names(sidecars: Sequence[DataColumnSidecar]) -> Sequence[str]: + """ + Returns the file names for sidecars. + """ + return [get_sidecar_file_name(sidecar) for sidecar in sidecars] + + +def get_sidecar_file_name(sidecar: DataColumnSidecar) -> str: + """ + Returns the file name for a single sidecar. + """ + return f"sidecar_{encode_hex(sidecar.hash_tree_root())}" + + def on_tick_and_append_step(spec, store, time, test_steps): assert time >= store.time spec.on_tick(store, time) @@ -237,18 +296,23 @@ def add_block( blobs_root = blobs.hash_tree_root() yield get_blobs_file_name(blobs_root=blobs_root), blobs - is_blob_data_test = blob_data is not None + if blob_data.sidecars is not None: + for sidecar in blob_data.sidecars: + yield get_sidecar_file_name(sidecar), sidecar - def _append_step(is_blob_data_test, valid=True): - if is_blob_data_test: - test_steps.append( - { - "block": get_block_file_name(signed_block), - "blobs": get_blobs_file_name(blobs_root=blobs_root), - "proofs": [encode_hex(proof) for proof in blob_data.proofs], - "valid": valid, - } - ) + def _append_step(valid=True): + if blob_data is not None: + step = { + "block": get_block_file_name(signed_block), + "blobs": get_blobs_file_name(blobs_root=blobs_root), + "valid": valid, + } + if blob_data.proofs is not None: + step["proofs"] = [encode_hex(proof) for proof in blob_data.proofs] + if blob_data.sidecars is not None: + step["sidecars"] = get_sidecars_file_names(blob_data.sidecars) + + test_steps.append(step) else: test_steps.append( { @@ -260,20 +324,20 @@ def _append_step(is_blob_data_test, valid=True): if not valid: if is_optimistic: run_on_block(spec, store, signed_block, valid=True) - _append_step(is_blob_data_test, valid=False) + _append_step(valid=False) else: try: run_on_block(spec, store, signed_block, valid=True) except (AssertionError, BlockNotFoundException) as e: if isinstance(e, BlockNotFoundException) and not block_not_found: assert False - _append_step(is_blob_data_test, valid=False) + _append_step(valid=False) return else: assert False else: run_on_block(spec, store, signed_block, valid=True) - _append_step(is_blob_data_test) + _append_step() # An on_block step implies receiving block's attestations for attestation in signed_block.message.body.attestations: diff --git a/tests/formats/fork_choice/README.md b/tests/formats/fork_choice/README.md index f640c4560e..c519d2f5e2 100644 --- a/tests/formats/fork_choice/README.md +++ b/tests/formats/fork_choice/README.md @@ -84,6 +84,7 @@ The parameter that is required for executing `on_block(store, block)`. blobs: string -- optional, the name of the `blobs_<32-byte-root>.ssz_snappy` file. The blobs file content is a `List[Blob, MAX_BLOB_COMMITMENTS_PER_BLOCK]` SSZ object. proofs: array of byte48 hex string -- optional, the proofs of blob commitments. + sidecars: string -- optional, array of the names of the `sidecar_<32-byte-root>.ssz_snappy` files. valid: bool -- optional, default to `true`. If it's `false`, this execution step is expected to be invalid. }