From e89155d841a85bacd495cee096b49ae06c8d268c Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Mon, 21 Feb 2022 11:53:23 +0300 Subject: [PATCH] Encode and estimate Rococo/Wococo/Kusama/Polkadot messages (#1322) * encode and estimate Rococo/Wococo/Kusama/Polkadot messages * allow send-message for non-bundled chains * weight -> dispatch-weight * fmt * fix spelling --- bridges/primitives/polkadot-core/src/lib.rs | 20 +++--- bridges/primitives/runtime/src/chain.rs | 65 ++++++++++++++++++- bridges/primitives/runtime/src/lib.rs | 4 +- .../relays/bin-substrate/src/chains/kusama.rs | 64 ++++++++++++++---- .../src/chains/kusama_messages_to_polkadot.rs | 8 +-- .../relays/bin-substrate/src/chains/millau.rs | 24 ++++--- .../src/chains/millau_messages_to_rialto.rs | 11 ++-- .../relays/bin-substrate/src/chains/mod.rs | 10 +-- .../bin-substrate/src/chains/polkadot.rs | 64 ++++++++++++++---- .../src/chains/polkadot_messages_to_kusama.rs | 8 +-- .../relays/bin-substrate/src/chains/rialto.rs | 24 ++++--- .../src/chains/rialto_messages_to_millau.rs | 11 ++-- .../src/chains/rialto_parachain.rs | 15 +++-- .../relays/bin-substrate/src/chains/rococo.rs | 63 ++++++++++++++---- .../relays/bin-substrate/src/chains/wococo.rs | 65 +++++++++++++++---- .../bin-substrate/src/cli/encode_call.rs | 10 ++- .../bin-substrate/src/cli/encode_message.rs | 11 +++- .../bin-substrate/src/cli/estimate_fee.rs | 5 +- .../bin-substrate/src/cli/init_bridge.rs | 8 +-- .../src/cli/register_parachain.rs | 27 ++++---- .../src/cli/relay_headers_and_messages.rs | 8 +-- .../src/cli/resubmit_transactions.rs | 4 +- .../bin-substrate/src/cli/send_message.rs | 28 +++++--- .../bin-substrate/src/cli/swap_tokens.rs | 24 +++---- bridges/relays/client-kusama/src/lib.rs | 10 +-- bridges/relays/client-millau/src/lib.rs | 14 ++-- bridges/relays/client-polkadot/src/lib.rs | 10 +-- bridges/relays/client-rialto/src/lib.rs | 14 ++-- bridges/relays/client-rococo/src/lib.rs | 10 +-- bridges/relays/client-substrate/src/chain.rs | 8 +-- bridges/relays/client-substrate/src/client.rs | 8 +-- bridges/relays/client-wococo/src/lib.rs | 10 +-- .../src/finality_target.rs | 8 +-- .../src/headers_initialize.rs | 14 +++- .../src/messages_source.rs | 26 ++++---- .../src/messages_target.rs | 46 +++++++------ 36 files changed, 518 insertions(+), 241 deletions(-) diff --git a/bridges/primitives/polkadot-core/src/lib.rs b/bridges/primitives/polkadot-core/src/lib.rs index 50e8423437405..ce27d22b240b9 100644 --- a/bridges/primitives/polkadot-core/src/lib.rs +++ b/bridges/primitives/polkadot-core/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use bp_messages::MessageNonce; -use bp_runtime::Chain; +use bp_runtime::{Chain, EncodedOrDecodedCall}; use frame_support::{ dispatch::Dispatchable, parameter_types, @@ -228,8 +228,12 @@ pub type SignedBlock = generic::SignedBlock; pub type Balance = u128; /// Unchecked Extrinsic type. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic>; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic< + AccountAddress, + EncodedOrDecodedCall, + Signature, + SignedExtensions, +>; /// Account address, used by the Polkadot-like chain. pub type Address = MultiAddress; @@ -336,12 +340,12 @@ where fn pre_dispatch( self, - who: &Self::AccountId, - call: &Self::Call, - info: &DispatchInfoOf, - len: usize, + _who: &Self::AccountId, + _call: &Self::Call, + _info: &DispatchInfoOf, + _len: usize, ) -> Result { - Ok(self.validate(who, call, info, len).map(|_| ())?) + Ok(()) } } diff --git a/bridges/primitives/runtime/src/chain.rs b/bridges/primitives/runtime/src/chain.rs index 30e754b5702fc..1c80622472291 100644 --- a/bridges/primitives/runtime/src/chain.rs +++ b/bridges/primitives/runtime/src/chain.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use codec::{Decode, Encode}; use frame_support::{weights::Weight, Parameter}; use num_traits::{AsPrimitive, Bounded, CheckedSub, Saturating, SaturatingAdd, Zero}; use sp_runtime::{ @@ -23,7 +24,69 @@ use sp_runtime::{ }, FixedPointOperand, }; -use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr}; +use sp_std::{convert::TryFrom, fmt::Debug, hash::Hash, str::FromStr, vec, vec::Vec}; + +/// Chain call, that is either SCALE-encoded, or decoded. +#[derive(Debug, Clone)] +pub enum EncodedOrDecodedCall { + /// The call that is SCALE-encoded. + /// + /// This variant is used when we the chain runtime is not bundled with the relay, but + /// we still need the represent call in some RPC calls or transactions. + Encoded(Vec), + /// The decoded call. + Decoded(ChainCall), +} + +impl EncodedOrDecodedCall { + /// Returns decoded call. + pub fn to_decoded(&self) -> Result { + match self { + Self::Encoded(ref encoded_call) => + ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), + Self::Decoded(ref decoded_call) => Ok(decoded_call.clone()), + } + } + + /// Converts self to decoded call. + pub fn into_decoded(self) -> Result { + match self { + Self::Encoded(encoded_call) => + ChainCall::decode(&mut &encoded_call[..]).map_err(Into::into), + Self::Decoded(decoded_call) => Ok(decoded_call), + } + } +} + +impl From for EncodedOrDecodedCall { + fn from(call: ChainCall) -> EncodedOrDecodedCall { + EncodedOrDecodedCall::Decoded(call) + } +} + +impl Decode for EncodedOrDecodedCall { + fn decode(input: &mut I) -> Result { + // having encoded version is better than decoded, because decoding isn't required + // everywhere and for mocked calls it may lead to **unneeded** errors + match input.remaining_len()? { + Some(remaining_len) => { + let mut encoded_call = vec![0u8; remaining_len]; + input.read(&mut encoded_call)?; + Ok(EncodedOrDecodedCall::Encoded(encoded_call)) + }, + None => Ok(EncodedOrDecodedCall::Decoded(ChainCall::decode(input)?)), + } + } +} + +impl Encode for EncodedOrDecodedCall { + fn encode(&self) -> Vec { + match *self { + Self::Encoded(ref encoded_call) => encoded_call.clone(), + Self::Decoded(ref decoded_call) => decoded_call.encode(), + } + } +} /// Minimal Substrate-based chain representation that may be used from no_std environment. pub trait Chain: Send + Sync + 'static { diff --git a/bridges/primitives/runtime/src/lib.rs b/bridges/primitives/runtime/src/lib.rs index f69afca4c0851..1d8a40339ab0c 100644 --- a/bridges/primitives/runtime/src/lib.rs +++ b/bridges/primitives/runtime/src/lib.rs @@ -25,8 +25,8 @@ use sp_io::hashing::blake2_256; use sp_std::{convert::TryFrom, vec, vec::Vec}; pub use chain::{ - AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, HashOf, HasherOf, HeaderOf, - IndexOf, SignatureOf, TransactionEraOf, + AccountIdOf, AccountPublicOf, BalanceOf, BlockNumberOf, Chain, EncodedOrDecodedCall, HashOf, + HasherOf, HeaderOf, IndexOf, SignatureOf, TransactionEraOf, }; pub use frame_support::storage::storage_prefix as storage_value_final_key; pub use storage_proof::{Error as StorageProofError, StorageProofChecker}; diff --git a/bridges/relays/bin-substrate/src/chains/kusama.rs b/bridges/relays/bin-substrate/src/chains/kusama.rs index 5a65426c9dc1d..9cdc6cd125e02 100644 --- a/bridges/relays/bin-substrate/src/chains/kusama.rs +++ b/bridges/relays/bin-substrate/src/chains/kusama.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_kusama_client::Kusama; @@ -21,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Kusama. @@ -32,13 +37,15 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Kusama { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_kusama_client::runtime::Call::System( relay_kusama_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::KUSAMA_TO_POLKADOT_INDEX => { @@ -48,6 +55,7 @@ impl CliEncodeCall for Kusama { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -58,13 +66,11 @@ impl CliEncodeCall for Kusama { }) } - fn get_dispatch_info( - call: &relay_kusama_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_kusama_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_kusama_client::runtime::Call::System( relay_kusama_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::kusama::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -78,7 +84,12 @@ impl CliChain for Kusama { const RUNTIME_VERSION: RuntimeVersion = bp_kusama::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_kusama::AccountId, + bp_polkadot::AccountPublic, + bp_polkadot::Signature, + Vec, + >; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -88,8 +99,37 @@ impl CliChain for Kusama { } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - anyhow::bail!("Sending messages from Kusama is not yet supported.") + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Kusama's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Kusama; + type Target = relay_polkadot_client::Polkadot; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::KUSAMA_TO_POLKADOT_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Polkadot call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs b/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs index 5c0b91d8ffe35..3679b26478371 100644 --- a/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs +++ b/bridges/relays/bin-substrate/src/chains/kusama_messages_to_polkadot.rs @@ -82,7 +82,7 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Kusama::sign_transaction(SignParam { spec_version, transaction_version, @@ -96,12 +96,12 @@ pub(crate) async fn update_polkadot_to_kusama_conversion_rate( sp_runtime::FixedU128::from_float(updated_rate), ) ) - ), + ).into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/bridges/relays/bin-substrate/src/chains/millau.rs b/bridges/relays/bin-substrate/src/chains/millau.rs index 3d599c2e54513..1fc1e8308ef45 100644 --- a/bridges/relays/bin-substrate/src/chains/millau.rs +++ b/bridges/relays/bin-substrate/src/chains/millau.rs @@ -25,24 +25,27 @@ use crate::cli::{ }; use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_millau_client::Millau; use sp_version::RuntimeVersion; impl CliEncodeCall for Millau { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }), + }) + .into(), Call::Transfer { recipient, amount } => millau_runtime::Call::Balances(millau_runtime::BalancesCall::transfer { dest: recipient.raw_id(), value: amount.cast(), - }), + }) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::MILLAU_TO_RIALTO_INDEX => { @@ -54,6 +57,7 @@ impl CliEncodeCall for Millau { delivery_and_dispatch_fee: fee.cast(), }, ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -63,8 +67,8 @@ impl CliEncodeCall for Millau { }) } - fn get_dispatch_info(call: &millau_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -90,7 +94,7 @@ impl CliChain for Millau { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| anyhow!("Failed to decode Millau's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { type Source = Millau; type Target = relay_rialto_client::Rialto; @@ -102,11 +106,13 @@ impl CliChain for Millau { bridge::MILLAU_TO_RIALTO_INDEX, ); let call = Target::encode_call(&call)?; - let weight = call.get_dispatch_info().weight; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + call.to_decoded().map(|call| call.get_dispatch_info().weight) + })?; Ok(send_message::message_payload( spec_version, - weight, + dispatch_weight, origin, &call, DispatchFeePayment::AtSourceChain, diff --git a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 906141e2f2be7..a93007c1bb5a1 100644 --- a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -74,7 +74,7 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Millau::sign_transaction(SignParam { spec_version, transaction_version, @@ -82,17 +82,16 @@ pub(crate) async fn update_rialto_to_millau_conversion_rate( signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - millau_runtime::MessagesCall::update_pallet_parameter { + millau_runtime::Call::from(millau_runtime::MessagesCall::update_pallet_parameter { parameter: millau_runtime::rialto_messages::MillauToRialtoMessagesParameter::RialtoToMillauConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), - } - .into(), + }).into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/bridges/relays/bin-substrate/src/chains/mod.rs b/bridges/relays/bin-substrate/src/chains/mod.rs index e2a7a9a2b1eb7..16901143e19fb 100644 --- a/bridges/relays/bin-substrate/src/chains/mod.rs +++ b/bridges/relays/bin-substrate/src/chains/mod.rs @@ -210,8 +210,9 @@ mod tests { genesis_hash: Default::default(), signer: sp_keyring::AccountKeyring::Alice.pair(), era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(rialto_call.clone(), 0), - }); + unsigned: UnsignedTransaction::new(rialto_call.clone().into(), 0), + }) + .unwrap(); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); assert!( bp_rialto::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, @@ -231,8 +232,9 @@ mod tests { genesis_hash: Default::default(), signer: sp_keyring::AccountKeyring::Alice.pair(), era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(millau_call.clone(), 0), - }); + unsigned: UnsignedTransaction::new(millau_call.clone().into(), 0), + }) + .unwrap(); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); assert!( bp_millau::TX_EXTRA_BYTES as usize >= extra_bytes_in_transaction, diff --git a/bridges/relays/bin-substrate/src/chains/polkadot.rs b/bridges/relays/bin-substrate/src/chains/polkadot.rs index 16d44f46873f9..7ae1cbc477777 100644 --- a/bridges/relays/bin-substrate/src/chains/polkadot.rs +++ b/bridges/relays/bin-substrate/src/chains/polkadot.rs @@ -14,6 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . +use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_polkadot_client::Polkadot; @@ -21,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Polkadot. @@ -32,13 +37,15 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Polkadot { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_polkadot_client::runtime::Call::System( relay_polkadot_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::POLKADOT_TO_KUSAMA_INDEX => { @@ -48,6 +55,7 @@ impl CliEncodeCall for Polkadot { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -58,13 +66,11 @@ impl CliEncodeCall for Polkadot { }) } - fn get_dispatch_info( - call: &relay_polkadot_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_polkadot_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_polkadot_client::runtime::Call::System( relay_polkadot_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::polkadot::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -78,7 +84,12 @@ impl CliChain for Polkadot { const RUNTIME_VERSION: RuntimeVersion = bp_polkadot::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_polkadot::AccountId, + bp_kusama::AccountPublic, + bp_kusama::Signature, + Vec, + >; fn ss58_format() -> u16 { sp_core::crypto::Ss58AddressFormat::from( @@ -88,8 +99,37 @@ impl CliChain for Polkadot { } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - anyhow::bail!("Sending messages from Polkadot is not yet supported.") + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Polkadot's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Polkadot; + type Target = relay_kusama_client::Kusama; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::POLKADOT_TO_KUSAMA_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Kusama call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs b/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs index 65b1ce9b06dc8..9f8ec346db266 100644 --- a/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs +++ b/bridges/relays/bin-substrate/src/chains/polkadot_messages_to_kusama.rs @@ -82,7 +82,7 @@ pub(crate) async fn update_kusama_to_polkadot_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Polkadot::sign_transaction(SignParam { spec_version, transaction_version, @@ -96,12 +96,12 @@ pub(crate) async fn update_kusama_to_polkadot_conversion_rate( sp_runtime::FixedU128::from_float(updated_rate), ) ) - ), + ).into(), transaction_nonce, ) - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/bridges/relays/bin-substrate/src/chains/rialto.rs b/bridges/relays/bin-substrate/src/chains/rialto.rs index 8931c5112da80..8f26a64a4e326 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto.rs @@ -25,24 +25,27 @@ use crate::cli::{ }; use anyhow::anyhow; use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_client::Rialto; use sp_version::RuntimeVersion; impl CliEncodeCall for Rialto { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), - }), + }) + .into(), Call::Transfer { recipient, amount } => rialto_runtime::Call::Balances(rialto_runtime::BalancesCall::transfer { dest: recipient.raw_id().into(), value: amount.0, - }), + }) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::RIALTO_TO_MILLAU_INDEX => { @@ -54,6 +57,7 @@ impl CliEncodeCall for Rialto { delivery_and_dispatch_fee: fee.0, }, ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -63,8 +67,8 @@ impl CliEncodeCall for Rialto { }) } - fn get_dispatch_info(call: &rialto_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } @@ -89,7 +93,7 @@ impl CliChain for Rialto { match message { encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) .map_err(|e| anyhow!("Failed to decode Rialto's MessagePayload: {:?}", e)), - encode_message::MessagePayload::Call { mut call, mut sender } => { + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { type Source = Rialto; type Target = relay_millau_client::Millau; @@ -101,11 +105,13 @@ impl CliChain for Rialto { bridge::RIALTO_TO_MILLAU_INDEX, ); let call = Target::encode_call(&call)?; - let weight = call.get_dispatch_info().weight; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + call.to_decoded().map(|call| call.get_dispatch_info().weight) + })?; Ok(send_message::message_payload( spec_version, - weight, + dispatch_weight, origin, &call, DispatchFeePayment::AtSourceChain, diff --git a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index 4a570050f4eb8..6de10d2346f93 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -74,7 +74,7 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(signer_id, move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Rialto::sign_transaction(SignParam { spec_version, transaction_version, @@ -82,17 +82,16 @@ pub(crate) async fn update_millau_to_rialto_conversion_rate( signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - rialto_runtime::MessagesCall::update_pallet_parameter { + rialto_runtime::Call::from(rialto_runtime::MessagesCall::update_pallet_parameter { parameter: rialto_runtime::millau_messages::RialtoToMillauMessagesParameter::MillauToRialtoConversionRate( sp_runtime::FixedU128::from_float(updated_rate), ), - } - .into(), + }).into(), transaction_nonce, ) - }) + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs b/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs index da400a4dafd87..0ed39faa543b7 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_parachain.rs @@ -21,34 +21,37 @@ use crate::cli::{ encode_message, CliChain, }; use bp_message_dispatch::MessagePayload; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchInfo, GetDispatchInfo}; use relay_rialto_parachain_client::RialtoParachain; use sp_version::RuntimeVersion; impl CliEncodeCall for RialtoParachain { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { - Call::Raw { data } => Decode::decode(&mut &*data.0)?, + Call::Raw { data } => Self::Call::decode(&mut &*data.0)?.into(), Call::Remark { remark_payload, .. } => rialto_parachain_runtime::Call::System( rialto_parachain_runtime::SystemCall::remark { remark: remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), }, - ), + ) + .into(), Call::Transfer { recipient, amount } => rialto_parachain_runtime::Call::Balances( rialto_parachain_runtime::BalancesCall::transfer { dest: recipient.raw_id().into(), value: amount.0, }, - ), + ) + .into(), Call::BridgeSendMessage { .. } => { anyhow::bail!("Bridge messages are not (yet) supported here",) }, }) } - fn get_dispatch_info(call: &rialto_parachain_runtime::Call) -> anyhow::Result { - Ok(call.get_dispatch_info()) + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { + Ok(call.to_decoded()?.get_dispatch_info()) } } diff --git a/bridges/relays/bin-substrate/src/chains/rococo.rs b/bridges/relays/bin-substrate/src/chains/rococo.rs index ef49899ec791d..ceef4c1f532c9 100644 --- a/bridges/relays/bin-substrate/src/chains/rococo.rs +++ b/bridges/relays/bin-substrate/src/chains/rococo.rs @@ -15,6 +15,8 @@ // along with Parity Bridges Common. If not, see . use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays, Weight}; use relay_rococo_client::Rococo; @@ -22,8 +24,10 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; /// Weight of the `system::remark` call at Rococo. @@ -33,13 +37,15 @@ use crate::cli::{ pub(crate) const SYSTEM_REMARK_CALL_WEIGHT: Weight = 2 * 1_345_000; impl CliEncodeCall for Rococo { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_rococo_client::runtime::Call::System( relay_rococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::ROCOCO_TO_WOCOCO_INDEX => { @@ -49,6 +55,7 @@ impl CliEncodeCall for Rococo { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -59,13 +66,11 @@ impl CliEncodeCall for Rococo { }) } - fn get_dispatch_info( - call: &relay_rococo_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_rococo_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_rococo_client::runtime::Call::System( relay_rococo_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, @@ -79,15 +84,49 @@ impl CliChain for Rococo { const RUNTIME_VERSION: RuntimeVersion = bp_rococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_rococo::AccountId, + bp_wococo::AccountPublic, + bp_wococo::Signature, + Vec, + >; fn ss58_format() -> u16 { 42 } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - Err(anyhow!("Sending messages from Rococo is not yet supported.")) + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Rococo's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Rococo; + type Target = relay_wococo_client::Wococo; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::ROCOCO_TO_WOCOCO_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Wococo call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/bridges/relays/bin-substrate/src/chains/wococo.rs b/bridges/relays/bin-substrate/src/chains/wococo.rs index 2acc8af484567..46dec2a3c90e3 100644 --- a/bridges/relays/bin-substrate/src/chains/wococo.rs +++ b/bridges/relays/bin-substrate/src/chains/wococo.rs @@ -15,6 +15,8 @@ // along with Parity Bridges Common. If not, see . use anyhow::anyhow; +use bp_message_dispatch::{CallOrigin, MessagePayload}; +use bp_runtime::EncodedOrDecodedCall; use codec::Decode; use frame_support::weights::{DispatchClass, DispatchInfo, Pays}; use relay_wococo_client::Wococo; @@ -22,18 +24,22 @@ use sp_version::RuntimeVersion; use crate::cli::{ bridge, - encode_call::{Call, CliEncodeCall}, - encode_message, CliChain, + encode_call::{self, Call, CliEncodeCall}, + encode_message, + send_message::{self, DispatchFeePayment}, + CliChain, }; impl CliEncodeCall for Wococo { - fn encode_call(call: &Call) -> anyhow::Result { + fn encode_call(call: &Call) -> anyhow::Result> { Ok(match call { + Call::Raw { data } => EncodedOrDecodedCall::Encoded(data.0.clone()), Call::Remark { remark_payload, .. } => relay_wococo_client::runtime::Call::System( relay_wococo_client::runtime::SystemCall::remark( remark_payload.as_ref().map(|x| x.0.clone()).unwrap_or_default(), ), - ), + ) + .into(), Call::BridgeSendMessage { lane, payload, fee, bridge_instance_index } => match *bridge_instance_index { bridge::WOCOCO_TO_ROCOCO_INDEX => { @@ -43,6 +49,7 @@ impl CliEncodeCall for Wococo { lane.0, payload, fee.0, ), ) + .into() }, _ => anyhow::bail!( "Unsupported target bridge pallet with instance index: {}", @@ -53,18 +60,16 @@ impl CliEncodeCall for Wococo { }) } - fn get_dispatch_info( - call: &relay_wococo_client::runtime::Call, - ) -> anyhow::Result { + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result { match *call { - relay_wococo_client::runtime::Call::System( + EncodedOrDecodedCall::Decoded(relay_wococo_client::runtime::Call::System( relay_wococo_client::runtime::SystemCall::remark(_), - ) => Ok(DispatchInfo { + )) => Ok(DispatchInfo { weight: crate::chains::rococo::SYSTEM_REMARK_CALL_WEIGHT, class: DispatchClass::Normal, pays_fee: Pays::Yes, }), - _ => anyhow::bail!("Unsupported Rococo call: {:?}", call), + _ => anyhow::bail!("Unsupported Wococo call: {:?}", call), } } } @@ -73,15 +78,49 @@ impl CliChain for Wococo { const RUNTIME_VERSION: RuntimeVersion = bp_wococo::VERSION; type KeyPair = sp_core::sr25519::Pair; - type MessagePayload = (); + type MessagePayload = MessagePayload< + bp_wococo::AccountId, + bp_rococo::AccountPublic, + bp_rococo::Signature, + Vec, + >; fn ss58_format() -> u16 { 42 } fn encode_message( - _message: encode_message::MessagePayload, + message: encode_message::MessagePayload, ) -> anyhow::Result { - Err(anyhow!("Sending messages from Wococo is not yet supported.")) + match message { + encode_message::MessagePayload::Raw { data } => MessagePayload::decode(&mut &*data.0) + .map_err(|e| anyhow!("Failed to decode Wococo's MessagePayload: {:?}", e)), + encode_message::MessagePayload::Call { mut call, mut sender, dispatch_weight } => { + type Source = Wococo; + type Target = relay_rococo_client::Rococo; + + sender.enforce_chain::(); + let spec_version = Target::RUNTIME_VERSION.spec_version; + let origin = CallOrigin::SourceAccount(sender.raw_id()); + encode_call::preprocess_call::( + &mut call, + bridge::WOCOCO_TO_ROCOCO_INDEX, + ); + let call = Target::encode_call(&call)?; + let dispatch_weight = dispatch_weight.map(Ok).unwrap_or_else(|| { + Err(anyhow::format_err!( + "Please specify dispatch weight of the encoded Rococo call" + )) + })?; + + Ok(send_message::message_payload( + spec_version, + dispatch_weight, + origin, + &call, + DispatchFeePayment::AtSourceChain, + )) + }, + } } } diff --git a/bridges/relays/bin-substrate/src/cli/encode_call.rs b/bridges/relays/bin-substrate/src/cli/encode_call.rs index 707e78378302f..e288e2c13d6cd 100644 --- a/bridges/relays/bin-substrate/src/cli/encode_call.rs +++ b/bridges/relays/bin-substrate/src/cli/encode_call.rs @@ -20,6 +20,7 @@ use crate::{ }, select_full_bridge, }; +use bp_runtime::EncodedOrDecodedCall; use frame_support::weights::DispatchInfo; use relay_substrate_client::Chain; use structopt::StructOpt; @@ -85,10 +86,10 @@ pub enum Call { pub trait CliEncodeCall: Chain { /// Encode a CLI call. - fn encode_call(call: &Call) -> anyhow::Result; + fn encode_call(call: &Call) -> anyhow::Result>; /// Get dispatch info for the call. - fn get_dispatch_info(call: &Self::Call) -> anyhow::Result; + fn get_dispatch_info(call: &EncodedOrDecodedCall) -> anyhow::Result; } impl EncodeCall { @@ -100,7 +101,10 @@ impl EncodeCall { let encoded = HexBytes::encode(&call); log::info!(target: "bridge", "Generated {} call: {:#?}", Source::NAME, call); - log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call)?.weight); + log::info!(target: "bridge", "Weight of {} call: {}", Source::NAME, Source::get_dispatch_info(&call) + .map(|dispatch_info| format!("{}", dispatch_info.weight)) + .unwrap_or_else(|_| "".to_string()) + ); log::info!(target: "bridge", "Encoded {} call: {:?}", Source::NAME, encoded); Ok(encoded) diff --git a/bridges/relays/bin-substrate/src/cli/encode_message.rs b/bridges/relays/bin-substrate/src/cli/encode_message.rs index ee77fc4a46efe..677fc29ef1531 100644 --- a/bridges/relays/bin-substrate/src/cli/encode_message.rs +++ b/bridges/relays/bin-substrate/src/cli/encode_message.rs @@ -18,6 +18,7 @@ use crate::{ cli::{bridge::FullBridge, AccountId, CliChain, HexBytes}, select_full_bridge, }; +use frame_support::weights::Weight; use structopt::StructOpt; use strum::VariantNames; @@ -37,6 +38,12 @@ pub enum MessagePayload { /// SS58 encoded Source account that will send the payload. #[structopt(long)] sender: AccountId, + /// Weight of the call. + /// + /// It must be specified if the chain runtime is not bundled with the relay, or if + /// you want to override bundled weight. + #[structopt(long)] + dispatch_weight: Option, }, } @@ -97,6 +104,8 @@ mod tests { "call", "--sender", &sender, + "--dispatch-weight", + "42", "remark", "--remark-size", "12", @@ -106,6 +115,6 @@ mod tests { let hex = encode_message.encode().unwrap(); // then - assert_eq!(format!("{:?}", hex), "0x01000000000000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); + assert_eq!(format!("{:?}", hex), "0x010000002a0000000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000"); } } diff --git a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs index 18e7341fc9658..30bcae079b091 100644 --- a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs @@ -103,6 +103,8 @@ mod tests { "call", "--sender", &alice, + "--dispatch-weight", + "42", "remark", "--remark-payload", "1234", @@ -129,7 +131,8 @@ mod tests { call: encode_call::Call::Remark { remark_payload: Some(HexBytes(vec![0x12, 0x34])), remark_size: None, - } + }, + dispatch_weight: Some(42), } } ); diff --git a/bridges/relays/bin-substrate/src/cli/init_bridge.rs b/bridges/relays/bin-substrate/src/cli/init_bridge.rs index 50be6c87ccc46..ad133e369f59a 100644 --- a/bridges/relays/bin-substrate/src/cli/init_bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/init_bridge.rs @@ -222,7 +222,7 @@ impl InitBridge { target_client.clone(), target_sign.public().into(), move |transaction_nonce, initialization_data| { - Bytes( + Ok(Bytes( Target::sign_transaction(SignParam { spec_version, transaction_version, @@ -230,12 +230,12 @@ impl InitBridge { signer: target_sign, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - encode_init_bridge(initialization_data), + encode_init_bridge(initialization_data).into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await; diff --git a/bridges/relays/bin-substrate/src/cli/register_parachain.rs b/bridges/relays/bin-substrate/src/cli/register_parachain.rs index d42e10d708fb6..4ede369026111 100644 --- a/bridges/relays/bin-substrate/src/cli/register_parachain.rs +++ b/bridges/relays/bin-substrate/src/cli/register_parachain.rs @@ -132,7 +132,7 @@ impl RegisterParachain { .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Relaychain::sign_transaction(SignParam { spec_version, transaction_version, @@ -140,12 +140,12 @@ impl RegisterParachain { signer: reserve_parachain_signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - reserve_parachain_id_call, + reserve_parachain_id_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -181,7 +181,7 @@ impl RegisterParachain { .submit_and_watch_signed_extrinsic( relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Relaychain::sign_transaction(SignParam { spec_version, transaction_version, @@ -189,12 +189,12 @@ impl RegisterParachain { signer: register_parathread_signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - register_parathread_call, + register_parathread_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -243,17 +243,20 @@ impl RegisterParachain { let force_lease_signer = relay_sign.clone(); relay_client .submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Relaychain::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: relay_genesis_hash, signer: force_lease_signer, era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(force_lease_call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new( + force_lease_call.into(), + transaction_nonce, + ), + })? .encode(), - ) + )) }) .await?; log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index 4a4d24964fc5e..c8d74b8faec13 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -615,17 +615,17 @@ where let (spec_version, transaction_version) = client.simple_runtime_version().await?; client .submit_signed_extrinsic(sign.public().into(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( C::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash, signer: sign, era: relay_substrate_client::TransactionEra::immortal(), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) }) .await .map(drop) diff --git a/bridges/relays/bin-substrate/src/cli/resubmit_transactions.rs b/bridges/relays/bin-substrate/src/cli/resubmit_transactions.rs index 8b021df86372d..81fa54dcd2dfb 100644 --- a/bridges/relays/bin-substrate/src/cli/resubmit_transactions.rs +++ b/bridges/relays/bin-substrate/src/cli/resubmit_transactions.rs @@ -445,7 +445,7 @@ async fn update_transaction_tip>( signer: key_pair.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: unsigned_tx.clone(), - }), + })?, ) .await?? .priority; @@ -468,7 +468,7 @@ async fn update_transaction_tip>( signer: key_pair.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: unsigned_tx, - }), + })?, )) } diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index e3597f766b740..45f5fa89d02e9 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -124,9 +124,13 @@ impl SendMessage { let payload = { let target_call_weight = prepare_call_dispatch_weight( dispatch_weight, - ExplicitOrMaximal::Explicit(Target::get_dispatch_info(&target_call)?.weight), + || { + Ok(ExplicitOrMaximal::Explicit( + Target::get_dispatch_info(&target_call)?.weight, + )) + }, compute_maximal_message_dispatch_weight(Target::max_extrinsic_weight()), - ); + )?; let source_sender_public: MultiSigner = source_sign.public().into(); let source_account_id = source_sender_public.into_account(); @@ -200,7 +204,7 @@ impl SendMessage { signer: source_sign.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), - }) + })? .encode(), )) .await?; @@ -213,7 +217,7 @@ impl SendMessage { signer: source_sign.clone(), era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), - }) + })? .encode(); log::info!( @@ -241,7 +245,7 @@ impl SendMessage { HexBytes::encode(&signed_source_call) ); - Bytes(signed_source_call) + Ok(Bytes(signed_source_call)) }) .await?; }); @@ -252,12 +256,16 @@ impl SendMessage { fn prepare_call_dispatch_weight( user_specified_dispatch_weight: &Option>, - weight_from_pre_dispatch_call: ExplicitOrMaximal, + weight_from_pre_dispatch_call: impl Fn() -> anyhow::Result>, maximal_allowed_weight: Weight, -) -> Weight { - match user_specified_dispatch_weight.clone().unwrap_or(weight_from_pre_dispatch_call) { - ExplicitOrMaximal::Explicit(weight) => weight, - ExplicitOrMaximal::Maximal => maximal_allowed_weight, +) -> anyhow::Result { + match user_specified_dispatch_weight + .clone() + .map(Ok) + .unwrap_or_else(weight_from_pre_dispatch_call)? + { + ExplicitOrMaximal::Explicit(weight) => Ok(weight), + ExplicitOrMaximal::Maximal => Ok(maximal_allowed_weight), } } diff --git a/bridges/relays/bin-substrate/src/cli/swap_tokens.rs b/bridges/relays/bin-substrate/src/cli/swap_tokens.rs index 16ec0d6a6fa16..b9cdac7d3487e 100644 --- a/bridges/relays/bin-substrate/src/cli/swap_tokens.rs +++ b/bridges/relays/bin-substrate/src/cli/swap_tokens.rs @@ -245,7 +245,7 @@ impl SwapTokens { .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Source::sign_transaction(SignParam { spec_version, transaction_version, @@ -253,12 +253,12 @@ impl SwapTokens { signer: create_swap_signer, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - create_swap_call, + create_swap_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -386,7 +386,7 @@ impl SwapTokens { .submit_and_watch_signed_extrinsic( accounts.target_account_at_bridged_chain.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Target::sign_transaction(SignParam { spec_version, transaction_version, @@ -394,12 +394,12 @@ impl SwapTokens { signer: target_sign, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - send_message_call, + send_message_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, @@ -430,7 +430,7 @@ impl SwapTokens { .submit_and_watch_signed_extrinsic( accounts.source_account_at_this_chain.clone(), move |_, transaction_nonce| { - Bytes( + Ok(Bytes( Source::sign_transaction(SignParam { spec_version, transaction_version, @@ -438,12 +438,12 @@ impl SwapTokens { signer: source_sign, era: relay_substrate_client::TransactionEra::immortal(), unsigned: UnsignedTransaction::new( - cancel_swap_call, + cancel_swap_call.into(), transaction_nonce, ), - }) + })? .encode(), - ) + )) }, ) .await?, diff --git a/bridges/relays/client-kusama/src/lib.rs b/bridges/relays/client-kusama/src/lib.rs index 982bf88d82a96..532049e7056e8 100644 --- a/bridges/relays/client-kusama/src/lib.rs +++ b/bridges/relays/client-kusama/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -101,7 +101,7 @@ impl TransactionSignScheme for Kusama { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_kusama::SignedExtensions::new( @@ -119,12 +119,12 @@ impl TransactionSignScheme for Kusama { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_kusama::UncheckedExtrinsic::new_signed( + Ok(bp_kusama::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/bridges/relays/client-millau/src/lib.rs b/bridges/relays/client-millau/src/lib.rs index 3c159907f7d00..cb181bc04ee92 100644 --- a/bridges/relays/client-millau/src/lib.rs +++ b/bridges/relays/client-millau/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, IndexOf, - SignParam, TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -103,7 +103,7 @@ impl TransactionSignScheme for Millau { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = millau_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( param.unsigned.call.clone(), ( @@ -129,12 +129,12 @@ impl TransactionSignScheme for Millau { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - millau_runtime::UncheckedExtrinsic::new_signed( - call, + Ok(millau_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, signer.into_account(), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -153,7 +153,7 @@ impl TransactionSignScheme for Millau { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { - call: tx.function, + call: tx.function.into(), nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? diff --git a/bridges/relays/client-polkadot/src/lib.rs b/bridges/relays/client-polkadot/src/lib.rs index 6671b8c7228fc..c4098c819a02f 100644 --- a/bridges/relays/client-polkadot/src/lib.rs +++ b/bridges/relays/client-polkadot/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -102,7 +102,7 @@ impl TransactionSignScheme for Polkadot { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_polkadot::SignedExtensions::new( @@ -120,12 +120,12 @@ impl TransactionSignScheme for Polkadot { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_polkadot::UncheckedExtrinsic::new_signed( + Ok(bp_polkadot::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/bridges/relays/client-rialto/src/lib.rs b/bridges/relays/client-rialto/src/lib.rs index 4062a36b0d747..e8a892a2ff415 100644 --- a/bridges/relays/client-rialto/src/lib.rs +++ b/bridges/relays/client-rialto/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::{Compact, Decode, Encode}; use frame_support::weights::Weight; use relay_substrate_client::{ - BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, IndexOf, - SignParam, TransactionSignScheme, UnsignedTransaction, + BalanceOf, Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, IndexOf, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -103,7 +103,7 @@ impl TransactionSignScheme for Rialto { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = rialto_runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::from_raw( param.unsigned.call.clone(), ( @@ -129,12 +129,12 @@ impl TransactionSignScheme for Rialto { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - rialto_runtime::UncheckedExtrinsic::new_signed( - call, + Ok(rialto_runtime::UncheckedExtrinsic::new_signed( + call.into_decoded()?, signer.into_account().into(), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { @@ -151,7 +151,7 @@ impl TransactionSignScheme for Rialto { fn parse_transaction(tx: Self::SignedTransaction) -> Option> { let extra = &tx.signature.as_ref()?.2; Some(UnsignedTransaction { - call: tx.function, + call: tx.function.into(), nonce: Compact::>::decode(&mut &extra.4.encode()[..]).ok()?.into(), tip: Compact::>::decode(&mut &extra.6.encode()[..]) .ok()? diff --git a/bridges/relays/client-rococo/src/lib.rs b/bridges/relays/client-rococo/src/lib.rs index 56ca95606a8e7..e8b5a1abd41e0 100644 --- a/bridges/relays/client-rococo/src/lib.rs +++ b/bridges/relays/client-rococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -104,7 +104,7 @@ impl TransactionSignScheme for Rococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_rococo::SignedExtensions::new( @@ -122,12 +122,12 @@ impl TransactionSignScheme for Rococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_rococo::UncheckedExtrinsic::new_signed( + Ok(bp_rococo::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/bridges/relays/client-substrate/src/chain.rs b/bridges/relays/client-substrate/src/chain.rs index 24b0127f3a7c0..97a2288f478d3 100644 --- a/bridges/relays/client-substrate/src/chain.rs +++ b/bridges/relays/client-substrate/src/chain.rs @@ -15,7 +15,7 @@ // along with Parity Bridges Common. If not, see . use bp_messages::MessageNonce; -use bp_runtime::{Chain as ChainBase, HashOf, TransactionEraOf}; +use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; use codec::{Codec, Encode}; use frame_support::weights::{Weight, WeightToFeePolynomial}; use jsonrpsee_ws_client::types::{DeserializeOwned, Serialize}; @@ -141,7 +141,7 @@ pub trait BlockWithJustification
{ #[derive(Clone, Debug)] pub struct UnsignedTransaction { /// Runtime call of this transaction. - pub call: C::Call, + pub call: EncodedOrDecodedCall, /// Transaction nonce. pub nonce: C::Index, /// Tip included into transaction. @@ -150,7 +150,7 @@ pub struct UnsignedTransaction { impl UnsignedTransaction { /// Create new unsigned transaction with given call, nonce and zero tip. - pub fn new(call: C::Call, nonce: C::Index) -> Self { + pub fn new(call: EncodedOrDecodedCall, nonce: C::Index) -> Self { Self { call, nonce, tip: Zero::zero() } } @@ -174,7 +174,7 @@ pub trait TransactionSignScheme { type SignedTransaction: Clone + Debug + Codec + Send + 'static; /// Create transaction for given runtime call, signed by given account. - fn sign_transaction(param: SignParam) -> Self::SignedTransaction + fn sign_transaction(param: SignParam) -> Result where Self: Sized; diff --git a/bridges/relays/client-substrate/src/client.rs b/bridges/relays/client-substrate/src/client.rs index 685f938d18a43..f35281e2d35c5 100644 --- a/bridges/relays/client-substrate/src/client.rs +++ b/bridges/relays/client-substrate/src/client.rs @@ -373,7 +373,7 @@ impl Client { pub async fn submit_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, ) -> Result { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -390,7 +390,7 @@ impl Client { }; self.jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; let tx_hash = Substrate::::author_submit_extrinsic(&*client, extrinsic).await?; log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); Ok(tx_hash) @@ -403,7 +403,7 @@ impl Client { pub async fn submit_and_watch_signed_extrinsic( &self, extrinsic_signer: C::AccountId, - prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Bytes + Send + 'static, + prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result + Send + 'static, ) -> Result>> { let _guard = self.submit_signed_extrinsic_lock.lock().await; let transaction_nonce = self.next_account_index(extrinsic_signer).await?; @@ -411,7 +411,7 @@ impl Client { let best_header_id = HeaderId(*best_header.number(), best_header.hash()); let subscription = self .jsonrpsee_execute(move |client| async move { - let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce); + let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce)?; let tx_hash = C::Hasher::hash(&extrinsic.0); let subscription = client .subscribe( diff --git a/bridges/relays/client-wococo/src/lib.rs b/bridges/relays/client-wococo/src/lib.rs index fd45fc0dc186f..cb4c04903cb88 100644 --- a/bridges/relays/client-wococo/src/lib.rs +++ b/bridges/relays/client-wococo/src/lib.rs @@ -20,8 +20,8 @@ use bp_messages::MessageNonce; use codec::Encode; use frame_support::weights::Weight; use relay_substrate_client::{ - Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, SignParam, - TransactionSignScheme, UnsignedTransaction, + Chain, ChainBase, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, + Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -104,7 +104,7 @@ impl TransactionSignScheme for Wococo { type AccountKeyPair = sp_core::sr25519::Pair; type SignedTransaction = crate::runtime::UncheckedExtrinsic; - fn sign_transaction(param: SignParam) -> Self::SignedTransaction { + fn sign_transaction(param: SignParam) -> Result { let raw_payload = SignedPayload::new( param.unsigned.call.clone(), bp_wococo::SignedExtensions::new( @@ -122,12 +122,12 @@ impl TransactionSignScheme for Wococo { let signer: sp_runtime::MultiSigner = param.signer.public().into(); let (call, extra, _) = raw_payload.deconstruct(); - bp_wococo::UncheckedExtrinsic::new_signed( + Ok(bp_wococo::UncheckedExtrinsic::new_signed( call, sp_runtime::MultiAddress::Id(signer.into_account()), signature.into(), extra, - ) + )) } fn is_signed(tx: &Self::SignedTransaction) -> bool { diff --git a/bridges/relays/lib-substrate-relay/src/finality_target.rs b/bridges/relays/lib-substrate-relay/src/finality_target.rs index 9a92c88a234a9..e7a7487ae2c17 100644 --- a/bridges/relays/lib-substrate-relay/src/finality_target.rs +++ b/bridges/relays/lib-substrate-relay/src/finality_target.rs @@ -123,17 +123,17 @@ where .submit_signed_extrinsic( self.transaction_params.signer.public().into(), move |best_block_id, transaction_nonce| { - Bytes( + Ok(Bytes( P::TransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash, signer: transaction_params.signer.clone(), era: TransactionEra::new(best_block_id, transaction_params.mortality), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) }, ) .await diff --git a/bridges/relays/lib-substrate-relay/src/headers_initialize.rs b/bridges/relays/lib-substrate-relay/src/headers_initialize.rs index 8713663dd8296..0e1371c53c815 100644 --- a/bridges/relays/lib-substrate-relay/src/headers_initialize.rs +++ b/bridges/relays/lib-substrate-relay/src/headers_initialize.rs @@ -31,7 +31,9 @@ use bp_header_chain::{ use codec::Decode; use finality_grandpa::voter_set::VoterSet; use num_traits::{One, Zero}; -use relay_substrate_client::{BlockNumberOf, Chain, ChainWithGrandpa, Client, HashOf}; +use relay_substrate_client::{ + BlockNumberOf, Chain, ChainWithGrandpa, Client, Error as SubstrateError, HashOf, +}; use sp_core::Bytes; use sp_finality_grandpa::AuthorityList as GrandpaAuthoritiesSet; use sp_runtime::traits::Header as HeaderT; @@ -41,7 +43,10 @@ pub async fn initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + prepare_initialize_transaction: impl FnOnce( + TargetChain::Index, + InitializationData, + ) -> Result + Send + 'static, ) { @@ -77,7 +82,10 @@ async fn do_initialize( source_client: Client, target_client: Client, target_transactions_signer: TargetChain::AccountId, - prepare_initialize_transaction: impl FnOnce(TargetChain::Index, InitializationData) -> Bytes + prepare_initialize_transaction: impl FnOnce( + TargetChain::Index, + InitializationData, + ) -> Result + Send + 'static, ) -> Result< diff --git a/bridges/relays/lib-substrate-relay/src/messages_source.rs b/bridges/relays/lib-substrate-relay/src/messages_source.rs index de2306be3fef4..96e19beba25ca 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_source.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_source.rs @@ -282,8 +282,8 @@ where Ok(v) => v, Err(_) => return BalanceOf::::max_value(), }; - self.client - .estimate_extrinsic_fee(make_messages_delivery_proof_transaction::

( + async { + let dummy_tx = make_messages_delivery_proof_transaction::

( runtime_version.spec_version, runtime_version.transaction_version, self.client.genesis_hash(), @@ -292,10 +292,14 @@ where Zero::zero(), prepare_dummy_messages_delivery_proof::(), false, - )) - .await - .map(|fee| fee.inclusion_fee()) - .unwrap_or_else(|_| BalanceOf::::max_value()) + )?; + self.client + .estimate_extrinsic_fee(dummy_tx) + .await + .map(|fee| fee.inclusion_fee()) + } + .await + .unwrap_or_else(|_| BalanceOf::::max_value()) } } @@ -328,7 +332,7 @@ fn make_messages_delivery_proof_transaction( transaction_nonce: IndexOf, proof: SubstrateMessagesDeliveryProof, trace_call: bool, -) -> Bytes +) -> Result where P::SourceTransactionSignScheme: TransactionSignScheme, { @@ -336,17 +340,17 @@ where P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( proof, trace_call, ); - Bytes( + Ok(Bytes( P::SourceTransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: *source_genesis_hash, signer: source_transaction_params.signer.clone(), era: TransactionEra::new(source_best_block_id, source_transaction_params.mortality), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) } /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. diff --git a/bridges/relays/lib-substrate-relay/src/messages_target.rs b/bridges/relays/lib-substrate-relay/src/messages_target.rs index 5336e065a92b0..72267cbc09ac6 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_target.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_target.rs @@ -298,7 +298,7 @@ where total_size, ), false, - ); + )?; let delivery_tx_fee = self.client.estimate_extrinsic_fee(delivery_tx).await?; let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); @@ -323,25 +323,23 @@ where let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); - let larger_delivery_tx_fee = self - .client - .estimate_extrinsic_fee(make_messages_delivery_transaction::

( - spec_version, - transaction_version, - self.client.genesis_hash(), - &self.transaction_params, - HeaderId(Default::default(), Default::default()), - Zero::zero(), - self.relayer_id_at_source.clone(), + let dummy_tx = make_messages_delivery_transaction::

( + spec_version, + transaction_version, + self.client.genesis_hash(), + &self.transaction_params, + HeaderId(Default::default(), Default::default()), + Zero::zero(), + self.relayer_id_at_source.clone(), + nonces.clone(), + prepare_dummy_messages_proof::( nonces.clone(), - prepare_dummy_messages_proof::( - nonces.clone(), - larger_dispatch_weight, - total_size, - ), - false, - )) - .await?; + larger_dispatch_weight, + total_size, + ), + false, + )?; + let larger_delivery_tx_fee = self.client.estimate_extrinsic_fee(dummy_tx).await?; compute_prepaid_messages_refund::( total_prepaid_nonces, @@ -402,7 +400,7 @@ fn make_messages_delivery_transaction( nonces: RangeInclusive, proof: SubstrateMessagesProof, trace_call: bool, -) -> Bytes +) -> Result where P::TargetTransactionSignScheme: TransactionSignScheme, { @@ -415,17 +413,17 @@ where dispatch_weight, trace_call, ); - Bytes( + Ok(Bytes( P::TargetTransactionSignScheme::sign_transaction(SignParam { spec_version, transaction_version, genesis_hash: *target_genesis_hash, signer: target_transaction_params.signer.clone(), era: TransactionEra::new(target_best_block_id, target_transaction_params.mortality), - unsigned: UnsignedTransaction::new(call, transaction_nonce), - }) + unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), + })? .encode(), - ) + )) } /// Prepare 'dummy' messages proof that will compose the delivery transaction.