mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-29 20:27:14 +00:00
Merge remote-tracking branch 'origin/unstable' into gloas-containers
This commit is contained in:
@@ -4,11 +4,10 @@ use beacon_chain::attestation_simulator::produce_unaggregated_attestation;
|
||||
use beacon_chain::test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy};
|
||||
use beacon_chain::validator_monitor::UNAGGREGATED_ATTESTATION_LAG_SLOTS;
|
||||
use beacon_chain::{StateSkipConfig, WhenSlotSkipped, metrics};
|
||||
use bls::{AggregateSignature, Keypair};
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use tree_hash::TreeHash;
|
||||
use types::{
|
||||
AggregateSignature, Attestation, EthSpec, Keypair, MainnetEthSpec, RelativeEpoch, Slot,
|
||||
};
|
||||
use types::{Attestation, EthSpec, MainnetEthSpec, RelativeEpoch, Slot};
|
||||
|
||||
pub const VALIDATOR_COUNT: usize = 16;
|
||||
|
||||
|
||||
@@ -13,15 +13,17 @@ use beacon_chain::{
|
||||
single_attestation_to_attestation, test_spec,
|
||||
},
|
||||
};
|
||||
use bls::{AggregateSignature, Keypair, SecretKey};
|
||||
use fixed_bytes::FixedBytesExtended;
|
||||
use genesis::{DEFAULT_ETH1_BLOCK_HASH, interop_genesis_state};
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use state_processing::per_slot_processing;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use tree_hash::TreeHash;
|
||||
use typenum::Unsigned;
|
||||
use types::{
|
||||
Address, AggregateSignature, Attestation, AttestationRef, ChainSpec, Epoch, EthSpec,
|
||||
FixedBytesExtended, ForkName, Hash256, Keypair, MainnetEthSpec, SecretKey, SelectionProof,
|
||||
SignedAggregateAndProof, SingleAttestation, Slot, SubnetId, Unsigned,
|
||||
Address, Attestation, AttestationRef, ChainSpec, Epoch, EthSpec, ForkName, Hash256,
|
||||
MainnetEthSpec, SelectionProof, SignedAggregateAndProof, SingleAttestation, Slot, SubnetId,
|
||||
signed_aggregate_and_proof::SignedAggregateAndProofRefMut,
|
||||
test_utils::generate_deterministic_keypair,
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ use beacon_chain::{
|
||||
AvailabilityProcessingStatus, BlockError, ChainConfig, InvalidSignature, NotifyExecutionLayer,
|
||||
block_verification_types::AsBlock,
|
||||
};
|
||||
use bls::{Keypair, Signature};
|
||||
use logging::create_test_tracing_subscriber;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use types::{blob_sidecar::FixedBlobSidecarList, *};
|
||||
|
||||
@@ -13,6 +13,8 @@ use beacon_chain::{
|
||||
BeaconSnapshot, BlockError, ChainConfig, ChainSegmentResult, IntoExecutionPendingBlock,
|
||||
InvalidSignature, NotifyExecutionLayer,
|
||||
};
|
||||
use bls::{AggregateSignature, Keypair, Signature};
|
||||
use fixed_bytes::FixedBytesExtended;
|
||||
use logging::create_test_tracing_subscriber;
|
||||
use slasher::{Config as SlasherConfig, Slasher};
|
||||
use state_processing::{
|
||||
|
||||
@@ -9,6 +9,7 @@ use beacon_chain::{
|
||||
AvailabilityProcessingStatus, BlockError, ChainConfig, InvalidSignature, NotifyExecutionLayer,
|
||||
block_verification_types::AsBlock,
|
||||
};
|
||||
use bls::{Keypair, Signature};
|
||||
use logging::create_test_tracing_subscriber;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use types::*;
|
||||
|
||||
@@ -9,6 +9,7 @@ use beacon_chain::{
|
||||
AttestationStrategy, BeaconChainHarness, BlockStrategy, DiskHarnessType, test_spec,
|
||||
},
|
||||
};
|
||||
use bls::Keypair;
|
||||
use state_processing::per_block_processing::errors::{
|
||||
AttesterSlashingInvalid, BlockOperationError, ExitInvalid, ProposerSlashingInvalid,
|
||||
};
|
||||
|
||||
@@ -7,8 +7,9 @@ use beacon_chain::test_utils::{
|
||||
use beacon_chain::{
|
||||
BlockError, ChainConfig, StateSkipConfig, WhenSlotSkipped,
|
||||
test_utils::{AttestationStrategy, BlockStrategy, RelativeSyncCommittee},
|
||||
types::{Epoch, EthSpec, Keypair, MinimalEthSpec},
|
||||
types::{Epoch, EthSpec, MinimalEthSpec},
|
||||
};
|
||||
use bls::Keypair;
|
||||
use eth2::types::{StandardAttestationRewards, TotalAttestationRewards, ValidatorId};
|
||||
use state_processing::{BlockReplayError, BlockReplayer};
|
||||
use std::array::IntoIter;
|
||||
|
||||
@@ -4,6 +4,7 @@ use beacon_chain::{
|
||||
persisted_custody::PersistedCustody,
|
||||
test_utils::{BeaconChainHarness, DiskHarnessType, test_spec},
|
||||
};
|
||||
use bls::Keypair;
|
||||
use logging::create_test_tracing_subscriber;
|
||||
use operation_pool::PersistedOperationPool;
|
||||
use ssz::Encode;
|
||||
@@ -16,7 +17,7 @@ use store::{
|
||||
};
|
||||
use strum::IntoEnumIterator;
|
||||
use tempfile::{TempDir, tempdir};
|
||||
use types::{ChainSpec, Hash256, Keypair, MainnetEthSpec, Slot};
|
||||
use types::{ChainSpec, Hash256, MainnetEthSpec, Slot};
|
||||
|
||||
type E = MainnetEthSpec;
|
||||
type Store<E> = Arc<HotColdDB<E, BeaconNodeBackend<E>, BeaconNodeBackend<E>>>;
|
||||
|
||||
@@ -25,11 +25,14 @@ use beacon_chain::{
|
||||
historical_blocks::HistoricalBlockError,
|
||||
migrate::MigratorConfig,
|
||||
};
|
||||
use bls::{Keypair, Signature, SignatureBytes};
|
||||
use fixed_bytes::FixedBytesExtended;
|
||||
use logging::create_test_tracing_subscriber;
|
||||
use maplit::hashset;
|
||||
use rand::Rng;
|
||||
use rand::rngs::StdRng;
|
||||
use slot_clock::{SlotClock, TestingSlotClock};
|
||||
use ssz_types::VariableList;
|
||||
use state_processing::{BlockReplayer, state_advance::complete_state_advance};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
@@ -2783,6 +2786,158 @@ async fn weak_subjectivity_sync_without_blobs() {
|
||||
weak_subjectivity_sync_test(slots, checkpoint_slot, None, false).await
|
||||
}
|
||||
|
||||
// Ensures that an unaligned checkpoint sync (the block is older than the state)
|
||||
// works correctly even when `prune_payloads` is enabled.
|
||||
//
|
||||
// Previously, the `HotColdDB` would refuse to load the execution payload for the
|
||||
// anchor block because it was considered "pruned", causing the node to fail startup.
|
||||
#[tokio::test]
|
||||
async fn reproduction_unaligned_checkpoint_sync_pruned_payload() {
|
||||
let spec = test_spec::<E>();
|
||||
|
||||
// Requires Execution Payloads.
|
||||
let Some(_) = spec.deneb_fork_epoch else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Create an unaligned checkpoint with a gap of 3 slots.
|
||||
let num_initial_slots = E::slots_per_epoch() * 11;
|
||||
let checkpoint_slot = Slot::new(E::slots_per_epoch() * 9 - 3);
|
||||
|
||||
let slots = (1..num_initial_slots)
|
||||
.map(Slot::new)
|
||||
.filter(|&slot| slot <= checkpoint_slot || slot > checkpoint_slot + 3)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let temp1 = tempdir().unwrap();
|
||||
let full_store = get_store_generic(&temp1, StoreConfig::default(), spec.clone());
|
||||
|
||||
let harness = get_harness_import_all_data_columns(full_store.clone(), LOW_VALIDATOR_COUNT);
|
||||
let all_validators = (0..LOW_VALIDATOR_COUNT).collect::<Vec<_>>();
|
||||
|
||||
let (genesis_state, genesis_state_root) = harness.get_current_state_and_root();
|
||||
harness
|
||||
.add_attested_blocks_at_slots(
|
||||
genesis_state.clone(),
|
||||
genesis_state_root,
|
||||
&slots,
|
||||
&all_validators,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Extract snapshot data from the harness.
|
||||
let wss_block_root = harness
|
||||
.chain
|
||||
.block_root_at_slot(checkpoint_slot, WhenSlotSkipped::Prev)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let wss_state_root = harness
|
||||
.chain
|
||||
.state_root_at_slot(checkpoint_slot)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
let wss_block = harness
|
||||
.chain
|
||||
.store
|
||||
.get_full_block(&wss_block_root)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// The test premise requires the anchor block to have a payload.
|
||||
assert!(wss_block.message().execution_payload().is_ok());
|
||||
|
||||
let wss_blobs_opt = harness
|
||||
.chain
|
||||
.get_or_reconstruct_blobs(&wss_block_root)
|
||||
.unwrap();
|
||||
|
||||
let wss_state = full_store
|
||||
.get_state(&wss_state_root, Some(checkpoint_slot), CACHE_STATE_IN_TESTS)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
// Configure the client with `prune_payloads = true`.
|
||||
// This triggers the path where `try_get_full_block` must explicitly handle the anchor block.
|
||||
let temp2 = tempdir().unwrap();
|
||||
let store_config = StoreConfig {
|
||||
prune_payloads: true,
|
||||
..StoreConfig::default()
|
||||
};
|
||||
|
||||
let store = get_store_generic(&temp2, store_config, spec.clone());
|
||||
|
||||
let slot_clock = TestingSlotClock::new(
|
||||
Slot::new(0),
|
||||
Duration::from_secs(harness.chain.genesis_time),
|
||||
Duration::from_secs(spec.seconds_per_slot),
|
||||
);
|
||||
slot_clock.set_slot(harness.get_current_slot().as_u64());
|
||||
|
||||
let chain_config = ChainConfig {
|
||||
reconstruct_historic_states: true,
|
||||
..ChainConfig::default()
|
||||
};
|
||||
|
||||
let trusted_setup = get_kzg(&spec);
|
||||
let (shutdown_tx, _shutdown_rx) = futures::channel::mpsc::channel(1);
|
||||
let mock = mock_execution_layer_from_parts(
|
||||
harness.spec.clone(),
|
||||
harness.runtime.task_executor.clone(),
|
||||
);
|
||||
let all_custody_columns = (0..spec.number_of_custody_groups).collect::<Vec<_>>();
|
||||
|
||||
// Attempt to build the BeaconChain.
|
||||
// If the bug is present, this will panic with `MissingFullBlockExecutionPayloadPruned`.
|
||||
let beacon_chain = BeaconChainBuilder::<DiskHarnessType<E>>::new(MinimalEthSpec, trusted_setup)
|
||||
.chain_config(chain_config)
|
||||
.store(store.clone())
|
||||
.custom_spec(spec.clone().into())
|
||||
.task_executor(harness.chain.task_executor.clone())
|
||||
.weak_subjectivity_state(
|
||||
wss_state,
|
||||
wss_block.clone(),
|
||||
wss_blobs_opt.clone(),
|
||||
genesis_state,
|
||||
)
|
||||
.unwrap()
|
||||
.store_migrator_config(MigratorConfig::default().blocking())
|
||||
.slot_clock(slot_clock)
|
||||
.shutdown_sender(shutdown_tx)
|
||||
.event_handler(Some(ServerSentEventHandler::new_with_capacity(1)))
|
||||
.execution_layer(Some(mock.el))
|
||||
.ordered_custody_column_indices(all_custody_columns)
|
||||
.rng(Box::new(StdRng::seed_from_u64(42)))
|
||||
.build();
|
||||
|
||||
assert!(
|
||||
beacon_chain.is_ok(),
|
||||
"Beacon Chain failed to build. The anchor payload may have been incorrectly pruned. Error: {:?}",
|
||||
beacon_chain.err()
|
||||
);
|
||||
|
||||
let chain = beacon_chain.as_ref().unwrap();
|
||||
let wss_block_slot = wss_block.slot();
|
||||
|
||||
assert_ne!(
|
||||
wss_block_slot,
|
||||
chain.head_snapshot().beacon_state.slot(),
|
||||
"Test invalid: Checkpoint was aligned (Slot {} == Slot {}). The test did not trigger the unaligned edge case.",
|
||||
wss_block_slot,
|
||||
chain.head_snapshot().beacon_state.slot()
|
||||
);
|
||||
|
||||
let payload_exists = chain
|
||||
.store
|
||||
.execution_payload_exists(&wss_block_root)
|
||||
.unwrap_or(false);
|
||||
|
||||
assert!(
|
||||
payload_exists,
|
||||
"Split block payload must exist in the new node's store after checkpoint sync"
|
||||
);
|
||||
}
|
||||
|
||||
async fn weak_subjectivity_sync_test(
|
||||
slots: Vec<Slot>,
|
||||
checkpoint_slot: Slot,
|
||||
@@ -5529,7 +5684,6 @@ fn get_finalized_epoch_boundary_blocks(
|
||||
dump: &[BeaconSnapshot<MinimalEthSpec, BlindedPayload<MinimalEthSpec>>],
|
||||
) -> HashSet<SignedBeaconBlockHash> {
|
||||
dump.iter()
|
||||
.cloned()
|
||||
.map(|checkpoint| checkpoint.beacon_state.finalized_checkpoint().root.into())
|
||||
.collect()
|
||||
}
|
||||
@@ -5538,7 +5692,6 @@ fn get_blocks(
|
||||
dump: &[BeaconSnapshot<MinimalEthSpec, BlindedPayload<MinimalEthSpec>>],
|
||||
) -> HashSet<SignedBeaconBlockHash> {
|
||||
dump.iter()
|
||||
.cloned()
|
||||
.map(|checkpoint| checkpoint.beacon_block_root.into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
use beacon_chain::sync_committee_verification::{Error as SyncCommitteeError, SyncCommitteeData};
|
||||
use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType, RelativeSyncCommittee};
|
||||
use bls::{AggregateSignature, Keypair, SecretKey};
|
||||
use fixed_bytes::FixedBytesExtended;
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use safe_arith::SafeArith;
|
||||
use state_processing::{
|
||||
@@ -11,10 +13,11 @@ use state_processing::{
|
||||
use std::sync::LazyLock;
|
||||
use store::{SignedContributionAndProof, SyncCommitteeMessage};
|
||||
use tree_hash::TreeHash;
|
||||
use typenum::Unsigned;
|
||||
use types::consts::altair::SYNC_COMMITTEE_SUBNET_COUNT;
|
||||
use types::{
|
||||
AggregateSignature, Epoch, EthSpec, FixedBytesExtended, Hash256, Keypair, MainnetEthSpec,
|
||||
SecretKey, Slot, SyncContributionData, SyncSelectionProof, SyncSubnetId, Unsigned,
|
||||
Epoch, EthSpec, Hash256, MainnetEthSpec, Slot, SyncContributionData, SyncSelectionProof,
|
||||
SyncSubnetId,
|
||||
};
|
||||
|
||||
pub type E = MainnetEthSpec;
|
||||
|
||||
@@ -8,13 +8,14 @@ use beacon_chain::{
|
||||
OP_POOL_DB_KEY,
|
||||
},
|
||||
};
|
||||
use bls::Keypair;
|
||||
use operation_pool::PersistedOperationPool;
|
||||
use state_processing::EpochProcessingError;
|
||||
use state_processing::{per_slot_processing, per_slot_processing::Error as SlotProcessingError};
|
||||
use std::sync::LazyLock;
|
||||
use types::{
|
||||
BeaconState, BeaconStateError, BlockImportSource, Checkpoint, EthSpec, Hash256, Keypair,
|
||||
MinimalEthSpec, RelativeEpoch, Slot,
|
||||
BeaconState, BeaconStateError, BlockImportSource, Checkpoint, EthSpec, Hash256, MinimalEthSpec,
|
||||
RelativeEpoch, Slot,
|
||||
};
|
||||
|
||||
type E = MinimalEthSpec;
|
||||
|
||||
@@ -2,8 +2,9 @@ use beacon_chain::test_utils::{
|
||||
AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType,
|
||||
};
|
||||
use beacon_chain::validator_monitor::{MISSED_BLOCK_LAG_SLOTS, ValidatorMonitorConfig};
|
||||
use bls::{Keypair, PublicKeyBytes};
|
||||
use std::sync::LazyLock;
|
||||
use types::{Epoch, EthSpec, Hash256, Keypair, MainnetEthSpec, PublicKeyBytes, Slot};
|
||||
use types::{Epoch, EthSpec, Hash256, MainnetEthSpec, Slot};
|
||||
|
||||
// Should ideally be divisible by 3.
|
||||
pub const VALIDATOR_COUNT: usize = 48;
|
||||
|
||||
Reference in New Issue
Block a user