mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-21 06:48:27 +00:00
Merge branch 'unstable' of github.com:sigp/lighthouse into gloas-fc-proto
This commit is contained in:
@@ -3,10 +3,10 @@
|
||||
use beacon_chain::block_verification_types::RpcBlock;
|
||||
use beacon_chain::{
|
||||
BeaconChainError, BlockError, ChainConfig, ExecutionPayloadError,
|
||||
INVALID_JUSTIFIED_PAYLOAD_SHUTDOWN_REASON, NotifyExecutionLayer, OverrideForkchoiceUpdate,
|
||||
StateSkipConfig, WhenSlotSkipped,
|
||||
INVALID_JUSTIFIED_PAYLOAD_SHUTDOWN_REASON, NotifyExecutionLayer, StateSkipConfig,
|
||||
WhenSlotSkipped,
|
||||
canonical_head::{CachedHead, CanonicalHead},
|
||||
test_utils::{BeaconChainHarness, EphemeralHarnessType, test_spec},
|
||||
test_utils::{BeaconChainHarness, EphemeralHarnessType, fork_name_from_env, test_spec},
|
||||
};
|
||||
use execution_layer::{
|
||||
ExecutionLayer, ForkchoiceState, PayloadAttributes,
|
||||
@@ -138,25 +138,6 @@ impl InvalidPayloadRig {
|
||||
payload_attributes
|
||||
}
|
||||
|
||||
fn move_to_terminal_block(&self) {
|
||||
let mock_execution_layer = self.harness.mock_execution_layer.as_ref().unwrap();
|
||||
mock_execution_layer
|
||||
.server
|
||||
.execution_block_generator()
|
||||
.move_to_terminal_block()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn latest_execution_block_hash(&self) -> ExecutionBlockHash {
|
||||
let mock_execution_layer = self.harness.mock_execution_layer.as_ref().unwrap();
|
||||
mock_execution_layer
|
||||
.server
|
||||
.execution_block_generator()
|
||||
.latest_execution_block()
|
||||
.unwrap()
|
||||
.block_hash
|
||||
}
|
||||
|
||||
async fn build_blocks(&mut self, num_blocks: u64, is_valid: Payload) -> Vec<Hash256> {
|
||||
let mut roots = Vec::with_capacity(num_blocks as usize);
|
||||
for _ in 0..num_blocks {
|
||||
@@ -389,8 +370,10 @@ impl InvalidPayloadRig {
|
||||
/// Simple test of the different import types.
|
||||
#[tokio::test]
|
||||
async fn valid_invalid_syncing() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new();
|
||||
rig.move_to_terminal_block();
|
||||
|
||||
rig.import_block(Payload::Valid).await;
|
||||
rig.import_block(Payload::Invalid {
|
||||
@@ -404,8 +387,10 @@ async fn valid_invalid_syncing() {
|
||||
/// `latest_valid_hash`.
|
||||
#[tokio::test]
|
||||
async fn invalid_payload_invalidates_parent() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
rig.move_to_first_justification(Payload::Syncing).await;
|
||||
|
||||
@@ -437,7 +422,6 @@ async fn immediate_forkchoice_update_invalid_test(
|
||||
invalid_payload: impl FnOnce(Option<ExecutionBlockHash>) -> Payload,
|
||||
) {
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
rig.move_to_first_justification(Payload::Syncing).await;
|
||||
|
||||
@@ -460,6 +444,9 @@ async fn immediate_forkchoice_update_invalid_test(
|
||||
|
||||
#[tokio::test]
|
||||
async fn immediate_forkchoice_update_payload_invalid() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
immediate_forkchoice_update_invalid_test(|latest_valid_hash| Payload::Invalid {
|
||||
latest_valid_hash,
|
||||
})
|
||||
@@ -468,11 +455,17 @@ async fn immediate_forkchoice_update_payload_invalid() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn immediate_forkchoice_update_payload_invalid_block_hash() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
immediate_forkchoice_update_invalid_test(|_| Payload::InvalidBlockHash).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn immediate_forkchoice_update_payload_invalid_terminal_block() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
immediate_forkchoice_update_invalid_test(|_| Payload::Invalid {
|
||||
latest_valid_hash: Some(ExecutionBlockHash::zero()),
|
||||
})
|
||||
@@ -482,8 +475,10 @@ async fn immediate_forkchoice_update_payload_invalid_terminal_block() {
|
||||
/// Ensure the client tries to exit when the justified checkpoint is invalidated.
|
||||
#[tokio::test]
|
||||
async fn justified_checkpoint_becomes_invalid() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
rig.move_to_first_justification(Payload::Syncing).await;
|
||||
|
||||
@@ -524,11 +519,13 @@ async fn justified_checkpoint_becomes_invalid() {
|
||||
/// Ensure that a `latest_valid_hash` for a pre-finality block only reverts a single block.
|
||||
#[tokio::test]
|
||||
async fn pre_finalized_latest_valid_hash() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let num_blocks = E::slots_per_epoch() * 4;
|
||||
let finalized_epoch = 2;
|
||||
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
let mut blocks = vec![];
|
||||
blocks.push(rig.import_block(Payload::Valid).await); // Import a valid transition block.
|
||||
blocks.extend(rig.build_blocks(num_blocks - 1, Payload::Syncing).await);
|
||||
@@ -571,10 +568,12 @@ async fn pre_finalized_latest_valid_hash() {
|
||||
/// - Will not validate `latest_valid_root` and its ancestors.
|
||||
#[tokio::test]
|
||||
async fn latest_valid_hash_will_not_validate() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
const LATEST_VALID_SLOT: u64 = 3;
|
||||
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
|
||||
let mut blocks = vec![];
|
||||
blocks.push(rig.import_block(Payload::Valid).await); // Import a valid transition block.
|
||||
@@ -618,11 +617,13 @@ async fn latest_valid_hash_will_not_validate() {
|
||||
/// Check behaviour when the `latest_valid_hash` is a junk value.
|
||||
#[tokio::test]
|
||||
async fn latest_valid_hash_is_junk() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let num_blocks = E::slots_per_epoch() * 5;
|
||||
let finalized_epoch = 3;
|
||||
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
let mut blocks = vec![];
|
||||
blocks.push(rig.import_block(Payload::Valid).await); // Import a valid transition block.
|
||||
blocks.extend(rig.build_blocks(num_blocks, Payload::Syncing).await);
|
||||
@@ -659,12 +660,14 @@ async fn latest_valid_hash_is_junk() {
|
||||
/// Check that descendants of invalid blocks are also invalidated.
|
||||
#[tokio::test]
|
||||
async fn invalidates_all_descendants() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let num_blocks = E::slots_per_epoch() * 4 + E::slots_per_epoch() / 2;
|
||||
let finalized_epoch = 2;
|
||||
let finalized_slot = E::slots_per_epoch() * 2;
|
||||
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
let blocks = rig.build_blocks(num_blocks, Payload::Syncing).await;
|
||||
|
||||
@@ -766,12 +769,14 @@ async fn invalidates_all_descendants() {
|
||||
/// Check that the head will switch after the canonical branch is invalidated.
|
||||
#[tokio::test]
|
||||
async fn switches_heads() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let num_blocks = E::slots_per_epoch() * 4 + E::slots_per_epoch() / 2;
|
||||
let finalized_epoch = 2;
|
||||
let finalized_slot = E::slots_per_epoch() * 2;
|
||||
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
let blocks = rig.build_blocks(num_blocks, Payload::Syncing).await;
|
||||
|
||||
@@ -869,8 +874,10 @@ async fn switches_heads() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_during_processing() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new();
|
||||
rig.move_to_terminal_block();
|
||||
|
||||
let roots = &[
|
||||
rig.import_block(Payload::Valid).await,
|
||||
@@ -901,8 +908,10 @@ async fn invalid_during_processing() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_after_optimistic_sync() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
let mut roots = vec![
|
||||
@@ -939,8 +948,10 @@ async fn invalid_after_optimistic_sync() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn manually_validate_child() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
let parent = rig.import_block(Payload::Syncing).await;
|
||||
@@ -957,8 +968,10 @@ async fn manually_validate_child() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn manually_validate_parent() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
let parent = rig.import_block(Payload::Syncing).await;
|
||||
@@ -975,8 +988,10 @@ async fn manually_validate_parent() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn payload_preparation() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await;
|
||||
|
||||
let el = rig.execution_layer();
|
||||
@@ -1036,8 +1051,10 @@ async fn payload_preparation() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn invalid_parent() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
// Import a syncing block atop the transition block (we'll call this the "parent block" since we
|
||||
@@ -1105,83 +1122,12 @@ async fn invalid_parent() {
|
||||
));
|
||||
}
|
||||
|
||||
/// Tests to ensure that we will still send a proposer preparation
|
||||
#[tokio::test]
|
||||
async fn payload_preparation_before_transition_block() {
|
||||
let rig = InvalidPayloadRig::new();
|
||||
let el = rig.execution_layer();
|
||||
|
||||
// Run the watchdog routine so that the status of the execution engine is set. This ensures
|
||||
// that we don't end up with `eth_syncing` requests later in this function that will impede
|
||||
// testing.
|
||||
el.watchdog_task().await;
|
||||
|
||||
let head = rig.harness.chain.head_snapshot();
|
||||
assert_eq!(
|
||||
head.beacon_block
|
||||
.message()
|
||||
.body()
|
||||
.execution_payload()
|
||||
.unwrap()
|
||||
.block_hash(),
|
||||
ExecutionBlockHash::zero(),
|
||||
"the head block is post-bellatrix but pre-transition"
|
||||
);
|
||||
|
||||
let current_slot = rig.harness.chain.slot().unwrap();
|
||||
let next_slot = current_slot + 1;
|
||||
let proposer = head
|
||||
.beacon_state
|
||||
.get_beacon_proposer_index(next_slot, &rig.harness.chain.spec)
|
||||
.unwrap();
|
||||
let fee_recipient = Address::repeat_byte(99);
|
||||
|
||||
// Provide preparation data to the EL for `proposer`.
|
||||
el.update_proposer_preparation(
|
||||
Epoch::new(0),
|
||||
[(
|
||||
&ProposerPreparationData {
|
||||
validator_index: proposer as u64,
|
||||
fee_recipient,
|
||||
},
|
||||
&None,
|
||||
)],
|
||||
)
|
||||
.await;
|
||||
|
||||
rig.move_to_terminal_block();
|
||||
|
||||
rig.harness
|
||||
.chain
|
||||
.prepare_beacon_proposer(current_slot)
|
||||
.await
|
||||
.unwrap();
|
||||
let forkchoice_update_params = rig
|
||||
.harness
|
||||
.chain
|
||||
.canonical_head
|
||||
.fork_choice_read_lock()
|
||||
.get_forkchoice_update_parameters();
|
||||
rig.harness
|
||||
.chain
|
||||
.update_execution_engine_forkchoice(
|
||||
current_slot,
|
||||
forkchoice_update_params,
|
||||
OverrideForkchoiceUpdate::Yes,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (fork_choice_state, payload_attributes) = rig.previous_forkchoice_update_params();
|
||||
let latest_block_hash = rig.latest_execution_block_hash();
|
||||
assert_eq!(payload_attributes.suggested_fee_recipient(), fee_recipient);
|
||||
assert_eq!(fork_choice_state.head_block_hash, latest_block_hash);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn attesting_to_optimistic_head() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
let root = rig.import_block(Payload::Syncing).await;
|
||||
@@ -1304,7 +1250,6 @@ impl InvalidHeadSetup {
|
||||
async fn new() -> InvalidHeadSetup {
|
||||
let slots_per_epoch = E::slots_per_epoch();
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
// Import blocks until the first time the chain finalizes. This avoids
|
||||
@@ -1392,6 +1337,9 @@ impl InvalidHeadSetup {
|
||||
|
||||
#[tokio::test]
|
||||
async fn recover_from_invalid_head_by_importing_blocks() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let InvalidHeadSetup {
|
||||
rig,
|
||||
fork_block,
|
||||
@@ -1437,6 +1385,9 @@ async fn recover_from_invalid_head_by_importing_blocks() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn recover_from_invalid_head_after_persist_and_reboot() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let InvalidHeadSetup {
|
||||
rig,
|
||||
fork_block: _,
|
||||
@@ -1479,8 +1430,10 @@ async fn recover_from_invalid_head_after_persist_and_reboot() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn weights_after_resetting_optimistic_status() {
|
||||
if fork_name_from_env().is_some_and(|f| !f.bellatrix_enabled()) {
|
||||
return;
|
||||
}
|
||||
let mut rig = InvalidPayloadRig::new().enable_attestations();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid).await; // Import a valid transition block.
|
||||
|
||||
let mut roots = vec![];
|
||||
|
||||
Reference in New Issue
Block a user