diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs index 5fa20fc2f6645..960ab3140d7c0 100644 --- a/core/finality-grandpa/src/import.rs +++ b/core/finality-grandpa/src/import.rs @@ -546,8 +546,9 @@ impl, RA, PRA> GrandpaBlockImport Result<(), ConsensusError> { - let justification = GrandpaJustification::decode_and_verify( + let justification = GrandpaJustification::decode_and_verify_finalizes( justification, + (hash, number), self.authority_set.set_id(), &self.authority_set.current_authorities(), ); diff --git a/core/finality-grandpa/src/justification.rs b/core/finality-grandpa/src/justification.rs index d837e6a30862e..dce05296a8d20 100644 --- a/core/finality-grandpa/src/justification.rs +++ b/core/finality-grandpa/src/justification.rs @@ -93,18 +93,26 @@ impl> GrandpaJustification { } /// Decode a GRANDPA justification and validate the commit and the votes' - /// ancestry proofs. - pub(crate) fn decode_and_verify( + /// ancestry proofs finalize the given block. + pub(crate) fn decode_and_verify_finalizes( encoded: Vec, + finalized_target: (Block::Hash, NumberFor), set_id: u64, voters: &VoterSet, ) -> Result, ClientError> where NumberFor: grandpa::BlockNumberOps, { - GrandpaJustification::::decode(&mut &*encoded).ok_or_else(|| { + let justification = GrandpaJustification::::decode(&mut &*encoded).ok_or_else(|| { let msg = "failed to decode grandpa justification".to_string(); - ClientErrorKind::BadJustification(msg).into() - }).and_then(|just| just.verify(set_id, voters).map(|_| just)) + ClientError::from(ClientErrorKind::BadJustification(msg)) + })?; + + if (justification.commit.target_hash, justification.commit.target_number) != finalized_target { + let msg = "invalid commit target in grandpa justification".to_string(); + Err(ClientErrorKind::BadJustification(msg).into()) + } else { + justification.verify(set_id, voters).map(|_| justification) + } } /// Validate the commit and the votes' ancestry proofs.