diff --git a/anchor/message_validator/src/consensus_message.rs b/anchor/message_validator/src/consensus_message.rs index e4a3d3196..54475db2e 100644 --- a/anchor/message_validator/src/consensus_message.rs +++ b/anchor/message_validator/src/consensus_message.rs @@ -142,7 +142,7 @@ pub(crate) fn validate_consensus_message_semantics( }); } - validate_justifications(consensus_message, operator_pub_keys)?; + validate_justifications(consensus_message, operator_pub_keys, true)?; Ok(()) } @@ -150,6 +150,7 @@ pub(crate) fn validate_consensus_message_semantics( pub(crate) fn validate_justifications( consensus_message: &QbftMessage, operator_pub_keys: &HashMap>, + check_inner_justifications: bool, ) -> Result<(), ValidationFailure> { // Rule: Can only exist for Proposal messages let prepare_justifications = &consensus_message.prepare_justification; @@ -172,7 +173,17 @@ pub(crate) fn validate_justifications( .iter() .chain(round_change_justifications.iter()) .try_for_each(|signed_message| { - verify_message_signatures(signed_message, operator_pub_keys) + verify_message_signatures(signed_message, operator_pub_keys)?; + // Also check the justifications' justifications + if check_inner_justifications { + validate_justifications( + &QbftMessage::from_ssz_bytes(signed_message.ssv_message().data()) + .map_err(|_| ValidationFailure::MalformedJustifications)?, + operator_pub_keys, + false, + )?; + } + Ok(()) })?; Ok(()) diff --git a/anchor/message_validator/src/lib.rs b/anchor/message_validator/src/lib.rs index 1dba027ad..b84cf8a30 100644 --- a/anchor/message_validator/src/lib.rs +++ b/anchor/message_validator/src/lib.rs @@ -153,9 +153,8 @@ pub enum ValidationFailure { want: usize, }, DifferentProposalData, - MalformedPrepareJustifications, + MalformedJustifications, UnexpectedPrepareJustifications, - MalformedRoundChangeJustifications, UnexpectedRoundChangeJustifications, NoPartialSignatureMessages, NoValidators,