diff --git a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py index 80684b9e6e..ba48d98d8c 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py +++ b/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py @@ -1,6 +1,7 @@ from eth_hash.auto import keccak from hashlib import sha256 from trie import HexaryTrie +from random import Random from rlp import encode from rlp.sedes import big_endian_int, Binary, List @@ -263,6 +264,34 @@ def compute_el_block_hash_for_block(spec, block): spec, block.body.execution_payload, block.parent_root, requests_hash) +def build_randomized_execution_payload_header(spec, state, rng=Random(10000)): + execution_payload = build_randomized_execution_payload(spec, state, rng) + execution_payload_header = spec.ExecutionPayloadHeader( + parent_hash=execution_payload.parent_hash, + fee_recipient=execution_payload.fee_recipient, + state_root=execution_payload.state_root, + receipts_root=execution_payload.receipts_root, + logs_bloom=execution_payload.logs_bloom, + prev_randao=execution_payload.prev_randao, + block_number=execution_payload.block_number, + gas_limit=execution_payload.gas_limit, + gas_used=execution_payload.gas_used, + timestamp=execution_payload.timestamp, + extra_data=execution_payload.extra_data, + base_fee_per_gas=execution_payload.base_fee_per_gas, + block_hash=execution_payload.block_hash, + transactions_root=spec.hash_tree_root(execution_payload.transactions), + ) + + if is_post_capella(spec): + execution_payload_header.withdrawals_root = spec.hash_tree_root(execution_payload.withdrawals) + if is_post_deneb(spec): + execution_payload_header.blob_gas_used = execution_payload.blob_gas_used + execution_payload_header.excess_blob_gas = execution_payload.excess_blob_gas + + return execution_payload_header + + def build_empty_post_eip7732_execution_payload_header(spec, state): if not is_post_eip7732(spec): return @@ -331,6 +360,7 @@ def build_empty_execution_payload(spec, state, randao_mix=None): def build_randomized_execution_payload(spec, state, rng): execution_payload = build_empty_execution_payload(spec, state) + # Note: the payload's parent hash is already populated execution_payload.fee_recipient = spec.ExecutionAddress(get_random_bytes_list(rng, 20)) execution_payload.state_root = spec.Bytes32(get_random_bytes_list(rng, 32)) execution_payload.receipts_root = spec.Bytes32(get_random_bytes_list(rng, 32)) @@ -345,13 +375,17 @@ def build_randomized_execution_payload(spec, state, rng): get_random_bytes_list(rng, extra_data_length) ) execution_payload.base_fee_per_gas = rng.randint(0, 2**256 - 1) - - num_transactions = rng.randint(0, 100) execution_payload.transactions = [ get_random_tx(rng) - for _ in range(num_transactions) + for _ in range(rng.randint(0, 100)) ] + # Note: for Capella, the payload's withdrawals are already populated + + if is_post_deneb(spec): + execution_payload.blob_gas_used = rng.randint(0, int(10e10)) + execution_payload.excess_blob_gas = rng.randint(0, int(10e10)) + execution_payload.block_hash = compute_el_block_hash(spec, execution_payload, state) return execution_payload diff --git a/tests/core/pyspec/eth2spec/test/helpers/random.py b/tests/core/pyspec/eth2spec/test/helpers/random.py index eb280076f6..de0eb5c800 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/random.py +++ b/tests/core/pyspec/eth2spec/test/helpers/random.py @@ -4,6 +4,7 @@ from eth2spec.test.helpers.deposits import mock_deposit from eth2spec.test.helpers.forks import is_post_altair from eth2spec.test.helpers.state import next_epoch +from eth2spec.test.helpers.execution_payload import build_randomized_execution_payload_header def set_some_activations(spec, state, rng, activation_epoch=None): @@ -162,6 +163,10 @@ def randomize_attestation_participation(spec, state, rng=Random(8020)): randomize_epoch_participation(spec, state, spec.get_current_epoch(state), rng) +def randomize_execution_payload_header(spec, state, rng=Random(8020)): + state.latest_execution_payload_header = build_randomized_execution_payload_header(spec, state, rng) + + def randomize_state(spec, state, rng=Random(8020), exit_fraction=0.5, slash_fraction=0.5): set_some_new_deposits(spec, state, rng) exit_random_validators(spec, state, rng, fraction=exit_fraction) diff --git a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py index 1c9dec0060..95efe7c968 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py +++ b/tests/core/pyspec/eth2spec/test/helpers/withdrawals.py @@ -9,6 +9,20 @@ def get_expected_withdrawals(spec, state): return spec.get_expected_withdrawals(state) +def get_random_withdrawal(spec, state, rng): + if is_post_electra(spec): + amount = rng.randint(0, spec.MAX_EFFECTIVE_BALANCE_ELECTRA) + else: + amount = rng.randint(0, spec.MAX_EFFECTIVE_BALANCE) + + return spec.Withdrawal( + index=rng.randrange(0, spec.MAX_WITHDRAWALS_PER_PAYLOAD), + validator_index=rng.randrange(0, len(state.validators)), + address=rng.getrandbits(160).to_bytes(20, 'big'), + amount=amount, + ) + + def set_validator_fully_withdrawable(spec, state, index, withdrawable_epoch=None): if withdrawable_epoch is None: withdrawable_epoch = spec.get_current_epoch(state) diff --git a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py index 3dae15c694..ce52461e4e 100644 --- a/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py +++ b/tests/core/pyspec/eth2spec/test/utils/randomized_block_tests.py @@ -24,6 +24,7 @@ from eth2spec.test.helpers.random import ( randomize_state as randomize_state_helper, patch_state_to_non_leaking, + randomize_execution_payload_header, ) from eth2spec.test.helpers.blob import ( get_sample_blob_tx, @@ -76,7 +77,7 @@ def randomize_state_bellatrix(spec, state, stats, exit_fraction=0.1, slash_fract stats, exit_fraction=exit_fraction, slash_fraction=slash_fraction) - # TODO: randomize execution payload, merge status, etc. + randomize_execution_payload_header(spec, state) return scenario_state @@ -86,7 +87,6 @@ def randomize_state_capella(spec, state, stats, exit_fraction=0.1, slash_fractio stats, exit_fraction=exit_fraction, slash_fraction=slash_fraction) - # TODO: randomize withdrawals return scenario_state @@ -96,7 +96,6 @@ def randomize_state_deneb(spec, state, stats, exit_fraction=0.1, slash_fraction= stats, exit_fraction=exit_fraction, slash_fraction=slash_fraction) - # TODO: randomize execution payload return scenario_state