From b8593ccd1bddacc87a11559fe845db43b7f4ec6d Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 30 Apr 2024 16:42:50 +0300 Subject: [PATCH] BEEFY: Define basic fisherman (#4328) Related to https://github.com/paritytech/polkadot-sdk/pull/1903 For #1903 we will need to add a Fisherman struct. This PR: - defines a basic version of `Fisherman` and moves into it the logic that we have now for reporting double voting equivocations - splits the logic for generating the key ownership proofs into a more generic separate method - renames `EquivocationProof` to `DoubleVotingProof` since later we will introduce a new type of equivocation The PR doesn't contain any functional changes --- polkadot/node/service/src/fake_runtime_api.rs | 2 +- polkadot/runtime/rococo/src/lib.rs | 2 +- polkadot/runtime/test-runtime/src/lib.rs | 2 +- polkadot/runtime/westend/src/lib.rs | 2 +- substrate/bin/node/runtime/src/lib.rs | 2 +- substrate/client/consensus/beefy/Cargo.toml | 2 +- .../client/consensus/beefy/src/fisherman.rs | 162 ++++++++++++++++++ substrate/client/consensus/beefy/src/lib.rs | 19 +- substrate/client/consensus/beefy/src/round.rs | 10 +- substrate/client/consensus/beefy/src/tests.rs | 6 +- .../client/consensus/beefy/src/worker.rs | 93 +++------- substrate/frame/beefy/src/equivocation.rs | 4 +- substrate/frame/beefy/src/lib.rs | 8 +- .../primitives/consensus/beefy/src/lib.rs | 8 +- .../consensus/beefy/src/test_utils.rs | 6 +- 15 files changed, 225 insertions(+), 103 deletions(-) create mode 100644 substrate/client/consensus/beefy/src/fisherman.rs diff --git a/polkadot/node/service/src/fake_runtime_api.rs b/polkadot/node/service/src/fake_runtime_api.rs index c6cfb7a27d04..89613040dca1 100644 --- a/polkadot/node/service/src/fake_runtime_api.rs +++ b/polkadot/node/service/src/fake_runtime_api.rs @@ -242,7 +242,7 @@ sp_api::impl_runtime_apis! { } fn submit_report_equivocation_unsigned_extrinsic( - _: beefy_primitives::EquivocationProof< + _: beefy_primitives::DoubleVotingProof< BlockNumber, BeefyId, BeefySignature, diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 1cfe9adfe13d..287ae9937da4 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2018,7 +2018,7 @@ sp_api::impl_runtime_apis! { } fn submit_report_equivocation_unsigned_extrinsic( - equivocation_proof: beefy_primitives::EquivocationProof< + equivocation_proof: beefy_primitives::DoubleVotingProof< BlockNumber, BeefyId, BeefySignature, diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index d0f1ff0035fc..87becf73cb74 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -1009,7 +1009,7 @@ sp_api::impl_runtime_apis! { } fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: beefy_primitives::EquivocationProof< + _equivocation_proof: beefy_primitives::DoubleVotingProof< BlockNumber, BeefyId, BeefySignature, diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index de961bb4c398..7125f5d34c40 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1966,7 +1966,7 @@ sp_api::impl_runtime_apis! { } fn submit_report_equivocation_unsigned_extrinsic( - equivocation_proof: beefy_primitives::EquivocationProof< + equivocation_proof: beefy_primitives::DoubleVotingProof< BlockNumber, BeefyId, BeefySignature, diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 5d8016532a5d..18b0d0c31a4d 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -3053,7 +3053,7 @@ impl_runtime_apis! { } fn submit_report_equivocation_unsigned_extrinsic( - equivocation_proof: sp_consensus_beefy::EquivocationProof< + equivocation_proof: sp_consensus_beefy::DoubleVotingProof< BlockNumber, BeefyId, BeefySignature, diff --git a/substrate/client/consensus/beefy/Cargo.toml b/substrate/client/consensus/beefy/Cargo.toml index 7b61b3c6c01f..435604a9473b 100644 --- a/substrate/client/consensus/beefy/Cargo.toml +++ b/substrate/client/consensus/beefy/Cargo.toml @@ -39,7 +39,6 @@ sp-consensus-beefy = { path = "../../../primitives/consensus/beefy" } sp-core = { path = "../../../primitives/core" } sp-crypto-hashing = { path = "../../../primitives/crypto/hashing" } sp-keystore = { path = "../../../primitives/keystore" } -sp-mmr-primitives = { path = "../../../primitives/merkle-mountain-range" } sp-runtime = { path = "../../../primitives/runtime" } tokio = "1.37" @@ -51,6 +50,7 @@ sc-block-builder = { path = "../../block-builder" } sc-network-test = { path = "../../network/test" } sp-consensus-grandpa = { path = "../../../primitives/consensus/grandpa" } sp-keyring = { path = "../../../primitives/keyring" } +sp-mmr-primitives = { path = "../../../primitives/merkle-mountain-range" } sp-tracing = { path = "../../../primitives/tracing" } substrate-test-runtime-client = { path = "../../../test-utils/runtime/client" } diff --git a/substrate/client/consensus/beefy/src/fisherman.rs b/substrate/client/consensus/beefy/src/fisherman.rs new file mode 100644 index 000000000000..a2b4c8f945d1 --- /dev/null +++ b/substrate/client/consensus/beefy/src/fisherman.rs @@ -0,0 +1,162 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::{error::Error, keystore::BeefyKeystore, round::Rounds, LOG_TARGET}; +use log::{debug, error, warn}; +use sc_client_api::Backend; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_consensus_beefy::{ + check_equivocation_proof, + ecdsa_crypto::{AuthorityId, Signature}, + BeefyApi, BeefySignatureHasher, DoubleVotingProof, OpaqueKeyOwnershipProof, ValidatorSetId, +}; +use sp_runtime::{ + generic::BlockId, + traits::{Block, NumberFor}, +}; +use std::{marker::PhantomData, sync::Arc}; + +/// Helper struct containing the id and the key ownership proof for a validator. +pub struct ProvedValidator<'a> { + pub id: &'a AuthorityId, + pub key_owner_proof: OpaqueKeyOwnershipProof, +} + +/// Helper used to check and report equivocations. +pub struct Fisherman { + backend: Arc, + runtime: Arc, + key_store: Arc>, + + _phantom: PhantomData, +} + +impl, RuntimeApi: ProvideRuntimeApi> Fisherman +where + RuntimeApi::Api: BeefyApi, +{ + pub fn new( + backend: Arc, + runtime: Arc, + keystore: Arc>, + ) -> Self { + Self { backend, runtime, key_store: keystore, _phantom: Default::default() } + } + + fn prove_offenders<'a>( + &self, + at: BlockId, + offender_ids: impl Iterator, + validator_set_id: ValidatorSetId, + ) -> Result>, Error> { + let hash = match at { + BlockId::Hash(hash) => hash, + BlockId::Number(number) => self + .backend + .blockchain() + .expect_block_hash_from_id(&BlockId::Number(number)) + .map_err(|err| { + Error::Backend(format!( + "Couldn't get hash for block #{:?} (error: {:?}). \ + Skipping report for equivocation", + at, err + )) + })?, + }; + + let runtime_api = self.runtime.runtime_api(); + let mut proved_offenders = vec![]; + for offender_id in offender_ids { + match runtime_api.generate_key_ownership_proof( + hash, + validator_set_id, + offender_id.clone(), + ) { + Ok(Some(key_owner_proof)) => { + proved_offenders.push(ProvedValidator { id: offender_id, key_owner_proof }); + }, + Ok(None) => { + debug!( + target: LOG_TARGET, + "🥩 Equivocation offender {} not part of the authority set {}.", + offender_id, validator_set_id + ); + }, + Err(e) => { + error!( + target: LOG_TARGET, + "🥩 Error generating key ownership proof for equivocation offender {} \ + in authority set {}: {}", + offender_id, validator_set_id, e + ); + }, + }; + } + + Ok(proved_offenders) + } + + /// Report the given equivocation to the BEEFY runtime module. This method + /// generates a session membership proof of the offender and then submits an + /// extrinsic to report the equivocation. In particular, the session membership + /// proof must be generated at the block at which the given set was active which + /// isn't necessarily the best block if there are pending authority set changes. + pub fn report_double_voting( + &self, + proof: DoubleVotingProof, AuthorityId, Signature>, + active_rounds: &Rounds, + ) -> Result<(), Error> { + let (validators, validator_set_id) = + (active_rounds.validators(), active_rounds.validator_set_id()); + let offender_id = proof.offender_id(); + + if !check_equivocation_proof::<_, _, BeefySignatureHasher>(&proof) { + debug!(target: LOG_TARGET, "🥩 Skipping report for bad equivocation {:?}", proof); + return Ok(()) + } + + if let Some(local_id) = self.key_store.authority_id(validators) { + if offender_id == &local_id { + warn!(target: LOG_TARGET, "🥩 Skipping report for own equivocation"); + return Ok(()) + } + } + + let key_owner_proofs = self.prove_offenders( + BlockId::Number(*proof.round_number()), + vec![offender_id].into_iter(), + validator_set_id, + )?; + + // submit equivocation report at **best** block + let best_block_hash = self.backend.blockchain().info().best_hash; + for ProvedValidator { key_owner_proof, .. } in key_owner_proofs { + self.runtime + .runtime_api() + .submit_report_equivocation_unsigned_extrinsic( + best_block_hash, + proof.clone(), + key_owner_proof, + ) + .map_err(Error::RuntimeApi)?; + } + + Ok(()) + } +} diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs index 2637481fbf3e..0e49839f0fd2 100644 --- a/substrate/client/consensus/beefy/src/lib.rs +++ b/substrate/client/consensus/beefy/src/lib.rs @@ -43,11 +43,10 @@ use sp_api::ProvideRuntimeApi; use sp_blockchain::{Backend as BlockchainBackend, HeaderBackend}; use sp_consensus::{Error as ConsensusError, SyncOracle}; use sp_consensus_beefy::{ - ecdsa_crypto::AuthorityId, BeefyApi, ConsensusLog, MmrRootHash, PayloadProvider, ValidatorSet, + ecdsa_crypto::AuthorityId, BeefyApi, ConsensusLog, PayloadProvider, ValidatorSet, BEEFY_ENGINE_ID, }; use sp_keystore::KeystorePtr; -use sp_mmr_primitives::MmrApi; use sp_runtime::traits::{Block, Header as HeaderT, NumberFor, Zero}; use std::{ collections::{BTreeMap, VecDeque}, @@ -69,6 +68,7 @@ pub mod justification; use crate::{ communication::gossip::GossipValidator, + fisherman::Fisherman, justification::BeefyVersionedFinalityProof, keystore::BeefyKeystore, metrics::VoterMetrics, @@ -80,6 +80,7 @@ pub use communication::beefy_protocol_name::{ }; use sp_runtime::generic::OpaqueDigestItemId; +mod fisherman; #[cfg(test)] mod tests; @@ -305,14 +306,16 @@ where pending_justifications: BTreeMap, BeefyVersionedFinalityProof>, is_authority: bool, ) -> BeefyWorker { + let key_store = Arc::new(self.key_store); BeefyWorker { - backend: self.backend, - runtime: self.runtime, - key_store: self.key_store, - metrics: self.metrics, - persisted_state: self.persisted_state, + backend: self.backend.clone(), + runtime: self.runtime.clone(), + key_store: key_store.clone(), payload_provider, sync, + fisherman: Arc::new(Fisherman::new(self.backend, self.runtime, key_store)), + metrics: self.metrics, + persisted_state: self.persisted_state, comms, links, pending_justifications, @@ -487,7 +490,7 @@ pub async fn start_beefy_gadget( C: Client + BlockBackend, P: PayloadProvider + Clone, R: ProvideRuntimeApi, - R::Api: BeefyApi + MmrApi>, + R::Api: BeefyApi, N: GossipNetwork + NetworkRequest + Send + Sync + 'static, S: GossipSyncing + SyncOracle + 'static, { diff --git a/substrate/client/consensus/beefy/src/round.rs b/substrate/client/consensus/beefy/src/round.rs index 0045dc70c260..5dae80cb1830 100644 --- a/substrate/client/consensus/beefy/src/round.rs +++ b/substrate/client/consensus/beefy/src/round.rs @@ -22,7 +22,7 @@ use codec::{Decode, Encode}; use log::{debug, info}; use sp_consensus_beefy::{ ecdsa_crypto::{AuthorityId, Signature}, - Commitment, EquivocationProof, SignedCommitment, ValidatorSet, ValidatorSetId, VoteMessage, + Commitment, DoubleVotingProof, SignedCommitment, ValidatorSet, ValidatorSetId, VoteMessage, }; use sp_runtime::traits::{Block, NumberFor}; use std::collections::BTreeMap; @@ -61,7 +61,7 @@ pub fn threshold(authorities: usize) -> usize { pub enum VoteImportResult { Ok, RoundConcluded(SignedCommitment, Signature>), - Equivocation(EquivocationProof, AuthorityId, Signature>), + DoubleVoting(DoubleVotingProof, AuthorityId, Signature>), Invalid, Stale, } @@ -153,7 +153,7 @@ where target: LOG_TARGET, "🥩 detected equivocated vote: 1st: {:?}, 2nd: {:?}", previous_vote, vote ); - return VoteImportResult::Equivocation(EquivocationProof { + return VoteImportResult::DoubleVoting(DoubleVotingProof { first: previous_vote.clone(), second: vote, }) @@ -207,7 +207,7 @@ mod tests { use sc_network_test::Block; use sp_consensus_beefy::{ - known_payloads::MMR_ROOT_ID, test_utils::Keyring, Commitment, EquivocationProof, Payload, + known_payloads::MMR_ROOT_ID, test_utils::Keyring, Commitment, DoubleVotingProof, Payload, SignedCommitment, ValidatorSet, VoteMessage, }; @@ -494,7 +494,7 @@ mod tests { let mut alice_vote2 = alice_vote1.clone(); alice_vote2.commitment = commitment2; - let expected_result = VoteImportResult::Equivocation(EquivocationProof { + let expected_result = VoteImportResult::DoubleVoting(DoubleVotingProof { first: alice_vote1.clone(), second: alice_vote2.clone(), }); diff --git a/substrate/client/consensus/beefy/src/tests.rs b/substrate/client/consensus/beefy/src/tests.rs index 9b13d1da6d7d..2bb145d660df 100644 --- a/substrate/client/consensus/beefy/src/tests.rs +++ b/substrate/client/consensus/beefy/src/tests.rs @@ -59,7 +59,7 @@ use sp_consensus_beefy::{ known_payloads, mmr::{find_mmr_root_digest, MmrRootProvider}, test_utils::Keyring as BeefyKeyring, - BeefyApi, Commitment, ConsensusLog, EquivocationProof, MmrRootHash, OpaqueKeyOwnershipProof, + BeefyApi, Commitment, ConsensusLog, DoubleVotingProof, MmrRootHash, OpaqueKeyOwnershipProof, Payload, SignedCommitment, ValidatorSet, ValidatorSetId, VersionedFinalityProof, VoteMessage, BEEFY_ENGINE_ID, }; @@ -259,7 +259,7 @@ pub(crate) struct TestApi { pub validator_set: Option, pub mmr_root_hash: MmrRootHash, pub reported_equivocations: - Option, AuthorityId, Signature>>>>>, + Option, AuthorityId, Signature>>>>>, } impl TestApi { @@ -313,7 +313,7 @@ sp_api::mock_impl_runtime_apis! { } fn submit_report_equivocation_unsigned_extrinsic( - proof: EquivocationProof, AuthorityId, Signature>, + proof: DoubleVotingProof, AuthorityId, Signature>, _dummy: OpaqueKeyOwnershipProof, ) -> Option<()> { if let Some(equivocations_buf) = self.inner.reported_equivocations.as_ref() { diff --git a/substrate/client/consensus/beefy/src/worker.rs b/substrate/client/consensus/beefy/src/worker.rs index 05575ae01c30..cfbb3d63aea4 100644 --- a/substrate/client/consensus/beefy/src/worker.rs +++ b/substrate/client/consensus/beefy/src/worker.rs @@ -23,6 +23,7 @@ use crate::{ }, error::Error, find_authorities_change, + fisherman::Fisherman, justification::BeefyVersionedFinalityProof, keystore::BeefyKeystore, metric_inc, metric_set, @@ -39,10 +40,9 @@ use sp_api::ProvideRuntimeApi; use sp_arithmetic::traits::{AtLeast32Bit, Saturating}; use sp_consensus::SyncOracle; use sp_consensus_beefy::{ - check_equivocation_proof, ecdsa_crypto::{AuthorityId, Signature}, - BeefyApi, BeefySignatureHasher, Commitment, EquivocationProof, PayloadProvider, ValidatorSet, - VersionedFinalityProof, VoteMessage, BEEFY_ENGINE_ID, + BeefyApi, Commitment, DoubleVotingProof, PayloadProvider, ValidatorSet, VersionedFinalityProof, + VoteMessage, BEEFY_ENGINE_ID, }; use sp_runtime::{ generic::BlockId, @@ -377,9 +377,10 @@ pub(crate) struct BeefyWorker { // utilities pub backend: Arc, pub runtime: Arc, - pub key_store: BeefyKeystore, + pub key_store: Arc>, pub payload_provider: P, pub sync: Arc, + pub fisherman: Arc>, // communication (created once, but returned and reused if worker is restarted/reinitialized) pub comms: BeefyComms, @@ -590,9 +591,9 @@ where } metric_inc!(self.metrics, beefy_good_votes_processed); }, - VoteImportResult::Equivocation(proof) => { + VoteImportResult::DoubleVoting(proof) => { metric_inc!(self.metrics, beefy_equivocation_votes); - self.report_equivocation(proof)?; + self.report_double_voting(proof)?; }, VoteImportResult::Invalid => metric_inc!(self.metrics, beefy_invalid_votes), VoteImportResult::Stale => metric_inc!(self.metrics, beefy_stale_votes), @@ -941,64 +942,13 @@ where (error, self.comms) } - /// Report the given equivocation to the BEEFY runtime module. This method - /// generates a session membership proof of the offender and then submits an - /// extrinsic to report the equivocation. In particular, the session membership - /// proof must be generated at the block at which the given set was active which - /// isn't necessarily the best block if there are pending authority set changes. - pub(crate) fn report_equivocation( + /// Report the given equivocation to the BEEFY runtime module. + fn report_double_voting( &self, - proof: EquivocationProof, AuthorityId, Signature>, + proof: DoubleVotingProof, AuthorityId, Signature>, ) -> Result<(), Error> { let rounds = self.persisted_state.voting_oracle.active_rounds()?; - let (validators, validator_set_id) = (rounds.validators(), rounds.validator_set_id()); - let offender_id = proof.offender_id().clone(); - - if !check_equivocation_proof::<_, _, BeefySignatureHasher>(&proof) { - debug!(target: LOG_TARGET, "🥩 Skip report for bad equivocation {:?}", proof); - return Ok(()) - } else if let Some(local_id) = self.key_store.authority_id(validators) { - if offender_id == local_id { - warn!(target: LOG_TARGET, "🥩 Skip equivocation report for own equivocation"); - return Ok(()) - } - } - - let number = *proof.round_number(); - let hash = self - .backend - .blockchain() - .expect_block_hash_from_id(&BlockId::Number(number)) - .map_err(|err| { - let err_msg = format!( - "Couldn't get hash for block #{:?} (error: {:?}), skipping report for equivocation", - number, err - ); - Error::Backend(err_msg) - })?; - let runtime_api = self.runtime.runtime_api(); - // generate key ownership proof at that block - let key_owner_proof = match runtime_api - .generate_key_ownership_proof(hash, validator_set_id, offender_id) - .map_err(Error::RuntimeApi)? - { - Some(proof) => proof, - None => { - debug!( - target: LOG_TARGET, - "🥩 Equivocation offender not part of the authority set." - ); - return Ok(()) - }, - }; - - // submit equivocation report at **best** block - let best_block_hash = self.backend.blockchain().info().best_hash; - runtime_api - .submit_report_equivocation_unsigned_extrinsic(best_block_hash, proof, key_owner_proof) - .map_err(Error::RuntimeApi)?; - - Ok(()) + self.fisherman.report_double_voting(proof, rounds) } } @@ -1165,13 +1115,15 @@ pub(crate) mod tests { .unwrap(); let payload_provider = MmrRootProvider::new(api.clone()); let comms = BeefyComms { gossip_engine, gossip_validator, on_demand_justifications }; + let key_store: Arc> = Arc::new(Some(keystore).into()); BeefyWorker { - backend, - runtime: api, - key_store: Some(keystore).into(), + backend: backend.clone(), + runtime: api.clone(), + key_store: key_store.clone(), metrics, payload_provider, sync: Arc::new(sync), + fisherman: Arc::new(Fisherman::new(backend, api, key_store)), links, comms, pending_justifications: BTreeMap::new(), @@ -1590,6 +1542,11 @@ pub(crate) mod tests { let mut net = BeefyTestNet::new(1); let mut worker = create_beefy_worker(net.peer(0), &keys[0], 1, validator_set.clone()); worker.runtime = api_alice.clone(); + worker.fisherman = Arc::new(Fisherman::new( + worker.backend.clone(), + worker.runtime.clone(), + worker.key_store.clone(), + )); // let there be a block with num = 1: let _ = net.peer(0).push_blocks(1, false); @@ -1604,7 +1561,7 @@ pub(crate) mod tests { ); { // expect voter (Alice) to successfully report it - assert_eq!(worker.report_equivocation(good_proof.clone()), Ok(())); + assert_eq!(worker.report_double_voting(good_proof.clone()), Ok(())); // verify Alice reports Bob equivocation to runtime let reported = api_alice.reported_equivocations.as_ref().unwrap().lock(); assert_eq!(reported.len(), 1); @@ -1616,7 +1573,7 @@ pub(crate) mod tests { let mut bad_proof = good_proof.clone(); bad_proof.first.id = Keyring::Charlie.public(); // bad proofs are simply ignored - assert_eq!(worker.report_equivocation(bad_proof), Ok(())); + assert_eq!(worker.report_double_voting(bad_proof), Ok(())); // verify nothing reported to runtime assert!(api_alice.reported_equivocations.as_ref().unwrap().lock().is_empty()); @@ -1625,7 +1582,7 @@ pub(crate) mod tests { old_proof.first.commitment.validator_set_id = 0; old_proof.second.commitment.validator_set_id = 0; // old proofs are simply ignored - assert_eq!(worker.report_equivocation(old_proof), Ok(())); + assert_eq!(worker.report_double_voting(old_proof), Ok(())); // verify nothing reported to runtime assert!(api_alice.reported_equivocations.as_ref().unwrap().lock().is_empty()); @@ -1635,7 +1592,7 @@ pub(crate) mod tests { (block_num, payload2.clone(), set_id, &Keyring::Alice), ); // equivocations done by 'self' are simply ignored (not reported) - assert_eq!(worker.report_equivocation(self_proof), Ok(())); + assert_eq!(worker.report_double_voting(self_proof), Ok(())); // verify nothing reported to runtime assert!(api_alice.reported_equivocations.as_ref().unwrap().lock().is_empty()); } diff --git a/substrate/frame/beefy/src/equivocation.rs b/substrate/frame/beefy/src/equivocation.rs index bbc6eae6af29..aecc9e721d5c 100644 --- a/substrate/frame/beefy/src/equivocation.rs +++ b/substrate/frame/beefy/src/equivocation.rs @@ -38,7 +38,7 @@ use codec::{self as codec, Decode, Encode}; use frame_support::traits::{Get, KeyOwnerProofSystem}; use frame_system::pallet_prelude::BlockNumberFor; use log::{error, info}; -use sp_consensus_beefy::{EquivocationProof, ValidatorSetId, KEY_TYPE as BEEFY_KEY_TYPE}; +use sp_consensus_beefy::{DoubleVotingProof, ValidatorSetId, KEY_TYPE as BEEFY_KEY_TYPE}; use sp_runtime::{ transaction_validity::{ InvalidTransaction, TransactionPriority, TransactionSource, TransactionValidity, @@ -123,7 +123,7 @@ pub struct EquivocationReportSystem(sp_std::marker::PhantomData<(T, /// Equivocation evidence convenience alias. pub type EquivocationEvidenceFor = ( - EquivocationProof< + DoubleVotingProof< BlockNumberFor, ::BeefyId, <::BeefyId as RuntimeAppPublic>::Signature, diff --git a/substrate/frame/beefy/src/lib.rs b/substrate/frame/beefy/src/lib.rs index 09cd13ab70a4..63f3e9bb309c 100644 --- a/substrate/frame/beefy/src/lib.rs +++ b/substrate/frame/beefy/src/lib.rs @@ -41,7 +41,7 @@ use sp_staking::{offence::OffenceReportSystem, SessionIndex}; use sp_std::prelude::*; use sp_consensus_beefy::{ - AuthorityIndex, BeefyAuthorityId, ConsensusLog, EquivocationProof, OnNewValidatorSet, + AuthorityIndex, BeefyAuthorityId, ConsensusLog, DoubleVotingProof, OnNewValidatorSet, ValidatorSet, BEEFY_ENGINE_ID, GENESIS_AUTHORITY_SET_ID, }; @@ -210,7 +210,7 @@ pub mod pallet { pub fn report_equivocation( origin: OriginFor, equivocation_proof: Box< - EquivocationProof< + DoubleVotingProof< BlockNumberFor, T::BeefyId, ::Signature, @@ -245,7 +245,7 @@ pub mod pallet { pub fn report_equivocation_unsigned( origin: OriginFor, equivocation_proof: Box< - EquivocationProof< + DoubleVotingProof< BlockNumberFor, T::BeefyId, ::Signature, @@ -368,7 +368,7 @@ impl Pallet { /// an unsigned extrinsic with a call to `report_equivocation_unsigned` and /// will push the transaction to the pool. Only useful in an offchain context. pub fn submit_unsigned_equivocation_report( - equivocation_proof: EquivocationProof< + equivocation_proof: DoubleVotingProof< BlockNumberFor, T::BeefyId, ::Signature, diff --git a/substrate/primitives/consensus/beefy/src/lib.rs b/substrate/primitives/consensus/beefy/src/lib.rs index 6f644c5f790d..390c0ff71273 100644 --- a/substrate/primitives/consensus/beefy/src/lib.rs +++ b/substrate/primitives/consensus/beefy/src/lib.rs @@ -306,14 +306,14 @@ pub struct VoteMessage { /// BEEFY happens when a voter votes on the same round/block for different payloads. /// Proving is achieved by collecting the signed commitments of conflicting votes. #[derive(Clone, Debug, Decode, Encode, PartialEq, TypeInfo)] -pub struct EquivocationProof { +pub struct DoubleVotingProof { /// The first vote in the equivocation. pub first: VoteMessage, /// The second vote in the equivocation. pub second: VoteMessage, } -impl EquivocationProof { +impl DoubleVotingProof { /// Returns the authority id of the equivocator. pub fn offender_id(&self) -> &Id { &self.first.id @@ -347,7 +347,7 @@ where /// Verifies the equivocation proof by making sure that both votes target /// different blocks and that its signatures are valid. pub fn check_equivocation_proof( - report: &EquivocationProof::Signature>, + report: &DoubleVotingProof::Signature>, ) -> bool where Id: BeefyAuthorityId + PartialEq, @@ -437,7 +437,7 @@ sp_api::decl_runtime_apis! { /// hardcoded to return `None`). Only useful in an offchain context. fn submit_report_equivocation_unsigned_extrinsic( equivocation_proof: - EquivocationProof, AuthorityId, ::Signature>, + DoubleVotingProof, AuthorityId, ::Signature>, key_owner_proof: OpaqueKeyOwnershipProof, ) -> Option<()>; diff --git a/substrate/primitives/consensus/beefy/src/test_utils.rs b/substrate/primitives/consensus/beefy/src/test_utils.rs index ec13c9c69004..d7fd49214f12 100644 --- a/substrate/primitives/consensus/beefy/src/test_utils.rs +++ b/substrate/primitives/consensus/beefy/src/test_utils.rs @@ -18,7 +18,7 @@ #[cfg(feature = "bls-experimental")] use crate::ecdsa_bls_crypto; use crate::{ - ecdsa_crypto, AuthorityIdBound, BeefySignatureHasher, Commitment, EquivocationProof, Payload, + ecdsa_crypto, AuthorityIdBound, BeefySignatureHasher, Commitment, DoubleVotingProof, Payload, ValidatorSetId, VoteMessage, }; use sp_application_crypto::{AppCrypto, AppPair, RuntimeAppPublic, Wraps}; @@ -140,7 +140,7 @@ impl From> for ecdsa_crypto::Public { pub fn generate_equivocation_proof( vote1: (u64, Payload, ValidatorSetId, &Keyring), vote2: (u64, Payload, ValidatorSetId, &Keyring), -) -> EquivocationProof { +) -> DoubleVotingProof { let signed_vote = |block_number: u64, payload: Payload, validator_set_id: ValidatorSetId, @@ -151,5 +151,5 @@ pub fn generate_equivocation_proof( }; let first = signed_vote(vote1.0, vote1.1, vote1.2, vote1.3); let second = signed_vote(vote2.0, vote2.1, vote2.2, vote2.3); - EquivocationProof { first, second } + DoubleVotingProof { first, second } }