diff --git a/beacon_chain/validation/src/block_validation.rs b/beacon_chain/validation/src/block_validation.rs index 3c3b828ed..08aae7c0e 100644 --- a/beacon_chain/validation/src/block_validation.rs +++ b/beacon_chain/validation/src/block_validation.rs @@ -53,6 +53,7 @@ pub enum SszBlockValidationError { UnknownPoWChainRef, UnknownParentHash, BadAttestationSsz, + ParentSlotHigherThanBlockSlot, AttestationValidationError(AttestationValidationError), AttestationSignatureFailed, ProposerAttestationHasObliqueHashes, @@ -204,6 +205,15 @@ impl BlockValidationContext } }; + /* + * The parent block slot must be less than the block slot. + * + * In other words, the parent must come before the child. + */ + if parent_block_slot >= block_slot { + return Err(SszBlockValidationError::ParentSlotHigherThanBlockSlot); + } + /* * Generate the context in which attestations will be validated. */ diff --git a/beacon_chain/validation/tests/block_validation/tests.rs b/beacon_chain/validation/tests/block_validation/tests.rs index 9e16756ec..3046998a9 100644 --- a/beacon_chain/validation/tests/block_validation/tests.rs +++ b/beacon_chain/validation/tests/block_validation/tests.rs @@ -94,6 +94,22 @@ fn test_block_validation_valid_known_block() { assert_eq!(status.unwrap(), (BlockStatus::KnownBlock, None)); } +#[test] +fn test_block_validation_parent_slot_too_high() { + let params = get_simple_params(); + + let mutator = |mut block: Block, attester_map, proposer_map, stores| { + block.slot_number = params.validation_context_justified_slot + 1; + (block, attester_map, proposer_map, stores) + }; + + let status = run_block_validation_scenario( + ¶ms, + mutator); + + assert_eq!(status, Err(SszBlockValidationError::ParentSlotHigherThanBlockSlot)); +} + #[test] fn test_block_validation_invalid_future_slot() { let params = get_simple_params();