mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-15 09:48:20 +00:00
Merge remote-tracking branch 'origin/deneb-free-blobs' into tree-states
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
use beacon_chain::{
|
||||
test_utils::{AttestationStrategy, BlockStrategy},
|
||||
GossipVerifiedBlock,
|
||||
GossipVerifiedBlock, IntoGossipVerifiedBlockContents,
|
||||
};
|
||||
use eth2::types::{
|
||||
BroadcastValidation, SignedBeaconBlock, SignedBlindedBeaconBlock, SignedBlockContents,
|
||||
SignedBlockContentsTuple,
|
||||
};
|
||||
use eth2::types::{BroadcastValidation, SignedBeaconBlock, SignedBlindedBeaconBlock};
|
||||
use http_api::test_utils::InteractiveTester;
|
||||
use http_api::{publish_blinded_block, publish_block, reconstruct_block, ProvenancedBlock};
|
||||
use std::sync::Arc;
|
||||
use tree_hash::TreeHash;
|
||||
use types::{Hash256, MainnetEthSpec, Slot};
|
||||
use types::{
|
||||
BlindedBlobSidecar, BlindedPayload, BlobSidecar, FullPayload, Hash256, MainnetEthSpec,
|
||||
SignedSidecarList, Slot,
|
||||
};
|
||||
use warp::Rejection;
|
||||
use warp_utils::reject::CustomBadRequest;
|
||||
|
||||
@@ -63,7 +70,7 @@ pub async fn gossip_invalid() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero();
|
||||
@@ -73,7 +80,7 @@ pub async fn gossip_invalid() {
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(&SignedBlockContents::new(block, blobs), validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -83,7 +90,7 @@ pub async fn gossip_invalid() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 }".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -115,7 +122,7 @@ pub async fn gossip_partial_pass() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::random()
|
||||
@@ -124,7 +131,7 @@ pub async fn gossip_partial_pass() {
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(&SignedBlockContents::new(block, blobs), validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -161,11 +168,15 @@ pub async fn gossip_full_pass() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester.harness.make_block(state_a, slot_b).await;
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a, slot_b).await;
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(
|
||||
&SignedBlockContents::new(block.clone(), blobs),
|
||||
validation_level,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
@@ -203,18 +214,19 @@ pub async fn gossip_full_pass_ssz() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester.harness.make_block(state_a, slot_b).await;
|
||||
let (block_contents_tuple, _) = tester.harness.make_block(state_a, slot_b).await;
|
||||
let block_contents = block_contents_tuple.into();
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2_ssz(&block, validation_level)
|
||||
.post_beacon_blocks_v2_ssz(&block_contents, validation_level)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
assert!(tester
|
||||
.harness
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block.canonical_root()));
|
||||
.block_is_known_to_fork_choice(&block_contents.signed_block().canonical_root()));
|
||||
}
|
||||
|
||||
/// This test checks that a block that is **invalid** from a gossip perspective gets rejected when using `broadcast_validation=consensus`.
|
||||
@@ -244,7 +256,7 @@ pub async fn consensus_invalid() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero();
|
||||
@@ -254,7 +266,7 @@ pub async fn consensus_invalid() {
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(&SignedBlockContents::new(block, blobs), validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -264,7 +276,7 @@ pub async fn consensus_invalid() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 }".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -296,14 +308,14 @@ pub async fn consensus_gossip() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(state_a, slot_b, |b| *b.state_root_mut() = Hash256::zero())
|
||||
.await;
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(&SignedBlockContents::new(block, blobs), validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -346,18 +358,20 @@ pub async fn consensus_partial_pass_only_consensus() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block_a, state_after_a): (SignedBeaconBlock<E>, _) =
|
||||
let ((block_a, _), state_after_a): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a.clone(), slot_b).await;
|
||||
let (block_b, state_after_b): (SignedBeaconBlock<E>, _) =
|
||||
let ((block_b, blobs_b), state_after_b): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a, slot_b).await;
|
||||
let block_b_root = block_b.canonical_root();
|
||||
|
||||
/* check for `make_block` curios */
|
||||
assert_eq!(block_a.state_root(), state_after_a.tree_hash_root());
|
||||
assert_eq!(block_b.state_root(), state_after_b.tree_hash_root());
|
||||
assert_ne!(block_a.state_root(), block_b.state_root());
|
||||
|
||||
let gossip_block_b = GossipVerifiedBlock::new(block_b.clone().into(), &tester.harness.chain);
|
||||
assert!(gossip_block_b.is_ok());
|
||||
let gossip_block_contents_b = SignedBlockContents::new(block_b, blobs_b)
|
||||
.into_gossip_verified_block(&tester.harness.chain);
|
||||
assert!(gossip_block_contents_b.is_ok());
|
||||
let gossip_block_a = GossipVerifiedBlock::new(block_a.clone().into(), &tester.harness.chain);
|
||||
assert!(gossip_block_a.is_err());
|
||||
|
||||
@@ -366,7 +380,7 @@ pub async fn consensus_partial_pass_only_consensus() {
|
||||
|
||||
let publication_result = publish_block(
|
||||
None,
|
||||
ProvenancedBlock::local(gossip_block_b.unwrap()),
|
||||
ProvenancedBlock::local(gossip_block_contents_b.unwrap()),
|
||||
tester.harness.chain.clone(),
|
||||
&channel.0,
|
||||
test_logger,
|
||||
@@ -379,7 +393,7 @@ pub async fn consensus_partial_pass_only_consensus() {
|
||||
assert!(tester
|
||||
.harness
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block_b.canonical_root()));
|
||||
.block_is_known_to_fork_choice(&block_b_root));
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective is accepted when using `broadcast_validation=consensus`.
|
||||
@@ -410,11 +424,15 @@ pub async fn consensus_full_pass() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester.harness.make_block(state_a, slot_b).await;
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a, slot_b).await;
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(
|
||||
&SignedBlockContents::new(block.clone(), blobs),
|
||||
validation_level,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
@@ -453,7 +471,7 @@ pub async fn equivocation_invalid() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero();
|
||||
@@ -463,7 +481,7 @@ pub async fn equivocation_invalid() {
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(&SignedBlockContents::new(block, blobs), validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -473,7 +491,7 @@ pub async fn equivocation_invalid() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 }".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -506,9 +524,9 @@ pub async fn equivocation_consensus_early_equivocation() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block_a, state_after_a): (SignedBeaconBlock<E>, _) =
|
||||
let ((block_a, blobs_a), state_after_a): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a.clone(), slot_b).await;
|
||||
let (block_b, state_after_b): (SignedBeaconBlock<E>, _) =
|
||||
let ((block_b, blobs_b), state_after_b): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a, slot_b).await;
|
||||
|
||||
/* check for `make_block` curios */
|
||||
@@ -519,7 +537,10 @@ pub async fn equivocation_consensus_early_equivocation() {
|
||||
/* submit `block_a` as valid */
|
||||
assert!(tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block_a, validation_level)
|
||||
.post_beacon_blocks_v2(
|
||||
&SignedBlockContents::new(block_a.clone(), blobs_a),
|
||||
validation_level
|
||||
)
|
||||
.await
|
||||
.is_ok());
|
||||
assert!(tester
|
||||
@@ -530,7 +551,10 @@ pub async fn equivocation_consensus_early_equivocation() {
|
||||
/* submit `block_b` which should induce equivocation */
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block_b, validation_level)
|
||||
.post_beacon_blocks_v2(
|
||||
&SignedBlockContents::new(block_b.clone(), blobs_b),
|
||||
validation_level,
|
||||
)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -539,7 +563,7 @@ pub async fn equivocation_consensus_early_equivocation() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: Slashable".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(Slashable)".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -572,14 +596,14 @@ pub async fn equivocation_gossip() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(state_a, slot_b, |b| *b.state_root_mut() = Hash256::zero())
|
||||
.await;
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(&SignedBlockContents::new(block, blobs), validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -593,9 +617,11 @@ pub async fn equivocation_gossip() {
|
||||
);
|
||||
}
|
||||
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective but that equivocates **late** is rejected when using `broadcast_validation=consensus_and_equivocation`.
|
||||
/// This test checks that a block that is valid from both a gossip and consensus perspective but
|
||||
/// that equivocates **late** is rejected when using `broadcast_validation=consensus_and_equivocation`.
|
||||
///
|
||||
/// This test is unique in that we can't actually test the HTTP API directly, but instead have to hook into the `publish_blocks` code manually. This is in order to handle the late equivocation case.
|
||||
/// This test is unique in that we can't actually test the HTTP API directly, but instead have to
|
||||
/// hook into the `publish_blocks` code manually. This is in order to handle the late equivocation case.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
pub async fn equivocation_consensus_late_equivocation() {
|
||||
/* this test targets gossip-level validation */
|
||||
@@ -625,9 +651,9 @@ pub async fn equivocation_consensus_late_equivocation() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block_a, state_after_a): (SignedBeaconBlock<E>, _) =
|
||||
let ((block_a, blobs_a), state_after_a): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a.clone(), slot_b).await;
|
||||
let (block_b, state_after_b): (SignedBeaconBlock<E>, _) =
|
||||
let ((block_b, blobs_b), state_after_b): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a, slot_b).await;
|
||||
|
||||
/* check for `make_block` curios */
|
||||
@@ -635,16 +661,18 @@ pub async fn equivocation_consensus_late_equivocation() {
|
||||
assert_eq!(block_b.state_root(), state_after_b.tree_hash_root());
|
||||
assert_ne!(block_a.state_root(), block_b.state_root());
|
||||
|
||||
let gossip_block_b = GossipVerifiedBlock::new(block_b.clone().into(), &tester.harness.chain);
|
||||
assert!(gossip_block_b.is_ok());
|
||||
let gossip_block_a = GossipVerifiedBlock::new(block_a.clone().into(), &tester.harness.chain);
|
||||
assert!(gossip_block_a.is_err());
|
||||
let gossip_block_contents_b = SignedBlockContents::new(block_b, blobs_b)
|
||||
.into_gossip_verified_block(&tester.harness.chain);
|
||||
assert!(gossip_block_contents_b.is_ok());
|
||||
let gossip_block_contents_a = SignedBlockContents::new(block_a, blobs_a)
|
||||
.into_gossip_verified_block(&tester.harness.chain);
|
||||
assert!(gossip_block_contents_a.is_err());
|
||||
|
||||
let channel = tokio::sync::mpsc::unbounded_channel();
|
||||
|
||||
let publication_result = publish_block(
|
||||
None,
|
||||
ProvenancedBlock::local(gossip_block_b.unwrap()),
|
||||
ProvenancedBlock::local(gossip_block_contents_b.unwrap()),
|
||||
tester.harness.chain,
|
||||
&channel.0,
|
||||
test_logger,
|
||||
@@ -694,11 +722,15 @@ pub async fn equivocation_full_pass() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester.harness.make_block(state_a, slot_b).await;
|
||||
let ((block, blobs), _): ((SignedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_block(state_a, slot_b).await;
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(
|
||||
&SignedBlockContents::new(block.clone(), blobs),
|
||||
validation_level,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
@@ -736,7 +768,7 @@ pub async fn blinded_gossip_invalid() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple, _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero();
|
||||
@@ -744,11 +776,11 @@ pub async fn blinded_gossip_invalid() {
|
||||
})
|
||||
.await;
|
||||
|
||||
let blinded_block: SignedBlindedBeaconBlock<E> = block.into();
|
||||
let blinded_block_contents = into_signed_blinded_block_contents(block_contents_tuple);
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -758,7 +790,7 @@ pub async fn blinded_gossip_invalid() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 }".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -790,18 +822,18 @@ pub async fn blinded_gossip_partial_pass() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple, _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero()
|
||||
})
|
||||
.await;
|
||||
|
||||
let blinded_block: SignedBlindedBeaconBlock<E> = block.into();
|
||||
let blinded_block_contents = into_signed_blinded_block_contents(block_contents_tuple);
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -838,19 +870,18 @@ pub async fn blinded_gossip_full_pass() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBlindedBeaconBlock<E>, _) =
|
||||
tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
|
||||
let (block_contents_tuple, _) = tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
let block_contents = block_contents_tuple.into();
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&block_contents, validation_level)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
assert!(tester
|
||||
.harness
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block.canonical_root()));
|
||||
.block_is_known_to_fork_choice(&block_contents.signed_block().canonical_root()));
|
||||
}
|
||||
|
||||
// This test checks that a block that is valid from both a gossip and consensus perspective is accepted when using `broadcast_validation=gossip`.
|
||||
@@ -881,19 +912,19 @@ pub async fn blinded_gossip_full_pass_ssz() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBlindedBeaconBlock<E>, _) =
|
||||
tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
let (block_contents_tuple, _) = tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
let block_contents = block_contents_tuple.into();
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2_ssz(&block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2_ssz(&block_contents, validation_level)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
assert!(tester
|
||||
.harness
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block.canonical_root()));
|
||||
.block_is_known_to_fork_choice(&block_contents.signed_block().canonical_root()));
|
||||
}
|
||||
|
||||
/// This test checks that a block that is **invalid** from a gossip perspective gets rejected when using `broadcast_validation=consensus`.
|
||||
@@ -924,7 +955,7 @@ pub async fn blinded_consensus_invalid() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple, _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero();
|
||||
@@ -932,11 +963,11 @@ pub async fn blinded_consensus_invalid() {
|
||||
})
|
||||
.await;
|
||||
|
||||
let blinded_block: SignedBlindedBeaconBlock<E> = block.into();
|
||||
let blinded_block_contents = into_signed_blinded_block_contents(block_contents_tuple);
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -946,7 +977,7 @@ pub async fn blinded_consensus_invalid() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 }".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -978,16 +1009,16 @@ pub async fn blinded_consensus_gossip() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple, _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(state_a, slot_b, |b| *b.state_root_mut() = Hash256::zero())
|
||||
.await;
|
||||
|
||||
let blinded_block: SignedBlindedBeaconBlock<E> = block.into();
|
||||
let blinded_block_contents = into_signed_blinded_block_contents(block_contents_tuple);
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -1029,19 +1060,19 @@ pub async fn blinded_consensus_full_pass() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBlindedBeaconBlock<E>, _) =
|
||||
tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
let (block_contents_tuple, _) = tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
|
||||
let block_contents = block_contents_tuple.into();
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&block_contents, validation_level)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
assert!(tester
|
||||
.harness
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block.canonical_root()));
|
||||
.block_is_known_to_fork_choice(&block_contents.signed_block().canonical_root()));
|
||||
}
|
||||
|
||||
/// This test checks that a block that is **invalid** from a gossip perspective gets rejected when using `broadcast_validation=consensus_and_equivocation`.
|
||||
@@ -1073,7 +1104,7 @@ pub async fn blinded_equivocation_invalid() {
|
||||
|
||||
tester.harness.advance_slot();
|
||||
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple, _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(chain_state_before, slot, |b| {
|
||||
*b.state_root_mut() = Hash256::zero();
|
||||
@@ -1081,11 +1112,11 @@ pub async fn blinded_equivocation_invalid() {
|
||||
})
|
||||
.await;
|
||||
|
||||
let blinded_block: SignedBlindedBeaconBlock<E> = block.into();
|
||||
let blinded_block_contents = into_signed_blinded_block_contents(block_contents_tuple);
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -1095,7 +1126,7 @@ pub async fn blinded_equivocation_invalid() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 }".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(NotFinalizedDescendant { block_parent_root: 0x0000000000000000000000000000000000000000000000000000000000000000 })".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1128,14 +1159,18 @@ pub async fn blinded_equivocation_consensus_early_equivocation() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block_a, state_after_a): (SignedBlindedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple_a, state_after_a) = tester
|
||||
.harness
|
||||
.make_blinded_block(state_a.clone(), slot_b)
|
||||
.await;
|
||||
let (block_b, state_after_b): (SignedBlindedBeaconBlock<E>, _) =
|
||||
let (block_contents_tuple_b, state_after_b) =
|
||||
tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
|
||||
/* check for `make_blinded_block` curios */
|
||||
let block_contents_a: SignedBlockContents<E, BlindedPayload<E>> = block_contents_tuple_a.into();
|
||||
let block_contents_b: SignedBlockContents<E, BlindedPayload<E>> = block_contents_tuple_b.into();
|
||||
let block_a = block_contents_a.signed_block();
|
||||
let block_b = block_contents_b.signed_block();
|
||||
assert_eq!(block_a.state_root(), state_after_a.tree_hash_root());
|
||||
assert_eq!(block_b.state_root(), state_after_b.tree_hash_root());
|
||||
assert_ne!(block_a.state_root(), block_b.state_root());
|
||||
@@ -1143,7 +1178,7 @@ pub async fn blinded_equivocation_consensus_early_equivocation() {
|
||||
/* submit `block_a` as valid */
|
||||
assert!(tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&block_a, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&block_contents_a, validation_level)
|
||||
.await
|
||||
.is_ok());
|
||||
assert!(tester
|
||||
@@ -1154,7 +1189,7 @@ pub async fn blinded_equivocation_consensus_early_equivocation() {
|
||||
/* submit `block_b` which should induce equivocation */
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&block_b, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&block_contents_b, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -1163,7 +1198,7 @@ pub async fn blinded_equivocation_consensus_early_equivocation() {
|
||||
assert_eq!(error_response.status(), Some(StatusCode::BAD_REQUEST));
|
||||
|
||||
assert!(
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: Slashable".to_string())
|
||||
matches!(error_response, eth2::Error::ServerMessage(err) if err.message == "BAD_REQUEST: BlockError(Slashable)".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1196,16 +1231,16 @@ pub async fn blinded_equivocation_gossip() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBeaconBlock<E>, _) = tester
|
||||
let (block_contents_tuple, _) = tester
|
||||
.harness
|
||||
.make_block_with_modifier(state_a, slot_b, |b| *b.state_root_mut() = Hash256::zero())
|
||||
.await;
|
||||
|
||||
let blinded_block: SignedBlindedBeaconBlock<E> = block.into();
|
||||
let blinded_block_contents = into_signed_blinded_block_contents(block_contents_tuple);
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, validation_level)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, validation_level)
|
||||
.await;
|
||||
assert!(response.is_err());
|
||||
|
||||
@@ -1251,11 +1286,11 @@ pub async fn blinded_equivocation_consensus_late_equivocation() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block_a, state_after_a): (SignedBlindedBeaconBlock<E>, _) = tester
|
||||
let ((block_a, blobs_a), state_after_a): ((SignedBlindedBeaconBlock<E>, _), _) = tester
|
||||
.harness
|
||||
.make_blinded_block(state_a.clone(), slot_b)
|
||||
.await;
|
||||
let (block_b, state_after_b): (SignedBlindedBeaconBlock<E>, _) =
|
||||
let ((block_b, blobs_b), state_after_b): ((SignedBlindedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
|
||||
/* check for `make_blinded_block` curios */
|
||||
@@ -1265,16 +1300,16 @@ pub async fn blinded_equivocation_consensus_late_equivocation() {
|
||||
|
||||
let unblinded_block_a = reconstruct_block(
|
||||
tester.harness.chain.clone(),
|
||||
block_a.state_root(),
|
||||
block_a,
|
||||
block_a.canonical_root(),
|
||||
SignedBlockContents::new(block_a, blobs_a),
|
||||
test_logger.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let unblinded_block_b = reconstruct_block(
|
||||
tester.harness.chain.clone(),
|
||||
block_b.clone().state_root(),
|
||||
block_b.clone(),
|
||||
block_b.canonical_root(),
|
||||
SignedBlockContents::new(block_b.clone(), blobs_b.clone()),
|
||||
test_logger.clone(),
|
||||
)
|
||||
.await
|
||||
@@ -1289,15 +1324,21 @@ pub async fn blinded_equivocation_consensus_late_equivocation() {
|
||||
ProvenancedBlock::Builder(b, _) => b,
|
||||
};
|
||||
|
||||
let gossip_block_b = GossipVerifiedBlock::new(inner_block_b, &tester.harness.chain);
|
||||
let gossip_block_b = GossipVerifiedBlock::new(
|
||||
Arc::new(inner_block_b.clone().deconstruct().0),
|
||||
&tester.harness.chain,
|
||||
);
|
||||
assert!(gossip_block_b.is_ok());
|
||||
let gossip_block_a = GossipVerifiedBlock::new(inner_block_a, &tester.harness.chain);
|
||||
let gossip_block_a = GossipVerifiedBlock::new(
|
||||
Arc::new(inner_block_a.clone().deconstruct().0),
|
||||
&tester.harness.chain,
|
||||
);
|
||||
assert!(gossip_block_a.is_err());
|
||||
|
||||
let channel = tokio::sync::mpsc::unbounded_channel();
|
||||
|
||||
let publication_result = publish_blinded_block(
|
||||
block_b,
|
||||
SignedBlockContents::new(block_b, blobs_b),
|
||||
tester.harness.chain,
|
||||
&channel.0,
|
||||
test_logger,
|
||||
@@ -1342,12 +1383,15 @@ pub async fn blinded_equivocation_full_pass() {
|
||||
let slot_b = slot_a + 1;
|
||||
|
||||
let state_a = tester.harness.get_current_state();
|
||||
let (block, _): (SignedBlindedBeaconBlock<E>, _) =
|
||||
let ((block, blobs), _): ((SignedBlindedBeaconBlock<E>, _), _) =
|
||||
tester.harness.make_blinded_block(state_a, slot_b).await;
|
||||
|
||||
let response: Result<(), eth2::Error> = tester
|
||||
.client
|
||||
.post_beacon_blocks_v2(&block, validation_level)
|
||||
.post_beacon_blocks_v2(
|
||||
&SignedBlockContents::new(block.clone(), blobs),
|
||||
validation_level,
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(response.is_ok());
|
||||
@@ -1356,3 +1400,20 @@ pub async fn blinded_equivocation_full_pass() {
|
||||
.chain
|
||||
.block_is_known_to_fork_choice(&block.canonical_root()));
|
||||
}
|
||||
|
||||
fn into_signed_blinded_block_contents(
|
||||
block_contents_tuple: SignedBlockContentsTuple<E, FullPayload<E>>,
|
||||
) -> SignedBlockContents<E, BlindedPayload<E>> {
|
||||
let (block, maybe_blobs) = block_contents_tuple;
|
||||
SignedBlockContents::new(block.into(), maybe_blobs.map(into_blinded_blob_sidecars))
|
||||
}
|
||||
|
||||
fn into_blinded_blob_sidecars(
|
||||
blobs: SignedSidecarList<E, BlobSidecar<E>>,
|
||||
) -> SignedSidecarList<E, BlindedBlobSidecar> {
|
||||
blobs
|
||||
.into_iter()
|
||||
.map(|blob| blob.into())
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use beacon_chain::{
|
||||
StateSkipConfig,
|
||||
};
|
||||
use eth2::types::{IndexedErrorMessage, StateId, SyncSubcommittee};
|
||||
use execution_layer::test_utils::generate_genesis_header;
|
||||
use genesis::{bls_withdrawal_credentials, interop_genesis_state_with_withdrawal_credentials};
|
||||
use http_api::test_utils::*;
|
||||
use std::collections::HashSet;
|
||||
@@ -355,12 +356,13 @@ async fn bls_to_execution_changes_update_all_around_capella_fork() {
|
||||
.iter()
|
||||
.map(|keypair| bls_withdrawal_credentials(&keypair.as_ref().unwrap().pk, &spec))
|
||||
.collect::<Vec<_>>();
|
||||
let header = generate_genesis_header(&spec, true);
|
||||
let genesis_state = interop_genesis_state_with_withdrawal_credentials(
|
||||
&validator_keypairs,
|
||||
&withdrawal_credentials,
|
||||
HARNESS_GENESIS_TIME,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
None,
|
||||
header,
|
||||
&spec,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -391,8 +391,8 @@ pub async fn proposer_boost_re_org_test(
|
||||
) {
|
||||
assert!(head_slot > 0);
|
||||
|
||||
// Test using Capella so that we simulate conditions as similar to mainnet as possible.
|
||||
let mut spec = ForkName::Capella.make_genesis_spec(E::default_spec());
|
||||
// Test using the latest fork so that we simulate conditions as similar to mainnet as possible.
|
||||
let mut spec = ForkName::latest().make_genesis_spec(E::default_spec());
|
||||
spec.terminal_total_difficulty = 1.into();
|
||||
|
||||
// Ensure there are enough validators to have `attesters_per_slot`.
|
||||
@@ -551,7 +551,7 @@ pub async fn proposer_boost_re_org_test(
|
||||
|
||||
// Produce block B and process it halfway through the slot.
|
||||
let (block_b, mut state_b) = harness.make_block(state_a.clone(), slot_b).await;
|
||||
let block_b_root = block_b.canonical_root();
|
||||
let block_b_root = block_b.0.canonical_root();
|
||||
|
||||
let obs_time = slot_clock.start_of(slot_b).unwrap() + slot_clock.slot_duration() / 2;
|
||||
slot_clock.set_current_time(obs_time);
|
||||
@@ -617,12 +617,13 @@ pub async fn proposer_boost_re_org_test(
|
||||
let randao_reveal = harness
|
||||
.sign_randao_reveal(&state_b, proposer_index, slot_c)
|
||||
.into();
|
||||
let unsigned_block_c = tester
|
||||
let unsigned_block_contents_c = tester
|
||||
.client
|
||||
.get_validator_blocks(slot_c, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
let (unsigned_block_c, block_c_blobs) = unsigned_block_contents_c.deconstruct();
|
||||
let block_c = harness.sign_beacon_block(unsigned_block_c, &state_b);
|
||||
|
||||
if should_re_org {
|
||||
@@ -633,9 +634,13 @@ pub async fn proposer_boost_re_org_test(
|
||||
assert_eq!(block_c.parent_root(), block_b_root);
|
||||
}
|
||||
|
||||
// Sign blobs.
|
||||
let block_c_signed_blobs =
|
||||
block_c_blobs.map(|blobs| harness.sign_blobs(blobs, &state_b, proposer_index));
|
||||
|
||||
// Applying block C should cause it to become head regardless (re-org or continuation).
|
||||
let block_root_c = harness
|
||||
.process_block_result(block_c.clone())
|
||||
.process_block_result((block_c.clone(), block_c_signed_blobs))
|
||||
.await
|
||||
.unwrap()
|
||||
.into();
|
||||
@@ -643,8 +648,18 @@ pub async fn proposer_boost_re_org_test(
|
||||
|
||||
// Check the fork choice updates that were sent.
|
||||
let forkchoice_updates = forkchoice_updates.lock();
|
||||
let block_a_exec_hash = block_a.message().execution_payload().unwrap().block_hash();
|
||||
let block_b_exec_hash = block_b.message().execution_payload().unwrap().block_hash();
|
||||
let block_a_exec_hash = block_a
|
||||
.0
|
||||
.message()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
.block_hash();
|
||||
let block_b_exec_hash = block_b
|
||||
.0
|
||||
.message()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
.block_hash();
|
||||
|
||||
let block_c_timestamp = block_c.message().execution_payload().unwrap().timestamp();
|
||||
|
||||
@@ -688,6 +703,11 @@ pub async fn proposer_boost_re_org_test(
|
||||
assert_ne!(expected_withdrawals, pre_advance_withdrawals);
|
||||
}
|
||||
|
||||
// Check that the `parent_beacon_block_root` of the payload attributes are correct.
|
||||
if let Ok(parent_beacon_block_root) = payload_attribs.parent_beacon_block_root() {
|
||||
assert_eq!(parent_beacon_block_root, block_c.parent_root());
|
||||
}
|
||||
|
||||
let lookahead = slot_clock
|
||||
.start_of(slot_c)
|
||||
.unwrap()
|
||||
@@ -749,7 +769,7 @@ pub async fn fork_choice_before_proposal() {
|
||||
let state_a = harness.get_current_state();
|
||||
let (block_b, state_b) = harness.make_block(state_a.clone(), slot_b).await;
|
||||
let block_root_b = harness
|
||||
.process_block(slot_b, block_b.canonical_root(), block_b)
|
||||
.process_block(slot_b, block_b.0.canonical_root(), block_b)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -764,7 +784,7 @@ pub async fn fork_choice_before_proposal() {
|
||||
|
||||
let (block_c, state_c) = harness.make_block(state_a, slot_c).await;
|
||||
let block_root_c = harness
|
||||
.process_block(slot_c, block_c.canonical_root(), block_c.clone())
|
||||
.process_block(slot_c, block_c.0.canonical_root(), block_c.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -804,7 +824,9 @@ pub async fn fork_choice_before_proposal() {
|
||||
.get_validator_blocks::<E, FullPayload<E>>(slot_d, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
.data
|
||||
.deconstruct()
|
||||
.0;
|
||||
|
||||
// Head is now B.
|
||||
assert_eq!(
|
||||
|
||||
@@ -100,9 +100,10 @@ async fn el_error_on_new_payload() {
|
||||
|
||||
// Make a block.
|
||||
let pre_state = harness.get_current_state();
|
||||
let (block, _) = harness
|
||||
let (block_contents, _) = harness
|
||||
.make_block(pre_state, Slot::new(num_blocks + 1))
|
||||
.await;
|
||||
let (block, blobs) = block_contents;
|
||||
let block_hash = block
|
||||
.message()
|
||||
.body()
|
||||
@@ -118,7 +119,9 @@ async fn el_error_on_new_payload() {
|
||||
// Attempt to process the block, which should error.
|
||||
harness.advance_slot();
|
||||
assert!(matches!(
|
||||
harness.process_block_result(block.clone()).await,
|
||||
harness
|
||||
.process_block_result((block.clone(), blobs.clone()))
|
||||
.await,
|
||||
Err(BlockError::ExecutionPayloadError(_))
|
||||
));
|
||||
|
||||
@@ -137,7 +140,7 @@ async fn el_error_on_new_payload() {
|
||||
validation_error: None,
|
||||
},
|
||||
);
|
||||
harness.process_block_result(block).await.unwrap();
|
||||
harness.process_block_result((block, blobs)).await.unwrap();
|
||||
|
||||
let api_response = tester.client.get_node_syncing().await.unwrap().data;
|
||||
assert_eq!(api_response.el_offline, Some(false));
|
||||
|
||||
@@ -62,8 +62,8 @@ struct ApiTester {
|
||||
harness: Arc<BeaconChainHarness<EphemeralHarnessType<E>>>,
|
||||
chain: Arc<BeaconChain<EphemeralHarnessType<E>>>,
|
||||
client: BeaconNodeHttpClient,
|
||||
next_block: SignedBeaconBlock<E>,
|
||||
reorg_block: SignedBeaconBlock<E>,
|
||||
next_block: SignedBlockContents<E>,
|
||||
reorg_block: SignedBlockContents<E>,
|
||||
attestations: Vec<Attestation<E>>,
|
||||
contribution_and_proofs: Vec<SignedContributionAndProof<E>>,
|
||||
attester_slashing: AttesterSlashing<E>,
|
||||
@@ -171,11 +171,13 @@ impl ApiTester {
|
||||
let (next_block, _next_state) = harness
|
||||
.make_block(head.beacon_state.clone(), harness.chain.slot().unwrap())
|
||||
.await;
|
||||
let next_block = SignedBlockContents::from(next_block);
|
||||
|
||||
// `make_block` adds random graffiti, so this will produce an alternate block
|
||||
let (reorg_block, _reorg_state) = harness
|
||||
.make_block(head.beacon_state.clone(), harness.chain.slot().unwrap() + 1)
|
||||
.await;
|
||||
let reorg_block = SignedBlockContents::from(reorg_block);
|
||||
|
||||
let head_state_root = head.beacon_state_root();
|
||||
let attestations = harness
|
||||
@@ -314,11 +316,13 @@ impl ApiTester {
|
||||
let (next_block, _next_state) = harness
|
||||
.make_block(head.beacon_state.clone(), harness.chain.slot().unwrap())
|
||||
.await;
|
||||
let next_block = SignedBlockContents::from(next_block);
|
||||
|
||||
// `make_block` adds random graffiti, so this will produce an alternate block
|
||||
let (reorg_block, _reorg_state) = harness
|
||||
.make_block(head.beacon_state.clone(), harness.chain.slot().unwrap())
|
||||
.await;
|
||||
let reorg_block = SignedBlockContents::from(reorg_block);
|
||||
|
||||
let head_state_root = head.beacon_state_root();
|
||||
let attestations = harness
|
||||
@@ -1256,9 +1260,9 @@ impl ApiTester {
|
||||
}
|
||||
|
||||
pub async fn test_post_beacon_blocks_valid(mut self) -> Self {
|
||||
let next_block = &self.next_block;
|
||||
let next_block = self.next_block.clone();
|
||||
|
||||
self.client.post_beacon_blocks(next_block).await.unwrap();
|
||||
self.client.post_beacon_blocks(&next_block).await.unwrap();
|
||||
|
||||
assert!(
|
||||
self.network_rx.network_recv.recv().await.is_some(),
|
||||
@@ -1297,7 +1301,11 @@ impl ApiTester {
|
||||
.await
|
||||
.0;
|
||||
|
||||
assert!(self.client.post_beacon_blocks(&block).await.is_err());
|
||||
assert!(self
|
||||
.client
|
||||
.post_beacon_blocks(&SignedBlockContents::from(block))
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
assert!(
|
||||
self.network_rx.network_recv.recv().await.is_some(),
|
||||
@@ -1320,7 +1328,11 @@ impl ApiTester {
|
||||
.await
|
||||
.0;
|
||||
|
||||
assert!(self.client.post_beacon_blocks_ssz(&block).await.is_err());
|
||||
assert!(self
|
||||
.client
|
||||
.post_beacon_blocks_ssz(&SignedBlockContents::from(block))
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
assert!(
|
||||
self.network_rx.network_recv.recv().await.is_some(),
|
||||
@@ -1331,48 +1343,56 @@ impl ApiTester {
|
||||
}
|
||||
|
||||
pub async fn test_post_beacon_blocks_duplicate(self) -> Self {
|
||||
let block = self
|
||||
let block_contents = self
|
||||
.harness
|
||||
.make_block(
|
||||
self.harness.get_current_state(),
|
||||
self.harness.get_current_slot(),
|
||||
)
|
||||
.await
|
||||
.0;
|
||||
.0
|
||||
.into();
|
||||
|
||||
assert!(self.client.post_beacon_blocks(&block).await.is_ok());
|
||||
assert!(self
|
||||
.client
|
||||
.post_beacon_blocks(&block_contents)
|
||||
.await
|
||||
.is_ok());
|
||||
|
||||
let blinded_block = block.clone_as_blinded();
|
||||
let blinded_block_contents = block_contents.clone_as_blinded();
|
||||
|
||||
// Test all the POST methods in sequence, they should all behave the same.
|
||||
let responses = vec![
|
||||
self.client.post_beacon_blocks(&block).await.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blocks_v2(&block, None)
|
||||
.post_beacon_blocks(&block_contents)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blocks_ssz(&block)
|
||||
.post_beacon_blocks_v2(&block_contents, None)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blocks_v2_ssz(&block, None)
|
||||
.post_beacon_blocks_ssz(&block_contents)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blinded_blocks(&blinded_block)
|
||||
.post_beacon_blocks_v2_ssz(&block_contents, None)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block, None)
|
||||
.post_beacon_blinded_blocks(&blinded_block_contents)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blinded_blocks_ssz(&blinded_block)
|
||||
.post_beacon_blinded_blocks_v2(&blinded_block_contents, None)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blinded_blocks_v2_ssz(&blinded_block, None)
|
||||
.post_beacon_blinded_blocks_ssz(&blinded_block_contents)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
self.client
|
||||
.post_beacon_blinded_blocks_v2_ssz(&blinded_block_contents, None)
|
||||
.await
|
||||
.unwrap_err(),
|
||||
];
|
||||
@@ -1798,9 +1818,9 @@ impl ApiTester {
|
||||
pub async fn test_get_config_spec(self) -> Self {
|
||||
let result = self
|
||||
.client
|
||||
.get_config_spec::<ConfigAndPresetCapella>()
|
||||
.get_config_spec::<ConfigAndPresetDeneb>()
|
||||
.await
|
||||
.map(|res| ConfigAndPreset::Capella(res.data))
|
||||
.map(|res| ConfigAndPreset::Deneb(res.data))
|
||||
.unwrap();
|
||||
let expected = ConfigAndPreset::from_chain_spec::<E>(&self.chain.spec, None);
|
||||
|
||||
@@ -2499,11 +2519,18 @@ impl ApiTester {
|
||||
.get_validator_blocks::<E, FullPayload<E>>(slot, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
.data
|
||||
.deconstruct()
|
||||
.0;
|
||||
|
||||
let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
let signed_block_contents =
|
||||
SignedBlockContents::try_from(signed_block.clone()).unwrap();
|
||||
|
||||
self.client.post_beacon_blocks(&signed_block).await.unwrap();
|
||||
self.client
|
||||
.post_beacon_blocks(&signed_block_contents)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(self.chain.head_beacon_block().as_ref(), &signed_block);
|
||||
|
||||
@@ -2558,18 +2585,22 @@ impl ApiTester {
|
||||
.unwrap()
|
||||
.expect("block bytes");
|
||||
|
||||
let block =
|
||||
BeaconBlock::<E, FullPayload<E>>::from_ssz_bytes(&block_bytes, &self.chain.spec)
|
||||
.expect("block bytes can be decoded");
|
||||
let block_contents =
|
||||
BlockContents::<E, FullPayload<E>>::from_ssz_bytes(&block_bytes, &self.chain.spec)
|
||||
.expect("block contents bytes can be decoded");
|
||||
|
||||
let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
let signed_block_contents =
|
||||
block_contents.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
|
||||
self.client
|
||||
.post_beacon_blocks_ssz(&signed_block)
|
||||
.post_beacon_blocks_ssz(&signed_block_contents)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(self.chain.head_beacon_block().as_ref(), &signed_block);
|
||||
assert_eq!(
|
||||
self.chain.head_beacon_block().as_ref(),
|
||||
signed_block_contents.signed_block()
|
||||
);
|
||||
|
||||
self.chain.slot_clock.set_slot(slot.as_u64() + 1);
|
||||
}
|
||||
@@ -2591,7 +2622,9 @@ impl ApiTester {
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
.data
|
||||
.deconstruct()
|
||||
.0;
|
||||
assert_eq!(block.slot(), slot);
|
||||
self.chain.slot_clock.set_slot(slot.as_u64() + 1);
|
||||
}
|
||||
@@ -2705,14 +2738,16 @@ impl ApiTester {
|
||||
.unwrap()
|
||||
.data;
|
||||
|
||||
let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
let signed_block_contents =
|
||||
block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
|
||||
self.client
|
||||
.post_beacon_blinded_blocks(&signed_block)
|
||||
.post_beacon_blinded_blocks(&signed_block_contents)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// This converts the generic `Payload` to a concrete type for comparison.
|
||||
let signed_block = signed_block_contents.deconstruct().0;
|
||||
let head_block = SignedBeaconBlock::from(signed_block.clone());
|
||||
assert_eq!(head_block, signed_block);
|
||||
|
||||
@@ -2758,24 +2793,29 @@ impl ApiTester {
|
||||
sk.sign(message).into()
|
||||
};
|
||||
|
||||
let block_bytes = self
|
||||
let block_contents_bytes = self
|
||||
.client
|
||||
.get_validator_blinded_blocks_ssz::<E, Payload>(slot, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.expect("block bytes");
|
||||
|
||||
let block = BeaconBlock::<E, Payload>::from_ssz_bytes(&block_bytes, &self.chain.spec)
|
||||
.expect("block bytes can be decoded");
|
||||
let block_contents = BlockContents::<E, Payload>::from_ssz_bytes(
|
||||
&block_contents_bytes,
|
||||
&self.chain.spec,
|
||||
)
|
||||
.expect("block contents bytes can be decoded");
|
||||
|
||||
let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
let signed_block_contents =
|
||||
block_contents.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
|
||||
|
||||
self.client
|
||||
.post_beacon_blinded_blocks_ssz(&signed_block)
|
||||
.post_beacon_blinded_blocks_ssz(&signed_block_contents)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// This converts the generic `Payload` to a concrete type for comparison.
|
||||
let signed_block = signed_block_contents.deconstruct().0;
|
||||
let head_block = SignedBeaconBlock::from(signed_block.clone());
|
||||
assert_eq!(head_block, signed_block);
|
||||
|
||||
@@ -2789,7 +2829,7 @@ impl ApiTester {
|
||||
for _ in 0..E::slots_per_epoch() {
|
||||
let slot = self.chain.slot().unwrap();
|
||||
|
||||
let block = self
|
||||
let block_contents = self
|
||||
.client
|
||||
.get_validator_blinded_blocks_modular::<E, Payload>(
|
||||
slot,
|
||||
@@ -2800,7 +2840,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
assert_eq!(block.slot(), slot);
|
||||
assert_eq!(block_contents.block().slot(), slot);
|
||||
self.chain.slot_clock.set_slot(slot.as_u64() + 1);
|
||||
}
|
||||
|
||||
@@ -3336,6 +3376,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3376,6 +3417,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3418,6 +3460,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3466,6 +3509,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3513,6 +3557,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3559,6 +3604,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3604,6 +3650,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3636,6 +3683,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3673,6 +3721,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3716,6 +3765,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3745,6 +3795,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3794,6 +3845,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3833,6 +3885,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3876,6 +3929,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3916,6 +3970,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3952,6 +4007,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -3988,6 +4044,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -4024,6 +4081,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -4050,19 +4108,6 @@ impl ApiTester {
|
||||
)));
|
||||
|
||||
let slot = self.chain.slot().unwrap();
|
||||
let propose_state = self
|
||||
.harness
|
||||
.chain
|
||||
.state_at_slot(slot, StateSkipConfig::WithoutStateRoots)
|
||||
.unwrap();
|
||||
let withdrawals = get_expected_withdrawals(&propose_state, &self.chain.spec).unwrap();
|
||||
let withdrawals_root = withdrawals.tree_hash_root();
|
||||
// Set withdrawals root for builder
|
||||
self.mock_builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.add_operation(Operation::WithdrawalsRoot(withdrawals_root));
|
||||
|
||||
let epoch = self.chain.epoch().unwrap();
|
||||
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
|
||||
|
||||
@@ -4072,6 +4117,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -4088,6 +4134,42 @@ impl ApiTester {
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_builder_works_post_deneb(self) -> Self {
|
||||
// Ensure builder payload is chosen
|
||||
self.mock_builder
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.add_operation(Operation::Value(Uint256::from(
|
||||
DEFAULT_MOCK_EL_PAYLOAD_VALUE_WEI + 1,
|
||||
)));
|
||||
|
||||
let slot = self.chain.slot().unwrap();
|
||||
let epoch = self.chain.epoch().unwrap();
|
||||
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
|
||||
|
||||
let block_contents = self
|
||||
.client
|
||||
.get_validator_blinded_blocks::<E, BlindedPayload<E>>(slot, &randao_reveal, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
let (block, maybe_sidecars) = block_contents.deconstruct();
|
||||
|
||||
// Response should contain blob sidecars
|
||||
assert!(maybe_sidecars.is_some());
|
||||
|
||||
// The builder's payload should've been chosen, so this cache should not be populated
|
||||
let payload: BlindedPayload<E> = block.body().execution_payload().unwrap().into();
|
||||
assert!(self
|
||||
.chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_payload_by_root(&payload.tree_hash_root())
|
||||
.is_none());
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_lighthouse_rejects_invalid_withdrawals_root(self) -> Self {
|
||||
// Ensure builder payload *would be* chosen
|
||||
self.mock_builder
|
||||
@@ -4112,6 +4194,7 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.block()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
@@ -4367,12 +4450,12 @@ impl ApiTester {
|
||||
|
||||
// Submit the next block, which is on an epoch boundary, so this will produce a finalized
|
||||
// checkpoint event, head event, and block event
|
||||
let block_root = self.next_block.canonical_root();
|
||||
let block_root = self.next_block.signed_block().canonical_root();
|
||||
|
||||
// current_duty_dependent_root = block root because this is the first slot of the epoch
|
||||
let current_duty_dependent_root = self.chain.head_beacon_block_root();
|
||||
let current_slot = self.chain.slot().unwrap();
|
||||
let next_slot = self.next_block.slot();
|
||||
let next_slot = self.next_block.signed_block().slot();
|
||||
let finalization_distance = E::slots_per_epoch() * 2;
|
||||
|
||||
let expected_block = EventKind::Block(SseBlock {
|
||||
@@ -4384,7 +4467,7 @@ impl ApiTester {
|
||||
let expected_head = EventKind::Head(SseHead {
|
||||
block: block_root,
|
||||
slot: next_slot,
|
||||
state: self.next_block.state_root(),
|
||||
state: self.next_block.signed_block().state_root(),
|
||||
current_duty_dependent_root,
|
||||
previous_duty_dependent_root: self
|
||||
.chain
|
||||
@@ -4433,13 +4516,17 @@ impl ApiTester {
|
||||
.unwrap();
|
||||
|
||||
let expected_reorg = EventKind::ChainReorg(SseChainReorg {
|
||||
slot: self.reorg_block.slot(),
|
||||
slot: self.reorg_block.signed_block().slot(),
|
||||
depth: 1,
|
||||
old_head_block: self.next_block.canonical_root(),
|
||||
old_head_state: self.next_block.state_root(),
|
||||
new_head_block: self.reorg_block.canonical_root(),
|
||||
new_head_state: self.reorg_block.state_root(),
|
||||
epoch: self.next_block.slot().epoch(E::slots_per_epoch()),
|
||||
old_head_block: self.next_block.signed_block().canonical_root(),
|
||||
old_head_state: self.next_block.signed_block().state_root(),
|
||||
new_head_block: self.reorg_block.signed_block().canonical_root(),
|
||||
new_head_state: self.reorg_block.signed_block().state_root(),
|
||||
epoch: self
|
||||
.next_block
|
||||
.signed_block()
|
||||
.slot()
|
||||
.epoch(E::slots_per_epoch()),
|
||||
execution_optimistic: false,
|
||||
});
|
||||
|
||||
@@ -4569,8 +4656,8 @@ impl ApiTester {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let block_root = self.next_block.canonical_root();
|
||||
let next_slot = self.next_block.slot();
|
||||
let block_root = self.next_block.signed_block().canonical_root();
|
||||
let next_slot = self.next_block.signed_block().slot();
|
||||
|
||||
let expected_block = EventKind::Block(SseBlock {
|
||||
block: block_root,
|
||||
@@ -4581,7 +4668,7 @@ impl ApiTester {
|
||||
let expected_head = EventKind::Head(SseHead {
|
||||
block: block_root,
|
||||
slot: next_slot,
|
||||
state: self.next_block.state_root(),
|
||||
state: self.next_block.signed_block().state_root(),
|
||||
current_duty_dependent_root: self.chain.genesis_block_root,
|
||||
previous_duty_dependent_root: self.chain.genesis_block_root,
|
||||
epoch_transition: false,
|
||||
@@ -5284,6 +5371,26 @@ async fn builder_works_post_capella() {
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn builder_works_post_deneb() {
|
||||
let mut config = ApiTesterConfig {
|
||||
builder_threshold: Some(0),
|
||||
retain_historic_states: false,
|
||||
spec: E::default_spec(),
|
||||
};
|
||||
config.spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||
config.spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||
config.spec.capella_fork_epoch = Some(Epoch::new(0));
|
||||
config.spec.deneb_fork_epoch = Some(Epoch::new(0));
|
||||
|
||||
ApiTester::new_from_config(config)
|
||||
.await
|
||||
.test_post_validator_register_validator()
|
||||
.await
|
||||
.test_builder_works_post_deneb()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn post_validator_liveness_epoch() {
|
||||
ApiTester::new()
|
||||
|
||||
Reference in New Issue
Block a user