mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-29 20:27:14 +00:00
Add tests for importing blocks on invalid parents (#3123)
## Issue Addressed NA ## Proposed Changes - Adds more checks to prevent importing blocks atop parent with invalid execution payloads. - Adds a test for these conditions. ## Additional Info NA
This commit is contained in:
@@ -8,8 +8,10 @@ use beacon_chain::{
|
||||
use execution_layer::{
|
||||
json_structures::JsonPayloadAttributesV1, ExecutionLayer, PayloadAttributes,
|
||||
};
|
||||
use proto_array::ExecutionStatus;
|
||||
use fork_choice::{Error as ForkChoiceError, InvalidationOperation, PayloadVerificationStatus};
|
||||
use proto_array::{Error as ProtoArrayError, ExecutionStatus};
|
||||
use slot_clock::SlotClock;
|
||||
use std::time::Duration;
|
||||
use task_executor::ShutdownReason;
|
||||
use types::*;
|
||||
|
||||
@@ -233,6 +235,13 @@ impl InvalidPayloadRig {
|
||||
|
||||
block_root
|
||||
}
|
||||
|
||||
fn invalidate_manually(&self, block_root: Hash256) {
|
||||
self.harness
|
||||
.chain
|
||||
.process_invalid_execution_payload(&InvalidationOperation::InvalidateOne { block_root })
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple test of the different import types.
|
||||
@@ -693,3 +702,66 @@ fn payload_preparation() {
|
||||
};
|
||||
assert_eq!(rig.previous_payload_attributes(), payload_attributes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_parent() {
|
||||
let mut rig = InvalidPayloadRig::new();
|
||||
rig.move_to_terminal_block();
|
||||
rig.import_block(Payload::Valid); // Import a valid transition block.
|
||||
|
||||
// Import a syncing block atop the transition block (we'll call this the "parent block" since we
|
||||
// build another block on it later).
|
||||
let parent_root = rig.import_block(Payload::Syncing);
|
||||
let parent_block = rig.harness.get_block(parent_root.into()).unwrap();
|
||||
let parent_state = rig
|
||||
.harness
|
||||
.get_hot_state(parent_block.state_root().into())
|
||||
.unwrap();
|
||||
|
||||
// Produce another block atop the parent, but don't import yet.
|
||||
let slot = parent_block.slot() + 1;
|
||||
rig.harness.set_current_slot(slot);
|
||||
let (block, state) = rig.harness.make_block(parent_state, slot);
|
||||
let block_root = block.canonical_root();
|
||||
assert_eq!(block.parent_root(), parent_root);
|
||||
|
||||
// Invalidate the parent block.
|
||||
rig.invalidate_manually(parent_root);
|
||||
assert!(rig.execution_status(parent_root).is_invalid());
|
||||
|
||||
// Ensure the block built atop an invalid payload is invalid for gossip.
|
||||
assert!(matches!(
|
||||
rig.harness.chain.verify_block_for_gossip(block.clone()),
|
||||
Err(BlockError::ParentExecutionPayloadInvalid { parent_root: invalid_root })
|
||||
if invalid_root == parent_root
|
||||
));
|
||||
|
||||
// Ensure the block built atop an invalid payload is invalid for import.
|
||||
assert!(matches!(
|
||||
rig.harness.chain.process_block(block.clone()),
|
||||
Err(BlockError::ParentExecutionPayloadInvalid { parent_root: invalid_root })
|
||||
if invalid_root == parent_root
|
||||
));
|
||||
|
||||
// Ensure the block built atop an invalid payload cannot be imported to fork choice.
|
||||
let (block, _block_signature) = block.deconstruct();
|
||||
assert!(matches!(
|
||||
rig.harness.chain.fork_choice.write().on_block(
|
||||
slot,
|
||||
&block,
|
||||
block_root,
|
||||
Duration::from_secs(0),
|
||||
&state,
|
||||
PayloadVerificationStatus::NotVerified,
|
||||
&rig.harness.chain.spec
|
||||
),
|
||||
Err(ForkChoiceError::ProtoArrayError(message))
|
||||
if message.contains(&format!(
|
||||
"{:?}",
|
||||
ProtoArrayError::ParentExecutionStatusIsInvalid {
|
||||
block_root,
|
||||
parent_root
|
||||
}
|
||||
))
|
||||
));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user