mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Merge branch 'unstable' into deneb-merge-from-unstable-20230627
# Conflicts: # beacon_node/beacon_chain/src/beacon_chain.rs # beacon_node/beacon_chain/src/block_verification.rs # beacon_node/beacon_chain/src/lib.rs # beacon_node/beacon_chain/src/test_utils.rs # beacon_node/beacon_chain/tests/block_verification.rs # beacon_node/beacon_chain/tests/store_tests.rs # beacon_node/beacon_chain/tests/tests.rs # beacon_node/http_api/src/publish_blocks.rs # beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs # beacon_node/lighthouse_network/src/rpc/methods.rs # beacon_node/lighthouse_network/src/rpc/outbound.rs # beacon_node/lighthouse_network/src/rpc/protocol.rs # beacon_node/lighthouse_network/src/service/api_types.rs # beacon_node/network/src/beacon_processor/worker/gossip_methods.rs # beacon_node/network/src/beacon_processor/worker/rpc_methods.rs # beacon_node/network/src/beacon_processor/worker/sync_methods.rs # beacon_node/network/src/sync/block_lookups/single_block_lookup.rs # beacon_node/network/src/sync/network_context.rs # beacon_node/network/src/sync/range_sync/batch.rs # beacon_node/network/src/sync/range_sync/chain.rs # common/eth2/src/types.rs # consensus/fork_choice/src/fork_choice.rs
This commit is contained in:
@@ -5,8 +5,9 @@ use beacon_chain::{
|
||||
blob_verification::AsBlock,
|
||||
test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType},
|
||||
};
|
||||
use beacon_chain::{BeaconSnapshot, BlockError, ChainSegmentResult, NotifyExecutionLayer};
|
||||
use fork_choice::CountUnrealized;
|
||||
use beacon_chain::{
|
||||
BeaconSnapshot, BlockError, ChainSegmentResult, IntoExecutionPendingBlock, NotifyExecutionLayer,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use logging::test_logger;
|
||||
use slasher::{Config as SlasherConfig, Slasher};
|
||||
@@ -153,18 +154,14 @@ async fn chain_segment_full_segment() {
|
||||
// Sneak in a little check to ensure we can process empty chain segments.
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(vec![], CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(vec![], NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.expect("should import empty chain segment");
|
||||
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
blocks.clone(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(blocks.clone(), NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.expect("should import chain segment");
|
||||
@@ -196,11 +193,7 @@ async fn chain_segment_varying_chunk_size() {
|
||||
for chunk in blocks.chunks(*chunk_size) {
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
chunk.to_vec(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(chunk.to_vec(), NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.unwrap_or_else(|_| panic!("should import chain segment of len {}", chunk_size));
|
||||
@@ -239,7 +232,7 @@ async fn chain_segment_non_linear_parent_roots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearParentRoots)
|
||||
@@ -263,7 +256,7 @@ async fn chain_segment_non_linear_parent_roots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearParentRoots)
|
||||
@@ -297,7 +290,7 @@ async fn chain_segment_non_linear_slots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearSlots)
|
||||
@@ -321,7 +314,7 @@ async fn chain_segment_non_linear_slots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearSlots)
|
||||
@@ -347,7 +340,7 @@ async fn assert_invalid_signature(
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::InvalidSignature)
|
||||
@@ -369,11 +362,7 @@ async fn assert_invalid_signature(
|
||||
// imported prior to this test.
|
||||
let _ = harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
ancestor_blocks,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(ancestor_blocks, NotifyExecutionLayer::Yes)
|
||||
.await;
|
||||
harness.chain.recompute_head_at_current_slot().await;
|
||||
|
||||
@@ -382,7 +371,6 @@ async fn assert_invalid_signature(
|
||||
.process_block(
|
||||
snapshots[block_index].beacon_block.canonical_root(),
|
||||
snapshots[block_index].beacon_block.clone(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await;
|
||||
@@ -435,11 +423,7 @@ async fn invalid_signature_gossip_block() {
|
||||
.collect();
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
ancestor_blocks,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(ancestor_blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.expect("should import all blocks prior to the one being tested");
|
||||
@@ -451,7 +435,6 @@ async fn invalid_signature_gossip_block() {
|
||||
.process_block(
|
||||
signed_block.canonical_root(),
|
||||
Arc::new(signed_block),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await,
|
||||
@@ -486,7 +469,7 @@ async fn invalid_signature_block_proposal() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::InvalidSignature)
|
||||
@@ -684,7 +667,7 @@ async fn invalid_signature_deposit() {
|
||||
!matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::InvalidSignature)
|
||||
@@ -764,7 +747,6 @@ async fn block_gossip_verification() {
|
||||
.process_block(
|
||||
gossip_verified.block_root,
|
||||
gossip_verified,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1039,7 +1021,6 @@ async fn verify_block_for_gossip_slashing_detection() {
|
||||
.process_block(
|
||||
verified_block.block_root,
|
||||
verified_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1079,7 +1060,6 @@ async fn verify_block_for_gossip_doppelganger_detection() {
|
||||
.process_block(
|
||||
verified_block.block_root,
|
||||
verified_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1227,7 +1207,6 @@ async fn add_base_block_to_altair_chain() {
|
||||
.process_block(
|
||||
base_block.canonical_root(),
|
||||
Arc::new(base_block.clone()),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1243,11 +1222,7 @@ async fn add_base_block_to_altair_chain() {
|
||||
assert!(matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
vec![Arc::new(base_block).into()],
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(vec![Arc::new(base_block).into()], NotifyExecutionLayer::Yes,)
|
||||
.await,
|
||||
ChainSegmentResult::Failed {
|
||||
imported_blocks: 0,
|
||||
@@ -1366,7 +1341,6 @@ async fn add_altair_block_to_base_chain() {
|
||||
.process_block(
|
||||
altair_block.canonical_root(),
|
||||
Arc::new(altair_block.clone()),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1384,7 +1358,6 @@ async fn add_altair_block_to_base_chain() {
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
vec![Arc::new(altair_block).into()],
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes
|
||||
)
|
||||
.await,
|
||||
@@ -1397,3 +1370,100 @@ async fn add_altair_block_to_base_chain() {
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn import_duplicate_block_unrealized_justification() {
|
||||
let spec = MainnetEthSpec::default_spec();
|
||||
|
||||
let harness = BeaconChainHarness::builder(MainnetEthSpec)
|
||||
.spec(spec)
|
||||
.keypairs(KEYPAIRS[..].to_vec())
|
||||
.fresh_ephemeral_store()
|
||||
.mock_execution_layer()
|
||||
.build();
|
||||
let chain = &harness.chain;
|
||||
|
||||
// Move out of the genesis slot.
|
||||
harness.advance_slot();
|
||||
|
||||
// Build the chain out to the first justification opportunity 2/3rds of the way through epoch 2.
|
||||
let num_slots = E::slots_per_epoch() as usize * 8 / 3;
|
||||
harness
|
||||
.extend_chain(
|
||||
num_slots,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
AttestationStrategy::AllValidators,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Move into the next empty slot.
|
||||
harness.advance_slot();
|
||||
|
||||
// The store's justified checkpoint must still be at epoch 0, while unrealized justification
|
||||
// must be at epoch 1.
|
||||
let fc = chain.canonical_head.fork_choice_read_lock();
|
||||
assert_eq!(fc.justified_checkpoint().epoch, 0);
|
||||
assert_eq!(fc.unrealized_justified_checkpoint().epoch, 1);
|
||||
drop(fc);
|
||||
|
||||
// Produce a block to justify epoch 2.
|
||||
let state = harness.get_current_state();
|
||||
let slot = harness.get_current_slot();
|
||||
let (block, _) = harness.make_block(state.clone(), slot).await;
|
||||
let block = Arc::new(block);
|
||||
let block_root = block.canonical_root();
|
||||
|
||||
// Create two verified variants of the block, representing the same block being processed in
|
||||
// parallel.
|
||||
let notify_execution_layer = NotifyExecutionLayer::Yes;
|
||||
let verified_block1 = block
|
||||
.clone()
|
||||
.into_execution_pending_block(block_root, &chain, notify_execution_layer)
|
||||
.unwrap();
|
||||
let verified_block2 = block
|
||||
.into_execution_pending_block(block_root, &chain, notify_execution_layer)
|
||||
.unwrap();
|
||||
|
||||
// Import the first block, simulating a block processed via a finalized chain segment.
|
||||
chain
|
||||
.clone()
|
||||
.import_execution_pending_block(verified_block1)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Unrealized justification should NOT have updated.
|
||||
let fc = chain.canonical_head.fork_choice_read_lock();
|
||||
assert_eq!(fc.justified_checkpoint().epoch, 0);
|
||||
let unrealized_justification = fc.unrealized_justified_checkpoint();
|
||||
assert_eq!(unrealized_justification.epoch, 2);
|
||||
|
||||
// The fork choice node for the block should have unrealized justification.
|
||||
let fc_block = fc.get_block(&block_root).unwrap();
|
||||
assert_eq!(
|
||||
fc_block.unrealized_justified_checkpoint,
|
||||
Some(unrealized_justification)
|
||||
);
|
||||
drop(fc);
|
||||
|
||||
// Import the second verified block, simulating a block processed via RPC.
|
||||
chain
|
||||
.clone()
|
||||
.import_execution_pending_block(verified_block2)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Unrealized justification should still be updated.
|
||||
let fc = chain.canonical_head.fork_choice_read_lock();
|
||||
assert_eq!(fc.justified_checkpoint().epoch, 0);
|
||||
assert_eq!(
|
||||
fc.unrealized_justified_checkpoint(),
|
||||
unrealized_justification
|
||||
);
|
||||
|
||||
// The fork choice node for the block should still have the unrealized justified checkpoint.
|
||||
let fc_block = fc.get_block(&block_root).unwrap();
|
||||
assert_eq!(
|
||||
fc_block.unrealized_justified_checkpoint,
|
||||
Some(unrealized_justification)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user