mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 19:02:42 +00:00
Fix duplicate proposer slashing bug (#1086)
Remove parallelism from proposer slashing verification. Closes #1065
This commit is contained in:
@@ -283,26 +283,25 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
||||
verify_signatures: VerifySignatures,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), BlockProcessingError> {
|
||||
// Verify proposer slashings in parallel.
|
||||
// Verify and apply proposer slashings in series.
|
||||
// We have to verify in series because an invalid block may contain multiple slashings
|
||||
// for the same validator, and we need to correctly detect and reject that.
|
||||
proposer_slashings
|
||||
.par_iter()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.try_for_each(|(i, proposer_slashing)| {
|
||||
verify_proposer_slashing(proposer_slashing, &state, verify_signatures, spec)
|
||||
.map_err(|e| e.into_with_index(i))
|
||||
})?;
|
||||
.map_err(|e| e.into_with_index(i))?;
|
||||
|
||||
// Update the state.
|
||||
for proposer_slashing in proposer_slashings {
|
||||
slash_validator(
|
||||
state,
|
||||
proposer_slashing.signed_header_1.message.proposer_index as usize,
|
||||
None,
|
||||
spec,
|
||||
)?;
|
||||
}
|
||||
slash_validator(
|
||||
state,
|
||||
proposer_slashing.signed_header_1.message.proposer_index as usize,
|
||||
None,
|
||||
spec,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Validates each `AttesterSlashing` and updates the state, short-circuiting on an invalid object.
|
||||
|
||||
@@ -1029,6 +1029,37 @@ fn invalid_proposer_slashing_not_slashable() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_proposer_slashing_duplicate_slashing() {
|
||||
let spec = MainnetEthSpec::default_spec();
|
||||
let builder = get_builder(&spec, SLOT_OFFSET, VALIDATOR_COUNT);
|
||||
let test_task = ProposerSlashingTestTask::Valid;
|
||||
let (mut block, mut state) =
|
||||
builder.build_with_proposer_slashing(test_task, 1, None, None, &spec);
|
||||
|
||||
let slashing = block.message.body.proposer_slashings[0].clone();
|
||||
let slashed_proposer = slashing.signed_header_1.message.proposer_index;
|
||||
block.message.body.proposer_slashings.push(slashing);
|
||||
|
||||
let result = per_block_processing(
|
||||
&mut state,
|
||||
&block,
|
||||
None,
|
||||
BlockSignatureStrategy::NoVerification,
|
||||
&spec,
|
||||
);
|
||||
|
||||
// Expecting ProposerNotSlashable for the 2nd slashing because the validator has been
|
||||
// slashed by the 1st slashing.
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(BlockProcessingError::ProposerSlashingInvalid {
|
||||
index: 1,
|
||||
reason: ProposerSlashingInvalid::ProposerNotSlashable(slashed_proposer)
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_bad_proposal_1_signature() {
|
||||
let spec = MainnetEthSpec::default_spec();
|
||||
|
||||
Reference in New Issue
Block a user