From 1f926142b8492e67c5c1cb9efafdcb85d4f144a3 Mon Sep 17 00:00:00 2001 From: terence Date: Mon, 3 Nov 2025 12:54:02 -0500 Subject: [PATCH] Update spec test to v1.6.0-beta.2 (#15960) --- WORKSPACE | 4 +- changelog/ttsao-v1.6.0-beta.2.md | 3 + specrefs/.ethspecify.yml | 2 +- specrefs/functions.yml | 115 +++++++++++++++++++++---------- 4 files changed, 86 insertions(+), 38 deletions(-) create mode 100644 changelog/ttsao-v1.6.0-beta.2.md diff --git a/WORKSPACE b/WORKSPACE index 39d0904098..651d8177c3 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -253,7 +253,7 @@ filegroup( url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz", ) -consensus_spec_version = "v1.6.0-beta.1" +consensus_spec_version = "v1.6.0-beta.2" load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests") @@ -278,7 +278,7 @@ filegroup( visibility = ["//visibility:public"], ) """, - integrity = "sha256-yrq3tdwPS8Ri+ueeLAHssIT3ssMrX7zvHiJ8Xf9GVYs=", + integrity = "sha256-MForEP9dTe0z3ZkTHjX4H6waSkSTghf3gQHPwrSCCro=", strip_prefix = "consensus-specs-" + consensus_spec_version[1:], url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version, ) diff --git a/changelog/ttsao-v1.6.0-beta.2.md b/changelog/ttsao-v1.6.0-beta.2.md new file mode 100644 index 0000000000..94b777e0f4 --- /dev/null +++ b/changelog/ttsao-v1.6.0-beta.2.md @@ -0,0 +1,3 @@ +### Changed + +- Updated consensus spec tests to v1.6.0-beta.2 \ No newline at end of file diff --git a/specrefs/.ethspecify.yml b/specrefs/.ethspecify.yml index 5e8446447f..2fd5381136 100644 --- a/specrefs/.ethspecify.yml +++ b/specrefs/.ethspecify.yml @@ -1,4 +1,4 @@ -version: v1.6.0-beta.1 +version: v1.6.0-beta.2 style: full specrefs: diff --git a/specrefs/functions.yml b/specrefs/functions.yml index 0dc9e4799b..843c822400 100644 --- a/specrefs/functions.yml +++ b/specrefs/functions.yml @@ -1560,26 +1560,30 @@ - file: beacon-chain/core/altair/attestation.go search: func AttestationParticipationFlagIndices( spec: | - + def get_attestation_participation_flag_indices( state: BeaconState, data: AttestationData, inclusion_delay: uint64 ) -> Sequence[int]: """ Return the flag indices that are satisfied by an attestation. """ + # Matching source if data.target.epoch == get_current_epoch(state): justified_checkpoint = state.current_justified_checkpoint else: justified_checkpoint = state.previous_justified_checkpoint - - # Matching roots is_matching_source = data.source == justified_checkpoint - is_matching_target = is_matching_source and data.target.root == get_block_root( - state, data.target.epoch - ) - is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot( - state, data.slot - ) + + # Matching target + target_root = get_block_root(state, data.target.epoch) + target_root_matches = data.target.root == target_root + is_matching_target = is_matching_source and target_root_matches + + # Matching head + head_root = get_block_root_at_slot(state, data.slot) + head_root_matches = data.beacon_block_root == head_root + is_matching_head = is_matching_target and head_root_matches + assert is_matching_source participation_flag_indices = [] @@ -1598,26 +1602,30 @@ - file: beacon-chain/core/altair/attestation.go search: func AttestationParticipationFlagIndices( spec: | - + def get_attestation_participation_flag_indices( state: BeaconState, data: AttestationData, inclusion_delay: uint64 ) -> Sequence[int]: """ Return the flag indices that are satisfied by an attestation. """ + # Matching source if data.target.epoch == get_current_epoch(state): justified_checkpoint = state.current_justified_checkpoint else: justified_checkpoint = state.previous_justified_checkpoint - - # Matching roots is_matching_source = data.source == justified_checkpoint - is_matching_target = is_matching_source and data.target.root == get_block_root( - state, data.target.epoch - ) - is_matching_head = is_matching_target and data.beacon_block_root == get_block_root_at_slot( - state, data.slot - ) + + # Matching target + target_root = get_block_root(state, data.target.epoch) + target_root_matches = data.target.root == target_root + is_matching_target = is_matching_source and target_root_matches + + # Matching head + head_root = get_block_root_at_slot(state, data.slot) + head_root_matches = data.beacon_block_root == head_root + is_matching_head = is_matching_target and head_root_matches + assert is_matching_source participation_flag_indices = [] @@ -5949,7 +5957,7 @@ - file: beacon-chain/core/blocks/payload.go search: func ProcessPayload( spec: | - + def process_execution_payload( state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine ) -> None: @@ -5961,20 +5969,23 @@ assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp assert payload.timestamp == compute_time_at_slot(state, state.slot) - - # [New in Deneb:EIP4844] Verify commitments are under limit + # [New in Deneb:EIP4844] + # Verify commitments are under limit assert len(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK - # Verify the execution payload is valid - # [Modified in Deneb:EIP4844] Pass `versioned_hashes` to Execution Engine - # [Modified in Deneb:EIP4788] Pass `parent_beacon_block_root` to Execution Engine + # [New in Deneb:EIP4844] + # Compute list of versioned hashes versioned_hashes = [ kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments ] + + # Verify the execution payload is valid assert execution_engine.verify_and_notify_new_payload( NewPayloadRequest( execution_payload=payload, + # [New in Deneb:EIP4844] versioned_hashes=versioned_hashes, + # [New in Deneb:EIP4788] parent_beacon_block_root=state.latest_block_header.parent_root, ) ) @@ -6008,7 +6019,7 @@ - file: beacon-chain/core/blocks/payload.go search: func ProcessPayload( spec: | - + def process_execution_payload( state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine ) -> None: @@ -6020,12 +6031,16 @@ assert payload.prev_randao == get_randao_mix(state, get_current_epoch(state)) # Verify timestamp assert payload.timestamp == compute_time_at_slot(state, state.slot) - # [Modified in Electra:EIP7691] Verify commitments are under limit + # [Modified in Electra:EIP7691] + # Verify commitments are under limit assert len(body.blob_kzg_commitments) <= MAX_BLOBS_PER_BLOCK_ELECTRA - # Verify the execution payload is valid + + # Compute list of versioned hashes versioned_hashes = [ kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments ] + + # Verify the execution payload is valid assert execution_engine.verify_and_notify_new_payload( NewPayloadRequest( execution_payload=payload, @@ -6035,6 +6050,7 @@ execution_requests=body.execution_requests, ) ) + # Cache execution payload header state.latest_execution_payload_header = ExecutionPayloadHeader( parent_hash=payload.parent_hash, @@ -6062,7 +6078,7 @@ - file: beacon-chain/core/blocks/payload.go search: func ProcessPayload( spec: | - + def process_execution_payload( state: BeaconState, body: BeaconBlockBody, execution_engine: ExecutionEngine ) -> None: @@ -6080,10 +6096,13 @@ len(body.blob_kzg_commitments) <= get_blob_parameters(get_current_epoch(state)).max_blobs_per_block ) - # Verify the execution payload is valid + + # Compute list of versioned hashes versioned_hashes = [ kzg_commitment_to_versioned_hash(commitment) for commitment in body.blob_kzg_commitments ] + + # Verify the execution payload is valid assert execution_engine.verify_and_notify_new_payload( NewPayloadRequest( execution_payload=payload, @@ -6092,6 +6111,7 @@ execution_requests=body.execution_requests, ) ) + # Cache execution payload header state.latest_execution_payload_header = ExecutionPayloadHeader( parent_hash=payload.parent_hash, @@ -6924,16 +6944,40 @@ - file: beacon-chain/core/altair/block.go search: func ProcessSyncAggregate( spec: | - + def process_sync_aggregate(state: BeaconState, sync_aggregate: SyncAggregate) -> None: # Verify sync committee aggregate signature signing over the previous slot block root committee_pubkeys = state.current_sync_committee.pubkeys - participant_pubkeys = [ - pubkey for pubkey, bit in zip(committee_pubkeys, sync_aggregate.sync_committee_bits) if bit - ] + committee_bits = sync_aggregate.sync_committee_bits + if sum(committee_bits) == SYNC_COMMITTEE_SIZE: + # All members participated - use precomputed aggregate key + participant_pubkeys = [state.current_sync_committee.aggregate_pubkey] + elif sum(committee_bits) > SYNC_COMMITTEE_SIZE // 2: + # More than half participated - subtract non-participant keys. + # First determine nonparticipating members + non_participant_pubkeys = [ + pubkey for pubkey, bit in zip(committee_pubkeys, committee_bits) if not bit + ] + # Compute aggregate of non-participants + non_participant_aggregate = eth_aggregate_pubkeys(non_participant_pubkeys) + # Subtract non-participants from the full aggregate + # This is equivalent to: aggregate_pubkey + (-non_participant_aggregate) + participant_pubkey = bls.add( + bls.bytes48_to_G1(state.current_sync_committee.aggregate_pubkey), + bls.neg(bls.bytes48_to_G1(non_participant_aggregate)), + ) + participant_pubkeys = [BLSPubkey(bls.G1_to_bytes48(participant_pubkey))] + else: + # Less than half participated - aggregate participant keys + participant_pubkeys = [ + pubkey + for pubkey, bit in zip(committee_pubkeys, sync_aggregate.sync_committee_bits) + if bit + ] previous_slot = max(state.slot, Slot(1)) - Slot(1) domain = get_domain(state, DOMAIN_SYNC_COMMITTEE, compute_epoch_at_slot(previous_slot)) signing_root = compute_signing_root(get_block_root_at_slot(state, previous_slot), domain) + # Note: eth_fast_aggregate_verify works with a singleton list containing an aggregated key assert eth_fast_aggregate_verify( participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature ) @@ -7196,7 +7240,7 @@ - file: beacon-chain/core/blocks/withdrawals.go search: func ProcessWithdrawals( spec: | - + def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None: # [Modified in Electra:EIP7251] expected_withdrawals, processed_partial_withdrawals_count = get_expected_withdrawals(state) @@ -7206,7 +7250,8 @@ for withdrawal in expected_withdrawals: decrease_balance(state, withdrawal.validator_index, withdrawal.amount) - # [New in Electra:EIP7251] Update pending partial withdrawals + # [New in Electra:EIP7251] + # Update pending partial withdrawals state.pending_partial_withdrawals = state.pending_partial_withdrawals[ processed_partial_withdrawals_count: ]