diff --git a/bin/millau/runtime/Cargo.toml b/bin/millau/runtime/Cargo.toml index c92698edae29..f4ad89159e06 100644 --- a/bin/millau/runtime/Cargo.toml +++ b/bin/millau/runtime/Cargo.toml @@ -13,6 +13,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Bridge dependencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-parachains = { path = "../../../primitives/parachains", default-features = false } diff --git a/bin/millau/runtime/src/lib.rs b/bin/millau/runtime/src/lib.rs index dfd6fc322e50..f0e23cc8d77f 100644 --- a/bin/millau/runtime/src/lib.rs +++ b/bin/millau/runtime/src/lib.rs @@ -882,12 +882,22 @@ impl_runtime_apis! { fn best_finalized() -> Option> { BridgeRialtoGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeRialtoGrandpa::accepted_finality_proofs() + } } impl bp_westend::WestendFinalityApi for Runtime { fn best_finalized() -> Option> { BridgeWestendGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeWestendGrandpa::accepted_finality_proofs() + } } impl bp_westend::AssetHubWestendFinalityApi for Runtime { diff --git a/bin/rialto-parachain/runtime/Cargo.toml b/bin/rialto-parachain/runtime/Cargo.toml index 41ca0bff9bf4..1b87205e9e9c 100644 --- a/bin/rialto-parachain/runtime/Cargo.toml +++ b/bin/rialto-parachain/runtime/Cargo.toml @@ -16,6 +16,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Bridge depedencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } diff --git a/bin/rialto-parachain/runtime/src/lib.rs b/bin/rialto-parachain/runtime/src/lib.rs index 18c915819d5f..db3113ce4489 100644 --- a/bin/rialto-parachain/runtime/src/lib.rs +++ b/bin/rialto-parachain/runtime/src/lib.rs @@ -746,6 +746,11 @@ impl_runtime_apis! { fn best_finalized() -> Option> { BridgeMillauGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeMillauGrandpa::accepted_finality_proofs() + } } impl bp_millau::ToMillauOutboundLaneApi for Runtime { diff --git a/bin/rialto/runtime/Cargo.toml b/bin/rialto/runtime/Cargo.toml index 2320665cf9a3..7f1b18bf99cb 100644 --- a/bin/rialto/runtime/Cargo.toml +++ b/bin/rialto/runtime/Cargo.toml @@ -12,6 +12,7 @@ scale-info = { version = "2.9.0", default-features = false, features = ["derive" # Bridge dependencies +bp-header-chain = { path = "../../../primitives/header-chain", default-features = false } bp-messages = { path = "../../../primitives/messages", default-features = false } bp-millau = { path = "../../../primitives/chain-millau", default-features = false } bp-relayers = { path = "../../../primitives/relayers", default-features = false } diff --git a/bin/rialto/runtime/src/lib.rs b/bin/rialto/runtime/src/lib.rs index 1d93d24951e9..b4e64072afc0 100644 --- a/bin/rialto/runtime/src/lib.rs +++ b/bin/rialto/runtime/src/lib.rs @@ -694,6 +694,11 @@ impl_runtime_apis! { fn best_finalized() -> Option> { BridgeMillauGrandpa::best_finalized() } + + fn accepted_grandpa_finality_proofs( + ) -> Vec> { + BridgeMillauGrandpa::accepted_finality_proofs() + } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { diff --git a/modules/grandpa/src/lib.rs b/modules/grandpa/src/lib.rs index eb49849ac881..fd9361948b65 100644 --- a/modules/grandpa/src/lib.rs +++ b/modules/grandpa/src/lib.rs @@ -49,7 +49,7 @@ use sp_runtime::{ traits::{Header as HeaderT, Zero}, SaturatedConversion, }; -use sp_std::{boxed::Box, convert::TryInto}; +use sp_std::{boxed::Box, convert::TryInto, prelude::*}; mod call_ext; #[cfg(test)] @@ -237,7 +237,7 @@ pub mod pallet { let actual_weight = pre_dispatch_weight .set_proof_size(pre_dispatch_weight.proof_size().saturating_sub(unused_proof_size)); - Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash }); + Self::deposit_event(Event::UpdatedBestFinalizedHeader { number, hash, justification }); Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee }) } @@ -402,6 +402,8 @@ pub mod pallet { UpdatedBestFinalizedHeader { number: BridgedBlockNumber, hash: BridgedBlockHash, + /// Justification. + justification: GrandpaJustification>, }, } @@ -603,10 +605,22 @@ pub mod pallet { } } -impl, I: 'static> Pallet { - /// Get the best finalized block number. - pub fn best_finalized_number() -> Option> { - BestFinalized::::get().map(|id| id.number()) +impl, I: 'static> Pallet +where + ::RuntimeEvent: TryInto>, +{ + /// Get the GRANDPA justifications accepted in the current block. + pub fn accepted_finality_proofs() -> Vec>> { + frame_system::Pallet::::read_events_no_consensus() + .filter_map(|event| { + if let Event::::UpdatedBestFinalizedHeader { justification, .. } = + event.event.try_into().ok()? + { + return Some(justification) + } + None + }) + .collect() } } @@ -913,10 +927,12 @@ mod tests { event: TestEvent::Grandpa(Event::UpdatedBestFinalizedHeader { number: *header.number(), hash: header.hash(), + justification: justification.clone(), }), topics: vec![], }], ); + assert_eq!(Pallet::::accepted_finality_proofs(), vec![justification]); }) } diff --git a/modules/parachains/src/lib.rs b/modules/parachains/src/lib.rs index 4f78a45d4b77..3380b63aa5cf 100644 --- a/modules/parachains/src/lib.rs +++ b/modules/parachains/src/lib.rs @@ -691,12 +691,13 @@ pub(crate) mod tests { use super::*; use crate::mock::{ run_test, test_relay_header, BigParachainHeader, RegularParachainHasher, - RegularParachainHeader, RuntimeEvent as TestEvent, RuntimeOrigin, TestRuntime, - UNTRACKED_PARACHAIN_ID, + RegularParachainHeader, RelayBlockHeader, RuntimeEvent as TestEvent, RuntimeOrigin, + TestRuntime, UNTRACKED_PARACHAIN_ID, }; use bp_test_utils::prepare_parachain_heads_proof; use codec::Encode; + use bp_header_chain::justification::GrandpaJustification; use bp_parachains::{ BestParaHeadHash, BridgeParachainCall, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider, }; @@ -740,7 +741,10 @@ pub(crate) mod tests { test_relay_header(0, state_root).hash() } - fn proceed(num: RelayBlockNumber, state_root: RelayBlockHash) -> ParaHash { + fn proceed( + num: RelayBlockNumber, + state_root: RelayBlockHash, + ) -> (ParaHash, GrandpaJustification) { pallet_bridge_grandpa::Pallet::::on_initialize( 0, ); @@ -752,11 +756,11 @@ pub(crate) mod tests { pallet_bridge_grandpa::Pallet::::submit_finality_proof( RuntimeOrigin::signed(1), Box::new(header), - justification, + justification.clone(), ) ); - hash + (hash, justification) } fn initial_best_head(parachain: u32) -> ParaInfo { @@ -993,7 +997,7 @@ pub(crate) mod tests { ); // import head#10 of parachain#1 at relay block #1 - let relay_1_hash = proceed(1, state_root_10); + let (relay_1_hash, justification) = proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( ParasInfo::::get(ParaId(1)), @@ -1032,6 +1036,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification } ), topics: vec![], @@ -1149,7 +1154,7 @@ pub(crate) mod tests { // try to import head#0 of parachain#1 at relay block#1 // => call succeeds, but nothing is changed - let relay_1_hash = proceed(1, state_root); + let (relay_1_hash, justification) = proceed(1, state_root); assert_ok!(import_parachain_1_head(1, state_root, parachains, proof)); assert_eq!(ParasInfo::::get(ParaId(1)), Some(initial_best_head(1))); assert_eq!( @@ -1169,6 +1174,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification } ), topics: vec![], @@ -1197,7 +1203,7 @@ pub(crate) mod tests { initialize(state_root_5); // head#10 of parachain#1 at relay block#1 - let relay_1_hash = proceed(1, state_root_10); + let (relay_1_hash, justification) = proceed(1, state_root_10); assert_ok!(import_parachain_1_head(1, state_root_10, parachains_10, proof_10)); assert_eq!( ParasInfo::::get(ParaId(1)), @@ -1218,6 +1224,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification: justification.clone() } ), topics: vec![], @@ -1255,6 +1262,7 @@ pub(crate) mod tests { pallet_bridge_grandpa::Event::UpdatedBestFinalizedHeader { number: 1, hash: relay_1_hash, + justification } ), topics: vec![], diff --git a/primitives/chain-kusama/src/lib.rs b/primitives/chain-kusama/src/lib.rs index 229905a3d4ac..80be182abfb7 100644 --- a/primitives/chain-kusama/src/lib.rs +++ b/primitives/chain-kusama/src/lib.rs @@ -69,4 +69,4 @@ pub const WITH_KUSAMA_GRANDPA_PALLET_NAME: &str = "BridgeKusamaGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -decl_bridge_finality_runtime_apis!(kusama); +decl_bridge_finality_runtime_apis!(kusama, grandpa); diff --git a/primitives/chain-millau/src/lib.rs b/primitives/chain-millau/src/lib.rs index a752b5f7114a..7acaa2c4018e 100644 --- a/primitives/chain-millau/src/lib.rs +++ b/primitives/chain-millau/src/lib.rs @@ -25,7 +25,7 @@ use bp_header_chain::ChainWithGrandpa; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{decl_bridge_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, @@ -244,4 +244,4 @@ pub const WITH_MILLAU_MESSAGES_PALLET_NAME: &str = "BridgeMillauMessages"; /// Name of the transaction payment pallet at the Millau runtime. pub const TRANSACTION_PAYMENT_PALLET_NAME: &str = "TransactionPayment"; -decl_bridge_runtime_apis!(millau); +decl_bridge_runtime_apis!(millau, grandpa); diff --git a/primitives/chain-polkadot/src/lib.rs b/primitives/chain-polkadot/src/lib.rs index 628634bb46f0..fb87c3644238 100644 --- a/primitives/chain-polkadot/src/lib.rs +++ b/primitives/chain-polkadot/src/lib.rs @@ -69,4 +69,4 @@ pub const WITH_POLKADOT_GRANDPA_PALLET_NAME: &str = "BridgePolkadotGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -decl_bridge_finality_runtime_apis!(polkadot); +decl_bridge_finality_runtime_apis!(polkadot, grandpa); diff --git a/primitives/chain-rialto/src/lib.rs b/primitives/chain-rialto/src/lib.rs index d5be78516a21..1104e17bb03a 100644 --- a/primitives/chain-rialto/src/lib.rs +++ b/primitives/chain-rialto/src/lib.rs @@ -22,7 +22,7 @@ use bp_header_chain::ChainWithGrandpa; use bp_messages::{ InboundMessageDetails, LaneId, MessageNonce, MessagePayload, OutboundMessageDetails, }; -use bp_runtime::{decl_bridge_runtime_apis, Chain}; +use bp_runtime::{decl_bridge_finality_runtime_apis, decl_bridge_runtime_apis, Chain}; use frame_support::{ dispatch::DispatchClass, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, IdentityFee, Weight}, @@ -211,4 +211,4 @@ pub const PARAS_REGISTRAR_PALLET_NAME: &str = "Registrar"; /// Name of the parachains pallet in the Rialto runtime. pub const PARAS_PALLET_NAME: &str = "Paras"; -decl_bridge_runtime_apis!(rialto); +decl_bridge_runtime_apis!(rialto, grandpa); diff --git a/primitives/chain-rococo/src/lib.rs b/primitives/chain-rococo/src/lib.rs index a825c8b39787..a5aa46edde0e 100644 --- a/primitives/chain-rococo/src/lib.rs +++ b/primitives/chain-rococo/src/lib.rs @@ -73,4 +73,4 @@ pub const WITH_ROCOCO_GRANDPA_PALLET_NAME: &str = "BridgeRococoGrandpa"; /// reserve. pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; -decl_bridge_finality_runtime_apis!(rococo); +decl_bridge_finality_runtime_apis!(rococo, grandpa); diff --git a/primitives/chain-westend/src/lib.rs b/primitives/chain-westend/src/lib.rs index cdda46ba7b2b..c1cab3198fbb 100644 --- a/primitives/chain-westend/src/lib.rs +++ b/primitives/chain-westend/src/lib.rs @@ -19,6 +19,7 @@ #![allow(clippy::too_many_arguments)] pub use bp_polkadot_core::*; +use frame_support::sp_std::prelude::*; use bp_header_chain::ChainWithGrandpa; use bp_runtime::{decl_bridge_finality_runtime_apis, Chain, Parachain}; @@ -103,6 +104,6 @@ pub const MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE: u32 = 128; /// Identifier of `AssetHubWestend` parachain at the Westend relay chain. pub const ASSET_HUB_WESTEND_PARACHAIN_ID: u32 = 1000; -decl_bridge_finality_runtime_apis!(westend); +decl_bridge_finality_runtime_apis!(westend, grandpa); decl_bridge_finality_runtime_apis!(AssetHubWestend); diff --git a/primitives/chain-wococo/src/lib.rs b/primitives/chain-wococo/src/lib.rs index fb63613427d0..8009fde023a2 100644 --- a/primitives/chain-wococo/src/lib.rs +++ b/primitives/chain-wococo/src/lib.rs @@ -62,4 +62,4 @@ impl ChainWithGrandpa for Wococo { /// Name of the With-Wococo GRANDPA pallet instance that is deployed at bridged chains. pub const WITH_WOCOCO_GRANDPA_PALLET_NAME: &str = "BridgeWococoGrandpa"; -decl_bridge_finality_runtime_apis!(wococo); +decl_bridge_finality_runtime_apis!(wococo, grandpa); diff --git a/primitives/header-chain/src/lib.rs b/primitives/header-chain/src/lib.rs index 5268e7d5c5fa..1f5102203ca2 100644 --- a/primitives/header-chain/src/lib.rs +++ b/primitives/header-chain/src/lib.rs @@ -21,7 +21,7 @@ use bp_runtime::{ BasicOperatingMode, Chain, HashOf, HasherOf, HeaderOf, RawStorageProof, StorageProofChecker, - StorageProofError, + StorageProofError, UnderlyingChainProvider, }; use codec::{Codec, Decode, Encode, EncodeLike, MaxEncodedLen}; use core::{clone::Clone, cmp::Eq, default::Default, fmt::Debug}; @@ -234,3 +234,17 @@ pub trait ChainWithGrandpa: Chain { /// refund amount and doing calls which exceed the limit, may be costly to submitter. const AVERAGE_HEADER_SIZE_IN_JUSTIFICATION: u32; } + +/// A trait that provides the type of the underlying `ChainWithGrandpa`. +pub trait UnderlyingChainWithGrandpaProvider: UnderlyingChainProvider { + /// Underlying `ChainWithGrandpa` type. + type ChainWithGrandpa: ChainWithGrandpa; +} + +impl UnderlyingChainWithGrandpaProvider for T +where + T: UnderlyingChainProvider, + T::Chain: ChainWithGrandpa, +{ + type ChainWithGrandpa = T::Chain; +} diff --git a/primitives/runtime/src/chain.rs b/primitives/runtime/src/chain.rs index 8c47662a7c13..a5fb8a28809d 100644 --- a/primitives/runtime/src/chain.rs +++ b/primitives/runtime/src/chain.rs @@ -279,10 +279,11 @@ pub type TransactionEraOf = crate::TransactionEra, HashOf /// - `FinalityApi` /// - constants that are stringified names of runtime API methods: /// - `BEST_FINALIZED__HEADER_METHOD` +/// - `_ACCEPTED__FINALITY_PROOFS_METHOD` /// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). #[macro_export] macro_rules! decl_bridge_finality_runtime_apis { - ($chain: ident) => { + ($chain: ident $(, $consensus: ident => $justification_type: ty)?) => { bp_runtime::paste::item! { mod [<$chain _finality_api>] { use super::*; @@ -291,6 +292,13 @@ macro_rules! decl_bridge_finality_runtime_apis { pub const []: &str = stringify!([<$chain:camel FinalityApi_best_finalized>]); + $( + /// Name of the `FinalityApi::accepted__finality_proofs` + /// runtime method. + pub const [<$chain:upper _ACCEPTED_ $consensus:upper _FINALITY_PROOFS_METHOD>]: &str = + stringify!([<$chain:camel FinalityApi_accepted_ $consensus:lower _finality_proofs>]); + )? + sp_api::decl_runtime_apis! { /// API for querying information about the finalized chain headers. /// @@ -299,6 +307,12 @@ macro_rules! decl_bridge_finality_runtime_apis { pub trait [<$chain:camel FinalityApi>] { /// Returns number and hash of the best finalized header known to the bridge module. fn best_finalized() -> Option>; + + $( + /// Returns the justifications accepted in the current block. + fn []( + ) -> Vec<$justification_type>; + )? } } } @@ -306,6 +320,9 @@ macro_rules! decl_bridge_finality_runtime_apis { pub use [<$chain _finality_api>]::*; } }; + ($chain: ident, grandpa) => { + decl_bridge_finality_runtime_apis!($chain, grandpa => bp_header_chain::justification::GrandpaJustification
); + }; } /// Convenience macro that declares bridge messages runtime apis and related constants for a chain. @@ -376,8 +393,8 @@ macro_rules! decl_bridge_messages_runtime_apis { /// The name of the chain has to be specified in snake case (e.g. `rialto_parachain`). #[macro_export] macro_rules! decl_bridge_runtime_apis { - ($chain: ident) => { - bp_runtime::decl_bridge_finality_runtime_apis!($chain); + ($chain: ident $(, $consensus: ident)?) => { + bp_runtime::decl_bridge_finality_runtime_apis!($chain $(, $consensus)?); bp_runtime::decl_bridge_messages_runtime_apis!($chain); }; } diff --git a/relays/client-kusama/src/lib.rs b/relays/client-kusama/src/lib.rs index 3d53fe8f9f18..0f4172248f38 100644 --- a/relays/client-kusama/src/lib.rs +++ b/relays/client-kusama/src/lib.rs @@ -16,9 +16,11 @@ //! Types used to connect to the Kusama chain. -use bp_kusama::AccountInfoStorageMapKeyProvider; +use bp_kusama::{AccountInfoStorageMapKeyProvider, KUSAMA_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD}; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -47,6 +49,11 @@ impl Chain for Kusama { type Call = (); } +impl ChainWithGrandpa for Kusama { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + KUSAMA_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Kusama { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-millau/src/lib.rs b/relays/client-millau/src/lib.rs index d6ce47d847dd..1e899c7fdac3 100644 --- a/relays/client-millau/src/lib.rs +++ b/relays/client-millau/src/lib.rs @@ -17,12 +17,13 @@ //! Types used to connect to the Millau-Substrate chain. use bp_messages::MessageNonce; +use bp_millau::MILLAU_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - ChainWithUtilityPallet, Error as SubstrateError, FullRuntimeUtilityPallet, NonceOf, SignParam, - UnderlyingChainProvider, UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + FullRuntimeUtilityPallet, NonceOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -65,6 +66,11 @@ impl Chain for Millau { type Call = millau_runtime::RuntimeCall; } +impl ChainWithGrandpa for Millau { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + MILLAU_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Millau { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { use frame_support::storage::generator::StorageMap; diff --git a/relays/client-polkadot/src/lib.rs b/relays/client-polkadot/src/lib.rs index 96453ab9041a..f65f06c7de4e 100644 --- a/relays/client-polkadot/src/lib.rs +++ b/relays/client-polkadot/src/lib.rs @@ -16,9 +16,13 @@ //! Types used to connect to the Polkadot chain. -use bp_polkadot::AccountInfoStorageMapKeyProvider; +use bp_polkadot::{ + AccountInfoStorageMapKeyProvider, POLKADOT_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD, +}; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -47,6 +51,11 @@ impl Chain for Polkadot { type Call = (); } +impl ChainWithGrandpa for Polkadot { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + POLKADOT_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Polkadot { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-rialto/src/lib.rs b/relays/client-rialto/src/lib.rs index 97b6c7ee802b..00c98876e477 100644 --- a/relays/client-rialto/src/lib.rs +++ b/relays/client-rialto/src/lib.rs @@ -17,12 +17,13 @@ //! Types used to connect to the Rialto-Substrate chain. use bp_messages::MessageNonce; +use bp_rialto::RIALTO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; use bp_runtime::ChainId; use codec::{Compact, Decode, Encode}; use relay_substrate_client::{ - BalanceOf, Chain, ChainWithBalances, ChainWithMessages, ChainWithTransactions, - Error as SubstrateError, NonceOf, RelayChain, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + ChainWithTransactions, Error as SubstrateError, NonceOf, RelayChain, SignParam, + UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -50,6 +51,11 @@ impl Chain for Rialto { type Call = rialto_runtime::RuntimeCall; } +impl ChainWithGrandpa for Rialto { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + RIALTO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl RelayChain for Rialto { const PARAS_PALLET_NAME: &'static str = bp_rialto::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = diff --git a/relays/client-rococo/src/lib.rs b/relays/client-rococo/src/lib.rs index ede1bf1ded4e..5254b877ea82 100644 --- a/relays/client-rococo/src/lib.rs +++ b/relays/client-rococo/src/lib.rs @@ -16,8 +16,11 @@ //! Types used to connect to the Rococo-Substrate chain. +use bp_rococo::ROCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -46,6 +49,11 @@ impl Chain for Rococo { type Call = (); } +impl ChainWithGrandpa for Rococo { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + ROCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Rococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_rococo::AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/client-substrate/src/chain.rs b/relays/client-substrate/src/chain.rs index f733a10d06b2..0d178da3db89 100644 --- a/relays/client-substrate/src/chain.rs +++ b/relays/client-substrate/src/chain.rs @@ -16,6 +16,7 @@ use crate::calls::UtilityCall; +use bp_header_chain::UnderlyingChainWithGrandpaProvider; use bp_messages::MessageNonce; use bp_runtime::{ Chain as ChainBase, ChainId, EncodedOrDecodedCall, HashOf, Parachain as ParachainBase, @@ -77,22 +78,13 @@ pub trait RelayChain: Chain { /// /// Keep in mind that parachains are relying on relay chain GRANDPA, so they should not implement /// this trait. -pub trait ChainWithGrandpa: Chain { - /// Name of the bridge GRANDPA pallet (used in `construct_runtime` macro call) that is deployed - /// at some other chain to bridge with this `ChainWithGrandpa`. +pub trait ChainWithGrandpa: Chain + UnderlyingChainWithGrandpaProvider { + /// Name of the runtime API method that is returning the GRANDPA justifications accepted + /// by the `submit_finality_proofs` extrinsic in the queried block. /// - /// We assume that all chains that are bridging with this `ChainWithGrandpa` are using - /// the same name. - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str; -} - -impl ChainWithGrandpa for T -where - T: Chain + UnderlyingChainProvider, - T::Chain: bp_header_chain::ChainWithGrandpa, -{ - const WITH_CHAIN_GRANDPA_PALLET_NAME: &'static str = - ::WITH_CHAIN_GRANDPA_PALLET_NAME; + /// Keep in mind that this method is normally provided by the other chain, which is + /// bridged with this chain. + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str; } /// Substrate-based parachain from minimal relay-client point of view. diff --git a/relays/client-westend/src/lib.rs b/relays/client-westend/src/lib.rs index 1251276fcfdb..67f1f61c547b 100644 --- a/relays/client-westend/src/lib.rs +++ b/relays/client-westend/src/lib.rs @@ -17,7 +17,10 @@ //! Types used to connect to the Westend chain. use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use bp_westend::WESTEND_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -46,6 +49,11 @@ impl Chain for Westend { type Call = (); } +impl ChainWithGrandpa for Westend { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + WESTEND_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl RelayChain for Westend { const PARAS_PALLET_NAME: &'static str = bp_westend::PARAS_PALLET_NAME; const PARACHAINS_FINALITY_PALLET_NAME: &'static str = diff --git a/relays/client-wococo/src/lib.rs b/relays/client-wococo/src/lib.rs index 2f0d6b22f929..acb41be50e6d 100644 --- a/relays/client-wococo/src/lib.rs +++ b/relays/client-wococo/src/lib.rs @@ -17,7 +17,10 @@ //! Types used to connect to the Wococo-Substrate chain. use bp_runtime::ChainId; -use relay_substrate_client::{Chain, ChainWithBalances, RelayChain, UnderlyingChainProvider}; +use bp_wococo::WOCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +use relay_substrate_client::{ + Chain, ChainWithBalances, ChainWithGrandpa, RelayChain, UnderlyingChainProvider, +}; use sp_core::storage::StorageKey; use std::time::Duration; @@ -46,6 +49,11 @@ impl Chain for Wococo { type Call = (); } +impl ChainWithGrandpa for Wococo { + const ACCEPTED_FINALITY_PROOFS_METHOD: &'static str = + WOCOCO_ACCEPTED_GRANDPA_FINALITY_PROOFS_METHOD; +} + impl ChainWithBalances for Wococo { fn account_info_storage_key(account_id: &Self::AccountId) -> StorageKey { bp_wococo::AccountInfoStorageMapKeyProvider::final_key(account_id) diff --git a/relays/lib-substrate-relay/src/finality/engine.rs b/relays/lib-substrate-relay/src/finality/engine.rs index 3f7e3eecbaa9..0092db969925 100644 --- a/relays/lib-substrate-relay/src/finality/engine.rs +++ b/relays/lib-substrate-relay/src/finality/engine.rs @@ -20,7 +20,8 @@ use crate::error::Error; use async_trait::async_trait; use bp_header_chain::{ justification::{verify_and_optimize_justification, GrandpaJustification}, - ConsensusLogReader, FinalityProof, GrandpaConsensusLogReader, + ChainWithGrandpa as ChainWithGrandpaBase, ConsensusLogReader, FinalityProof, + GrandpaConsensusLogReader, }; use bp_runtime::{BasicOperatingMode, HeaderIdProvider, OperatingMode}; use codec::{Decode, Encode}; @@ -83,8 +84,10 @@ pub trait Engine: Send { } /// A method to subscribe to encoded finality proofs, given source client. - async fn finality_proofs(client: &Client) -> Result, SubstrateError> { - client.subscribe_finality_justifications::().await + async fn source_finality_proofs( + source_client: &Client, + ) -> Result, SubstrateError> { + source_client.subscribe_finality_justifications::().await } /// Optimize finality proof before sending it to the target node. @@ -139,11 +142,15 @@ impl Engine for Grandpa { type OperatingMode = BasicOperatingMode; fn is_initialized_key() -> StorageKey { - bp_header_chain::storage_keys::best_finalized_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + bp_header_chain::storage_keys::best_finalized_key( + C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, + ) } fn pallet_operating_mode_key() -> StorageKey { - bp_header_chain::storage_keys::pallet_operating_mode_key(C::WITH_CHAIN_GRANDPA_PALLET_NAME) + bp_header_chain::storage_keys::pallet_operating_mode_key( + C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, + ) } async fn optimize_proof( @@ -152,7 +159,7 @@ impl Engine for Grandpa { proof: &mut Self::FinalityProof, ) -> Result<(), SubstrateError> { let current_authority_set_key = bp_header_chain::storage_keys::current_authority_set_key( - C::WITH_CHAIN_GRANDPA_PALLET_NAME, + C::ChainWithGrandpa::WITH_CHAIN_GRANDPA_PALLET_NAME, ); let (authority_set, authority_set_id): ( sp_consensus_grandpa::AuthorityList, @@ -199,7 +206,7 @@ impl Engine for Grandpa { // But now there are problems with this approach - `CurrentSetId` may return invalid value. // So here we're waiting for the next justification, read the authorities set and then try // to figure out the set id with bruteforce. - let justifications = Self::finality_proofs(&source_client) + let justifications = Self::source_finality_proofs(&source_client) .await .map_err(|err| Error::Subscribe(C::NAME, err))?; // Read next justification - the header that it finalizes will be used as initial header. diff --git a/relays/lib-substrate-relay/src/finality/source.rs b/relays/lib-substrate-relay/src/finality/source.rs index c8f11d99461b..6227263902ae 100644 --- a/relays/lib-substrate-relay/src/finality/source.rs +++ b/relays/lib-substrate-relay/src/finality/source.rs @@ -234,7 +234,7 @@ impl SourceClient Result { Ok(unfold( - P::FinalityEngine::finality_proofs(&self.client).await?, + P::FinalityEngine::source_finality_proofs(&self.client).await?, move |subscription| async move { loop { let log_error = |err| {