{
+ match self {
+ EquivocationEvidenceFor::DoubleVotingProof(equivocation_proof, _) => {
+ equivocation_proof.round_number()
+ },
+ EquivocationEvidenceFor::ForkVotingProof(equivocation_proof, _) => {
+ &equivocation_proof.vote.commitment.block_number
+ },
+ EquivocationEvidenceFor::FutureBlockVotingProof(equivocation_proof, _) => {
+ &equivocation_proof.vote.commitment.block_number
+ },
+ }
+ }
+
+ /// Returns the set id at which the equivocation occurred.
+ fn set_id(&self) -> ValidatorSetId {
+ match self {
+ EquivocationEvidenceFor::DoubleVotingProof(equivocation_proof, _) => {
+ equivocation_proof.set_id()
+ },
+ EquivocationEvidenceFor::ForkVotingProof(equivocation_proof, _) => {
+ equivocation_proof.vote.commitment.validator_set_id
+ },
+ EquivocationEvidenceFor::FutureBlockVotingProof(equivocation_proof, _) => {
+ equivocation_proof.vote.commitment.validator_set_id
+ },
+ }
+ }
+
+ /// Returns the set id at which the equivocation occurred.
+ fn key_owner_proof(&self) -> &T::KeyOwnerProof {
+ match self {
+ EquivocationEvidenceFor::DoubleVotingProof(_, key_owner_proof) => key_owner_proof,
+ EquivocationEvidenceFor::ForkVotingProof(_, key_owner_proof) => key_owner_proof,
+ EquivocationEvidenceFor::FutureBlockVotingProof(_, key_owner_proof) => key_owner_proof,
+ }
+ }
+
+ fn checked_offender(&self) -> Option
+ where
+ P: KeyOwnerProofSystem<(KeyTypeId, T::BeefyId), Proof = T::KeyOwnerProof>,
+ {
+ let key = (BEEFY_KEY_TYPE, self.offender_id().clone());
+ P::check_proof(key, self.key_owner_proof().clone())
+ }
+
+ fn check_equivocation_proof(self) -> Result<(), Error> {
+ match self {
+ EquivocationEvidenceFor::DoubleVotingProof(equivocation_proof, _) => {
+ // Validate equivocation proof (check votes are different and signatures are valid).
+ if !sp_consensus_beefy_etf::check_double_voting_proof(&equivocation_proof) {
+ return Err(Error::::InvalidDoubleVotingProof);
+ }
+
+ return Ok(());
+ },
+ EquivocationEvidenceFor::ForkVotingProof(equivocation_proof, _) => {
+ let ForkVotingProof { vote, ancestry_proof, header } = equivocation_proof;
+
+ let maybe_validation_context = ,
+ >>::extract_validation_context(header);
+ let validation_context = match maybe_validation_context {
+ Some(validation_context) => validation_context,
+ None => {
+ return Err(Error::::InvalidForkVotingProof);
+ },
+ };
+
+ let is_non_canonical =
+ >>::is_non_canonical(
+ &vote.commitment,
+ ancestry_proof,
+ validation_context,
+ );
+ if !is_non_canonical {
+ return Err(Error::::InvalidForkVotingProof);
+ }
+
+ let is_signature_valid =
+ check_commitment_signature(&vote.commitment, &vote.id, &vote.signature);
+ if !is_signature_valid {
+ return Err(Error::::InvalidForkVotingProof);
+ }
+
+ Ok(())
+ },
+ EquivocationEvidenceFor::FutureBlockVotingProof(equivocation_proof, _) => {
+ let FutureBlockVotingProof { vote } = equivocation_proof;
+ // Check if the commitment actually targets a future block
+ if vote.commitment.block_number < frame_system::Pallet::::block_number() {
+ return Err(Error::::InvalidFutureBlockVotingProof);
+ }
+
+ let is_signature_valid =
+ check_commitment_signature(&vote.commitment, &vote.id, &vote.signature);
+ if !is_signature_valid {
+ return Err(Error::::InvalidForkVotingProof);
+ }
+
+ Ok(())
+ },
+ }
+ }
+}
impl OffenceReportSystem