mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 20:57:10 +00:00
resolve merge conflicts
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
use serde::Deserialize;
|
||||
use std::marker::PhantomData;
|
||||
use types::data_column_custody_group::{CustodyIndex, compute_columns_for_custody_group};
|
||||
use types::data::{CustodyIndex, compute_columns_for_custody_group};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(bound = "E: EthSpec", deny_unknown_fields)]
|
||||
|
||||
@@ -12,7 +12,7 @@ use state_processing::per_epoch_processing::effective_balance_updates::{
|
||||
process_effective_balance_updates, process_effective_balance_updates_slow,
|
||||
};
|
||||
use state_processing::per_epoch_processing::single_pass::{
|
||||
SinglePassConfig, process_epoch_single_pass, process_proposer_lookahead,
|
||||
SinglePassConfig, process_epoch_single_pass, process_proposer_lookahead, process_ptc_window,
|
||||
};
|
||||
use state_processing::per_epoch_processing::{
|
||||
altair, base,
|
||||
@@ -58,6 +58,8 @@ pub struct Eth1DataReset;
|
||||
#[derive(Debug)]
|
||||
pub struct PendingBalanceDeposits;
|
||||
#[derive(Debug)]
|
||||
pub struct PendingDepositsChurn;
|
||||
#[derive(Debug)]
|
||||
pub struct PendingConsolidations;
|
||||
#[derive(Debug)]
|
||||
pub struct EffectiveBalanceUpdates;
|
||||
@@ -79,6 +81,10 @@ pub struct InactivityUpdates;
|
||||
pub struct ParticipationFlagUpdates;
|
||||
#[derive(Debug)]
|
||||
pub struct ProposerLookahead;
|
||||
#[derive(Debug)]
|
||||
pub struct PtcWindow;
|
||||
#[derive(Debug)]
|
||||
pub struct BuilderPendingPayments;
|
||||
|
||||
type_name!(
|
||||
JustificationAndFinalization,
|
||||
@@ -89,6 +95,7 @@ type_name!(RegistryUpdates, "registry_updates");
|
||||
type_name!(Slashings, "slashings");
|
||||
type_name!(Eth1DataReset, "eth1_data_reset");
|
||||
type_name!(PendingBalanceDeposits, "pending_deposits");
|
||||
type_name!(PendingDepositsChurn, "pending_deposits_churn");
|
||||
type_name!(PendingConsolidations, "pending_consolidations");
|
||||
type_name!(EffectiveBalanceUpdates, "effective_balance_updates");
|
||||
type_name!(SlashingsReset, "slashings_reset");
|
||||
@@ -100,6 +107,8 @@ type_name!(SyncCommitteeUpdates, "sync_committee_updates");
|
||||
type_name!(InactivityUpdates, "inactivity_updates");
|
||||
type_name!(ParticipationFlagUpdates, "participation_flag_updates");
|
||||
type_name!(ProposerLookahead, "proposer_lookahead");
|
||||
type_name!(PtcWindow, "ptc_window");
|
||||
type_name!(BuilderPendingPayments, "builder_pending_payments");
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for JustificationAndFinalization {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
@@ -185,6 +194,20 @@ impl<E: EthSpec> EpochTransition<E> for PendingBalanceDeposits {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for PendingDepositsChurn {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
process_epoch_single_pass(
|
||||
state,
|
||||
spec,
|
||||
SinglePassConfig {
|
||||
pending_deposits: true,
|
||||
..SinglePassConfig::disable_all()
|
||||
},
|
||||
)
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for PendingConsolidations {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
initialize_epoch_cache(state, spec)?;
|
||||
@@ -293,6 +316,30 @@ impl<E: EthSpec> EpochTransition<E> for ProposerLookahead {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for PtcWindow {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
process_ptc_window(state, spec).map(|_| ())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> EpochTransition<E> for BuilderPendingPayments {
|
||||
fn run(state: &mut BeaconState<E>, spec: &ChainSpec) -> Result<(), EpochProcessingError> {
|
||||
process_epoch_single_pass(
|
||||
state,
|
||||
spec,
|
||||
SinglePassConfig {
|
||||
builder_pending_payments: true,
|
||||
..SinglePassConfig::disable_all()
|
||||
},
|
||||
)
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, T: EpochTransition<E>> LoadCase for EpochProcessing<E, T> {
|
||||
fn load_from_dir(path: &Path, fork_name: ForkName) -> Result<Self, Error> {
|
||||
let spec = &testing_spec::<E>(fork_name);
|
||||
@@ -356,6 +403,14 @@ impl<E: EthSpec, T: EpochTransition<E>> Case for EpochProcessing<E, T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !fork_name.gloas_enabled()
|
||||
&& (T::name() == "builder_pending_payments"
|
||||
|| T::name() == "ptc_window"
|
||||
|| T::name() == "pending_deposits_churn")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yam
|
||||
use ::fork_choice::{PayloadVerificationStatus, ProposerHeadError};
|
||||
use beacon_chain::beacon_proposer_cache::compute_proposer_duties_from_head;
|
||||
use beacon_chain::blob_verification::GossipBlobError;
|
||||
use beacon_chain::block_verification_types::RpcBlock;
|
||||
use beacon_chain::block_verification_types::LookupBlock;
|
||||
use beacon_chain::chain_config::{
|
||||
DEFAULT_RE_ORG_HEAD_THRESHOLD, DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
|
||||
DEFAULT_RE_ORG_PARENT_THRESHOLD, DisallowedReOrgOffsets,
|
||||
@@ -19,18 +19,23 @@ use beacon_chain::{
|
||||
custody_context::NodeCustodyType,
|
||||
test_utils::{BeaconChainHarness, EphemeralHarnessType},
|
||||
};
|
||||
use execution_layer::{PayloadStatusV1, json_structures::JsonPayloadStatusV1Status};
|
||||
use execution_layer::{
|
||||
PayloadStatusV1, PayloadStatusV1Status, json_structures::JsonPayloadStatusV1Status,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use ssz_derive::Decode;
|
||||
use state_processing::VerifySignatures;
|
||||
use state_processing::envelope_processing::verify_execution_payload_envelope;
|
||||
use state_processing::state_advance::complete_state_advance;
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use types::{
|
||||
Attestation, AttestationRef, AttesterSlashing, AttesterSlashingRef, BeaconBlock, BeaconState,
|
||||
BlobSidecar, BlobsList, BlockImportSource, Checkpoint, DataColumnSidecarList,
|
||||
DataColumnSubnetId, ExecutionBlockHash, Hash256, IndexedAttestation, KzgProof,
|
||||
ProposerPreparationData, SignedBeaconBlock, Slot, Uint256,
|
||||
BlobSidecar, BlobsList, BlockImportSource, Checkpoint, DataColumnSidecar,
|
||||
DataColumnSidecarList, DataColumnSubnetId, ExecutionBlockHash, Hash256, IndexedAttestation,
|
||||
KzgProof, ProposerPreparationData, SignedBeaconBlock, SignedExecutionPayloadEnvelope, Slot,
|
||||
Uint256,
|
||||
};
|
||||
|
||||
// When set to true, cache any states fetched from the db.
|
||||
@@ -72,6 +77,7 @@ pub struct Checks {
|
||||
proposer_boost_root: Option<Hash256>,
|
||||
get_proposer_head: Option<Hash256>,
|
||||
should_override_forkchoice_update: Option<ShouldOverrideFcu>,
|
||||
head_payload_status: Option<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
@@ -94,7 +100,15 @@ impl From<PayloadStatus> for PayloadStatusV1 {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(untagged, deny_unknown_fields)]
|
||||
pub enum Step<TBlock, TBlobs, TColumns, TAttestation, TAttesterSlashing, TPowBlock> {
|
||||
pub enum Step<
|
||||
TBlock,
|
||||
TBlobs,
|
||||
TColumns,
|
||||
TAttestation,
|
||||
TAttesterSlashing,
|
||||
TPowBlock,
|
||||
TExecutionPayload = String,
|
||||
> {
|
||||
Tick {
|
||||
tick: u64,
|
||||
},
|
||||
@@ -128,6 +142,10 @@ pub enum Step<TBlock, TBlobs, TColumns, TAttestation, TAttesterSlashing, TPowBlo
|
||||
columns: Option<TColumns>,
|
||||
valid: bool,
|
||||
},
|
||||
OnExecutionPayload {
|
||||
execution_payload: TExecutionPayload,
|
||||
valid: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
@@ -151,6 +169,7 @@ pub struct ForkChoiceTest<E: EthSpec> {
|
||||
Attestation<E>,
|
||||
AttesterSlashing<E>,
|
||||
PowBlock,
|
||||
SignedExecutionPayloadEnvelope<E>,
|
||||
>,
|
||||
>,
|
||||
}
|
||||
@@ -252,7 +271,15 @@ impl<E: EthSpec> LoadCase for ForkChoiceTest<E> {
|
||||
columns_vec
|
||||
.into_iter()
|
||||
.map(|column| {
|
||||
ssz_decode_file(&path.join(format!("{column}.ssz_snappy")))
|
||||
ssz_decode_file_with(
|
||||
&path.join(format!("{column}.ssz_snappy")),
|
||||
|bytes| {
|
||||
DataColumnSidecar::from_ssz_bytes_for_fork(
|
||||
bytes, fork_name,
|
||||
)
|
||||
.map(Arc::new)
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
})
|
||||
@@ -263,6 +290,17 @@ impl<E: EthSpec> LoadCase for ForkChoiceTest<E> {
|
||||
valid,
|
||||
})
|
||||
}
|
||||
Step::OnExecutionPayload {
|
||||
execution_payload,
|
||||
valid,
|
||||
} => {
|
||||
let envelope =
|
||||
ssz_decode_file(&path.join(format!("{execution_payload}.ssz_snappy")))?;
|
||||
Ok(Step::OnExecutionPayload {
|
||||
execution_payload: envelope,
|
||||
valid,
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
let anchor_state = ssz_decode_state(&path.join("anchor_state.ssz_snappy"), spec)?;
|
||||
@@ -342,6 +380,7 @@ impl<E: EthSpec> Case for ForkChoiceTest<E> {
|
||||
proposer_boost_root,
|
||||
get_proposer_head,
|
||||
should_override_forkchoice_update: should_override_fcu,
|
||||
head_payload_status,
|
||||
} = checks.as_ref();
|
||||
|
||||
if let Some(expected_head) = head {
|
||||
@@ -388,6 +427,10 @@ impl<E: EthSpec> Case for ForkChoiceTest<E> {
|
||||
if let Some(expected_proposer_head) = get_proposer_head {
|
||||
tester.check_expected_proposer_head(*expected_proposer_head)?;
|
||||
}
|
||||
|
||||
if let Some(expected_status) = head_payload_status {
|
||||
tester.check_head_payload_status(*expected_status)?;
|
||||
}
|
||||
}
|
||||
|
||||
Step::MaybeValidBlockAndColumns {
|
||||
@@ -397,6 +440,12 @@ impl<E: EthSpec> Case for ForkChoiceTest<E> {
|
||||
} => {
|
||||
tester.process_block_and_columns(block.clone(), columns.clone(), *valid)?;
|
||||
}
|
||||
Step::OnExecutionPayload {
|
||||
execution_payload,
|
||||
valid,
|
||||
} => {
|
||||
tester.process_execution_payload(execution_payload, *valid)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +480,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
.spec(spec.clone())
|
||||
.keypairs(vec![])
|
||||
.chain_config(ChainConfig {
|
||||
reconstruct_historic_states: true,
|
||||
archive: true,
|
||||
..ChainConfig::default()
|
||||
})
|
||||
.genesis_state_ephemeral_store(case.anchor_state.clone())
|
||||
@@ -471,7 +520,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
let since_genesis = tick
|
||||
.checked_sub(genesis_time)
|
||||
.ok_or_else(|| Error::FailedToParseTest("tick is prior to genesis".into()))?;
|
||||
let slots_since_genesis = since_genesis / self.spec.seconds_per_slot;
|
||||
let slots_since_genesis = since_genesis / self.spec.get_slot_duration().as_secs();
|
||||
Ok(self.spec.genesis_slot + slots_since_genesis)
|
||||
}
|
||||
|
||||
@@ -515,13 +564,15 @@ impl<E: EthSpec> Tester<E> {
|
||||
valid: bool,
|
||||
) -> Result<(), Error> {
|
||||
let block_root = block.canonical_root();
|
||||
|
||||
let mut data_column_success = true;
|
||||
|
||||
if let Some(columns) = columns.clone() {
|
||||
let gossip_verified_data_columns = columns
|
||||
.into_iter()
|
||||
.map(|column| {
|
||||
let subnet_id = DataColumnSubnetId::from_column_index(column.index, &self.spec);
|
||||
let subnet_id =
|
||||
DataColumnSubnetId::from_column_index(*column.index(), &self.spec);
|
||||
GossipVerifiedDataColumn::new(column.clone(), subnet_id, &self.harness.chain)
|
||||
.unwrap_or_else(|_| {
|
||||
data_column_success = false;
|
||||
@@ -544,7 +595,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
let result: Result<Result<Hash256, ()>, _> = self
|
||||
.block_on_dangerous(self.harness.chain.process_block(
|
||||
block_root,
|
||||
RpcBlock::new_without_blobs(Some(block_root), block.clone()),
|
||||
LookupBlock::new(block.clone()),
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::Lookup,
|
||||
|| Ok(()),
|
||||
@@ -565,6 +616,18 @@ impl<E: EthSpec> Tester<E> {
|
||||
self.apply_invalid_block(&block)?;
|
||||
}
|
||||
|
||||
// Per spec test runner: an on_block step implies receiving block's attestations
|
||||
// and attester slashings.
|
||||
if success {
|
||||
for attestation in block.message().body().attestations() {
|
||||
let att = attestation.clone_as_attestation();
|
||||
let _ = self.process_attestation(&att);
|
||||
}
|
||||
for attester_slashing in block.message().body().attester_slashings() {
|
||||
self.process_attester_slashing(attester_slashing);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -592,11 +655,8 @@ impl<E: EthSpec> Tester<E> {
|
||||
// Zipping will stop when any of the zipped lists runs out, which is what we want. Some
|
||||
// of the tests don't provide enough proofs/blobs, and should fail the availability
|
||||
// check.
|
||||
for (i, ((blob, kzg_proof), kzg_commitment)) in blobs
|
||||
.into_iter()
|
||||
.zip(proofs)
|
||||
.zip(commitments.into_iter())
|
||||
.enumerate()
|
||||
for (i, ((blob, kzg_proof), kzg_commitment)) in
|
||||
blobs.into_iter().zip(proofs).zip(commitments).enumerate()
|
||||
{
|
||||
let blob_sidecar = Arc::new(BlobSidecar {
|
||||
index: i as u64,
|
||||
@@ -634,7 +694,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
let result: Result<Result<Hash256, ()>, _> = self
|
||||
.block_on_dangerous(self.harness.chain.process_block(
|
||||
block_root,
|
||||
RpcBlock::new_without_blobs(Some(block_root), block.clone()),
|
||||
LookupBlock::new(block.clone()),
|
||||
NotifyExecutionLayer::Yes,
|
||||
BlockImportSource::Lookup,
|
||||
|| Ok(()),
|
||||
@@ -655,6 +715,18 @@ impl<E: EthSpec> Tester<E> {
|
||||
self.apply_invalid_block(&block)?;
|
||||
}
|
||||
|
||||
// Per spec test runner: an on_block step implies receiving block's attestations
|
||||
// and attester slashings.
|
||||
if success {
|
||||
for attestation in block.message().body().attestations() {
|
||||
let att = attestation.clone_as_attestation();
|
||||
let _ = self.process_attestation(&att);
|
||||
}
|
||||
for attester_slashing in block.message().body().attester_slashings() {
|
||||
self.process_attester_slashing(attester_slashing);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -710,6 +782,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
block_delay,
|
||||
&state,
|
||||
PayloadVerificationStatus::Irrelevant,
|
||||
block.message().proposer_index(),
|
||||
&self.harness.chain.spec,
|
||||
);
|
||||
|
||||
@@ -894,7 +967,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
) -> Result<(), Error> {
|
||||
let mut fc = self.harness.chain.canonical_head.fork_choice_write_lock();
|
||||
let slot = self.harness.chain.slot().unwrap();
|
||||
let canonical_head = fc.get_head(slot, &self.harness.spec).unwrap();
|
||||
let (canonical_head, _) = fc.get_head(slot, &self.harness.spec).unwrap();
|
||||
let proposer_head_result = fc.get_proposer_head(
|
||||
slot,
|
||||
canonical_head,
|
||||
@@ -904,7 +977,7 @@ impl<E: EthSpec> Tester<E> {
|
||||
DEFAULT_RE_ORG_MAX_EPOCHS_SINCE_FINALIZATION,
|
||||
);
|
||||
let proposer_head = match proposer_head_result {
|
||||
Ok(head) => head.parent_node.root,
|
||||
Ok(head) => head.parent_node.root(),
|
||||
Err(ProposerHeadError::DoNotReOrg(_)) => canonical_head,
|
||||
_ => panic!("Unexpected error in get proposer head"),
|
||||
};
|
||||
@@ -912,6 +985,115 @@ impl<E: EthSpec> Tester<E> {
|
||||
check_equal("proposer_head", proposer_head, expected_proposer_head)
|
||||
}
|
||||
|
||||
pub fn process_execution_payload(
|
||||
&self,
|
||||
signed_envelope: &SignedExecutionPayloadEnvelope<E>,
|
||||
valid: bool,
|
||||
) -> Result<(), Error> {
|
||||
let block_root = signed_envelope.message.beacon_block_root;
|
||||
let block_hash = signed_envelope.message.payload.block_hash;
|
||||
let store = &self.harness.chain.store;
|
||||
let spec = &self.harness.chain.spec;
|
||||
|
||||
// Simulate the EL: pre-configure the mock execution engine to return VALID
|
||||
// for envelopes the test expects to be valid. Invalid envelopes are left
|
||||
// unconfigured so the mock EE's default (SYNCING) rejects them.
|
||||
let el = self.harness.mock_execution_layer.as_ref().unwrap();
|
||||
if valid {
|
||||
el.server.set_new_payload_status(
|
||||
block_hash,
|
||||
PayloadStatusV1 {
|
||||
status: JsonPayloadStatusV1Status::Valid.into(),
|
||||
latest_valid_hash: Some(block_hash),
|
||||
validation_error: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Attempt to verify the envelope against the block's post-state.
|
||||
let verification_result = (|| {
|
||||
let block = store
|
||||
.get_blinded_block(&block_root)
|
||||
.map_err(|e| Error::InternalError(format!("Failed to load block: {e:?}")))?
|
||||
.ok_or_else(|| {
|
||||
Error::InternalError(format!("Block not found for root {block_root:?}"))
|
||||
})?;
|
||||
let block_state_root = block.state_root();
|
||||
|
||||
let state = store
|
||||
.get_hot_state(&block_state_root, CACHE_STATE_IN_TESTS)
|
||||
.map_err(|e| Error::InternalError(format!("Failed to load state: {e:?}")))?
|
||||
.ok_or_else(|| {
|
||||
Error::InternalError(format!("State not found for root {block_state_root:?}"))
|
||||
})?;
|
||||
|
||||
verify_execution_payload_envelope(
|
||||
&state,
|
||||
signed_envelope,
|
||||
VerifySignatures::True,
|
||||
block_state_root,
|
||||
spec,
|
||||
)
|
||||
.map_err(|e| {
|
||||
Error::InternalError(format!("Failed to process execution payload: {e:?}"))
|
||||
})?;
|
||||
|
||||
// Check the mock EE's response for this block hash (simulates newPayload).
|
||||
let ee_valid = el
|
||||
.server
|
||||
.ctx
|
||||
.get_new_payload_status(&block_hash)
|
||||
.and_then(|r| r.ok())
|
||||
.is_some_and(|s| s.status == PayloadStatusV1Status::Valid);
|
||||
if !ee_valid {
|
||||
return Err(Error::InternalError(format!(
|
||||
"Mock EE rejected payload with block hash {block_hash:?}",
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})();
|
||||
|
||||
if valid {
|
||||
verification_result?;
|
||||
|
||||
// Store the envelope so that child blocks can load the parent's payload.
|
||||
store
|
||||
.put_payload_envelope(&block_root, signed_envelope)
|
||||
.map_err(|e| {
|
||||
Error::InternalError(format!(
|
||||
"Failed to store payload envelope for {block_root:?}: {e:?}",
|
||||
))
|
||||
})?;
|
||||
|
||||
self.harness
|
||||
.chain
|
||||
.canonical_head
|
||||
.fork_choice_write_lock()
|
||||
.on_valid_payload_envelope_received(block_root)
|
||||
.map_err(|e| {
|
||||
Error::InternalError(format!(
|
||||
"on_execution_payload for block root {} failed: {:?}",
|
||||
block_root, e
|
||||
))
|
||||
})?;
|
||||
} else if verification_result.is_ok() {
|
||||
return Err(Error::DidntFail(format!(
|
||||
"on_execution_payload envelope for block root {} should have failed",
|
||||
block_root
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn check_head_payload_status(&self, expected_status: u8) -> Result<(), Error> {
|
||||
let head = self.find_head()?;
|
||||
// PayloadStatus repr: Empty=0, Full=1, Pending=2 (matches spec constants).
|
||||
let actual = head.head_payload_status() as u8;
|
||||
check_equal("head_payload_status", actual, expected_status)
|
||||
}
|
||||
|
||||
pub fn check_should_override_fcu(
|
||||
&self,
|
||||
expected_should_override_fcu: ShouldOverrideFcu,
|
||||
|
||||
@@ -2,7 +2,7 @@ use super::*;
|
||||
use alloy_primitives::U256;
|
||||
use serde::Deserialize;
|
||||
use std::marker::PhantomData;
|
||||
use types::data_column_custody_group::get_custody_groups;
|
||||
use types::data::get_custody_groups;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(bound = "E: EthSpec", deny_unknown_fields)]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use crate::case_result::compare_result;
|
||||
use kzg::{Bytes48, Error as KzgError};
|
||||
use kzg::Error as KzgError;
|
||||
use serde::Deserialize;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -47,8 +47,8 @@ impl<E: EthSpec> Case for KZGVerifyCellKZGProofBatch<E> {
|
||||
|
||||
let result =
|
||||
parse_input(&self.input).and_then(|(cells, proofs, cell_indices, commitments)| {
|
||||
let proofs: Vec<Bytes48> = proofs.iter().map(|&proof| proof.into()).collect();
|
||||
let commitments: Vec<Bytes48> = commitments.iter().map(|&c| c.into()).collect();
|
||||
let proofs = proofs.iter().map(|&proof| proof.0).collect::<Vec<_>>();
|
||||
let commitments = commitments.iter().map(|&c| c.0).collect::<Vec<_>>();
|
||||
let cells = cells.iter().map(|c| c.as_ref()).collect::<Vec<_>>();
|
||||
let kzg = get_kzg();
|
||||
match kzg.verify_cell_proof_batch(&cells, &proofs, cell_indices, &commitments) {
|
||||
|
||||
@@ -7,7 +7,7 @@ use typenum::Unsigned;
|
||||
use types::{
|
||||
BeaconBlockBody, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyEip7805,
|
||||
BeaconBlockBodyElectra, BeaconBlockBodyFulu, BeaconBlockBodyGloas, BeaconState, FullPayload,
|
||||
light_client_update,
|
||||
light_client,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
@@ -98,16 +98,16 @@ impl<E: EthSpec> Case for BeaconStateMerkleProofValidity<E> {
|
||||
state.update_tree_hash_cache().unwrap();
|
||||
|
||||
let proof = match self.merkle_proof.leaf_index {
|
||||
light_client_update::CURRENT_SYNC_COMMITTEE_INDEX_ELECTRA
|
||||
| light_client_update::CURRENT_SYNC_COMMITTEE_INDEX => {
|
||||
light_client::consts::CURRENT_SYNC_COMMITTEE_INDEX_ELECTRA
|
||||
| light_client::consts::CURRENT_SYNC_COMMITTEE_INDEX => {
|
||||
state.compute_current_sync_committee_proof()
|
||||
}
|
||||
light_client_update::NEXT_SYNC_COMMITTEE_INDEX_ELECTRA
|
||||
| light_client_update::NEXT_SYNC_COMMITTEE_INDEX => {
|
||||
light_client::consts::NEXT_SYNC_COMMITTEE_INDEX_ELECTRA
|
||||
| light_client::consts::NEXT_SYNC_COMMITTEE_INDEX => {
|
||||
state.compute_next_sync_committee_proof()
|
||||
}
|
||||
light_client_update::FINALIZED_ROOT_INDEX_ELECTRA
|
||||
| light_client_update::FINALIZED_ROOT_INDEX => state.compute_finalized_root_proof(),
|
||||
light_client::consts::FINALIZED_ROOT_INDEX_ELECTRA
|
||||
| light_client::consts::FINALIZED_ROOT_INDEX => state.compute_finalized_root_proof(),
|
||||
_ => {
|
||||
return Err(Error::FailedToParseTest(
|
||||
"Could not retrieve merkle proof, invalid index".to_string(),
|
||||
|
||||
@@ -5,21 +5,25 @@ use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yam
|
||||
use serde::Deserialize;
|
||||
use ssz::Decode;
|
||||
use state_processing::common::update_progressive_balances_cache::initialize_progressive_balances_cache;
|
||||
use state_processing::envelope_processing::verify_execution_payload_envelope;
|
||||
use state_processing::epoch_cache::initialize_epoch_cache;
|
||||
use state_processing::per_block_processing::process_operations::{
|
||||
process_consolidation_requests, process_deposit_requests, process_withdrawal_requests,
|
||||
process_consolidation_requests, process_deposit_requests_post_gloas,
|
||||
process_deposit_requests_pre_gloas, process_withdrawal_requests,
|
||||
};
|
||||
use state_processing::{
|
||||
ConsensusContext,
|
||||
envelope_processing::EnvelopeProcessingError,
|
||||
per_block_processing::{
|
||||
VerifyBlockRoot, VerifySignatures,
|
||||
errors::BlockProcessingError,
|
||||
process_block_header, process_execution_payload,
|
||||
process_block_header, process_execution_payload, process_execution_payload_bid,
|
||||
process_operations::{
|
||||
altair_deneb, base, process_attester_slashings, process_bls_to_execution_changes,
|
||||
process_deposits, process_exits, process_proposer_slashings,
|
||||
altair_deneb, base, gloas, process_attester_slashings,
|
||||
process_bls_to_execution_changes, process_deposits, process_exits,
|
||||
process_payload_attestation, process_proposer_slashings,
|
||||
},
|
||||
process_sync_aggregate, process_withdrawals,
|
||||
process_parent_execution_payload, process_sync_aggregate, withdrawals,
|
||||
},
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
@@ -27,8 +31,9 @@ use types::{
|
||||
Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix,
|
||||
BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyFulu,
|
||||
BeaconState, BlindedPayload, ConsolidationRequest, Deposit, DepositRequest, ExecutionPayload,
|
||||
ForkVersionDecode, FullPayload, ProposerSlashing, SignedBlsToExecutionChange,
|
||||
SignedVoluntaryExit, SyncAggregate, WithdrawalRequest,
|
||||
ForkVersionDecode, FullPayload, PayloadAttestation, ProposerSlashing,
|
||||
SignedBlsToExecutionChange, SignedExecutionPayloadEnvelope, SignedVoluntaryExit, SyncAggregate,
|
||||
WithdrawalRequest,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
@@ -45,7 +50,28 @@ struct ExecutionMetadata {
|
||||
/// Newtype for testing withdrawals.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct WithdrawalsPayload<E: EthSpec> {
|
||||
payload: FullPayload<E>,
|
||||
payload: Option<ExecutionPayload<E>>,
|
||||
}
|
||||
|
||||
/// Newtype for testing voluntary exit churn (Gloas+).
|
||||
///
|
||||
/// The test case applies the same `process_voluntary_exit` operation as the regular
|
||||
/// `voluntary_exit` test, but under the `voluntary_exit_churn` handler directory.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VoluntaryExitChurn {
|
||||
exit: SignedVoluntaryExit,
|
||||
}
|
||||
|
||||
/// Newtype for testing execution payload bids.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct ExecutionPayloadBidBlock<E: EthSpec> {
|
||||
block: BeaconBlock<E>,
|
||||
}
|
||||
|
||||
/// Newtype for testing parent execution payload processing.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct ParentExecutionPayloadBlock<E: EthSpec> {
|
||||
block: BeaconBlock<E>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -58,6 +84,8 @@ pub struct Operations<E: EthSpec, O: Operation<E>> {
|
||||
}
|
||||
|
||||
pub trait Operation<E: EthSpec>: Debug + Sync + Sized {
|
||||
type Error: Debug;
|
||||
|
||||
fn handler_name() -> String;
|
||||
|
||||
fn filename() -> String {
|
||||
@@ -75,10 +103,12 @@ pub trait Operation<E: EthSpec>: Debug + Sync + Sized {
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
_: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError>;
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for Attestation<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"attestation".into()
|
||||
}
|
||||
@@ -98,9 +128,18 @@ impl<E: EthSpec> Operation<E> for Attestation<E> {
|
||||
_: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
initialize_epoch_cache(state, spec)?;
|
||||
initialize_progressive_balances_cache(state, spec)?;
|
||||
let mut ctxt = ConsensusContext::new(state.slot());
|
||||
if state.fork_name_unchecked().altair_enabled() {
|
||||
initialize_progressive_balances_cache(state, spec)?;
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
gloas::process_attestation(
|
||||
state,
|
||||
self.to_ref(),
|
||||
0,
|
||||
&mut ctxt,
|
||||
VerifySignatures::True,
|
||||
spec,
|
||||
)
|
||||
} else if state.fork_name_unchecked().altair_enabled() {
|
||||
altair_deneb::process_attestation(
|
||||
state,
|
||||
self.to_ref(),
|
||||
@@ -122,6 +161,8 @@ impl<E: EthSpec> Operation<E> for Attestation<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for AttesterSlashing<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"attester_slashing".into()
|
||||
}
|
||||
@@ -153,6 +194,8 @@ impl<E: EthSpec> Operation<E> for AttesterSlashing<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for Deposit {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"deposit".into()
|
||||
}
|
||||
@@ -177,6 +220,8 @@ impl<E: EthSpec> Operation<E> for Deposit {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for ProposerSlashing {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"proposer_slashing".into()
|
||||
}
|
||||
@@ -204,6 +249,8 @@ impl<E: EthSpec> Operation<E> for ProposerSlashing {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for SignedVoluntaryExit {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"voluntary_exit".into()
|
||||
}
|
||||
@@ -227,7 +274,43 @@ impl<E: EthSpec> Operation<E> for SignedVoluntaryExit {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for VoluntaryExitChurn {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"voluntary_exit_churn".into()
|
||||
}
|
||||
|
||||
fn filename() -> String {
|
||||
"voluntary_exit.ssz_snappy".into()
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
fork_name.gloas_enabled()
|
||||
}
|
||||
|
||||
fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
|
||||
ssz_decode_file(path).map(|exit| VoluntaryExitChurn { exit })
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
&self,
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
_: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
process_exits(
|
||||
state,
|
||||
std::slice::from_ref(&self.exit),
|
||||
VerifySignatures::True,
|
||||
spec,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for BeaconBlock<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"block_header".into()
|
||||
}
|
||||
@@ -259,6 +342,8 @@ impl<E: EthSpec> Operation<E> for BeaconBlock<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for SyncAggregate<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"sync_aggregate".into()
|
||||
}
|
||||
@@ -287,6 +372,8 @@ impl<E: EthSpec> Operation<E> for SyncAggregate<E> {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, FullPayload<E>> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"execution_payload".into()
|
||||
}
|
||||
@@ -296,7 +383,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, FullPayload<E>> {
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
fork_name.bellatrix_enabled()
|
||||
fork_name.bellatrix_enabled() && !fork_name.gloas_enabled()
|
||||
}
|
||||
|
||||
fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
|
||||
@@ -307,8 +394,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, FullPayload<E>> {
|
||||
ForkName::Deneb => BeaconBlockBody::Deneb(<_>::from_ssz_bytes(bytes)?),
|
||||
ForkName::Electra => BeaconBlockBody::Electra(<_>::from_ssz_bytes(bytes)?),
|
||||
ForkName::Fulu => BeaconBlockBody::Fulu(<_>::from_ssz_bytes(bytes)?),
|
||||
// TODO(EIP-7732): See if we need to handle Gloas here
|
||||
_ => panic!(),
|
||||
_ => panic!("Not supported after Gloas"),
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -330,7 +416,10 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, FullPayload<E>> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, BlindedPayload<E>> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"execution_payload".into()
|
||||
}
|
||||
@@ -340,7 +429,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, BlindedPayload<E>> {
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
fork_name.bellatrix_enabled()
|
||||
fork_name.bellatrix_enabled() && !fork_name.gloas_enabled()
|
||||
}
|
||||
|
||||
fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
|
||||
@@ -367,8 +456,7 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, BlindedPayload<E>> {
|
||||
let inner = <BeaconBlockBodyFulu<E, FullPayload<E>>>::from_ssz_bytes(bytes)?;
|
||||
BeaconBlockBody::Fulu(inner.clone_as_blinded())
|
||||
}
|
||||
// TODO(EIP-7732): See if we need to handle Gloas here
|
||||
_ => panic!(),
|
||||
_ => panic!("Not supported after Gloas"),
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -391,7 +479,116 @@ impl<E: EthSpec> Operation<E> for BeaconBlockBody<E, BlindedPayload<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for SignedExecutionPayloadEnvelope<E> {
|
||||
type Error = EnvelopeProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"execution_payload".into()
|
||||
}
|
||||
|
||||
fn filename() -> String {
|
||||
"signed_envelope.ssz_snappy".into()
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(_fork_name: ForkName) -> bool {
|
||||
// TODO(gloas): re-enable this test when enabled upstream
|
||||
// fork_name.gloas_enabled()
|
||||
false
|
||||
}
|
||||
|
||||
fn decode(path: &Path, _: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
|
||||
ssz_decode_file(path)
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
&self,
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
extra: &Operations<E, Self>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let valid = extra
|
||||
.execution_metadata
|
||||
.as_ref()
|
||||
.is_some_and(|e| e.execution_valid);
|
||||
if valid {
|
||||
let block_state_root = state.update_tree_hash_cache()?;
|
||||
verify_execution_payload_envelope(
|
||||
state,
|
||||
self,
|
||||
VerifySignatures::True,
|
||||
block_state_root,
|
||||
spec,
|
||||
)
|
||||
} else {
|
||||
Err(EnvelopeProcessingError::ExecutionInvalid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for ExecutionPayloadBidBlock<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"execution_payload_bid".into()
|
||||
}
|
||||
|
||||
fn filename() -> String {
|
||||
"block.ssz_snappy".into()
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
fork_name.gloas_enabled()
|
||||
}
|
||||
|
||||
fn decode(path: &Path, _fork_name: ForkName, spec: &ChainSpec) -> Result<Self, Error> {
|
||||
ssz_decode_file_with(path, |bytes| BeaconBlock::from_ssz_bytes(bytes, spec))
|
||||
.map(|block| ExecutionPayloadBidBlock { block })
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
&self,
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
_: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
process_execution_payload_bid(state, self.block.to_ref(), VerifySignatures::True, spec)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for ParentExecutionPayloadBlock<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"parent_execution_payload".into()
|
||||
}
|
||||
|
||||
fn filename() -> String {
|
||||
"block.ssz_snappy".into()
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
fork_name.gloas_enabled()
|
||||
}
|
||||
|
||||
fn decode(path: &Path, _fork_name: ForkName, spec: &ChainSpec) -> Result<Self, Error> {
|
||||
ssz_decode_file_with(path, |bytes| BeaconBlock::from_ssz_bytes(bytes, spec))
|
||||
.map(|block| ParentExecutionPayloadBlock { block })
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
&self,
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
_: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
process_parent_execution_payload(state, self.block.to_ref(), spec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for WithdrawalsPayload<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"withdrawals".into()
|
||||
}
|
||||
@@ -405,12 +602,17 @@ impl<E: EthSpec> Operation<E> for WithdrawalsPayload<E> {
|
||||
}
|
||||
|
||||
fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
|
||||
ssz_decode_file_with(path, |bytes| {
|
||||
ExecutionPayload::from_ssz_bytes_by_fork(bytes, fork_name)
|
||||
})
|
||||
.map(|payload| WithdrawalsPayload {
|
||||
payload: payload.into(),
|
||||
})
|
||||
if fork_name.gloas_enabled() {
|
||||
// No payload present or required for Gloas tests.
|
||||
Ok(WithdrawalsPayload { payload: None })
|
||||
} else {
|
||||
ssz_decode_file_with(path, |bytes| {
|
||||
ExecutionPayload::from_ssz_bytes_by_fork(bytes, fork_name)
|
||||
})
|
||||
.map(|payload| WithdrawalsPayload {
|
||||
payload: Some(payload),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
@@ -419,12 +621,22 @@ impl<E: EthSpec> Operation<E> for WithdrawalsPayload<E> {
|
||||
spec: &ChainSpec,
|
||||
_: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
// TODO(EIP-7732): implement separate gloas and non-gloas variants of process_withdrawals
|
||||
process_withdrawals::<_, FullPayload<_>>(state, self.payload.to_ref(), spec)
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
withdrawals::gloas::process_withdrawals(state, spec)
|
||||
} else {
|
||||
let full_payload = FullPayload::from(self.payload.clone().unwrap());
|
||||
withdrawals::capella_electra::process_withdrawals::<_, FullPayload<_>>(
|
||||
state,
|
||||
full_payload.to_ref(),
|
||||
spec,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for SignedBlsToExecutionChange {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"bls_to_execution_change".into()
|
||||
}
|
||||
@@ -457,6 +669,8 @@ impl<E: EthSpec> Operation<E> for SignedBlsToExecutionChange {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for WithdrawalRequest {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"withdrawal_request".into()
|
||||
}
|
||||
@@ -481,6 +695,8 @@ impl<E: EthSpec> Operation<E> for WithdrawalRequest {
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for DepositRequest {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"deposit_request".into()
|
||||
}
|
||||
@@ -499,11 +715,17 @@ impl<E: EthSpec> Operation<E> for DepositRequest {
|
||||
spec: &ChainSpec,
|
||||
_extra: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
process_deposit_requests(state, std::slice::from_ref(self), spec)
|
||||
if state.fork_name_unchecked().gloas_enabled() {
|
||||
process_deposit_requests_post_gloas(state, std::slice::from_ref(self), spec)
|
||||
} else {
|
||||
process_deposit_requests_pre_gloas(state, std::slice::from_ref(self), spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for ConsolidationRequest {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"consolidation_request".into()
|
||||
}
|
||||
@@ -527,6 +749,32 @@ impl<E: EthSpec> Operation<E> for ConsolidationRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> Operation<E> for PayloadAttestation<E> {
|
||||
type Error = BlockProcessingError;
|
||||
|
||||
fn handler_name() -> String {
|
||||
"payload_attestation".into()
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
|
||||
fork_name.gloas_enabled()
|
||||
}
|
||||
|
||||
fn decode(path: &Path, _fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
|
||||
ssz_decode_file(path)
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
&self,
|
||||
state: &mut BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
_extra: &Operations<E, Self>,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
let mut ctxt = ConsensusContext::new(state.slot());
|
||||
process_payload_attestation(state, self, 0, VerifySignatures::True, &mut ctxt, spec)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec, O: Operation<E>> LoadCase for Operations<E, O> {
|
||||
fn load_from_dir(path: &Path, fork_name: ForkName) -> Result<Self, Error> {
|
||||
let spec = &testing_spec::<E>(fork_name);
|
||||
@@ -549,8 +797,9 @@ impl<E: EthSpec, O: Operation<E>> LoadCase for Operations<E, O> {
|
||||
|
||||
// Check BLS setting here before SSZ deserialization, as most types require signatures
|
||||
// to be valid.
|
||||
let operation_path = path.join(O::filename());
|
||||
let (operation, bls_error) = if metadata.bls_setting.unwrap_or_default().check().is_ok() {
|
||||
match O::decode(&path.join(O::filename()), fork_name, spec) {
|
||||
match O::decode(&operation_path, fork_name, spec) {
|
||||
Ok(op) => (Some(op), None),
|
||||
Err(Error::InvalidBLSInput(error)) => (None, Some(error)),
|
||||
Err(e) => return Err(e),
|
||||
|
||||
@@ -33,14 +33,14 @@ pub fn log_file_access<P: AsRef<Path>>(file_accessed: P) {
|
||||
}
|
||||
|
||||
pub fn yaml_decode<T: serde::de::DeserializeOwned>(string: &str) -> Result<T, Error> {
|
||||
serde_yaml::from_str(string).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
|
||||
yaml_serde::from_str(string).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
|
||||
}
|
||||
|
||||
pub fn context_yaml_decode<'de, T, C>(string: &'de str, context: C) -> Result<T, Error>
|
||||
where
|
||||
T: ContextDeserialize<'de, C>,
|
||||
{
|
||||
let deserializer = serde_yaml::Deserializer::from_str(string);
|
||||
let deserializer = yaml_serde::Deserializer::from_str(string);
|
||||
T::context_deserialize(deserializer, context)
|
||||
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub trait Handler {
|
||||
// Add forks here to exclude them from EF spec testing. Helpful for adding future or
|
||||
// unspecified forks.
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
vec![ForkName::Gloas]
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||
@@ -305,6 +305,10 @@ impl<T, E> SszStaticHandler<T, E> {
|
||||
Self::for_forks(vec![ForkName::Fulu])
|
||||
}
|
||||
|
||||
pub fn gloas_only() -> Self {
|
||||
Self::for_forks(vec![ForkName::Gloas])
|
||||
}
|
||||
|
||||
pub fn altair_and_later() -> Self {
|
||||
Self::for_forks(ForkName::list_all()[1..].to_vec())
|
||||
}
|
||||
@@ -329,9 +333,17 @@ impl<T, E> SszStaticHandler<T, E> {
|
||||
Self::for_forks(ForkName::list_all()[6..].to_vec())
|
||||
}
|
||||
|
||||
pub fn gloas_and_later() -> Self {
|
||||
Self::for_forks(ForkName::list_all()[7..].to_vec())
|
||||
}
|
||||
|
||||
pub fn pre_electra() -> Self {
|
||||
Self::for_forks(ForkName::list_all()[0..5].to_vec())
|
||||
}
|
||||
|
||||
pub fn pre_capella() -> Self {
|
||||
Self::for_forks(ForkName::list_all()[0..3].to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler for SSZ types that implement `CachedTreeHash`.
|
||||
@@ -579,6 +591,15 @@ impl<E: EthSpec + TypeName> Handler for RewardsHandler<E> {
|
||||
fn handler_name(&self) -> String {
|
||||
self.handler_name.to_string()
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||
if self.handler_name == "inactivity_scores" {
|
||||
// These tests were added in v1.7.0-alpha.2 and are available for Altair and later.
|
||||
fork_name.altair_enabled()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -687,15 +708,31 @@ impl<E: EthSpec + TypeName> Handler for ForkChoiceHandler<E> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No FCU override tests prior to bellatrix.
|
||||
// No FCU override tests prior to bellatrix, and removed in Gloas.
|
||||
if self.handler_name == "should_override_forkchoice_update"
|
||||
&& !fork_name.bellatrix_enabled()
|
||||
&& (!fork_name.bellatrix_enabled() || fork_name.gloas_enabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Deposit tests exist only after Electra.
|
||||
if self.handler_name == "deposit_with_reorg" && !fork_name.electra_enabled() {
|
||||
// Deposit tests exist only for Electra and Fulu (not Gloas).
|
||||
if self.handler_name == "deposit_with_reorg"
|
||||
&& (!fork_name.electra_enabled() || fork_name.gloas_enabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Proposer head tests removed in Gloas.
|
||||
if self.handler_name == "get_proposer_head" && fork_name.gloas_enabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// on_execution_payload_envelope and get_parent_payload_status tests exist only for
|
||||
// Gloas and later.
|
||||
if (self.handler_name == "on_execution_payload_envelope"
|
||||
|| self.handler_name == "get_parent_payload_status")
|
||||
&& !fork_name.gloas_enabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -703,6 +740,10 @@ impl<E: EthSpec + TypeName> Handler for ForkChoiceHandler<E> {
|
||||
// run them with fake crypto.
|
||||
cfg!(not(feature = "fake_crypto"))
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -732,6 +773,11 @@ impl<E: EthSpec + TypeName> Handler for OptimisticSyncHandler<E> {
|
||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||
fork_name.bellatrix_enabled() && cfg!(not(feature = "fake_crypto"))
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas optimistic sync tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -952,6 +998,11 @@ impl<E: EthSpec> Handler for KZGComputeCellsHandler<E> {
|
||||
fn handler_name(&self) -> String {
|
||||
"compute_cells".into()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas KZG tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -972,6 +1023,11 @@ impl<E: EthSpec> Handler for KZGComputeCellsAndKZGProofHandler<E> {
|
||||
fn handler_name(&self) -> String {
|
||||
"compute_cells_and_kzg_proofs".into()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas KZG tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -992,6 +1048,11 @@ impl<E: EthSpec> Handler for KZGVerifyCellKZGProofBatchHandler<E> {
|
||||
fn handler_name(&self) -> String {
|
||||
"verify_cell_kzg_proof_batch".into()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas KZG tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -1012,6 +1073,11 @@ impl<E: EthSpec> Handler for KZGRecoverCellsAndKZGProofHandler<E> {
|
||||
fn handler_name(&self) -> String {
|
||||
"recover_cells_and_kzg_proofs".into()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas KZG tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -1036,6 +1102,11 @@ impl<E: EthSpec + TypeName> Handler for KzgInclusionMerkleProofValidityHandler<E
|
||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||
fork_name.deneb_enabled()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas KZG merkle proof tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -1060,6 +1131,11 @@ impl<E: EthSpec + TypeName> Handler for MerkleProofValidityHandler<E> {
|
||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||
fork_name.altair_enabled()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas light client tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
@@ -1085,6 +1161,11 @@ impl<E: EthSpec + TypeName> Handler for LightClientUpdateHandler<E> {
|
||||
// Enabled in Altair
|
||||
fork_name.altair_enabled()
|
||||
}
|
||||
|
||||
fn disabled_forks(&self) -> Vec<ForkName> {
|
||||
// TODO(gloas): remove once we have Gloas light client tests
|
||||
vec![ForkName::Gloas]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Educe)]
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
pub use case_result::CaseResult;
|
||||
pub use cases::WithdrawalsPayload;
|
||||
pub use cases::{
|
||||
Case, EffectiveBalanceUpdates, Eth1DataReset, FeatureName, HistoricalRootsUpdate,
|
||||
HistoricalSummariesUpdate, InactivityUpdates, JustificationAndFinalization,
|
||||
ParticipationFlagUpdates, ParticipationRecordUpdates, PendingBalanceDeposits,
|
||||
PendingConsolidations, ProposerLookahead, RandaoMixesReset, RegistryUpdates,
|
||||
RewardsAndPenalties, Slashings, SlashingsReset, SyncCommitteeUpdates,
|
||||
BuilderPendingPayments, Case, EffectiveBalanceUpdates, Eth1DataReset, ExecutionPayloadBidBlock,
|
||||
FeatureName, HistoricalRootsUpdate, HistoricalSummariesUpdate, InactivityUpdates,
|
||||
JustificationAndFinalization, ParentExecutionPayloadBlock, ParticipationFlagUpdates,
|
||||
ParticipationRecordUpdates, PendingBalanceDeposits, PendingConsolidations,
|
||||
PendingDepositsChurn, ProposerLookahead, PtcWindow, RandaoMixesReset, RegistryUpdates,
|
||||
RewardsAndPenalties, Slashings, SlashingsReset, SyncCommitteeUpdates, VoluntaryExitChurn,
|
||||
WithdrawalsPayload,
|
||||
};
|
||||
pub use decode::log_file_access;
|
||||
pub use error::Error;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Mapping from types to canonical string identifiers used in testing.
|
||||
use types::historical_summary::HistoricalSummary;
|
||||
use types::state::HistoricalSummary;
|
||||
use types::*;
|
||||
|
||||
pub trait TypeName {
|
||||
@@ -55,12 +55,15 @@ type_name_generic!(BeaconBlockBodyCapella, "BeaconBlockBody");
|
||||
type_name_generic!(BeaconBlockBodyDeneb, "BeaconBlockBody");
|
||||
type_name_generic!(BeaconBlockBodyElectra, "BeaconBlockBody");
|
||||
type_name_generic!(BeaconBlockBodyFulu, "BeaconBlockBody");
|
||||
type_name_generic!(BeaconBlockBodyGloas, "BeaconBlockBody");
|
||||
type_name!(BeaconBlockHeader);
|
||||
type_name_generic!(BeaconState);
|
||||
type_name!(BlobIdentifier);
|
||||
type_name_generic!(DataColumnsByRootIdentifier, "DataColumnsByRootIdentifier");
|
||||
type_name_generic!(BlobSidecar);
|
||||
type_name_generic!(DataColumnSidecar);
|
||||
type_name_generic!(DataColumnSidecarFulu, "DataColumnSidecar");
|
||||
type_name_generic!(DataColumnSidecarGloas, "DataColumnSidecar");
|
||||
type_name!(Checkpoint);
|
||||
type_name!(ConsolidationRequest);
|
||||
type_name_generic!(ContributionAndProof);
|
||||
@@ -69,6 +72,9 @@ type_name!(DepositData);
|
||||
type_name!(DepositMessage);
|
||||
type_name!(DepositRequest);
|
||||
type_name!(Eth1Data);
|
||||
type_name!(Builder);
|
||||
type_name!(BuilderPendingPayment);
|
||||
type_name!(BuilderPendingWithdrawal);
|
||||
type_name!(WithdrawalRequest);
|
||||
type_name_generic!(ExecutionPayload);
|
||||
type_name_generic!(ExecutionPayloadBellatrix, "ExecutionPayload");
|
||||
@@ -77,6 +83,7 @@ type_name_generic!(ExecutionPayloadDeneb, "ExecutionPayload");
|
||||
type_name_generic!(ExecutionPayloadElectra, "ExecutionPayload");
|
||||
type_name_generic!(ExecutionPayloadFulu, "ExecutionPayload");
|
||||
type_name_generic!(ExecutionPayloadEip7805, "ExecutionPayload");
|
||||
type_name_generic!(ExecutionPayloadGloas, "ExecutionPayload");
|
||||
type_name_generic!(FullPayload, "ExecutionPayload");
|
||||
type_name_generic!(ExecutionPayloadHeader);
|
||||
type_name_generic!(ExecutionPayloadHeaderBellatrix, "ExecutionPayloadHeader");
|
||||
@@ -85,7 +92,11 @@ type_name_generic!(ExecutionPayloadHeaderDeneb, "ExecutionPayloadHeader");
|
||||
type_name_generic!(ExecutionPayloadHeaderElectra, "ExecutionPayloadHeader");
|
||||
type_name_generic!(ExecutionPayloadHeaderFulu, "ExecutionPayloadHeader");
|
||||
type_name_generic!(ExecutionPayloadHeaderEip7805, "ExecutionPayloadHeader");
|
||||
type_name_generic!(ExecutionPayloadBid);
|
||||
type_name_generic!(SignedExecutionPayloadBid);
|
||||
type_name_generic!(ExecutionRequests);
|
||||
type_name_generic!(ExecutionPayloadEnvelope);
|
||||
type_name_generic!(SignedExecutionPayloadEnvelope);
|
||||
type_name_generic!(BlindedPayload, "ExecutionPayloadHeader");
|
||||
type_name!(Fork);
|
||||
type_name!(ForkData);
|
||||
@@ -93,6 +104,7 @@ type_name_generic!(HistoricalBatch);
|
||||
type_name_generic!(IndexedAttestation);
|
||||
type_name_generic!(IndexedAttestationBase, "IndexedAttestation");
|
||||
type_name_generic!(IndexedAttestationElectra, "IndexedAttestation");
|
||||
type_name_generic!(IndexedPayloadAttestation);
|
||||
type_name_generic!(LightClientBootstrap);
|
||||
type_name_generic!(LightClientBootstrapAltair, "LightClientBootstrap");
|
||||
type_name_generic!(LightClientBootstrapCapella, "LightClientBootstrap");
|
||||
@@ -145,10 +157,15 @@ type_name_generic!(LightClientUpdateDeneb, "LightClientUpdate");
|
||||
type_name_generic!(LightClientUpdateElectra, "LightClientUpdate");
|
||||
type_name_generic!(LightClientUpdateFulu, "LightClientUpdate");
|
||||
type_name_generic!(PendingAttestation);
|
||||
type_name_generic!(PayloadAttestation);
|
||||
type_name!(PayloadAttestationData);
|
||||
type_name!(PayloadAttestationMessage);
|
||||
type_name!(PendingConsolidation);
|
||||
type_name!(PendingPartialWithdrawal);
|
||||
type_name!(PendingDeposit);
|
||||
type_name!(ProposerSlashing);
|
||||
type_name!(ProposerPreferences);
|
||||
type_name!(SignedProposerPreferences);
|
||||
type_name_generic!(SignedAggregateAndProof);
|
||||
type_name_generic!(SignedAggregateAndProofBase, "SignedAggregateAndProof");
|
||||
type_name_generic!(SignedAggregateAndProofElectra, "SignedAggregateAndProof");
|
||||
|
||||
Reference in New Issue
Block a user