From 71f0eb9b6e29821c4b4b1ead0da8c72ebe75e7ca Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Tue, 27 Dec 2022 15:39:23 +0200 Subject: [PATCH] Replace `BATCH_CALL_SUPPORTED` (#1733) * Simplify submit_and_watch_signed_extrinsic The way submit_and_watch_signed_extrinsic is used now, we can always derive the SignParam from other params. If in the future we need more customization possibilities, we can define a new method. * Simplify submit_signed_extrinsic * Send maybe_batch_tx as a parameter Send `maybe_batch_tx` as a parameter to `submit_proof()`. This way we can deduplicate the logic that submits the extrinsic for `messages_source and `messages_target` and we can simplify the logic in the race loop a bit. * Define BatchProofTransaction Deduplicate BatchConfirmationTransaction and BatchDeliveryTransaction by replacing both of them with BatchProofTransaction * Define ChainWithUtilityPallet and BatchCallBuilderConstructor - Define `ChainWithUtilityPallet` in order to be able to associate the batching functionality with chains - Defining `BatchCallBuilderConstructor` in order to have a more reliable way of checking whether an end of a messages pipeline supports batching or no. `BatchCallBuilderConstructor::new_builder()` returns an `Option`.This is a bit safer because each time a caller tries to start creating a batch call, it will call `new_builder()` and will be required to handle the returned `Option`. Before we only had a bool `BATCH_CALL_SUPPORTED` the caller could have forgetten to check. --- .../rialto_parachain_messages_to_millau.rs | 4 +- .../bin-substrate/src/cli/init_bridge.rs | 11 +- .../src/cli/register_parachain.rs | 61 ++------ .../bin-substrate/src/cli/send_message.rs | 34 ++--- bridges/relays/client-millau/src/lib.rs | 8 +- bridges/relays/client-substrate/Cargo.toml | 1 + bridges/relays/client-substrate/src/chain.rs | 28 ++++ bridges/relays/client-substrate/src/client.rs | 33 +++-- bridges/relays/client-substrate/src/lib.rs | 5 +- .../src/finality/initialize.rs | 39 +++-- .../src/finality/target.rs | 14 +- bridges/relays/lib-substrate-relay/src/lib.rs | 64 ++++---- .../lib-substrate-relay/src/messages_lane.rs | 57 +++++++- .../src/messages_source.rs | 137 ++++------------- .../src/messages_target.rs | 138 ++++-------------- .../src/parachains/target.rs | 12 +- .../relays/messages/src/message_lane_loop.rs | 65 ++------- .../messages/src/message_race_delivery.rs | 5 +- .../relays/messages/src/message_race_loop.rs | 57 +++----- .../messages/src/message_race_receiving.rs | 7 +- 20 files changed, 288 insertions(+), 492 deletions(-) diff --git a/bridges/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs b/bridges/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs index 8400157b9d651..74db3738e6b00 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_parachain_messages_to_millau.rs @@ -23,7 +23,7 @@ use substrate_relay_helper::{ DirectReceiveMessagesDeliveryProofCallBuilder, DirectReceiveMessagesProofCallBuilder, SubstrateMessageLane, }, - BundledBatchCallBuilder, + UtilityPalletBatchCallBuilder, }; /// Description of RialtoParachain -> Millau messages bridge. @@ -46,5 +46,5 @@ impl SubstrateMessageLane for RialtoParachainMessagesToMillau { >; type SourceBatchCallBuilder = (); - type TargetBatchCallBuilder = BundledBatchCallBuilder; + type TargetBatchCallBuilder = UtilityPalletBatchCallBuilder; } diff --git a/bridges/relays/bin-substrate/src/cli/init_bridge.rs b/bridges/relays/bin-substrate/src/cli/init_bridge.rs index 52a3a6fce5a5b..cadc6be4df23f 100644 --- a/bridges/relays/bin-substrate/src/cli/init_bridge.rs +++ b/bridges/relays/bin-substrate/src/cli/init_bridge.rs @@ -29,7 +29,7 @@ use crate::{ cli::{bridge::CliBridgeBase, chain_schema::*}, }; use bp_runtime::Chain as ChainBase; -use relay_substrate_client::{AccountKeyPairOf, Chain, SignParam, UnsignedTransaction}; +use relay_substrate_client::{AccountKeyPairOf, Chain, UnsignedTransaction}; use sp_core::Pair; use structopt::StructOpt; use strum::{EnumString, EnumVariantNames, VariantNames}; @@ -83,17 +83,10 @@ where let target_sign = data.target_sign.to_keypair::()?; let dry_run = data.dry_run; - let (spec_version, transaction_version) = target_client.simple_runtime_version().await?; substrate_relay_helper::finality::initialize::initialize::( source_client, target_client.clone(), - target_sign.public().into(), - SignParam { - spec_version, - transaction_version, - genesis_hash: *target_client.genesis_hash(), - signer: target_sign, - }, + target_sign, move |transaction_nonce, initialization_data| { let call = Self::encode_init_bridge(initialization_data); log::info!( diff --git a/bridges/relays/bin-substrate/src/cli/register_parachain.rs b/bridges/relays/bin-substrate/src/cli/register_parachain.rs index 4febc4b04a8e1..1bc9f941ecf29 100644 --- a/bridges/relays/bin-substrate/src/cli/register_parachain.rs +++ b/bridges/relays/bin-substrate/src/cli/register_parachain.rs @@ -26,7 +26,7 @@ use polkadot_runtime_common::{ paras_registrar::Call as ParaRegistrarCall, slots::Call as ParaSlotsCall, }; use polkadot_runtime_parachains::paras::ParaLifecycle; -use relay_substrate_client::{AccountIdOf, CallOf, Chain, Client, SignParam, UnsignedTransaction}; +use relay_substrate_client::{AccountIdOf, CallOf, Chain, Client, UnsignedTransaction}; use relay_utils::{TrackedTransactionStatus, TransactionTracker}; use rialto_runtime::SudoCall; use sp_core::{ @@ -108,28 +108,16 @@ impl RegisterParachain { log::info!(target: "bridge", "Going to reserve parachain id: {:?}", para_id); // step 1: reserve a parachain id - let relay_genesis_hash = *relay_client.genesis_hash(); let relay_sudo_account: AccountIdOf = relay_sign.public().into(); let reserve_parachain_id_call: CallOf = ParaRegistrarCall::reserve {}.into(); - let reserve_parachain_signer = relay_sign.clone(); - let (spec_version, transaction_version) = relay_client.simple_runtime_version().await?; let reserve_result = relay_client - .submit_and_watch_signed_extrinsic( - relay_sudo_account.clone(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: reserve_parachain_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - reserve_parachain_id_call.into(), - transaction_nonce, - )) - }, - ) + .submit_and_watch_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { + Ok(UnsignedTransaction::new( + reserve_parachain_id_call.into(), + transaction_nonce, + )) + }) .await? .wait() .await; @@ -162,23 +150,10 @@ impl RegisterParachain { validation_code: ParaValidationCode(para_code), } .into(); - let register_parathread_signer = relay_sign.clone(); let register_result = relay_client - .submit_and_watch_signed_extrinsic( - relay_sudo_account.clone(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: register_parathread_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new( - register_parathread_call.into(), - transaction_nonce, - )) - }, - ) + .submit_and_watch_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { + Ok(UnsignedTransaction::new(register_parathread_call.into(), transaction_nonce)) + }) .await? .wait() .await; @@ -227,20 +202,10 @@ impl RegisterParachain { ), } .into(); - let force_lease_signer = relay_sign.clone(); relay_client - .submit_signed_extrinsic( - relay_sudo_account, - SignParam:: { - spec_version, - transaction_version, - genesis_hash: relay_genesis_hash, - signer: force_lease_signer, - }, - move |_, transaction_nonce| { - Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce)) - }, - ) + .submit_signed_extrinsic(&relay_sign, move |_, transaction_nonce| { + Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce)) + }) .await?; log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); diff --git a/bridges/relays/bin-substrate/src/cli/send_message.rs b/bridges/relays/bin-substrate/src/cli/send_message.rs index d492d3422c706..59a36566c0c6e 100644 --- a/bridges/relays/bin-substrate/src/cli/send_message.rs +++ b/bridges/relays/bin-substrate/src/cli/send_message.rs @@ -31,8 +31,7 @@ use crate::{ use async_trait::async_trait; use codec::{Decode, Encode}; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, SignParam, - UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, ChainBase, ChainWithTransactions, UnsignedTransaction, }; use sp_core::Pair; use sp_runtime::AccountId32; @@ -80,28 +79,17 @@ where data.bridge.bridge_instance_index(), )?; - let source_genesis_hash = *source_client.genesis_hash(); - let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; source_client - .submit_signed_extrinsic( - source_sign.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: source_genesis_hash, - signer: source_sign.clone(), - }, - move |_, transaction_nonce| { - let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); - log::info!( - target: "bridge", - "Sending message to {}. Size: {}", - Self::Target::NAME, - payload_len, - ); - Ok(unsigned) - }, - ) + .submit_signed_extrinsic(&source_sign, move |_, transaction_nonce| { + let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce); + log::info!( + target: "bridge", + "Sending message to {}. Size: {}", + Self::Target::NAME, + payload_len, + ); + Ok(unsigned) + }) .await?; Ok(()) diff --git a/bridges/relays/client-millau/src/lib.rs b/bridges/relays/client-millau/src/lib.rs index 815cd68f39f26..fb901a4b2de39 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 relay_substrate_client::{ BalanceOf, Chain, ChainWithBalances, ChainWithGrandpa, ChainWithMessages, - ChainWithTransactions, Error as SubstrateError, IndexOf, SignParam, UnderlyingChainProvider, - UnsignedTransaction, + ChainWithTransactions, ChainWithUtilityPallet, Error as SubstrateError, + FullRuntimeUtilityPallet, IndexOf, SignParam, UnderlyingChainProvider, UnsignedTransaction, }; use sp_core::{storage::StorageKey, Pair}; use sp_runtime::{generic::SignedPayload, traits::IdentifyAccount}; @@ -149,6 +149,10 @@ impl ChainWithTransactions for Millau { } } +impl ChainWithUtilityPallet for Millau { + type UtilityPallet = FullRuntimeUtilityPallet; +} + /// Millau signing params. pub type SigningParams = sp_core::sr25519::Pair; diff --git a/bridges/relays/client-substrate/Cargo.toml b/bridges/relays/client-substrate/Cargo.toml index 3f5156b76532e..29b910c11bd7e 100644 --- a/bridges/relays/client-substrate/Cargo.toml +++ b/bridges/relays/client-substrate/Cargo.toml @@ -34,6 +34,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-utility = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" } sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/bridges/relays/client-substrate/src/chain.rs b/bridges/relays/client-substrate/src/chain.rs index 10e3a4749e092..c199540cbfb31 100644 --- a/bridges/relays/client-substrate/src/chain.rs +++ b/bridges/relays/client-substrate/src/chain.rs @@ -234,3 +234,31 @@ impl BlockWithJustification for SignedBlock self.justifications.as_ref().and_then(|j| j.get(engine_id)) } } + +/// Trait that provides functionality defined inside `pallet-utility` +pub trait UtilityPallet { + /// Create batch call from given calls vector. + fn build_batch_call(calls: Vec) -> C::Call; +} + +/// Structure that implements `UtilityPalletProvider` based on a full runtime. +pub struct FullRuntimeUtilityPallet { + _phantom: std::marker::PhantomData, +} + +impl UtilityPallet for FullRuntimeUtilityPallet +where + C: Chain, + R: pallet_utility::Config, + ::RuntimeCall: From>, +{ + fn build_batch_call(calls: Vec) -> C::Call { + pallet_utility::Call::batch_all { calls }.into() + } +} + +/// Substrate-based chain that uses `pallet-utility`. +pub trait ChainWithUtilityPallet: Chain { + /// The utility pallet provider. + type UtilityPallet: UtilityPallet; +} diff --git a/bridges/relays/client-substrate/src/client.rs b/bridges/relays/client-substrate/src/client.rs index 07293a7e65375..c6387d6bce6f8 100644 --- a/bridges/relays/client-substrate/src/client.rs +++ b/bridges/relays/client-substrate/src/client.rs @@ -23,8 +23,8 @@ use crate::{ SubstrateFrameSystemClient, SubstrateStateClient, SubstrateSystemClient, SubstrateTransactionPaymentClient, }, - transaction_stall_timeout, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, - TransactionTracker, UnsignedTransaction, + transaction_stall_timeout, AccountKeyPairOf, ConnectionParams, Error, HashOf, HeaderIdOf, + Result, SignParam, TransactionTracker, UnsignedTransaction, }; use async_std::sync::{Arc, Mutex}; @@ -43,7 +43,7 @@ use pallet_transaction_payment::InclusionFee; use relay_utils::{relay_loop::RECONNECT_DELAY, STALL_TIMEOUT}; use sp_core::{ storage::{StorageData, StorageKey}, - Bytes, Hasher, + Bytes, Hasher, Pair, }; use sp_runtime::{ traits::Header as HeaderT, @@ -426,6 +426,19 @@ impl Client { .await } + async fn build_sign_params(&self, signer: AccountKeyPairOf) -> Result> + where + C: ChainWithTransactions, + { + let (spec_version, transaction_version) = self.simple_runtime_version().await?; + Ok(SignParam:: { + spec_version, + transaction_version, + genesis_hash: self.genesis_hash, + signer, + }) + } + /// Submit an extrinsic signed by given account. /// /// All calls of this method are synchronized, so there can't be more than one active @@ -435,18 +448,19 @@ impl Client { /// Note: The given transaction needs to be SCALE encoded beforehand. pub async fn submit_signed_extrinsic( &self, - extrinsic_signer: C::AccountId, - signing_data: SignParam, + signer: &AccountKeyPairOf, prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, ) -> Result where C: ChainWithTransactions, + C::AccountId: From<::Public>, { let _guard = self.submit_signed_extrinsic_lock.lock().await; - let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let transaction_nonce = self.next_account_index(signer.public().into()).await?; let best_header = self.best_header().await?; + let signing_data = self.build_sign_params(signer.clone()).await?; // By using parent of best block here, we are protecing again best-block reorganizations. // E.g. transaction may have been submitted when the best block was `A[num=100]`. Then it @@ -475,18 +489,19 @@ impl Client { /// after submission. pub async fn submit_and_watch_signed_extrinsic( &self, - extrinsic_signer: C::AccountId, - signing_data: SignParam, + signer: &AccountKeyPairOf, prepare_extrinsic: impl FnOnce(HeaderIdOf, C::Index) -> Result> + Send + 'static, ) -> Result> where C: ChainWithTransactions, + C::AccountId: From<::Public>, { let self_clone = self.clone(); + let signing_data = self.build_sign_params(signer.clone()).await?; let _guard = self.submit_signed_extrinsic_lock.lock().await; - let transaction_nonce = self.next_account_index(extrinsic_signer).await?; + let transaction_nonce = self.next_account_index(signer.public().into()).await?; let best_header = self.best_header().await?; let best_header_id = best_header.id(); let (sender, receiver) = futures::channel::mpsc::channel(MAX_SUBSCRIPTION_CAPACITY); diff --git a/bridges/relays/client-substrate/src/lib.rs b/bridges/relays/client-substrate/src/lib.rs index dc90737523144..e576aca1119d8 100644 --- a/bridges/relays/client-substrate/src/lib.rs +++ b/bridges/relays/client-substrate/src/lib.rs @@ -34,8 +34,9 @@ use std::time::Duration; pub use crate::{ chain::{ AccountKeyPairOf, BlockWithJustification, CallOf, Chain, ChainWithBalances, - ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, Parachain, RelayChain, - SignParam, TransactionStatusOf, UnsignedTransaction, + ChainWithGrandpa, ChainWithMessages, ChainWithTransactions, ChainWithUtilityPallet, + FullRuntimeUtilityPallet, Parachain, RelayChain, SignParam, TransactionStatusOf, + UnsignedTransaction, UtilityPallet, }, client::{ ChainRuntimeVersion, Client, OpaqueGrandpaAuthoritiesSet, Subscription, diff --git a/bridges/relays/lib-substrate-relay/src/finality/initialize.rs b/bridges/relays/lib-substrate-relay/src/finality/initialize.rs index 938f1330b2ead..b5f9b322c7cef 100644 --- a/bridges/relays/lib-substrate-relay/src/finality/initialize.rs +++ b/bridges/relays/lib-substrate-relay/src/finality/initialize.rs @@ -22,9 +22,11 @@ //! with this header. use crate::{error::Error, finality::engine::Engine}; +use sp_core::Pair; use relay_substrate_client::{ - Chain, ChainWithTransactions, Client, Error as SubstrateError, SignParam, UnsignedTransaction, + AccountKeyPairOf, Chain, ChainWithTransactions, Client, Error as SubstrateError, + UnsignedTransaction, }; use sp_runtime::traits::Header as HeaderT; @@ -37,8 +39,7 @@ pub async fn initialize< >( source_client: Client, target_client: Client, - target_transactions_signer: TargetChain::AccountId, - target_signing_data: SignParam, + target_signer: AccountKeyPairOf, prepare_initialize_transaction: F, dry_run: bool, ) where @@ -48,12 +49,12 @@ pub async fn initialize< ) -> Result, SubstrateError> + Send + 'static, + TargetChain::AccountId: From<::Public>, { let result = do_initialize::( source_client, target_client, - target_transactions_signer, - target_signing_data, + target_signer, prepare_initialize_transaction, dry_run, ) @@ -87,8 +88,7 @@ async fn do_initialize< >( source_client: Client, target_client: Client, - target_transactions_signer: TargetChain::AccountId, - target_signing_data: SignParam, + target_signer: AccountKeyPairOf, prepare_initialize_transaction: F, dry_run: bool, ) -> Result< @@ -102,6 +102,7 @@ where ) -> Result, SubstrateError> + Send + 'static, + TargetChain::AccountId: From<::Public>, { let is_initialized = E::is_initialized(&target_client) .await @@ -128,20 +129,16 @@ where ); let initialization_tx_hash = target_client - .submit_signed_extrinsic( - target_transactions_signer, - target_signing_data, - move |_, transaction_nonce| { - let tx = prepare_initialize_transaction(transaction_nonce, initialization_data); - if dry_run { - Err(SubstrateError::Custom( - "Not submitting extrinsic in `dry-run` mode!".to_string(), - )) - } else { - tx - } - }, - ) + .submit_signed_extrinsic(&target_signer, move |_, transaction_nonce| { + let tx = prepare_initialize_transaction(transaction_nonce, initialization_data); + if dry_run { + Err(SubstrateError::Custom( + "Not submitting extrinsic in `dry-run` mode!".to_string(), + )) + } else { + tx + } + }) .await .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; diff --git a/bridges/relays/lib-substrate-relay/src/finality/target.rs b/bridges/relays/lib-substrate-relay/src/finality/target.rs index 09d9ad15f5436..c255c07d148e0 100644 --- a/bridges/relays/lib-substrate-relay/src/finality/target.rs +++ b/bridges/relays/lib-substrate-relay/src/finality/target.rs @@ -27,8 +27,8 @@ use crate::{ use async_trait::async_trait; use finality_relay::TargetClient; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, - SyncHeader, TransactionEra, TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SyncHeader, + TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -111,20 +111,12 @@ where header: SyncHeader>, proof: SubstrateFinalityProof

, ) -> Result { - let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); let call = P::SubmitFinalityProofCallBuilder::build_submit_finality_proof_call(header, proof); - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; self.client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer.clone(), - }, + &self.transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(call.into(), transaction_nonce) .era(TransactionEra::new(best_block_id, transaction_params.mortality))) diff --git a/bridges/relays/lib-substrate-relay/src/lib.rs b/bridges/relays/lib-substrate-relay/src/lib.rs index 4f8f9640305a3..28c538b309a0b 100644 --- a/bridges/relays/lib-substrate-relay/src/lib.rs +++ b/bridges/relays/lib-substrate-relay/src/lib.rs @@ -18,7 +18,8 @@ #![warn(missing_docs)] -use relay_substrate_client::Error as SubstrateError; +use relay_substrate_client::{Chain, ChainWithUtilityPallet, UtilityPallet}; + use std::marker::PhantomData; pub mod error; @@ -90,50 +91,41 @@ impl TaggedAccount { } /// Batch call builder. -pub trait BatchCallBuilder { - /// Associated error type. - type Error; - /// If `true`, then batch calls are supported at the chain. - const BATCH_CALL_SUPPORTED: bool; - +pub trait BatchCallBuilder: Send { /// Create batch call from given calls vector. - fn build_batch_call(_calls: Vec) -> Result; + fn build_batch_call(&self, _calls: Vec) -> Call; } -impl BatchCallBuilder for () { - type Error = SubstrateError; - const BATCH_CALL_SUPPORTED: bool = false; +/// Batch call builder constructor. +pub trait BatchCallBuilderConstructor { + /// Create a new instance of a batch call builder. + fn new_builder() -> Option>>; +} - fn build_batch_call(_calls: Vec) -> Result { - debug_assert!( - false, - "only called if `BATCH_CALL_SUPPORTED` is true;\ - `BATCH_CALL_SUPPORTED` is false;\ - qed" - ); +/// Batch call builder based on `pallet-utility`. +pub struct UtilityPalletBatchCallBuilder(PhantomData); - Err(SubstrateError::Custom("<() as BatchCallBuilder>::build_batch_call() is called".into())) +impl BatchCallBuilder for UtilityPalletBatchCallBuilder +where + C: ChainWithUtilityPallet, +{ + fn build_batch_call(&self, calls: Vec) -> C::Call { + C::UtilityPallet::build_batch_call(calls) } } -/// Batch call builder for bundled runtimes. -pub struct BundledBatchCallBuilder(PhantomData); - -impl BatchCallBuilder<::RuntimeCall> for BundledBatchCallBuilder +impl BatchCallBuilderConstructor for UtilityPalletBatchCallBuilder where - R: pallet_utility::Config::RuntimeCall>, - ::RuntimeCall: From>, + C: ChainWithUtilityPallet, { - type Error = SubstrateError; - const BATCH_CALL_SUPPORTED: bool = true; - - fn build_batch_call( - mut calls: Vec<::RuntimeCall>, - ) -> Result<::RuntimeCall, SubstrateError> { - Ok(if calls.len() == 1 { - calls.remove(0) - } else { - pallet_utility::Call::batch_all { calls }.into() - }) + fn new_builder() -> Option>> { + Some(Box::new(Self(Default::default()))) + } +} + +/// A `BatchCallBuilderConstructor` that always returns `None`. +impl BatchCallBuilderConstructor for () { + fn new_builder() -> Option>> { + None } } diff --git a/bridges/relays/lib-substrate-relay/src/messages_lane.rs b/bridges/relays/lib-substrate-relay/src/messages_lane.rs index 8ec78d0ae2cb8..22ff3e7215b68 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_lane.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_lane.rs @@ -20,18 +20,18 @@ use crate::{ messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, on_demand::OnDemandRelay, - BatchCallBuilder, TransactionParams, + BatchCallBuilder, BatchCallBuilderConstructor, TransactionParams, }; use async_std::sync::Arc; use bp_messages::{LaneId, MessageNonce}; -use bp_runtime::{AccountIdOf, Chain as _, WeightExtraOps}; +use bp_runtime::{AccountIdOf, Chain as _, HeaderIdOf, WeightExtraOps}; use bridge_runtime_common::messages::{ source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, }; use codec::Encode; use frame_support::{dispatch::GetDispatchInfo, weights::Weight}; -use messages_relay::message_lane::MessageLane; +use messages_relay::{message_lane::MessageLane, message_lane_loop::BatchTransaction}; use pallet_bridge_messages::{Call as BridgeMessagesCall, Config as BridgeMessagesConfig}; use relay_substrate_client::{ transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, @@ -57,9 +57,9 @@ pub trait SubstrateMessageLane: 'static + Clone + Debug + Send + Sync { type ReceiveMessagesDeliveryProofCallBuilder: ReceiveMessagesDeliveryProofCallBuilder; /// How batch calls are built at the source chain? - type SourceBatchCallBuilder: BatchCallBuilder, Error = SubstrateError>; + type SourceBatchCallBuilder: BatchCallBuilderConstructor>; /// How batch calls are built at the target chain? - type TargetBatchCallBuilder: BatchCallBuilder, Error = SubstrateError>; + type TargetBatchCallBuilder: BatchCallBuilderConstructor>; } /// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`. @@ -105,6 +105,53 @@ pub struct MessagesRelayParams { pub metrics_params: MetricsParams, } +/// Batch transaction that brings headers + and messages delivery/receiving confirmations to the +/// source node. +pub struct BatchProofTransaction>> { + builder: Box>>, + proved_header: HeaderIdOf, + prove_calls: Vec>, + + /// Using `fn() -> B` in order to avoid implementing `Send` for `B`. + _phantom: PhantomData B>, +} + +impl>> + BatchProofTransaction +{ + /// Creates a new instance of `BatchProofTransaction`. + pub async fn new( + relay: Arc>, + block_num: BlockNumberOf, + ) -> Result, SubstrateError> { + if let Some(builder) = B::new_builder() { + let (proved_header, prove_calls) = relay.prove_header(block_num).await?; + return Ok(Some(Self { + builder, + proved_header, + prove_calls, + _phantom: Default::default(), + })) + } + + Ok(None) + } + + /// Return a batch call that includes the provided call. + pub fn append_call_and_build(mut self, call: CallOf) -> CallOf { + self.prove_calls.push(call); + self.builder.build_batch_call(self.prove_calls) + } +} + +impl>> + BatchTransaction> for BatchProofTransaction +{ + fn required_header_id(&self) -> HeaderIdOf { + self.proved_header + } +} + /// Run Substrate-to-Substrate messages sync loop. pub async fn run(params: MessagesRelayParams

) -> anyhow::Result<()> where diff --git a/bridges/relays/lib-substrate-relay/src/messages_source.rs b/bridges/relays/lib-substrate-relay/src/messages_source.rs index 28b5e69410efc..0e4a2caa258a4 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_source.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_source.rs @@ -20,11 +20,11 @@ use crate::{ messages_lane::{ - MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, SubstrateMessageLane, + BatchProofTransaction, MessageLaneAdapter, ReceiveMessagesDeliveryProofCallBuilder, + SubstrateMessageLane, }, - messages_target::SubstrateMessagesDeliveryProof, on_demand::OnDemandRelay, - BatchCallBuilder, TransactionParams, + TransactionParams, }; use async_std::sync::Arc; @@ -41,15 +41,15 @@ use frame_support::weights::Weight; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, message_lane_loop::{ - BatchTransaction, ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, - SourceClient, SourceClientState, + ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, + SourceClientState, }, }; use num_traits::Zero; use relay_substrate_client::{ - AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, ChainWithMessages, - Client, Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionTracker, UnsignedTransaction, + AccountIdOf, AccountKeyPairOf, BalanceOf, BlockNumberOf, Chain, ChainWithMessages, Client, + Error as SubstrateError, HashOf, HeaderIdOf, TransactionEra, TransactionTracker, + UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -140,7 +140,8 @@ impl SourceClient> for SubstrateM where AccountIdOf: From< as Pair>::Public>, { - type BatchTransaction = BatchConfirmationTransaction

; + type BatchTransaction = + BatchProofTransaction; type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { @@ -332,30 +333,27 @@ where async fn submit_messages_receiving_proof( &self, + maybe_batch_tx: Option, _generated_at_block: TargetHeaderIdOf>, proof: as MessageLane>::MessagesReceivingProof, ) -> Result { - let genesis_hash = *self.source_client.genesis_hash(); + let messages_proof_call = + P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( + proof, + maybe_batch_tx.is_none(), + ); + let final_call = match maybe_batch_tx { + Some(batch_tx) => batch_tx.append_call_and_build(messages_proof_call), + None => messages_proof_call, + }; + let transaction_params = self.transaction_params.clone(); - let (spec_version, transaction_version) = - self.source_client.simple_runtime_version().await?; self.source_client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: self.transaction_params.signer.clone(), - }, + &self.transaction_params.signer, move |best_block_id, transaction_nonce| { - make_messages_delivery_proof_transaction::

( - &transaction_params, - best_block_id, - transaction_nonce, - proof, - true, - ) + Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) }, ) .await @@ -366,14 +364,10 @@ where id: TargetHeaderIdOf>, ) -> Result, SubstrateError> { if let Some(ref target_to_source_headers_relay) = self.target_to_source_headers_relay { - if P::SourceBatchCallBuilder::BATCH_CALL_SUPPORTED { - let (proved_header, prove_calls) = - target_to_source_headers_relay.prove_header(id.0).await?; - return Ok(Some(BatchConfirmationTransaction { - messages_source: self.clone(), - proved_header, - prove_calls, - })) + if let Some(batch_tx) = + BatchProofTransaction::new(target_to_source_headers_relay.clone(), id.0).await? + { + return Ok(Some(batch_tx)) } target_to_source_headers_relay.require_more_headers(id.0).await; @@ -383,65 +377,6 @@ where } } -/// Batch transaction that brings target headers + and delivery confirmations to the source node. -pub struct BatchConfirmationTransaction { - messages_source: SubstrateMessagesSource

, - proved_header: TargetHeaderIdOf>, - prove_calls: Vec>, -} - -#[async_trait] -impl - BatchTransaction< - TargetHeaderIdOf>, - as MessageLane>::MessagesReceivingProof, - TransactionTracker>, - SubstrateError, - > for BatchConfirmationTransaction

-where - AccountIdOf: From< as Pair>::Public>, -{ - fn required_header_id(&self) -> TargetHeaderIdOf> { - self.proved_header - } - - async fn append_proof_and_send( - self, - proof: as MessageLane>::MessagesReceivingProof, - ) -> Result>, SubstrateError> { - let mut calls = self.prove_calls; - calls.push( - P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( - proof, false, - ), - ); - let batch_call = P::SourceBatchCallBuilder::build_batch_call(calls)?; - - let (spec_version, transaction_version) = - self.messages_source.source_client.simple_runtime_version().await?; - self.messages_source - .source_client - .submit_and_watch_signed_extrinsic( - self.messages_source.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: *self.messages_source.source_client.genesis_hash(), - signer: self.messages_source.transaction_params.signer.clone(), - }, - move |best_block_id, transaction_nonce| { - Ok(UnsignedTransaction::new(batch_call.into(), transaction_nonce).era( - TransactionEra::new( - best_block_id, - self.messages_source.transaction_params.mortality, - ), - )) - }, - ) - .await - } -} - /// Ensure that the messages pallet at source chain is active. pub(crate) async fn ensure_messages_pallet_active( client: &Client, @@ -462,22 +397,6 @@ where } } -/// Make messages delivery proof transaction from given proof. -fn make_messages_delivery_proof_transaction( - source_transaction_params: &TransactionParams>, - source_best_block_id: HeaderIdOf, - transaction_nonce: IndexOf, - proof: SubstrateMessagesDeliveryProof, - trace_call: bool, -) -> Result, SubstrateError> { - let call = - P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( - proof, trace_call, - ); - Ok(UnsignedTransaction::new(call.into(), transaction_nonce) - .era(TransactionEra::new(source_best_block_id, source_transaction_params.mortality))) -} - /// Read best blocks from given client. /// /// This function assumes that the chain that is followed by the `self_client` has diff --git a/bridges/relays/lib-substrate-relay/src/messages_target.rs b/bridges/relays/lib-substrate-relay/src/messages_target.rs index 5e67461ab3076..679f9fc140803 100644 --- a/bridges/relays/lib-substrate-relay/src/messages_target.rs +++ b/bridges/relays/lib-substrate-relay/src/messages_target.rs @@ -19,10 +19,13 @@ //! chain. use crate::{ - messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane}, + messages_lane::{ + BatchProofTransaction, MessageLaneAdapter, ReceiveMessagesProofCallBuilder, + SubstrateMessageLane, + }, messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof}, on_demand::OnDemandRelay, - BatchCallBuilder, TransactionParams, + TransactionParams, }; use async_std::sync::Arc; @@ -34,12 +37,11 @@ use bp_messages::{ use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof; use messages_relay::{ message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}, - message_lane_loop::{BatchTransaction, NoncesSubmitArtifacts, TargetClient, TargetClientState}, + message_lane_loop::{NoncesSubmitArtifacts, TargetClient, TargetClientState}, }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BalanceOf, CallOf, Chain, ChainWithMessages, Client, - Error as SubstrateError, HashOf, HeaderIdOf, IndexOf, SignParam, TransactionEra, - TransactionTracker, UnsignedTransaction, + Error as SubstrateError, HashOf, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::relay_loop::Client as RelayClient; use sp_core::Pair; @@ -132,7 +134,8 @@ where AccountIdOf: From< as Pair>::Public>, BalanceOf: TryFrom>, { - type BatchTransaction = BatchDeliveryTransaction

; + type BatchTransaction = + BatchProofTransaction; type TransactionTracker = TransactionTracker>; async fn state(&self) -> Result>, SubstrateError> { @@ -232,36 +235,30 @@ where async fn submit_messages_proof( &self, + maybe_batch_tx: Option, _generated_at_header: SourceHeaderIdOf>, nonces: RangeInclusive, proof: as MessageLane>::MessagesProof, ) -> Result, SubstrateError> { - let genesis_hash = *self.target_client.genesis_hash(); + let messages_proof_call = make_messages_delivery_call::

( + self.relayer_id_at_source.clone(), + proof.1.nonces_start..=proof.1.nonces_end, + proof, + maybe_batch_tx.is_none(), + ); + let final_call = match maybe_batch_tx { + Some(batch_tx) => batch_tx.append_call_and_build(messages_proof_call), + None => messages_proof_call, + }; + let transaction_params = self.transaction_params.clone(); - let relayer_id_at_source = self.relayer_id_at_source.clone(); - let nonces_clone = nonces.clone(); - let (spec_version, transaction_version) = - self.target_client.simple_runtime_version().await?; let tx_tracker = self .target_client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: self.transaction_params.signer.clone(), - }, + &self.transaction_params.signer, move |best_block_id, transaction_nonce| { - make_messages_delivery_transaction::

( - &transaction_params, - best_block_id, - transaction_nonce, - relayer_id_at_source, - nonces_clone, - proof, - true, - ) + Ok(UnsignedTransaction::new(final_call.into(), transaction_nonce) + .era(TransactionEra::new(best_block_id, transaction_params.mortality))) }, ) .await?; @@ -273,14 +270,10 @@ where id: SourceHeaderIdOf>, ) -> Result, SubstrateError> { if let Some(ref source_to_target_headers_relay) = self.source_to_target_headers_relay { - if P::TargetBatchCallBuilder::BATCH_CALL_SUPPORTED { - let (proved_header, prove_calls) = - source_to_target_headers_relay.prove_header(id.0).await?; - return Ok(Some(BatchDeliveryTransaction { - messages_target: self.clone(), - proved_header, - prove_calls, - })) + if let Some(batch_tx) = + BatchProofTransaction::new(source_to_target_headers_relay.clone(), id.0).await? + { + return Ok(Some(batch_tx)) } source_to_target_headers_relay.require_more_headers(id.0).await; @@ -290,66 +283,6 @@ where } } -/// Batch transaction that brings target headers + and delivery confirmations to the source node. -pub struct BatchDeliveryTransaction { - messages_target: SubstrateMessagesTarget

, - proved_header: SourceHeaderIdOf>, - prove_calls: Vec>, -} - -#[async_trait] -impl - BatchTransaction< - SourceHeaderIdOf>, - as MessageLane>::MessagesProof, - TransactionTracker>, - SubstrateError, - > for BatchDeliveryTransaction

-where - AccountIdOf: From< as Pair>::Public>, -{ - fn required_header_id(&self) -> SourceHeaderIdOf> { - self.proved_header - } - - async fn append_proof_and_send( - self, - proof: as MessageLane>::MessagesProof, - ) -> Result>, SubstrateError> { - let mut calls = self.prove_calls; - calls.push(make_messages_delivery_call::

( - self.messages_target.relayer_id_at_source, - proof.1.nonces_start..=proof.1.nonces_end, - proof, - false, - )); - let batch_call = P::TargetBatchCallBuilder::build_batch_call(calls)?; - - let (spec_version, transaction_version) = - self.messages_target.target_client.simple_runtime_version().await?; - self.messages_target - .target_client - .submit_and_watch_signed_extrinsic( - self.messages_target.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash: *self.messages_target.target_client.genesis_hash(), - signer: self.messages_target.transaction_params.signer.clone(), - }, - move |best_block_id, transaction_nonce| { - Ok(UnsignedTransaction::new(batch_call.into(), transaction_nonce).era( - TransactionEra::new( - best_block_id, - self.messages_target.transaction_params.mortality, - ), - )) - }, - ) - .await - } -} - /// Make messages delivery call from given proof. fn make_messages_delivery_call( relayer_id_at_source: AccountIdOf, @@ -367,18 +300,3 @@ fn make_messages_delivery_call( trace_call, ) } - -/// Make messages delivery transaction from given proof. -fn make_messages_delivery_transaction( - target_transaction_params: &TransactionParams>, - target_best_block_id: HeaderIdOf, - transaction_nonce: IndexOf, - relayer_id_at_source: AccountIdOf, - nonces: RangeInclusive, - proof: SubstrateMessagesProof, - trace_call: bool, -) -> Result, SubstrateError> { - let call = make_messages_delivery_call::

(relayer_id_at_source, nonces, proof, trace_call); - Ok(UnsignedTransaction::new(call.into(), transaction_nonce) - .era(TransactionEra::new(target_best_block_id, target_transaction_params.mortality))) -} diff --git a/bridges/relays/lib-substrate-relay/src/parachains/target.rs b/bridges/relays/lib-substrate-relay/src/parachains/target.rs index 027a6b7522231..5e765f10ff550 100644 --- a/bridges/relays/lib-substrate-relay/src/parachains/target.rs +++ b/bridges/relays/lib-substrate-relay/src/parachains/target.rs @@ -33,7 +33,7 @@ use parachains_relay::{ }; use relay_substrate_client::{ AccountIdOf, AccountKeyPairOf, BlockNumberOf, Chain, Client, Error as SubstrateError, HashOf, - HeaderIdOf, RelayChain, SignParam, TransactionEra, TransactionTracker, UnsignedTransaction, + HeaderIdOf, RelayChain, TransactionEra, TransactionTracker, UnsignedTransaction, }; use relay_utils::{relay_loop::Client as RelayClient, HeaderId}; use sp_core::{Bytes, Pair}; @@ -172,9 +172,7 @@ where updated_parachains: Vec<(ParaId, ParaHash)>, proof: ParaHeadsProof, ) -> Result { - let genesis_hash = *self.client.genesis_hash(); let transaction_params = self.transaction_params.clone(); - let (spec_version, transaction_version) = self.client.simple_runtime_version().await?; let call = P::SubmitParachainHeadsCallBuilder::build_submit_parachain_heads_call( at_relay_block, updated_parachains, @@ -182,13 +180,7 @@ where ); self.client .submit_and_watch_signed_extrinsic( - self.transaction_params.signer.public().into(), - SignParam:: { - spec_version, - transaction_version, - genesis_hash, - signer: transaction_params.signer, - }, + &transaction_params.signer, move |best_block_id, transaction_nonce| { Ok(UnsignedTransaction::new(call.into(), transaction_nonce) .era(TransactionEra::new(best_block_id, transaction_params.mortality))) diff --git a/bridges/relays/messages/src/message_lane_loop.rs b/bridges/relays/messages/src/message_lane_loop.rs index f4f91d50ddd8f..521baabb195f8 100644 --- a/bridges/relays/messages/src/message_lane_loop.rs +++ b/bridges/relays/messages/src/message_lane_loop.rs @@ -111,26 +111,17 @@ pub struct NoncesSubmitArtifacts { /// Batch transaction that already submit some headers and needs to be extended with /// messages/delivery proof before sending. -#[async_trait] -pub trait BatchTransaction: Send { +pub trait BatchTransaction: Send { /// Header that was required in the original call and which is bundled within this /// batch transaction. fn required_header_id(&self) -> HeaderId; - - /// Append proof and send transaction to the connected node. - async fn append_proof_and_send(self, proof: Proof) -> Result; } /// Source client trait. #[async_trait] pub trait SourceClient: RelayClient { /// Type of batch transaction that submits finality and message receiving proof. - type BatchTransaction: BatchTransaction< - TargetHeaderIdOf

, - P::MessagesReceivingProof, - Self::TransactionTracker, - Self::Error, - >; + type BatchTransaction: BatchTransaction>; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -170,6 +161,7 @@ pub trait SourceClient: RelayClient { /// Submit messages receiving proof. async fn submit_messages_receiving_proof( &self, + maybe_batch_tx: Option, generated_at_block: TargetHeaderIdOf

, proof: P::MessagesReceivingProof, ) -> Result; @@ -194,12 +186,7 @@ pub trait SourceClient: RelayClient { #[async_trait] pub trait TargetClient: RelayClient { /// Type of batch transaction that submits finality and messages proof. - type BatchTransaction: BatchTransaction< - SourceHeaderIdOf

, - P::MessagesProof, - Self::TransactionTracker, - Self::Error, - >; + type BatchTransaction: BatchTransaction>; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker>; @@ -233,6 +220,7 @@ pub trait TargetClient: RelayClient { /// Submit messages proof. async fn submit_messages_proof( &self, + maybe_batch_tx: Option, generated_at_header: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, @@ -533,57 +521,26 @@ pub(crate) mod tests { #[derive(Clone, Debug)] pub struct TestMessagesBatchTransaction { - data: Arc>, required_header_id: TestSourceHeaderId, - tx_tracker: TestTransactionTracker, } #[async_trait] - impl BatchTransaction - for TestMessagesBatchTransaction - { + impl BatchTransaction for TestMessagesBatchTransaction { fn required_header_id(&self) -> TestSourceHeaderId { self.required_header_id } - - async fn append_proof_and_send( - self, - proof: TestMessagesProof, - ) -> Result { - let mut data = self.data.lock(); - data.receive_messages(proof); - Ok(self.tx_tracker) - } } #[derive(Clone, Debug)] pub struct TestConfirmationBatchTransaction { - data: Arc>, required_header_id: TestTargetHeaderId, - tx_tracker: TestTransactionTracker, } #[async_trait] - impl - BatchTransaction< - TestTargetHeaderId, - TestMessagesReceivingProof, - TestTransactionTracker, - TestError, - > for TestConfirmationBatchTransaction - { + impl BatchTransaction for TestConfirmationBatchTransaction { fn required_header_id(&self) -> TestTargetHeaderId { self.required_header_id } - - async fn append_proof_and_send( - self, - proof: TestMessagesReceivingProof, - ) -> Result { - let mut data = self.data.lock(); - data.receive_messages_delivery_proof(proof); - Ok(self.tx_tracker) - } } #[derive(Clone, Debug)] @@ -800,6 +757,7 @@ pub(crate) mod tests { async fn submit_messages_receiving_proof( &self, + _maybe_batch_tx: Option, _generated_at_block: TargetHeaderIdOf, proof: TestMessagesReceivingProof, ) -> Result { @@ -924,6 +882,7 @@ pub(crate) mod tests { async fn submit_messages_proof( &self, + _maybe_batch_tx: Option, _generated_at_header: SourceHeaderIdOf, nonces: RangeInclusive, proof: TestMessagesProof, @@ -1287,8 +1246,6 @@ pub(crate) mod tests { target_latest_received_nonce: 0, ..Default::default() })); - let target_original_data = original_data.clone(); - let source_original_data = original_data.clone(); let result = run_loop_test( original_data, Arc::new(|_| {}), @@ -1298,9 +1255,7 @@ pub(crate) mod tests { { data.target_to_source_batch_transaction = Some(TestConfirmationBatchTransaction { - data: source_original_data.clone(), required_header_id: target_to_source_header_required, - tx_tracker: TestTransactionTracker::default(), }) } }), @@ -1310,9 +1265,7 @@ pub(crate) mod tests { data.source_to_target_header_required.take() { data.source_to_target_batch_transaction = Some(TestMessagesBatchTransaction { - data: target_original_data.clone(), required_header_id: source_to_target_header_required, - tx_tracker: TestTransactionTracker::default(), }) } diff --git a/bridges/relays/messages/src/message_race_delivery.rs b/bridges/relays/messages/src/message_race_delivery.rs index c551a88a1dd1c..0179a696bc7ff 100644 --- a/bridges/relays/messages/src/message_race_delivery.rs +++ b/bridges/relays/messages/src/message_race_delivery.rs @@ -214,11 +214,14 @@ where async fn submit_proof( &self, + maybe_batch_tx: Option, generated_at_block: SourceHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesProof, ) -> Result, Self::Error> { - self.client.submit_messages_proof(generated_at_block, nonces, proof).await + self.client + .submit_messages_proof(maybe_batch_tx, generated_at_block, nonces, proof) + .await } } diff --git a/bridges/relays/messages/src/message_race_loop.rs b/bridges/relays/messages/src/message_race_loop.rs index 0da2d3baf7f95..deac71e5b6efe 100644 --- a/bridges/relays/messages/src/message_race_loop.rs +++ b/bridges/relays/messages/src/message_race_loop.rs @@ -128,12 +128,7 @@ pub trait TargetClient { /// Type of the additional data from the target client, used by the race. type TargetNoncesData: std::fmt::Debug; /// Type of batch transaction that submits finality and proof to the target node. - type BatchTransaction: BatchTransaction< - P::SourceHeaderId, - P::Proof, - Self::TransactionTracker, - Self::Error, - >; + type BatchTransaction: BatchTransaction; /// Transaction tracker to track submitted transactions. type TransactionTracker: TransactionTracker; @@ -160,6 +155,7 @@ pub trait TargetClient { /// Submit proof to the target client. async fn submit_proof( &self, + maybe_batch_tx: Option, generated_at_block: P::SourceHeaderId, nonces: RangeInclusive, proof: P::Proof, @@ -575,41 +571,30 @@ pub async fn run, TC: TargetClient

>( target_client_is_online = false; if let Some((at_block, nonces_range, proof)) = race_state.nonces_to_submit.as_ref() { - if let Some(target_batch_transaction) = target_batch_transaction.take() { + log::debug!( + target: "bridge", + "Going to submit proof of messages in range {:?} to {} node", + nonces_range, + P::target_name(), + ); + if let Some(ref target_batch_transaction) = target_batch_transaction { log::debug!( target: "bridge", - "Going to submit batch transaction with header {:?} and proof of messages in range {:?} to {} node", + "This transaction is batched with sending the proof for header {:?}.", target_batch_transaction.required_header_id(), - nonces_range, - P::target_name(), - ); - - let nonces = nonces_range.clone(); - target_submit_proof.set( - target_batch_transaction - .append_proof_and_send(proof.clone()) - .map(|result| { - result - .map(|tx_tracker| NoncesSubmitArtifacts { nonces, tx_tracker }) - }) - .left_future() - .fuse(), - ); - } else { - log::debug!( - target: "bridge", - "Going to submit proof of messages in range {:?} to {} node", - nonces_range, - P::target_name(), - ); - - target_submit_proof.set( - race_target - .submit_proof(at_block.clone(), nonces_range.clone(), proof.clone()) - .right_future() - .fuse(), ); } + + target_submit_proof.set( + race_target + .submit_proof( + target_batch_transaction.take(), + at_block.clone(), + nonces_range.clone(), + proof.clone(), + ) + .fuse(), + ); } else if let Some(source_required_header) = source_required_header.clone() { log::debug!(target: "bridge", "Going to require {} header {:?} at {}", P::source_name(), source_required_header, P::target_name()); target_require_source_header diff --git a/bridges/relays/messages/src/message_race_receiving.rs b/bridges/relays/messages/src/message_race_receiving.rs index c807d76fe521b..70a3d7c24772a 100644 --- a/bridges/relays/messages/src/message_race_receiving.rs +++ b/bridges/relays/messages/src/message_race_receiving.rs @@ -182,12 +182,15 @@ where async fn submit_proof( &self, + maybe_batch_tx: Option, generated_at_block: TargetHeaderIdOf

, nonces: RangeInclusive, proof: P::MessagesReceivingProof, ) -> Result, Self::Error> { - let tx_tracker = - self.client.submit_messages_receiving_proof(generated_at_block, proof).await?; + let tx_tracker = self + .client + .submit_messages_receiving_proof(maybe_batch_tx, generated_at_block, proof) + .await?; Ok(NoncesSubmitArtifacts { nonces, tx_tracker }) } }