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<BatchCallBuilder>`.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.
This commit is contained in:
Serban Iorga
2022-12-27 15:39:23 +02:00
committed by Bastian Köcher
parent df1aed01c4
commit e47f1e42e0
20 changed files with 290 additions and 494 deletions
@@ -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<SourceChain>,
target_client: Client<TargetChain>,
target_transactions_signer: TargetChain::AccountId,
target_signing_data: SignParam<TargetChain>,
target_signer: AccountKeyPairOf<TargetChain>,
prepare_initialize_transaction: F,
dry_run: bool,
) where
@@ -48,12 +49,12 @@ pub async fn initialize<
) -> Result<UnsignedTransaction<TargetChain>, SubstrateError>
+ Send
+ 'static,
TargetChain::AccountId: From<<TargetChain::AccountKeyPair as Pair>::Public>,
{
let result = do_initialize::<E, _, _, _>(
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<SourceChain>,
target_client: Client<TargetChain>,
target_transactions_signer: TargetChain::AccountId,
target_signing_data: SignParam<TargetChain>,
target_signer: AccountKeyPairOf<TargetChain>,
prepare_initialize_transaction: F,
dry_run: bool,
) -> Result<
@@ -102,6 +102,7 @@ where
) -> Result<UnsignedTransaction<TargetChain>, SubstrateError>
+ Send
+ 'static,
TargetChain::AccountId: From<<TargetChain::AccountKeyPair as Pair>::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))?;
@@ -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<HeaderOf<P::SourceChain>>,
proof: SubstrateFinalityProof<P>,
) -> Result<Self::TransactionTracker, Error> {
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::<P::TargetChain> {
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)))
+30 -38
View File
@@ -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<AccountId> TaggedAccount<AccountId> {
}
/// Batch call builder.
pub trait BatchCallBuilder<Call> {
/// Associated error type.
type Error;
/// If `true`, then batch calls are supported at the chain.
const BATCH_CALL_SUPPORTED: bool;
pub trait BatchCallBuilder<Call>: Send {
/// Create batch call from given calls vector.
fn build_batch_call(_calls: Vec<Call>) -> Result<Call, Self::Error>;
fn build_batch_call(&self, _calls: Vec<Call>) -> Call;
}
impl<Call> BatchCallBuilder<Call> for () {
type Error = SubstrateError;
const BATCH_CALL_SUPPORTED: bool = false;
fn build_batch_call(_calls: Vec<Call>) -> Result<Call, SubstrateError> {
debug_assert!(
false,
"only called if `BATCH_CALL_SUPPORTED` is true;\
`BATCH_CALL_SUPPORTED` is false;\
qed"
);
Err(SubstrateError::Custom("<() as BatchCallBuilder>::build_batch_call() is called".into()))
}
/// Batch call builder constructor.
pub trait BatchCallBuilderConstructor<Call> {
/// Create a new instance of a batch call builder.
fn new_builder() -> Option<Box<dyn BatchCallBuilder<Call>>>;
}
/// Batch call builder for bundled runtimes.
pub struct BundledBatchCallBuilder<R>(PhantomData<R>);
/// Batch call builder based on `pallet-utility`.
pub struct UtilityPalletBatchCallBuilder<C: Chain>(PhantomData<C>);
impl<R> BatchCallBuilder<<R as frame_system::Config>::RuntimeCall> for BundledBatchCallBuilder<R>
impl<C: Chain> BatchCallBuilder<C::Call> for UtilityPalletBatchCallBuilder<C>
where
R: pallet_utility::Config<RuntimeCall = <R as frame_system::Config>::RuntimeCall>,
<R as frame_system::Config>::RuntimeCall: From<pallet_utility::Call<R>>,
C: ChainWithUtilityPallet,
{
type Error = SubstrateError;
const BATCH_CALL_SUPPORTED: bool = true;
fn build_batch_call(
mut calls: Vec<<R as frame_system::Config>::RuntimeCall>,
) -> Result<<R as frame_system::Config>::RuntimeCall, SubstrateError> {
Ok(if calls.len() == 1 {
calls.remove(0)
} else {
pallet_utility::Call::batch_all { calls }.into()
})
fn build_batch_call(&self, calls: Vec<C::Call>) -> C::Call {
C::UtilityPallet::build_batch_call(calls)
}
}
impl<C: Chain> BatchCallBuilderConstructor<C::Call> for UtilityPalletBatchCallBuilder<C>
where
C: ChainWithUtilityPallet,
{
fn new_builder() -> Option<Box<dyn BatchCallBuilder<C::Call>>> {
Some(Box::new(Self(Default::default())))
}
}
/// A `BatchCallBuilderConstructor` that always returns `None`.
impl<Call> BatchCallBuilderConstructor<Call> for () {
fn new_builder() -> Option<Box<dyn BatchCallBuilder<Call>>> {
None
}
}
@@ -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<Self>;
/// How batch calls are built at the source chain?
type SourceBatchCallBuilder: BatchCallBuilder<CallOf<Self::SourceChain>, Error = SubstrateError>;
type SourceBatchCallBuilder: BatchCallBuilderConstructor<CallOf<Self::SourceChain>>;
/// How batch calls are built at the target chain?
type TargetBatchCallBuilder: BatchCallBuilder<CallOf<Self::TargetChain>, Error = SubstrateError>;
type TargetBatchCallBuilder: BatchCallBuilderConstructor<CallOf<Self::TargetChain>>;
}
/// Adapter that allows all `SubstrateMessageLane` to act as `MessageLane`.
@@ -105,6 +105,53 @@ pub struct MessagesRelayParams<P: SubstrateMessageLane> {
pub metrics_params: MetricsParams,
}
/// Batch transaction that brings headers + and messages delivery/receiving confirmations to the
/// source node.
pub struct BatchProofTransaction<SC: Chain, TC: Chain, B: BatchCallBuilderConstructor<CallOf<SC>>> {
builder: Box<dyn BatchCallBuilder<CallOf<SC>>>,
proved_header: HeaderIdOf<TC>,
prove_calls: Vec<CallOf<SC>>,
/// Using `fn() -> B` in order to avoid implementing `Send` for `B`.
_phantom: PhantomData<fn() -> B>,
}
impl<SC: Chain, TC: Chain, B: BatchCallBuilderConstructor<CallOf<SC>>>
BatchProofTransaction<SC, TC, B>
{
/// Creates a new instance of `BatchProofTransaction`.
pub async fn new(
relay: Arc<dyn OnDemandRelay<TC, SC>>,
block_num: BlockNumberOf<TC>,
) -> Result<Option<Self>, 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<SC>) -> CallOf<SC> {
self.prove_calls.push(call);
self.builder.build_batch_call(self.prove_calls)
}
}
impl<SC: Chain, TC: Chain, B: BatchCallBuilderConstructor<CallOf<SC>>>
BatchTransaction<HeaderIdOf<TC>> for BatchProofTransaction<SC, TC, B>
{
fn required_header_id(&self) -> HeaderIdOf<TC> {
self.proved_header
}
}
/// Run Substrate-to-Substrate messages sync loop.
pub async fn run<P: SubstrateMessageLane>(params: MessagesRelayParams<P>) -> anyhow::Result<()>
where
@@ -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<P: SubstrateMessageLane> SourceClient<MessageLaneAdapter<P>> for SubstrateM
where
AccountIdOf<P::SourceChain>: From<<AccountKeyPairOf<P::SourceChain> as Pair>::Public>,
{
type BatchTransaction = BatchConfirmationTransaction<P>;
type BatchTransaction =
BatchProofTransaction<P::SourceChain, P::TargetChain, P::SourceBatchCallBuilder>;
type TransactionTracker = TransactionTracker<P::SourceChain, Client<P::SourceChain>>;
async fn state(&self) -> Result<SourceClientState<MessageLaneAdapter<P>>, SubstrateError> {
@@ -332,30 +333,27 @@ where
async fn submit_messages_receiving_proof(
&self,
maybe_batch_tx: Option<Self::BatchTransaction>,
_generated_at_block: TargetHeaderIdOf<MessageLaneAdapter<P>>,
proof: <MessageLaneAdapter<P> as MessageLane>::MessagesReceivingProof,
) -> Result<Self::TransactionTracker, SubstrateError> {
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::<P::SourceChain> {
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::<P>(
&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<MessageLaneAdapter<P>>,
) -> Result<Option<Self::BatchTransaction>, 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<P: SubstrateMessageLane> {
messages_source: SubstrateMessagesSource<P>,
proved_header: TargetHeaderIdOf<MessageLaneAdapter<P>>,
prove_calls: Vec<CallOf<P::SourceChain>>,
}
#[async_trait]
impl<P: SubstrateMessageLane>
BatchTransaction<
TargetHeaderIdOf<MessageLaneAdapter<P>>,
<MessageLaneAdapter<P> as MessageLane>::MessagesReceivingProof,
TransactionTracker<P::SourceChain, Client<P::SourceChain>>,
SubstrateError,
> for BatchConfirmationTransaction<P>
where
AccountIdOf<P::SourceChain>: From<<AccountKeyPairOf<P::SourceChain> as Pair>::Public>,
{
fn required_header_id(&self) -> TargetHeaderIdOf<MessageLaneAdapter<P>> {
self.proved_header
}
async fn append_proof_and_send(
self,
proof: <MessageLaneAdapter<P> as MessageLane>::MessagesReceivingProof,
) -> Result<TransactionTracker<P::SourceChain, Client<P::SourceChain>>, 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::<P::SourceChain> {
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<AtChain, WithChain>(
client: &Client<AtChain>,
@@ -462,22 +397,6 @@ where
}
}
/// Make messages delivery proof transaction from given proof.
fn make_messages_delivery_proof_transaction<P: SubstrateMessageLane>(
source_transaction_params: &TransactionParams<AccountKeyPairOf<P::SourceChain>>,
source_best_block_id: HeaderIdOf<P::SourceChain>,
transaction_nonce: IndexOf<P::SourceChain>,
proof: SubstrateMessagesDeliveryProof<P::TargetChain>,
trace_call: bool,
) -> Result<UnsignedTransaction<P::SourceChain>, 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
@@ -19,10 +19,13 @@
//! <BridgedName> 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<P::TargetChain>: From<<AccountKeyPairOf<P::TargetChain> as Pair>::Public>,
BalanceOf<P::SourceChain>: TryFrom<BalanceOf<P::TargetChain>>,
{
type BatchTransaction = BatchDeliveryTransaction<P>;
type BatchTransaction =
BatchProofTransaction<P::TargetChain, P::SourceChain, P::TargetBatchCallBuilder>;
type TransactionTracker = TransactionTracker<P::TargetChain, Client<P::TargetChain>>;
async fn state(&self) -> Result<TargetClientState<MessageLaneAdapter<P>>, SubstrateError> {
@@ -232,36 +235,30 @@ where
async fn submit_messages_proof(
&self,
maybe_batch_tx: Option<Self::BatchTransaction>,
_generated_at_header: SourceHeaderIdOf<MessageLaneAdapter<P>>,
nonces: RangeInclusive<MessageNonce>,
proof: <MessageLaneAdapter<P> as MessageLane>::MessagesProof,
) -> Result<NoncesSubmitArtifacts<Self::TransactionTracker>, SubstrateError> {
let genesis_hash = *self.target_client.genesis_hash();
let messages_proof_call = make_messages_delivery_call::<P>(
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::<P::TargetChain> {
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::<P>(
&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<MessageLaneAdapter<P>>,
) -> Result<Option<Self::BatchTransaction>, 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<P: SubstrateMessageLane> {
messages_target: SubstrateMessagesTarget<P>,
proved_header: SourceHeaderIdOf<MessageLaneAdapter<P>>,
prove_calls: Vec<CallOf<P::TargetChain>>,
}
#[async_trait]
impl<P: SubstrateMessageLane>
BatchTransaction<
SourceHeaderIdOf<MessageLaneAdapter<P>>,
<MessageLaneAdapter<P> as MessageLane>::MessagesProof,
TransactionTracker<P::TargetChain, Client<P::TargetChain>>,
SubstrateError,
> for BatchDeliveryTransaction<P>
where
AccountIdOf<P::TargetChain>: From<<AccountKeyPairOf<P::TargetChain> as Pair>::Public>,
{
fn required_header_id(&self) -> SourceHeaderIdOf<MessageLaneAdapter<P>> {
self.proved_header
}
async fn append_proof_and_send(
self,
proof: <MessageLaneAdapter<P> as MessageLane>::MessagesProof,
) -> Result<TransactionTracker<P::TargetChain, Client<P::TargetChain>>, SubstrateError> {
let mut calls = self.prove_calls;
calls.push(make_messages_delivery_call::<P>(
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::<P::TargetChain> {
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<P: SubstrateMessageLane>(
relayer_id_at_source: AccountIdOf<P::SourceChain>,
@@ -367,18 +300,3 @@ fn make_messages_delivery_call<P: SubstrateMessageLane>(
trace_call,
)
}
/// Make messages delivery transaction from given proof.
fn make_messages_delivery_transaction<P: SubstrateMessageLane>(
target_transaction_params: &TransactionParams<AccountKeyPairOf<P::TargetChain>>,
target_best_block_id: HeaderIdOf<P::TargetChain>,
transaction_nonce: IndexOf<P::TargetChain>,
relayer_id_at_source: AccountIdOf<P::SourceChain>,
nonces: RangeInclusive<MessageNonce>,
proof: SubstrateMessagesProof<P::SourceChain>,
trace_call: bool,
) -> Result<UnsignedTransaction<P::TargetChain>, SubstrateError> {
let call = make_messages_delivery_call::<P>(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)))
}
@@ -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<Self::TransactionTracker, Self::Error> {
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::<P::TargetChain> {
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)))