From 5b5627e9081640ed5691eb2891182843563fb99a Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Tue, 21 Feb 2023 12:22:59 +0100 Subject: [PATCH] Rewards refund for relaying BridgeHubRococo/BridgeHubWococo (#1894) * Rewards refund for relaying BridgeHubRococo/BridgeHubWococo * spellcheck + clippy * RefundBridgedParachainMessages move to bp-runtime * Dedicated RewardingBridgeSignedExtra for Rococo/Wococo shared runtime with two instances of `RefundBridgedParachainMessages` * RefundBridgedParachainMessages with Tuple support for multiple * Fix additional_signed * revert fix * Refactor to `RefundBridgedParachainMessagesSchema` * removed unused deps --- Cargo.lock | 1 + .../chain-bridge-hub-cumulus/Cargo.toml | 2 + .../chain-bridge-hub-cumulus/src/lib.rs | 73 ++++++++++++++++++- primitives/runtime/src/extensions.rs | 9 +++ relays/client-bridge-hub-rococo/src/lib.rs | 13 +++- .../src/runtime_wrapper.rs | 9 ++- relays/client-bridge-hub-wococo/src/lib.rs | 14 +++- .../src/runtime_wrapper.rs | 7 +- 8 files changed, 112 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da7247b1c52..899367d037a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -815,6 +815,7 @@ version = "0.1.0" dependencies = [ "bp-messages", "bp-polkadot-core", + "bp-runtime", "frame-support", "frame-system", "polkadot-primitives", diff --git a/primitives/chain-bridge-hub-cumulus/Cargo.toml b/primitives/chain-bridge-hub-cumulus/Cargo.toml index cb7f55d3361..2bbe3d029a3 100644 --- a/primitives/chain-bridge-hub-cumulus/Cargo.toml +++ b/primitives/chain-bridge-hub-cumulus/Cargo.toml @@ -11,6 +11,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" bp-polkadot-core = { path = "../../primitives/polkadot-core", default-features = false } bp-messages = { path = "../../primitives/messages", default-features = false } +bp-runtime = { path = "../../primitives/runtime", default-features = false } # Substrate Based Dependencies @@ -27,6 +28,7 @@ default = ["std"] std = [ "bp-polkadot-core/std", "bp-messages/std", + "bp-runtime/std", "frame-system/std", "frame-support/std", "sp-api/std", diff --git a/primitives/chain-bridge-hub-cumulus/src/lib.rs b/primitives/chain-bridge-hub-cumulus/src/lib.rs index dfa5afe2a5b..3a05cb48b3b 100644 --- a/primitives/chain-bridge-hub-cumulus/src/lib.rs +++ b/primitives/chain-bridge-hub-cumulus/src/lib.rs @@ -19,8 +19,8 @@ use bp_messages::*; pub use bp_polkadot_core::{ AccountId, AccountInfoStorageMapKeyProvider, AccountPublic, Balance, BlockNumber, Hash, Hasher, - Hashing, Header, Index, Nonce, Perbill, PolkadotSignedExtension, Signature, SignedBlock, - UncheckedExtrinsic, EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, + Hashing, Header, Index, Nonce, Perbill, Signature, SignedBlock, UncheckedExtrinsic, + EXTRA_STORAGE_PROOF_SIZE, TX_EXTRA_BYTES, }; use frame_support::{ dispatch::DispatchClass, @@ -124,3 +124,72 @@ pub const MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX: MessageNonce = 1024; /// Maximal number of unconfirmed messages at inbound lane for Cumulus-based parachains. pub const MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX: MessageNonce = 4096; + +/// Module with rewarding bridge signed extension support +pub mod rewarding_bridge_signed_extension { + use super::*; + use bp_polkadot_core::PolkadotLike; + use bp_runtime::extensions::*; + + type RewardingBridgeSignedExtra = ( + CheckNonZeroSender, + CheckSpecVersion, + CheckTxVersion, + CheckGenesis, + CheckEra, + CheckNonce, + CheckWeight, + ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + RefundBridgedParachainMessagesSchema, + ); + + /// The signed extension used by Cumulus and Cumulus-like parachain with bridging and rewarding. + pub type RewardingBridgeSignedExtension = GenericSignedExtension; + + pub fn from_params( + spec_version: u32, + transaction_version: u32, + era: bp_runtime::TransactionEraOf, + genesis_hash: Hash, + nonce: Nonce, + tip: Balance, + ) -> RewardingBridgeSignedExtension { + GenericSignedExtension::::new( + ( + (), // non-zero sender + (), // spec version + (), // tx version + (), // genesis + era.frame_era(), // era + nonce.into(), // nonce (compact encoding) + (), // Check weight + tip.into(), // transaction payment / tip (compact encoding) + (), // bridge reject obsolete headers and msgs + (), // bridge register reward to relayer for message passing + ), + Some(( + (), + spec_version, + transaction_version, + genesis_hash, + era.signed_payload(genesis_hash), + (), + (), + (), + (), + (), + )), + ) + } + + /// Return signer nonce, used to craft transaction. + pub fn nonce(sign_ext: &RewardingBridgeSignedExtension) -> Nonce { + sign_ext.payload.5.into() + } + + /// Return transaction tip. + pub fn tip(sign_ext: &RewardingBridgeSignedExtension) -> Balance { + sign_ext.payload.7.into() + } +} diff --git a/primitives/runtime/src/extensions.rs b/primitives/runtime/src/extensions.rs index eefe10f7057..ea51d03741c 100644 --- a/primitives/runtime/src/extensions.rs +++ b/primitives/runtime/src/extensions.rs @@ -76,6 +76,15 @@ pub type ChargeTransactionPayment = GenericSignedExtensionSchema; +/// The `SignedExtensionSchema` for `RefundBridgedParachainMessages`. +/// This schema is dedicated for `RefundBridgedParachainMessages` signed extension as +/// wildcard/placeholder, which relies on the scale encoding for `()` or `((), ())`, or `((), (), +/// ())` is the same. So runtime can contains any kind of tuple: +/// `(BridgeRefundBridgeHubRococoMessages)` +/// `(BridgeRefundBridgeHubRococoMessages, BridgeRefundBridgeHubWococoMessages)` +/// `(BridgeRefundParachainMessages1, ..., BridgeRefundParachainMessagesN)` +pub type RefundBridgedParachainMessagesSchema = GenericSignedExtensionSchema<(), ()>; + #[impl_for_tuples(1, 12)] impl SignedExtensionSchema for Tuple { for_tuples!( type Payload = ( #( Tuple::Payload ),* ); ); diff --git a/relays/client-bridge-hub-rococo/src/lib.rs b/relays/client-bridge-hub-rococo/src/lib.rs index d2e421423a5..b6b844021e0 100644 --- a/relays/client-bridge-hub-rococo/src/lib.rs +++ b/relays/client-bridge-hub-rococo/src/lib.rs @@ -17,7 +17,6 @@ //! Types used to connect to the BridgeHub-Rococo-Substrate parachain. use bp_bridge_hub_rococo::AVERAGE_BLOCK_INTERVAL; -use bp_bridge_hub_wococo::PolkadotSignedExtension; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -72,7 +71,7 @@ impl ChainWithTransactions for BridgeHubRococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_rococo::SignedExtension::from_params( + runtime::rewarding_bridge_signed_extension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -86,7 +85,7 @@ impl ChainWithTransactions for BridgeHubRococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(bp_bridge_hub_rococo::UncheckedExtrinsic::new_signed( + Ok(runtime::UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -109,7 +108,13 @@ impl ChainWithTransactions for BridgeHubRococo { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + Some( + UnsignedTransaction::new( + tx.function, + runtime::rewarding_bridge_signed_extension::nonce(extra), + ) + .tip(runtime::rewarding_bridge_signed_extension::tip(extra)), + ) } } diff --git a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs index fc945d8c950..711306b0127 100644 --- a/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-rococo/src/runtime_wrapper.rs @@ -14,21 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -// TODO: join with primitives do we need this here or move to the primitives? - //! Types that are specific to the BridgeHubRococo runtime. use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_bridge_hub_rococo::SignedExtension; +pub use bp_bridge_hub_rococo::rewarding_bridge_signed_extension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubRococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_rococo::UncheckedExtrinsic< + Call, + rewarding_bridge_signed_extension::RewardingBridgeSignedExtension, +>; // The indirect pallet call used to sync `Wococo` GRANDPA finality to `BHRococo`. pub type BridgeWococoGrandpaCall = BridgeGrandpaCallOf; diff --git a/relays/client-bridge-hub-wococo/src/lib.rs b/relays/client-bridge-hub-wococo/src/lib.rs index 2c211ae86cf..a466df35495 100644 --- a/relays/client-bridge-hub-wococo/src/lib.rs +++ b/relays/client-bridge-hub-wococo/src/lib.rs @@ -16,7 +16,7 @@ //! Types used to connect to the BridgeHub-Wococo-Substrate parachain. -use bp_bridge_hub_wococo::{PolkadotSignedExtension, AVERAGE_BLOCK_INTERVAL}; +use bp_bridge_hub_wococo::AVERAGE_BLOCK_INTERVAL; use bp_messages::MessageNonce; use codec::Encode; use relay_substrate_client::{ @@ -71,7 +71,7 @@ impl ChainWithTransactions for BridgeHubWococo { ) -> Result { let raw_payload = SignedPayload::new( unsigned.call, - bp_bridge_hub_wococo::SignedExtension::from_params( + runtime::rewarding_bridge_signed_extension::from_params( param.spec_version, param.transaction_version, unsigned.era, @@ -85,7 +85,7 @@ impl ChainWithTransactions for BridgeHubWococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - Ok(bp_bridge_hub_wococo::UncheckedExtrinsic::new_signed( + Ok(runtime::UncheckedExtrinsic::new_signed( call, signer.into_account().into(), signature.into(), @@ -108,7 +108,13 @@ impl ChainWithTransactions for BridgeHubWococo { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; - Some(UnsignedTransaction::new(tx.function, extra.nonce()).tip(extra.tip())) + Some( + UnsignedTransaction::new( + tx.function, + runtime::rewarding_bridge_signed_extension::nonce(extra), + ) + .tip(runtime::rewarding_bridge_signed_extension::tip(extra)), + ) } } diff --git a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs index c16e7d1a45b..13fb1a7e6ab 100644 --- a/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs +++ b/relays/client-bridge-hub-wococo/src/runtime_wrapper.rs @@ -19,14 +19,17 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use bp_bridge_hub_wococo::SignedExtension; +pub use bp_bridge_hub_wococo::rewarding_bridge_signed_extension; pub use bp_header_chain::BridgeGrandpaCallOf; pub use bp_parachains::BridgeParachainCall; pub use bridge_runtime_common::messages::BridgeMessagesCallOf; pub use relay_substrate_client::calls::{SystemCall, UtilityCall}; /// Unchecked BridgeHubWococo extrinsic. -pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic; +pub type UncheckedExtrinsic = bp_bridge_hub_wococo::UncheckedExtrinsic< + Call, + rewarding_bridge_signed_extension::RewardingBridgeSignedExtension, +>; // The indirect pallet call used to sync `Rococo` GRANDPA finality to `BHWococo`. pub type BridgeRococoGrandpaCall = BridgeGrandpaCallOf;