Skip to content

Commit

Permalink
Beefy equivocation: add runtime API methods (#4993)
Browse files Browse the repository at this point in the history
Related to #4523

Add runtime API methods for:
- generating the ancestry proof
- submiting a fork voting report
- submitting a future voting report
  • Loading branch information
serban300 authored Jul 23, 2024
1 parent 6d0926e commit 216e8fa
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 6 deletions.
25 changes: 25 additions & 0 deletions polkadot/node/service/src/fake_runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,37 @@ sp_api::impl_runtime_apis! {
unimplemented!()
}

fn submit_report_fork_voting_unsigned_extrinsic(
_: sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
_: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
unimplemented!()
}

fn submit_report_future_block_voting_unsigned_extrinsic(
_: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
_: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
unimplemented!()
}

fn generate_key_ownership_proof(
_: sp_consensus_beefy::ValidatorSetId,
_: BeefyId,
) -> Option<sp_consensus_beefy::OpaqueKeyOwnershipProof> {
unimplemented!()
}

fn generate_ancestry_proof(
_: BlockNumber,
_: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
unimplemented!()
}
}

impl sp_mmr_primitives::MmrApi<Block, Hash, BlockNumber> for Runtime {
Expand Down
38 changes: 37 additions & 1 deletion polkadot/runtime/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2054,7 +2054,7 @@ sp_api::impl_runtime_apis! {
}
}

#[api_version(4)]
#[api_version(5)]
impl sp_consensus_beefy::BeefyApi<Block, BeefyId> for Runtime {
fn beefy_genesis() -> Option<BlockNumber> {
pallet_beefy::GenesisBlock::<Runtime>::get()
Expand All @@ -2080,6 +2080,31 @@ sp_api::impl_runtime_apis! {
)
}

fn submit_report_fork_voting_unsigned_extrinsic(
equivocation_proof:
sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_fork_voting_report(
equivocation_proof.try_into()?,
key_owner_proof.decode()?,
)
}

fn submit_report_future_block_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_future_block_voting_report(
equivocation_proof,
key_owner_proof.decode()?,
)
}

fn generate_key_ownership_proof(
_set_id: sp_consensus_beefy::ValidatorSetId,
authority_id: BeefyId,
Expand All @@ -2090,6 +2115,17 @@ sp_api::impl_runtime_apis! {
.map(|p| p.encode())
.map(sp_consensus_beefy::OpaqueKeyOwnershipProof::new)
}

fn generate_ancestry_proof(
prev_block_number: BlockNumber,
best_known_block_number: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
use sp_consensus_beefy::AncestryHelper;

MmrLeaf::generate_proof(prev_block_number, best_known_block_number)
.map(|p| p.encode())
.map(sp_runtime::OpaqueValue::new)
}
}

#[api_version(2)]
Expand Down
26 changes: 26 additions & 0 deletions polkadot/runtime/test-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,12 +1029,38 @@ sp_api::impl_runtime_apis! {
None
}

fn submit_report_fork_voting_unsigned_extrinsic(
_equivocation_proof:
sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
_key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
None
}

fn submit_report_future_block_voting_unsigned_extrinsic(
_equivocation_proof: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
_key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
None
}

fn generate_key_ownership_proof(
_set_id: sp_consensus_beefy::ValidatorSetId,
_authority_id: BeefyId,
) -> Option<sp_consensus_beefy::OpaqueKeyOwnershipProof> {
None
}

fn generate_ancestry_proof(
_prev_block_number: BlockNumber,
_best_known_block_number: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
None
}
}

impl mmr::MmrApi<Block, Hash, BlockNumber> for Runtime {
Expand Down
38 changes: 37 additions & 1 deletion polkadot/runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2109,7 +2109,7 @@ sp_api::impl_runtime_apis! {
}
}

#[api_version(4)]
#[api_version(5)]
impl sp_consensus_beefy::BeefyApi<Block, BeefyId> for Runtime {
fn beefy_genesis() -> Option<BlockNumber> {
pallet_beefy::GenesisBlock::<Runtime>::get()
Expand All @@ -2135,6 +2135,31 @@ sp_api::impl_runtime_apis! {
)
}

fn submit_report_fork_voting_unsigned_extrinsic(
equivocation_proof:
sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_fork_voting_report(
equivocation_proof.try_into()?,
key_owner_proof.decode()?,
)
}

fn submit_report_future_block_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_future_block_voting_report(
equivocation_proof,
key_owner_proof.decode()?,
)
}

fn generate_key_ownership_proof(
_set_id: sp_consensus_beefy::ValidatorSetId,
authority_id: BeefyId,
Expand All @@ -2145,6 +2170,17 @@ sp_api::impl_runtime_apis! {
.map(|p| p.encode())
.map(sp_consensus_beefy::OpaqueKeyOwnershipProof::new)
}

fn generate_ancestry_proof(
prev_block_number: BlockNumber,
best_known_block_number: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
use sp_consensus_beefy::AncestryHelper;

BeefyMmrLeaf::generate_proof(prev_block_number, best_known_block_number)
.map(|p| p.encode())
.map(sp_runtime::OpaqueValue::new)
}
}

impl mmr::MmrApi<Block, Hash, BlockNumber> for Runtime {
Expand Down
27 changes: 27 additions & 0 deletions prdoc/pr_4993.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json

title: Added BEEFY equivocation-related methods to BeefyApi

doc:
- audience: Node Dev
description: |
This PR adds the `generate_ancestry_proof`, `submit_report_fork_voting_unsigned_extrinsic` and
`submit_report_future_block_voting_unsigned_extrinsic` to `BeefyApi` and bumps the `BeefyApi` version
from 4 to 5.

crates:
- name: pallet-beefy
bump: minor
- name: pallet-beefy-mmr
bump: minor
- name: kitchensink-runtime
bump: major
- name: rococo-runtime
bump: major
- name: westend-runtime
bump: major
- name: sp-consensus-beefy
bump: minor
- name: polkadot-service
bump: patch
38 changes: 37 additions & 1 deletion substrate/bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3038,7 +3038,7 @@ impl_runtime_apis! {
}
}

#[api_version(4)]
#[api_version(5)]
impl sp_consensus_beefy::BeefyApi<Block, BeefyId> for Runtime {
fn beefy_genesis() -> Option<BlockNumber> {
pallet_beefy::GenesisBlock::<Runtime>::get()
Expand All @@ -3064,6 +3064,31 @@ impl_runtime_apis! {
)
}

fn submit_report_fork_voting_unsigned_extrinsic(
equivocation_proof:
sp_consensus_beefy::ForkVotingProof<
<Block as BlockT>::Header,
BeefyId,
sp_runtime::OpaqueValue
>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_fork_voting_report(
equivocation_proof.try_into()?,
key_owner_proof.decode()?,
)
}

fn submit_report_future_block_voting_unsigned_extrinsic(
equivocation_proof: sp_consensus_beefy::FutureBlockVotingProof<BlockNumber, BeefyId>,
key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
) -> Option<()> {
Beefy::submit_unsigned_future_block_voting_report(
equivocation_proof,
key_owner_proof.decode()?,
)
}

fn generate_key_ownership_proof(
_set_id: sp_consensus_beefy::ValidatorSetId,
authority_id: BeefyId,
Expand All @@ -3072,6 +3097,17 @@ impl_runtime_apis! {
.map(|p| p.encode())
.map(sp_consensus_beefy::OpaqueKeyOwnershipProof::new)
}

fn generate_ancestry_proof(
prev_block_number: BlockNumber,
best_known_block_number: Option<BlockNumber>,
) -> Option<sp_runtime::OpaqueValue> {
use sp_consensus_beefy::AncestryHelper;

MmrLeaf::generate_proof(prev_block_number, best_known_block_number)
.map(|p| p.encode())
.map(sp_runtime::OpaqueValue::new)
}
}

impl pallet_mmr::primitives::MmrApi<
Expand Down
18 changes: 18 additions & 0 deletions substrate/frame/beefy-mmr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,24 @@ where
type Proof = AncestryProof<MerkleRootOf<T>>;
type ValidationContext = MerkleRootOf<T>;

fn generate_proof(
prev_block_number: BlockNumberFor<T>,
best_known_block_number: Option<BlockNumberFor<T>>,
) -> Option<Self::Proof> {
pallet_mmr::Pallet::<T>::generate_ancestry_proof(prev_block_number, best_known_block_number)
.map_err(|e| {
log::error!(
target: "runtime::beefy",
"Failed to generate ancestry proof for block {:?} at {:?}: {:?}",
prev_block_number,
best_known_block_number,
e
);
e
})
.ok()
}

fn extract_validation_context(header: HeaderFor<T>) -> Option<Self::ValidationContext> {
// Check if the provided header is canonical.
let expected_hash = frame_system::Pallet::<T>::block_hash(header.number());
Expand Down
35 changes: 33 additions & 2 deletions substrate/frame/beefy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,8 @@ impl<T: Config> Pallet<T> {
ValidatorSet::<T::BeefyId>::new(validators, id)
}

/// Submits an extrinsic to report an equivocation. This method will create
/// an unsigned extrinsic with a call to `report_equivocation_unsigned` and
/// Submits an extrinsic to report a double voting equivocation. This method will create
/// an unsigned extrinsic with a call to `report_double_voting_unsigned` and
/// will push the transaction to the pool. Only useful in an offchain context.
pub fn submit_unsigned_double_voting_report(
equivocation_proof: DoubleVotingProof<
Expand All @@ -556,6 +556,37 @@ impl<T: Config> Pallet<T> {
.ok()
}

/// Submits an extrinsic to report a fork voting equivocation. This method will create
/// an unsigned extrinsic with a call to `report_fork_voting_unsigned` and
/// will push the transaction to the pool. Only useful in an offchain context.
pub fn submit_unsigned_fork_voting_report(
equivocation_proof: ForkVotingProof<
HeaderFor<T>,
T::BeefyId,
<T::AncestryHelper as AncestryHelper<HeaderFor<T>>>::Proof,
>,
key_owner_proof: T::KeyOwnerProof,
) -> Option<()> {
T::EquivocationReportSystem::publish_evidence(EquivocationEvidenceFor::ForkVotingProof(
equivocation_proof,
key_owner_proof,
))
.ok()
}

/// Submits an extrinsic to report a future block voting equivocation. This method will create
/// an unsigned extrinsic with a call to `report_future_block_voting_unsigned` and
/// will push the transaction to the pool. Only useful in an offchain context.
pub fn submit_unsigned_future_block_voting_report(
equivocation_proof: FutureBlockVotingProof<BlockNumberFor<T>, T::BeefyId>,
key_owner_proof: T::KeyOwnerProof,
) -> Option<()> {
T::EquivocationReportSystem::publish_evidence(
EquivocationEvidenceFor::FutureBlockVotingProof(equivocation_proof, key_owner_proof),
)
.ok()
}

fn change_authorities(
new: BoundedVec<T::BeefyId, T::MaxAuthorities>,
queued: BoundedVec<T::BeefyId, T::MaxAuthorities>,
Expand Down
7 changes: 7 additions & 0 deletions substrate/frame/beefy/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ impl<Header: HeaderT> AncestryHelper<Header> for MockAncestryHelper {
type Proof = MockAncestryProof;
type ValidationContext = MockAncestryProofContext;

fn generate_proof(
_prev_block_number: Header::Number,
_best_known_block_number: Option<Header::Number>,
) -> Option<Self::Proof> {
unimplemented!()
}

fn extract_validation_context(_header: Header) -> Option<Self::ValidationContext> {
AncestryProofContext::get()
}
Expand Down
Loading

0 comments on commit 216e8fa

Please sign in to comment.