Emit mortal transactions from relay (#1073)

* mortal relay transactions

* sign block hash for mortal transactions

* TransactionEraOf

* add explanation

* enable mortal transactions for Westend -> Millau headers relay

* clippy

* spellcheck
This commit is contained in:
Svyatoslav Nikolsky
2021-09-02 10:55:57 +03:00
committed by Bastian Köcher
parent 8b52cd2593
commit 864c830618
33 changed files with 249 additions and 73 deletions
@@ -107,6 +107,7 @@ pub trait TransactionSignScheme {
fn sign_transaction(
genesis_hash: <Self::Chain as ChainBase>::Hash,
signer: &Self::AccountKeyPair,
era: bp_runtime::TransactionEraOf<Self::Chain>,
signer_nonce: <Self::Chain as Chain>::Index,
call: <Self::Chain as Chain>::Call,
) -> Self::SignedTransaction;
@@ -18,7 +18,7 @@
use crate::chain::{Chain, ChainWithBalances};
use crate::rpc::Substrate;
use crate::{ConnectionParams, Error, Result};
use crate::{ConnectionParams, Error, HeaderIdOf, Result};
use async_std::sync::{Arc, Mutex};
use codec::Decode;
@@ -29,8 +29,9 @@ use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBui
use num_traits::{Bounded, Zero};
use pallet_balances::AccountData;
use pallet_transaction_payment::InclusionFee;
use relay_utils::relay_loop::RECONNECT_DELAY;
use relay_utils::{relay_loop::RECONNECT_DELAY, HeaderId};
use sp_core::{storage::StorageKey, Bytes};
use sp_runtime::traits::Header as HeaderT;
use sp_trie::StorageProof;
use sp_version::RuntimeVersion;
use std::{convert::TryFrom, future::Future};
@@ -293,12 +294,14 @@ impl<C: Chain> Client<C> {
pub async fn submit_signed_extrinsic(
&self,
extrinsic_signer: C::AccountId,
prepare_extrinsic: impl FnOnce(C::Index) -> Bytes + Send + 'static,
prepare_extrinsic: impl FnOnce(HeaderIdOf<C>, C::Index) -> Bytes + Send + 'static,
) -> Result<C::Hash> {
let _guard = self.submit_signed_extrinsic_lock.lock().await;
let transaction_nonce = self.next_account_index(extrinsic_signer).await?;
let best_header = self.best_header().await?;
let best_header_id = HeaderId(*best_header.number(), best_header.hash());
self.jsonrpsee_execute(move |client| async move {
let extrinsic = prepare_extrinsic(transaction_nonce);
let extrinsic = prepare_extrinsic(best_header_id, transaction_nonce);
let tx_hash = Substrate::<C>::author_submit_extrinsic(&*client, extrinsic).await?;
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
Ok(tx_hash)
+14 -1
View File
@@ -29,11 +29,13 @@ pub mod guard;
pub mod headers_source;
pub mod metrics;
use std::time::Duration;
pub use crate::chain::{BlockWithJustification, Chain, ChainWithBalances, TransactionSignScheme};
pub use crate::client::{Client, JustificationsSubscription, OpaqueGrandpaAuthoritiesSet};
pub use crate::error::{Error, Result};
pub use crate::sync_header::SyncHeader;
pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf};
pub use bp_runtime::{BlockNumberOf, Chain as ChainBase, HashOf, HeaderOf, TransactionEra, TransactionEraOf};
/// Header id used by the chain.
pub type HeaderIdOf<C> = relay_utils::HeaderId<HashOf<C>, BlockNumberOf<C>>;
@@ -58,3 +60,14 @@ impl Default for ConnectionParams {
}
}
}
/// Returns stall timeout for relay loop.
///
/// Relay considers himself stalled if he has submitted transaction to the node, but it has not
/// been mined for this period.
///
/// Returns `None` if mortality period is `None`
pub fn transaction_stall_timeout(mortality_period: Option<u32>, average_block_interval: Duration) -> Option<Duration> {
// 1 extra block for transaction to reach the pool && 1 for relayer to awake after it is mined
mortality_period.map(|mortality_period| average_block_interval.saturating_mul(mortality_period + 1 + 1))
}