Extract unsigned tx from the SignParam structure (#1561)

* change sign_transaction method

* clippy

* rustup update && clippy

* remove redudnant clone
This commit is contained in:
Svyatoslav Nikolsky
2022-08-30 13:58:37 +03:00
committed by Bastian Köcher
parent effe0f11c8
commit f35b4f4897
29 changed files with 434 additions and 402 deletions
@@ -122,10 +122,7 @@ pub fn development_config(id: ParaId) -> ChainSpec {
move || { move || {
testnet_genesis( testnet_genesis(
get_account_id_from_seed::<sr25519::Public>(SUDO_ACCOUNT), get_account_id_from_seed::<sr25519::Public>(SUDO_ACCOUNT),
DEV_AUTHORITIES_ACCOUNTS DEV_AUTHORITIES_ACCOUNTS.into_iter().map(get_from_seed::<AuraId>).collect(),
.into_iter()
.map(|x| get_from_seed::<AuraId>(x))
.collect(),
endowed_accounts(), endowed_accounts(),
id, id,
) )
@@ -157,10 +154,7 @@ pub fn local_testnet_config(id: ParaId) -> ChainSpec {
move || { move || {
testnet_genesis( testnet_genesis(
get_account_id_from_seed::<sr25519::Public>(SUDO_ACCOUNT), get_account_id_from_seed::<sr25519::Public>(SUDO_ACCOUNT),
LOCAL_AUTHORITIES_ACCOUNTS LOCAL_AUTHORITIES_ACCOUNTS.into_iter().map(get_from_seed::<AuraId>).collect(),
.into_iter()
.map(|x| get_from_seed::<AuraId>(x))
.collect(),
endowed_accounts(), endowed_accounts(),
id, id,
) )
+9 -1
View File
@@ -183,7 +183,7 @@ impl Size for PreComputedSize {
} }
/// Era of specific transaction. /// Era of specific transaction.
#[derive(RuntimeDebug, Clone, Copy)] #[derive(RuntimeDebug, Clone, Copy, PartialEq)]
pub enum TransactionEra<BlockNumber, BlockHash> { pub enum TransactionEra<BlockNumber, BlockHash> {
/// Transaction is immortal. /// Transaction is immortal.
Immortal, Immortal,
@@ -207,6 +207,14 @@ impl<BlockNumber: Copy + Into<u64>, BlockHash: Copy> TransactionEra<BlockNumber,
TransactionEra::Immortal TransactionEra::Immortal
} }
/// Returns mortality period if transaction is mortal.
pub fn mortality_period(&self) -> Option<u32> {
match *self {
TransactionEra::Immortal => None,
TransactionEra::Mortal(_, period) => Some(period),
}
}
/// Returns era that is used by FRAME-based runtimes. /// Returns era that is used by FRAME-based runtimes.
pub fn frame_era(&self) -> sp_runtime::generic::Era { pub fn frame_era(&self) -> sp_runtime::generic::Era {
match *self { match *self {
+1 -1
View File
@@ -43,7 +43,7 @@ impl Account {
pub fn secret(&self) -> SecretKey { pub fn secret(&self) -> SecretKey {
let data = self.0.encode(); let data = self.0.encode();
let mut bytes = [0_u8; 32]; let mut bytes = [0_u8; 32];
bytes[0..data.len()].copy_from_slice(&*data); bytes[0..data.len()].copy_from_slice(&data);
SecretKey::from_bytes(&bytes) SecretKey::from_bytes(&bytes)
.expect("A static array of the correct length is a known good.") .expect("A static array of the correct length is a known good.")
} }
+18 -16
View File
@@ -71,14 +71,15 @@ mod tests {
fn rialto_tx_extra_bytes_constant_is_correct() { fn rialto_tx_extra_bytes_constant_is_correct() {
let rialto_call = let rialto_call =
rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] }); rialto_runtime::Call::System(rialto_runtime::SystemCall::remark { remark: vec![] });
let rialto_tx = Rialto::sign_transaction(SignParam { let rialto_tx = Rialto::sign_transaction(
spec_version: 1, SignParam {
transaction_version: 1, spec_version: 1,
genesis_hash: Default::default(), transaction_version: 1,
signer: sp_keyring::AccountKeyring::Alice.pair(), genesis_hash: Default::default(),
era: relay_substrate_client::TransactionEra::immortal(), signer: sp_keyring::AccountKeyring::Alice.pair(),
unsigned: UnsignedTransaction::new(rialto_call.clone().into(), 0), },
}) UnsignedTransaction::new(rialto_call.clone().into(), 0),
)
.unwrap(); .unwrap();
let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len(); let extra_bytes_in_transaction = rialto_tx.encode().len() - rialto_call.encode().len();
assert!( assert!(
@@ -93,14 +94,15 @@ mod tests {
fn millau_tx_extra_bytes_constant_is_correct() { fn millau_tx_extra_bytes_constant_is_correct() {
let millau_call = let millau_call =
millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] }); millau_runtime::Call::System(millau_runtime::SystemCall::remark { remark: vec![] });
let millau_tx = Millau::sign_transaction(SignParam { let millau_tx = Millau::sign_transaction(
spec_version: 0, SignParam {
transaction_version: 0, spec_version: 0,
genesis_hash: Default::default(), transaction_version: 0,
signer: sp_keyring::AccountKeyring::Alice.pair(), genesis_hash: Default::default(),
era: relay_substrate_client::TransactionEra::immortal(), signer: sp_keyring::AccountKeyring::Alice.pair(),
unsigned: UnsignedTransaction::new(millau_call.clone().into(), 0), },
}) UnsignedTransaction::new(millau_call.clone().into(), 0),
)
.unwrap(); .unwrap();
let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len(); let extra_bytes_in_transaction = millau_tx.encode().len() - millau_call.encode().len();
assert!( assert!(
@@ -26,11 +26,8 @@ use crate::{
cli::{bridge::CliBridgeBase, chain_schema::*}, cli::{bridge::CliBridgeBase, chain_schema::*},
}; };
use bp_runtime::Chain as ChainBase; use bp_runtime::Chain as ChainBase;
use codec::Encode; use relay_substrate_client::{AccountKeyPairOf, Chain, SignParam, UnsignedTransaction};
use relay_substrate_client::{ use sp_core::Pair;
AccountKeyPairOf, Chain, SignParam, TransactionSignScheme, UnsignedTransaction,
};
use sp_core::{Bytes, Pair};
use structopt::StructOpt; use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
use substrate_relay_helper::finality::engine::{Engine, Grandpa as GrandpaFinalityEngine}; use substrate_relay_helper::finality::engine::{Engine, Grandpa as GrandpaFinalityEngine};
@@ -82,20 +79,16 @@ where
source_client, source_client,
target_client.clone(), target_client.clone(),
target_sign.public().into(), target_sign.public().into(),
SignParam {
spec_version,
transaction_version,
genesis_hash: *target_client.genesis_hash(),
signer: target_sign,
},
move |transaction_nonce, initialization_data| { move |transaction_nonce, initialization_data| {
Ok(Bytes( Ok(UnsignedTransaction::new(
Self::Target::sign_transaction(SignParam { Self::encode_init_bridge(initialization_data).into(),
spec_version, transaction_nonce,
transaction_version,
genesis_hash: *target_client.genesis_hash(),
signer: target_sign,
era: relay_substrate_client::TransactionEra::immortal(),
unsigned: UnsignedTransaction::new(
Self::encode_init_bridge(initialization_data).into(),
transaction_nonce,
),
})?
.encode(),
)) ))
}, },
) )
@@ -223,13 +223,6 @@ impl std::fmt::Display for HexBytes {
} }
} }
impl HexBytes {
/// Encode given object and wrap into nicely formatted bytes.
pub fn encode<T: Encode>(t: &T) -> Self {
Self(t.encode())
}
}
/// Prometheus metrics params. /// Prometheus metrics params.
#[derive(Clone, Debug, PartialEq, StructOpt)] #[derive(Clone, Debug, PartialEq, StructOpt)]
pub struct PrometheusParams { pub struct PrometheusParams {
@@ -27,13 +27,13 @@ use polkadot_runtime_common::{
}; };
use polkadot_runtime_parachains::paras::ParaLifecycle; use polkadot_runtime_parachains::paras::ParaLifecycle;
use relay_substrate_client::{ use relay_substrate_client::{
AccountIdOf, CallOf, Chain, Client, HashOf, SignParam, Subscription, TransactionSignScheme, AccountIdOf, CallOf, Chain, Client, HashOf, SignParam, Subscription, TransactionStatusOf,
TransactionStatusOf, UnsignedTransaction, UnsignedTransaction,
}; };
use rialto_runtime::SudoCall; use rialto_runtime::SudoCall;
use sp_core::{ use sp_core::{
storage::{well_known_keys::CODE, StorageKey}, storage::{well_known_keys::CODE, StorageKey},
Bytes, Pair, Pair,
}; };
use structopt::StructOpt; use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames}; use strum::{EnumString, EnumVariantNames, VariantNames};
@@ -120,20 +120,16 @@ impl RegisterParachain {
relay_client relay_client
.submit_and_watch_signed_extrinsic( .submit_and_watch_signed_extrinsic(
relay_sudo_account.clone(), relay_sudo_account.clone(),
SignParam::<Relaychain> {
spec_version,
transaction_version,
genesis_hash: relay_genesis_hash,
signer: reserve_parachain_signer,
},
move |_, transaction_nonce| { move |_, transaction_nonce| {
Ok(Bytes( Ok(UnsignedTransaction::new(
Relaychain::sign_transaction(SignParam { reserve_parachain_id_call.into(),
spec_version, transaction_nonce,
transaction_version,
genesis_hash: relay_genesis_hash,
signer: reserve_parachain_signer,
era: relay_substrate_client::TransactionEra::immortal(),
unsigned: UnsignedTransaction::new(
reserve_parachain_id_call.into(),
transaction_nonce,
),
})?
.encode(),
)) ))
}, },
) )
@@ -169,20 +165,16 @@ impl RegisterParachain {
relay_client relay_client
.submit_and_watch_signed_extrinsic( .submit_and_watch_signed_extrinsic(
relay_sudo_account.clone(), relay_sudo_account.clone(),
SignParam::<Relaychain> {
spec_version,
transaction_version,
genesis_hash: relay_genesis_hash,
signer: register_parathread_signer,
},
move |_, transaction_nonce| { move |_, transaction_nonce| {
Ok(Bytes( Ok(UnsignedTransaction::new(
Relaychain::sign_transaction(SignParam { register_parathread_call.into(),
spec_version, transaction_nonce,
transaction_version,
genesis_hash: relay_genesis_hash,
signer: register_parathread_signer,
era: relay_substrate_client::TransactionEra::immortal(),
unsigned: UnsignedTransaction::new(
register_parathread_call.into(),
transaction_nonce,
),
})?
.encode(),
)) ))
}, },
) )
@@ -231,22 +223,18 @@ impl RegisterParachain {
.into(); .into();
let force_lease_signer = relay_sign.clone(); let force_lease_signer = relay_sign.clone();
relay_client relay_client
.submit_signed_extrinsic(relay_sudo_account.clone(), move |_, transaction_nonce| { .submit_signed_extrinsic(
Ok(Bytes( relay_sudo_account,
Relaychain::sign_transaction(SignParam { SignParam::<Relaychain> {
spec_version, spec_version,
transaction_version, transaction_version,
genesis_hash: relay_genesis_hash, genesis_hash: relay_genesis_hash,
signer: force_lease_signer, signer: force_lease_signer,
era: relay_substrate_client::TransactionEra::immortal(), },
unsigned: UnsignedTransaction::new( move |_, transaction_nonce| {
force_lease_call.into(), Ok(UnsignedTransaction::new(force_lease_call.into(), transaction_nonce))
transaction_nonce, },
), )
})?
.encode(),
))
})
.await?; .await?;
log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id); log::info!(target: "bridge", "Registered parachain leases: {:?}. Waiting for onboarding", para_id);
@@ -425,14 +425,15 @@ async fn update_transaction_tip<C: Chain, S: TransactionSignScheme<Chain = C>>(
current_priority = client current_priority = client
.validate_transaction( .validate_transaction(
at_block.1, at_block.1,
S::sign_transaction(SignParam { S::sign_transaction(
spec_version, SignParam {
transaction_version, spec_version,
genesis_hash: *client.genesis_hash(), transaction_version,
signer: transaction_params.signer.clone(), genesis_hash: *client.genesis_hash(),
era: relay_substrate_client::TransactionEra::immortal(), signer: transaction_params.signer.clone(),
unsigned: unsigned_tx.clone(), },
})?, unsigned_tx.clone(),
)?,
) )
.await?? .await??
.priority; .priority;
@@ -448,17 +449,18 @@ async fn update_transaction_tip<C: Chain, S: TransactionSignScheme<Chain = C>>(
Ok(( Ok((
old_tip != unsigned_tx.tip, old_tip != unsigned_tx.tip,
S::sign_transaction(SignParam { S::sign_transaction(
spec_version, SignParam {
transaction_version, spec_version,
genesis_hash: *client.genesis_hash(), transaction_version,
signer: transaction_params.signer.clone(), genesis_hash: *client.genesis_hash(),
era: relay_substrate_client::TransactionEra::new( signer: transaction_params.signer.clone(),
},
unsigned_tx.era(relay_substrate_client::TransactionEra::new(
at_block, at_block,
transaction_params.mortality, transaction_params.mortality,
), )),
unsigned: unsigned_tx, )?,
})?,
)) ))
} }
@@ -26,7 +26,7 @@ use crate::{
chain_schema::*, chain_schema::*,
encode_message::{self, CliEncodeMessage, RawMessage}, encode_message::{self, CliEncodeMessage, RawMessage},
estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride}, estimate_fee::{estimate_message_delivery_and_dispatch_fee, ConversionRateOverride},
Balance, CliChain, HexBytes, HexLaneId, Balance, CliChain, HexLaneId,
}, },
}; };
use async_trait::async_trait; use async_trait::async_trait;
@@ -146,55 +146,50 @@ where
let (spec_version, transaction_version) = source_client.simple_runtime_version().await?; let (spec_version, transaction_version) = source_client.simple_runtime_version().await?;
let estimated_transaction_fee = source_client let estimated_transaction_fee = source_client
.estimate_extrinsic_fee(Bytes( .estimate_extrinsic_fee(Bytes(
Self::Source::sign_transaction(SignParam { Self::Source::sign_transaction(
spec_version, SignParam {
transaction_version, spec_version,
genesis_hash: source_genesis_hash, transaction_version,
signer: source_sign.clone(), genesis_hash: source_genesis_hash,
era: relay_substrate_client::TransactionEra::immortal(), signer: source_sign.clone(),
unsigned: UnsignedTransaction::new(send_message_call.clone(), 0), },
})? UnsignedTransaction::new(send_message_call.clone(), 0),
)?
.encode(), .encode(),
)) ))
.await?; .await?;
source_client source_client
.submit_signed_extrinsic(source_sign.public().into(), move |_, transaction_nonce| { .submit_signed_extrinsic(
let signed_source_call = Self::Source::sign_transaction(SignParam { source_sign.public().into(),
SignParam::<Self::Source> {
spec_version, spec_version,
transaction_version, transaction_version,
genesis_hash: source_genesis_hash, genesis_hash: source_genesis_hash,
signer: source_sign.clone(), signer: source_sign.clone(),
era: relay_substrate_client::TransactionEra::immortal(), },
unsigned: UnsignedTransaction::new(send_message_call, transaction_nonce), move |_, transaction_nonce| {
})? let unsigned = UnsignedTransaction::new(send_message_call, transaction_nonce);
.encode(); log::info!(
target: "bridge",
"Sending message to {}. Lane: {:?}. Size: {}. Fee: {}",
Self::Target::NAME,
lane,
payload_len,
fee,
);
log::info!(
target: "bridge",
"The source account ({:?}) balance will be reduced by (at most) {} (message fee)
+ {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()),
fee.0,
estimated_transaction_fee.inclusion_fee(),
fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()),
Self::Source::NAME,
);
log::info!( Ok(unsigned)
target: "bridge", },
"Sending message to {}. Lane: {:?}. Size: {}. Fee: {}", )
Self::Target::NAME,
lane,
payload_len,
fee,
);
log::info!(
target: "bridge",
"The source account ({:?}) balance will be reduced by (at most) {} (message fee)
+ {} (tx fee ) = {} {} tokens", AccountId32::from(source_sign.public()),
fee.0,
estimated_transaction_fee.inclusion_fee(),
fee.0.saturating_add(estimated_transaction_fee.inclusion_fee().into()),
Self::Source::NAME,
);
log::info!(
target: "bridge",
"Signed {} Call: {:?}",
Self::Source::NAME,
HexBytes::encode(&signed_source_call)
);
Ok(Bytes(signed_source_call))
})
.await?; .await?;
Ok(()) Ok(())
@@ -230,7 +225,7 @@ fn decode_xcm(message: RawMessage) -> anyhow::Result<xcm::VersionedXcm<()>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::cli::ExplicitOrMaximal; use crate::cli::{ExplicitOrMaximal, HexBytes};
#[test] #[test]
fn send_raw_rialto_to_millau() { fn send_raw_rialto_to_millau() {
+30 -21
View File
@@ -102,18 +102,21 @@ impl TransactionSignScheme for Millau {
type AccountKeyPair = sp_core::sr25519::Pair; type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction = millau_runtime::UncheckedExtrinsic; type SignedTransaction = millau_runtime::UncheckedExtrinsic;
fn sign_transaction(param: SignParam<Self>) -> Result<Self::SignedTransaction, SubstrateError> { fn sign_transaction(
param: SignParam<Self>,
unsigned: UnsignedTransaction<Self::Chain>,
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::from_raw( let raw_payload = SignedPayload::from_raw(
param.unsigned.call, unsigned.call.clone(),
( (
frame_system::CheckNonZeroSender::<millau_runtime::Runtime>::new(), frame_system::CheckNonZeroSender::<millau_runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<millau_runtime::Runtime>::new(), frame_system::CheckSpecVersion::<millau_runtime::Runtime>::new(),
frame_system::CheckTxVersion::<millau_runtime::Runtime>::new(), frame_system::CheckTxVersion::<millau_runtime::Runtime>::new(),
frame_system::CheckGenesis::<millau_runtime::Runtime>::new(), frame_system::CheckGenesis::<millau_runtime::Runtime>::new(),
frame_system::CheckEra::<millau_runtime::Runtime>::from(param.era.frame_era()), frame_system::CheckEra::<millau_runtime::Runtime>::from(unsigned.era.frame_era()),
frame_system::CheckNonce::<millau_runtime::Runtime>::from(param.unsigned.nonce), frame_system::CheckNonce::<millau_runtime::Runtime>::from(unsigned.nonce),
frame_system::CheckWeight::<millau_runtime::Runtime>::new(), frame_system::CheckWeight::<millau_runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(param.unsigned.tip), pallet_transaction_payment::ChargeTransactionPayment::<millau_runtime::Runtime>::from(unsigned.tip),
millau_runtime::BridgeRejectObsoleteHeadersAndMessages, millau_runtime::BridgeRejectObsoleteHeadersAndMessages,
), ),
( (
@@ -121,7 +124,7 @@ impl TransactionSignScheme for Millau {
param.spec_version, param.spec_version,
param.transaction_version, param.transaction_version,
param.genesis_hash, param.genesis_hash,
param.era.signed_payload(param.genesis_hash), unsigned.era.signed_payload(param.genesis_hash),
(), (),
(), (),
(), (),
@@ -155,13 +158,17 @@ impl TransactionSignScheme for Millau {
fn parse_transaction(tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self::Chain>> { fn parse_transaction(tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self::Chain>> {
let extra = &tx.signature.as_ref()?.2; let extra = &tx.signature.as_ref()?.2;
Some(UnsignedTransaction { Some(
call: tx.function.into(), UnsignedTransaction::new(
nonce: Compact::<IndexOf<Self::Chain>>::decode(&mut &extra.5.encode()[..]).ok()?.into(), tx.function.into(),
tip: Compact::<BalanceOf<Self::Chain>>::decode(&mut &extra.7.encode()[..]) Compact::<IndexOf<Self::Chain>>::decode(&mut &extra.5.encode()[..]).ok()?.into(),
.ok()? )
.into(), .tip(
}) Compact::<BalanceOf<Self::Chain>>::decode(&mut &extra.7.encode()[..])
.ok()?
.into(),
),
)
} }
} }
@@ -185,15 +192,17 @@ mod tests {
.into(), .into(),
nonce: 777, nonce: 777,
tip: 888, tip: 888,
};
let signed_transaction = Millau::sign_transaction(SignParam {
spec_version: 42,
transaction_version: 50000,
genesis_hash: [42u8; 64].into(),
signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(),
era: TransactionEra::immortal(), era: TransactionEra::immortal(),
unsigned: unsigned.clone(), };
}) let signed_transaction = Millau::sign_transaction(
SignParam {
spec_version: 42,
transaction_version: 50000,
genesis_hash: [42u8; 64].into(),
signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(),
},
unsigned.clone(),
)
.unwrap(); .unwrap();
let parsed_transaction = Millau::parse_transaction(signed_transaction).unwrap(); let parsed_transaction = Millau::parse_transaction(signed_transaction).unwrap();
assert_eq!(parsed_transaction, unsigned); assert_eq!(parsed_transaction, unsigned);
@@ -101,31 +101,32 @@ impl TransactionSignScheme for RialtoParachain {
type AccountKeyPair = sp_core::sr25519::Pair; type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic; type SignedTransaction = rialto_parachain_runtime::UncheckedExtrinsic;
fn sign_transaction(param: SignParam<Self>) -> Result<Self::SignedTransaction, SubstrateError> { fn sign_transaction(
param: SignParam<Self>,
unsigned: UnsignedTransaction<Self::Chain>,
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::from_raw( let raw_payload = SignedPayload::from_raw(
param.unsigned.call, unsigned.call,
( (
frame_system::CheckNonZeroSender::<rialto_parachain_runtime::Runtime>::new(), frame_system::CheckNonZeroSender::<rialto_parachain_runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<rialto_parachain_runtime::Runtime>::new(), frame_system::CheckSpecVersion::<rialto_parachain_runtime::Runtime>::new(),
frame_system::CheckTxVersion::<rialto_parachain_runtime::Runtime>::new(), frame_system::CheckTxVersion::<rialto_parachain_runtime::Runtime>::new(),
frame_system::CheckGenesis::<rialto_parachain_runtime::Runtime>::new(), frame_system::CheckGenesis::<rialto_parachain_runtime::Runtime>::new(),
frame_system::CheckEra::<rialto_parachain_runtime::Runtime>::from( frame_system::CheckEra::<rialto_parachain_runtime::Runtime>::from(
param.era.frame_era(), unsigned.era.frame_era(),
),
frame_system::CheckNonce::<rialto_parachain_runtime::Runtime>::from(
param.unsigned.nonce,
), ),
frame_system::CheckNonce::<rialto_parachain_runtime::Runtime>::from(unsigned.nonce),
frame_system::CheckWeight::<rialto_parachain_runtime::Runtime>::new(), frame_system::CheckWeight::<rialto_parachain_runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::< pallet_transaction_payment::ChargeTransactionPayment::<
rialto_parachain_runtime::Runtime, rialto_parachain_runtime::Runtime,
>::from(param.unsigned.tip), >::from(unsigned.tip),
), ),
( (
(), (),
param.spec_version, param.spec_version,
param.transaction_version, param.transaction_version,
param.genesis_hash, param.genesis_hash,
param.era.signed_payload(param.genesis_hash), unsigned.era.signed_payload(param.genesis_hash),
(), (),
(), (),
(), (),
+30 -21
View File
@@ -109,25 +109,28 @@ impl TransactionSignScheme for Rialto {
type AccountKeyPair = sp_core::sr25519::Pair; type AccountKeyPair = sp_core::sr25519::Pair;
type SignedTransaction = rialto_runtime::UncheckedExtrinsic; type SignedTransaction = rialto_runtime::UncheckedExtrinsic;
fn sign_transaction(param: SignParam<Self>) -> Result<Self::SignedTransaction, SubstrateError> { fn sign_transaction(
param: SignParam<Self>,
unsigned: UnsignedTransaction<Self::Chain>,
) -> Result<Self::SignedTransaction, SubstrateError> {
let raw_payload = SignedPayload::from_raw( let raw_payload = SignedPayload::from_raw(
param.unsigned.call, unsigned.call.clone(),
( (
frame_system::CheckNonZeroSender::<rialto_runtime::Runtime>::new(), frame_system::CheckNonZeroSender::<rialto_runtime::Runtime>::new(),
frame_system::CheckSpecVersion::<rialto_runtime::Runtime>::new(), frame_system::CheckSpecVersion::<rialto_runtime::Runtime>::new(),
frame_system::CheckTxVersion::<rialto_runtime::Runtime>::new(), frame_system::CheckTxVersion::<rialto_runtime::Runtime>::new(),
frame_system::CheckGenesis::<rialto_runtime::Runtime>::new(), frame_system::CheckGenesis::<rialto_runtime::Runtime>::new(),
frame_system::CheckEra::<rialto_runtime::Runtime>::from(param.era.frame_era()), frame_system::CheckEra::<rialto_runtime::Runtime>::from(unsigned.era.frame_era()),
frame_system::CheckNonce::<rialto_runtime::Runtime>::from(param.unsigned.nonce), frame_system::CheckNonce::<rialto_runtime::Runtime>::from(unsigned.nonce),
frame_system::CheckWeight::<rialto_runtime::Runtime>::new(), frame_system::CheckWeight::<rialto_runtime::Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<rialto_runtime::Runtime>::from(param.unsigned.tip), pallet_transaction_payment::ChargeTransactionPayment::<rialto_runtime::Runtime>::from(unsigned.tip),
), ),
( (
(), (),
param.spec_version, param.spec_version,
param.transaction_version, param.transaction_version,
param.genesis_hash, param.genesis_hash,
param.era.signed_payload(param.genesis_hash), unsigned.era.signed_payload(param.genesis_hash),
(), (),
(), (),
(), (),
@@ -158,13 +161,17 @@ impl TransactionSignScheme for Rialto {
fn parse_transaction(tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self::Chain>> { fn parse_transaction(tx: Self::SignedTransaction) -> Option<UnsignedTransaction<Self::Chain>> {
let extra = &tx.signature.as_ref()?.2; let extra = &tx.signature.as_ref()?.2;
Some(UnsignedTransaction { Some(
call: tx.function.into(), UnsignedTransaction::new(
nonce: Compact::<IndexOf<Self::Chain>>::decode(&mut &extra.5.encode()[..]).ok()?.into(), tx.function.into(),
tip: Compact::<BalanceOf<Self::Chain>>::decode(&mut &extra.7.encode()[..]) Compact::<IndexOf<Self::Chain>>::decode(&mut &extra.5.encode()[..]).ok()?.into(),
.ok()? )
.into(), .tip(
}) Compact::<BalanceOf<Self::Chain>>::decode(&mut &extra.7.encode()[..])
.ok()?
.into(),
),
)
} }
} }
@@ -188,15 +195,17 @@ mod tests {
.into(), .into(),
nonce: 777, nonce: 777,
tip: 888, tip: 888,
};
let signed_transaction = Rialto::sign_transaction(SignParam {
spec_version: 42,
transaction_version: 50000,
genesis_hash: [42u8; 32].into(),
signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(),
era: TransactionEra::immortal(), era: TransactionEra::immortal(),
unsigned: unsigned.clone(), };
}) let signed_transaction = Rialto::sign_transaction(
SignParam {
spec_version: 42,
transaction_version: 50000,
genesis_hash: [42u8; 32].into(),
signer: sp_core::sr25519::Pair::from_seed_slice(&[1u8; 32]).unwrap(),
},
unsigned.clone(),
)
.unwrap(); .unwrap();
let parsed_transaction = Rialto::parse_transaction(signed_transaction).unwrap(); let parsed_transaction = Rialto::parse_transaction(signed_transaction).unwrap();
assert_eq!(parsed_transaction, unsigned); assert_eq!(parsed_transaction, unsigned);
+19 -9
View File
@@ -15,7 +15,9 @@
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
use bp_messages::MessageNonce; use bp_messages::MessageNonce;
use bp_runtime::{Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEraOf}; use bp_runtime::{
Chain as ChainBase, EncodedOrDecodedCall, HashOf, TransactionEra, TransactionEraOf,
};
use codec::{Codec, Encode}; use codec::{Codec, Encode};
use frame_support::weights::{Weight, WeightToFeePolynomial}; use frame_support::weights::{Weight, WeightToFeePolynomial};
use jsonrpsee::core::{DeserializeOwned, Serialize}; use jsonrpsee::core::{DeserializeOwned, Serialize};
@@ -158,12 +160,14 @@ pub struct UnsignedTransaction<C: Chain> {
pub nonce: C::Index, pub nonce: C::Index,
/// Tip included into transaction. /// Tip included into transaction.
pub tip: C::Balance, pub tip: C::Balance,
/// Transaction era used by the chain.
pub era: TransactionEraOf<C>,
} }
impl<C: Chain> UnsignedTransaction<C> { impl<C: Chain> UnsignedTransaction<C> {
/// Create new unsigned transaction with given call, nonce and zero tip. /// Create new unsigned transaction with given call, nonce, era and zero tip.
pub fn new(call: EncodedOrDecodedCall<C::Call>, nonce: C::Index) -> Self { pub fn new(call: EncodedOrDecodedCall<C::Call>, nonce: C::Index) -> Self {
Self { call, nonce, tip: Zero::zero() } Self { call, nonce, era: TransactionEra::Immortal, tip: Zero::zero() }
} }
/// Set transaction tip. /// Set transaction tip.
@@ -172,13 +176,20 @@ impl<C: Chain> UnsignedTransaction<C> {
self.tip = tip; self.tip = tip;
self self
} }
/// Set transaction era.
#[must_use]
pub fn era(mut self, era: TransactionEraOf<C>) -> Self {
self.era = era;
self
}
} }
/// Account key pair used by transactions signing scheme. /// Account key pair used by transactions signing scheme.
pub type AccountKeyPairOf<S> = <S as TransactionSignScheme>::AccountKeyPair; pub type AccountKeyPairOf<S> = <S as TransactionSignScheme>::AccountKeyPair;
/// Substrate-based chain transactions signing scheme. /// Substrate-based chain transactions signing scheme.
pub trait TransactionSignScheme { pub trait TransactionSignScheme: 'static {
/// Chain that this scheme is to be used. /// Chain that this scheme is to be used.
type Chain: Chain; type Chain: Chain;
/// Type of key pairs used to sign transactions. /// Type of key pairs used to sign transactions.
@@ -187,7 +198,10 @@ pub trait TransactionSignScheme {
type SignedTransaction: Clone + Debug + Codec + Send + 'static; type SignedTransaction: Clone + Debug + Codec + Send + 'static;
/// Create transaction for given runtime call, signed by given account. /// Create transaction for given runtime call, signed by given account.
fn sign_transaction(param: SignParam<Self>) -> Result<Self::SignedTransaction, crate::Error> fn sign_transaction(
param: SignParam<Self>,
unsigned: UnsignedTransaction<Self::Chain>,
) -> Result<Self::SignedTransaction, crate::Error>
where where
Self: Sized; Self: Sized;
@@ -213,10 +227,6 @@ pub struct SignParam<T: TransactionSignScheme> {
pub genesis_hash: <T::Chain as ChainBase>::Hash, pub genesis_hash: <T::Chain as ChainBase>::Hash,
/// Signer account /// Signer account
pub signer: T::AccountKeyPair, pub signer: T::AccountKeyPair,
/// Transaction era used by the chain.
pub era: TransactionEraOf<T::Chain>,
/// Transaction before it is signed.
pub unsigned: UnsignedTransaction<T::Chain>,
} }
impl<Block: BlockT> BlockWithJustification<Block::Header> for SignedBlock<Block> { impl<Block: BlockT> BlockWithJustification<Block::Header> for SignedBlock<Block> {
+34 -20
View File
@@ -17,13 +17,14 @@
//! Substrate node client. //! Substrate node client.
use crate::{ use crate::{
chain::{Chain, ChainWithBalances, TransactionStatusOf}, chain::{Chain, ChainWithBalances},
rpc::{ rpc::{
SubstrateAuthorClient, SubstrateChainClient, SubstrateFrameSystemClient, SubstrateAuthorClient, SubstrateChainClient, SubstrateFrameSystemClient,
SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient, SubstrateGrandpaClient, SubstrateStateClient, SubstrateSystemClient,
SubstrateTransactionPaymentClient, SubstrateTransactionPaymentClient,
}, },
ConnectionParams, Error, HashOf, HeaderIdOf, Result, ConnectionParams, Error, HashOf, HeaderIdOf, Result, SignParam, TransactionSignScheme,
TransactionStatusOf, UnsignedTransaction,
}; };
use async_std::sync::{Arc, Mutex}; use async_std::sync::{Arc, Mutex};
@@ -403,10 +404,13 @@ impl<C: Chain> Client<C> {
/// if all client instances are clones of the same initial `Client`. /// if all client instances are clones of the same initial `Client`.
/// ///
/// Note: The given transaction needs to be SCALE encoded beforehand. /// Note: The given transaction needs to be SCALE encoded beforehand.
pub async fn submit_signed_extrinsic( pub async fn submit_signed_extrinsic<S: TransactionSignScheme<Chain = C> + 'static>(
&self, &self,
extrinsic_signer: C::AccountId, extrinsic_signer: C::AccountId,
prepare_extrinsic: impl FnOnce(HeaderIdOf<C>, C::Index) -> Result<Bytes> + Send + 'static, signing_data: SignParam<S>,
prepare_extrinsic: impl FnOnce(HeaderIdOf<C>, C::Index) -> Result<UnsignedTransaction<C>>
+ Send
+ 'static,
) -> Result<C::Hash> { ) -> Result<C::Hash> {
let _guard = self.submit_signed_extrinsic_lock.lock().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(extrinsic_signer).await?;
@@ -421,12 +425,14 @@ impl<C: Chain> Client<C> {
self.jsonrpsee_execute(move |client| async move { 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 = SubstrateAuthorClient::<C>::submit_extrinsic(&*client, extrinsic) let signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode();
.await let tx_hash =
.map_err(|e| { SubstrateAuthorClient::<C>::submit_extrinsic(&*client, Bytes(signed_extrinsic))
log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); .await
e .map_err(|e| {
})?; log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e);
e
})?;
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
Ok(tx_hash) Ok(tx_hash)
}) })
@@ -435,10 +441,15 @@ impl<C: Chain> Client<C> {
/// Does exactly the same as `submit_signed_extrinsic`, but keeps watching for extrinsic status /// Does exactly the same as `submit_signed_extrinsic`, but keeps watching for extrinsic status
/// after submission. /// after submission.
pub async fn submit_and_watch_signed_extrinsic( pub async fn submit_and_watch_signed_extrinsic<
S: TransactionSignScheme<Chain = C> + 'static,
>(
&self, &self,
extrinsic_signer: C::AccountId, extrinsic_signer: C::AccountId,
prepare_extrinsic: impl FnOnce(HeaderIdOf<C>, C::Index) -> Result<Bytes> + Send + 'static, signing_data: SignParam<S>,
prepare_extrinsic: impl FnOnce(HeaderIdOf<C>, C::Index) -> Result<UnsignedTransaction<C>>
+ Send
+ 'static,
) -> Result<Subscription<TransactionStatusOf<C>>> { ) -> Result<Subscription<TransactionStatusOf<C>>> {
let _guard = self.submit_signed_extrinsic_lock.lock().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(extrinsic_signer).await?;
@@ -447,14 +458,17 @@ impl<C: Chain> Client<C> {
let subscription = self let subscription = self
.jsonrpsee_execute(move |client| async move { .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 signed_extrinsic = S::sign_transaction(signing_data, extrinsic)?.encode();
let subscription = let tx_hash = C::Hasher::hash(&signed_extrinsic);
SubstrateAuthorClient::<C>::submit_and_watch_extrinsic(&*client, extrinsic) let subscription = SubstrateAuthorClient::<C>::submit_and_watch_extrinsic(
.await &*client,
.map_err(|e| { Bytes(signed_extrinsic),
log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e); )
e .await
})?; .map_err(|e| {
log::error!(target: "bridge", "Failed to send transaction to {} node: {:?}", C::NAME, e);
e
})?;
log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash); log::trace!(target: "bridge", "Sent transaction to {} node: {:?}", C::NAME, tx_hash);
Ok(subscription) Ok(subscription)
}) })
@@ -127,7 +127,7 @@ impl SourceClient<TestFinalitySyncPipeline> for TestSourceClient {
async fn best_finalized_block_number(&self) -> Result<TestNumber, TestError> { async fn best_finalized_block_number(&self) -> Result<TestNumber, TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.on_method_call)(&mut *data); (self.on_method_call)(&mut data);
Ok(data.source_best_block_number) Ok(data.source_best_block_number)
} }
@@ -136,13 +136,13 @@ impl SourceClient<TestFinalitySyncPipeline> for TestSourceClient {
number: TestNumber, number: TestNumber,
) -> Result<(TestSourceHeader, Option<TestFinalityProof>), TestError> { ) -> Result<(TestSourceHeader, Option<TestFinalityProof>), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.on_method_call)(&mut *data); (self.on_method_call)(&mut data);
data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection) data.source_headers.get(&number).cloned().ok_or(TestError::NonConnection)
} }
async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, TestError> { async fn finality_proofs(&self) -> Result<Self::FinalityProofsStream, TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.on_method_call)(&mut *data); (self.on_method_call)(&mut data);
Ok(futures::stream::iter(data.source_proofs.clone()).boxed()) Ok(futures::stream::iter(data.source_proofs.clone()).boxed())
} }
} }
@@ -168,7 +168,7 @@ impl TargetClient<TestFinalitySyncPipeline> for TestTargetClient {
&self, &self,
) -> Result<HeaderId<TestHash, TestNumber>, TestError> { ) -> Result<HeaderId<TestHash, TestNumber>, TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.on_method_call)(&mut *data); (self.on_method_call)(&mut data);
Ok(data.target_best_block_id) Ok(data.target_best_block_id)
} }
@@ -178,7 +178,7 @@ impl TargetClient<TestFinalitySyncPipeline> for TestTargetClient {
proof: TestFinalityProof, proof: TestFinalityProof,
) -> Result<(), TestError> { ) -> Result<(), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.on_method_call)(&mut *data); (self.on_method_call)(&mut data);
data.target_best_block_id = HeaderId(header.number(), header.hash()); data.target_best_block_id = HeaderId(header.number(), header.hash());
data.target_headers.push((header, proof)); data.target_headers.push((header, proof));
Ok(()) Ok(())
@@ -18,13 +18,12 @@
use crate::{messages_lane::SubstrateMessageLane, TransactionParams}; use crate::{messages_lane::SubstrateMessageLane, TransactionParams};
use codec::Encode;
use relay_substrate_client::{ use relay_substrate_client::{
transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam, transaction_stall_timeout, AccountIdOf, AccountKeyPairOf, CallOf, Chain, Client, SignParam,
TransactionEra, TransactionSignScheme, UnsignedTransaction, TransactionEra, TransactionSignScheme, UnsignedTransaction,
}; };
use relay_utils::metrics::F64SharedRef; use relay_utils::metrics::F64SharedRef;
use sp_core::{Bytes, Pair}; use sp_core::Pair;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
/// Duration between updater iterations. /// Duration between updater iterations.
@@ -272,19 +271,19 @@ where
updated_rate, updated_rate,
)?; )?;
client client
.submit_signed_extrinsic(signer_id, move |best_block_id, transaction_nonce| { .submit_signed_extrinsic(
Ok(Bytes( signer_id,
Sign::sign_transaction(SignParam { SignParam::<Sign> {
spec_version, spec_version,
transaction_version, transaction_version,
genesis_hash, genesis_hash,
signer: transaction_params.signer, signer: transaction_params.signer,
era: TransactionEra::new(best_block_id, transaction_params.mortality), },
unsigned: UnsignedTransaction::new(call.into(), transaction_nonce), move |best_block_id, transaction_nonce| {
})? Ok(UnsignedTransaction::new(call.into(), transaction_nonce)
.encode(), .era(TransactionEra::new(best_block_id, transaction_params.mortality)))
)) },
}) )
.await .await
.map(drop) .map(drop)
.map_err(|err| anyhow::format_err!("{:?}", err)) .map_err(|err| anyhow::format_err!("{:?}", err))
@@ -53,7 +53,7 @@ pub enum Error<Hash: Debug + MaybeDisplay, HeaderNumber: Debug + MaybeDisplay> {
#[error("Failed to decode {0} GRANDPA authorities set at header {1}: {2:?}")] #[error("Failed to decode {0} GRANDPA authorities set at header {1}: {2:?}")]
DecodeAuthorities(&'static str, Hash, codec::Error), DecodeAuthorities(&'static str, Hash, codec::Error),
/// Failed to retrieve header by the hash from the source chain. /// Failed to retrieve header by the hash from the source chain.
#[error("Failed to retrieve {0} header with hash {1}: {:?}")] #[error("Failed to retrieve {0} header with hash {1}: {2:?}")]
RetrieveHeader(&'static str, Hash, client::Error), RetrieveHeader(&'static str, Hash, client::Error),
/// Failed to submit signed extrinsic from to the target chain. /// Failed to submit signed extrinsic from to the target chain.
#[error( #[error(
@@ -23,18 +23,28 @@
use crate::{error::Error, finality::engine::Engine}; use crate::{error::Error, finality::engine::Engine};
use relay_substrate_client::{Chain, Client, Error as SubstrateError}; use relay_substrate_client::{
use sp_core::Bytes; Chain, Client, Error as SubstrateError, SignParam, TransactionSignScheme, UnsignedTransaction,
};
use sp_runtime::traits::Header as HeaderT; use sp_runtime::traits::Header as HeaderT;
/// Submit headers-bridge initialization transaction. /// Submit headers-bridge initialization transaction.
pub async fn initialize<E: Engine<SourceChain>, SourceChain: Chain, TargetChain: Chain, F>( pub async fn initialize<
E: Engine<SourceChain>,
SourceChain: Chain,
TargetChain: Chain + TransactionSignScheme<Chain = TargetChain>,
F,
>(
source_client: Client<SourceChain>, source_client: Client<SourceChain>,
target_client: Client<TargetChain>, target_client: Client<TargetChain>,
target_transactions_signer: TargetChain::AccountId, target_transactions_signer: TargetChain::AccountId,
target_signing_data: SignParam<TargetChain>,
prepare_initialize_transaction: F, prepare_initialize_transaction: F,
) where ) where
F: FnOnce(TargetChain::Index, E::InitializationData) -> Result<Bytes, SubstrateError> F: FnOnce(
TargetChain::Index,
E::InitializationData,
) -> Result<UnsignedTransaction<TargetChain>, SubstrateError>
+ Send + Send
+ 'static, + 'static,
{ {
@@ -42,6 +52,7 @@ pub async fn initialize<E: Engine<SourceChain>, SourceChain: Chain, TargetChain:
source_client, source_client,
target_client, target_client,
target_transactions_signer, target_transactions_signer,
target_signing_data,
prepare_initialize_transaction, prepare_initialize_transaction,
) )
.await; .await;
@@ -66,17 +77,26 @@ pub async fn initialize<E: Engine<SourceChain>, SourceChain: Chain, TargetChain:
} }
/// Craft and submit initialization transaction, returning any error that may occur. /// Craft and submit initialization transaction, returning any error that may occur.
async fn do_initialize<E: Engine<SourceChain>, SourceChain: Chain, TargetChain: Chain, F>( async fn do_initialize<
E: Engine<SourceChain>,
SourceChain: Chain,
TargetChain: Chain + TransactionSignScheme<Chain = TargetChain>,
F,
>(
source_client: Client<SourceChain>, source_client: Client<SourceChain>,
target_client: Client<TargetChain>, target_client: Client<TargetChain>,
target_transactions_signer: TargetChain::AccountId, target_transactions_signer: TargetChain::AccountId,
target_signing_data: SignParam<TargetChain>,
prepare_initialize_transaction: F, prepare_initialize_transaction: F,
) -> Result< ) -> Result<
Option<TargetChain::Hash>, Option<TargetChain::Hash>,
Error<SourceChain::Hash, <SourceChain::Header as HeaderT>::Number>, Error<SourceChain::Hash, <SourceChain::Header as HeaderT>::Number>,
> >
where where
F: FnOnce(TargetChain::Index, E::InitializationData) -> Result<Bytes, SubstrateError> F: FnOnce(
TargetChain::Index,
E::InitializationData,
) -> Result<UnsignedTransaction<TargetChain>, SubstrateError>
+ Send + Send
+ 'static, + 'static,
{ {
@@ -103,10 +123,15 @@ where
); );
let initialization_tx_hash = target_client let initialization_tx_hash = target_client
.submit_signed_extrinsic(target_transactions_signer, move |_, transaction_nonce| { .submit_signed_extrinsic(
prepare_initialize_transaction(transaction_nonce, initialization_data) target_transactions_signer,
}) target_signing_data,
move |_, transaction_nonce| {
prepare_initialize_transaction(transaction_nonce, initialization_data)
},
)
.await .await
.map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?; .map_err(|err| Error::SubmitTransaction(TargetChain::NAME, err))?;
Ok(Some(initialization_tx_hash)) Ok(Some(initialization_tx_hash))
} }
@@ -194,7 +194,7 @@ where
stall_timeout: transaction_stall_timeout( stall_timeout: transaction_stall_timeout(
transaction_params.mortality, transaction_params.mortality,
P::TargetChain::AVERAGE_BLOCK_INTERVAL, P::TargetChain::AVERAGE_BLOCK_INTERVAL,
crate::STALL_TIMEOUT, relay_utils::STALL_TIMEOUT,
), ),
only_mandatory_headers, only_mandatory_headers,
}, },
@@ -25,14 +25,13 @@ use crate::{
}; };
use async_trait::async_trait; use async_trait::async_trait;
use codec::Encode;
use finality_relay::TargetClient; use finality_relay::TargetClient;
use relay_substrate_client::{ use relay_substrate_client::{
AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam, AccountIdOf, AccountKeyPairOf, Chain, Client, Error, HeaderIdOf, HeaderOf, SignParam,
SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction, SyncHeader, TransactionEra, TransactionSignScheme, UnsignedTransaction,
}; };
use relay_utils::relay_loop::Client as RelayClient; use relay_utils::relay_loop::Client as RelayClient;
use sp_core::{Bytes, Pair}; use sp_core::Pair;
/// Substrate client as Substrate finality target. /// Substrate client as Substrate finality target.
pub struct SubstrateFinalityTarget<P: SubstrateFinalitySyncPipeline> { pub struct SubstrateFinalityTarget<P: SubstrateFinalitySyncPipeline> {
@@ -119,18 +118,15 @@ where
self.client self.client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.transaction_params.signer.public().into(), self.transaction_params.signer.public().into(),
SignParam::<P::TransactionSignScheme> {
spec_version,
transaction_version,
genesis_hash,
signer: transaction_params.signer.clone(),
},
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
Ok(Bytes( Ok(UnsignedTransaction::new(call.into(), transaction_nonce)
P::TransactionSignScheme::sign_transaction(SignParam { .era(TransactionEra::new(best_block_id, transaction_params.mortality)))
spec_version,
transaction_version,
genesis_hash,
signer: transaction_params.signer.clone(),
era: TransactionEra::new(best_block_id, transaction_params.mortality),
unsigned: UnsignedTransaction::new(call.into(), transaction_nonce),
})?
.encode(),
))
}, },
) )
.await .await
@@ -18,8 +18,6 @@
#![warn(missing_docs)] #![warn(missing_docs)]
use std::time::Duration;
pub mod conversion_rate_update; pub mod conversion_rate_update;
pub mod error; pub mod error;
pub mod finality; pub mod finality;
@@ -31,15 +29,6 @@ pub mod messages_target;
pub mod on_demand; pub mod on_demand;
pub mod parachains; pub mod parachains;
/// Default relay loop stall timeout. If transactions generated by relay are immortal, then
/// this timeout is used.
///
/// There are no any strict requirements on block time in Substrate. But we assume here that all
/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest
/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine
/// transaction, or remove it from the pool.
pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60);
/// Transaction creation parameters. /// Transaction creation parameters.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TransactionParams<TS> { pub struct TransactionParams<TS> {
@@ -22,7 +22,7 @@ use crate::{
messages_source::{SubstrateMessagesProof, SubstrateMessagesSource}, messages_source::{SubstrateMessagesProof, SubstrateMessagesSource},
messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget}, messages_target::{SubstrateMessagesDeliveryProof, SubstrateMessagesTarget},
on_demand::OnDemandRelay, on_demand::OnDemandRelay,
TransactionParams, STALL_TIMEOUT, TransactionParams,
}; };
use async_std::sync::Arc; use async_std::sync::Arc;
@@ -39,7 +39,7 @@ use relay_substrate_client::{
transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain, transaction_stall_timeout, AccountKeyPairOf, BalanceOf, BlockNumberOf, CallOf, Chain,
ChainWithMessages, Client, HashOf, TransactionSignScheme, ChainWithMessages, Client, HashOf, TransactionSignScheme,
}; };
use relay_utils::metrics::MetricsParams; use relay_utils::{metrics::MetricsParams, STALL_TIMEOUT};
use sp_core::Pair; use sp_core::Pair;
use std::{convert::TryFrom, fmt::Debug, marker::PhantomData}; use std::{convert::TryFrom, fmt::Debug, marker::PhantomData};
@@ -346,11 +346,14 @@ where
self.source_client self.source_client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.transaction_params.signer.public().into(), self.transaction_params.signer.public().into(),
SignParam::<P::SourceTransactionSignScheme> {
spec_version,
transaction_version,
genesis_hash,
signer: self.transaction_params.signer.clone(),
},
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
make_messages_delivery_proof_transaction::<P>( make_messages_delivery_proof_transaction::<P>(
spec_version,
transaction_version,
&genesis_hash,
&transaction_params, &transaction_params,
best_block_id, best_block_id,
transaction_nonce, transaction_nonce,
@@ -377,18 +380,24 @@ where
Err(_) => return BalanceOf::<P::SourceChain>::max_value(), Err(_) => return BalanceOf::<P::SourceChain>::max_value(),
}; };
async { async {
let dummy_tx = make_messages_delivery_proof_transaction::<P>( let dummy_tx = P::SourceTransactionSignScheme::sign_transaction(
runtime_version.spec_version, SignParam::<P::SourceTransactionSignScheme> {
runtime_version.transaction_version, spec_version: runtime_version.spec_version,
self.source_client.genesis_hash(), transaction_version: runtime_version.transaction_version,
&self.transaction_params, genesis_hash: *self.source_client.genesis_hash(),
HeaderId(Default::default(), Default::default()), signer: self.transaction_params.signer.clone(),
Zero::zero(), },
prepare_dummy_messages_delivery_proof::<P::SourceChain, P::TargetChain>(), make_messages_delivery_proof_transaction::<P>(
false, &self.transaction_params,
)?; HeaderId(Default::default(), Default::default()),
Zero::zero(),
prepare_dummy_messages_delivery_proof::<P::SourceChain, P::TargetChain>(),
false,
)?,
)?
.encode();
self.source_client self.source_client
.estimate_extrinsic_fee(dummy_tx) .estimate_extrinsic_fee(Bytes(dummy_tx))
.await .await
.map(|fee| fee.inclusion_fee()) .map(|fee| fee.inclusion_fee())
} }
@@ -418,17 +427,13 @@ where
} }
/// Make messages delivery proof transaction from given proof. /// Make messages delivery proof transaction from given proof.
#[allow(clippy::too_many_arguments)]
fn make_messages_delivery_proof_transaction<P: SubstrateMessageLane>( fn make_messages_delivery_proof_transaction<P: SubstrateMessageLane>(
spec_version: u32,
transaction_version: u32,
source_genesis_hash: &HashOf<P::SourceChain>,
source_transaction_params: &TransactionParams<AccountKeyPairOf<P::SourceTransactionSignScheme>>, source_transaction_params: &TransactionParams<AccountKeyPairOf<P::SourceTransactionSignScheme>>,
source_best_block_id: HeaderIdOf<P::SourceChain>, source_best_block_id: HeaderIdOf<P::SourceChain>,
transaction_nonce: IndexOf<P::SourceChain>, transaction_nonce: IndexOf<P::SourceChain>,
proof: SubstrateMessagesDeliveryProof<P::TargetChain>, proof: SubstrateMessagesDeliveryProof<P::TargetChain>,
trace_call: bool, trace_call: bool,
) -> Result<Bytes, SubstrateError> ) -> Result<UnsignedTransaction<P::SourceChain>, SubstrateError>
where where
P::SourceTransactionSignScheme: TransactionSignScheme<Chain = P::SourceChain>, P::SourceTransactionSignScheme: TransactionSignScheme<Chain = P::SourceChain>,
{ {
@@ -436,17 +441,8 @@ where
P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call( P::ReceiveMessagesDeliveryProofCallBuilder::build_receive_messages_delivery_proof_call(
proof, trace_call, proof, trace_call,
); );
Ok(Bytes( Ok(UnsignedTransaction::new(call.into(), transaction_nonce)
P::SourceTransactionSignScheme::sign_transaction(SignParam { .era(TransactionEra::new(source_best_block_id, source_transaction_params.mortality)))
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.into(), transaction_nonce),
})?
.encode(),
))
} }
/// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction. /// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction.
@@ -255,11 +255,14 @@ where
self.target_client self.target_client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.transaction_params.signer.public().into(), self.transaction_params.signer.public().into(),
SignParam::<P::TargetTransactionSignScheme> {
spec_version,
transaction_version,
genesis_hash,
signer: self.transaction_params.signer.clone(),
},
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
make_messages_delivery_transaction::<P>( make_messages_delivery_transaction::<P>(
spec_version,
transaction_version,
&genesis_hash,
&transaction_params, &transaction_params,
best_block_id, best_block_id,
transaction_nonce, transaction_nonce,
@@ -299,23 +302,29 @@ where
let (spec_version, transaction_version) = let (spec_version, transaction_version) =
self.target_client.simple_runtime_version().await?; self.target_client.simple_runtime_version().await?;
// Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight. // Prepare 'dummy' delivery transaction - we only care about its length and dispatch weight.
let delivery_tx = make_messages_delivery_transaction::<P>( let delivery_tx = P::TargetTransactionSignScheme::sign_transaction(
spec_version, SignParam {
transaction_version, spec_version,
self.target_client.genesis_hash(), transaction_version,
&self.transaction_params, genesis_hash: Default::default(),
HeaderId(Default::default(), Default::default()), signer: self.transaction_params.signer.clone(),
Zero::zero(), },
self.relayer_id_at_source.clone(), make_messages_delivery_transaction::<P>(
nonces.clone(), &self.transaction_params,
prepare_dummy_messages_proof::<P::SourceChain>( HeaderId(Default::default(), Default::default()),
Zero::zero(),
self.relayer_id_at_source.clone(),
nonces.clone(), nonces.clone(),
total_dispatch_weight, prepare_dummy_messages_proof::<P::SourceChain>(
total_size, nonces.clone(),
), total_dispatch_weight,
false, total_size,
)?; ),
let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(delivery_tx).await?; false,
)?,
)?
.encode();
let delivery_tx_fee = self.target_client.estimate_extrinsic_fee(Bytes(delivery_tx)).await?;
let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee(); let inclusion_fee_in_target_tokens = delivery_tx_fee.inclusion_fee();
// The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch // The pre-dispatch cost of delivery transaction includes additional fee to cover dispatch
@@ -340,24 +349,30 @@ where
let (spec_version, transaction_version) = let (spec_version, transaction_version) =
self.target_client.simple_runtime_version().await?; self.target_client.simple_runtime_version().await?;
let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE); let larger_dispatch_weight = total_dispatch_weight.saturating_add(WEIGHT_DIFFERENCE);
let dummy_tx = make_messages_delivery_transaction::<P>( let dummy_tx = P::TargetTransactionSignScheme::sign_transaction(
spec_version, SignParam {
transaction_version, spec_version,
self.target_client.genesis_hash(), transaction_version,
&self.transaction_params, genesis_hash: Default::default(),
HeaderId(Default::default(), Default::default()), signer: self.transaction_params.signer.clone(),
Zero::zero(), },
self.relayer_id_at_source.clone(), make_messages_delivery_transaction::<P>(
nonces.clone(), &self.transaction_params,
prepare_dummy_messages_proof::<P::SourceChain>( HeaderId(Default::default(), Default::default()),
Zero::zero(),
self.relayer_id_at_source.clone(),
nonces.clone(), nonces.clone(),
larger_dispatch_weight, prepare_dummy_messages_proof::<P::SourceChain>(
total_size, nonces.clone(),
), larger_dispatch_weight,
false, total_size,
)?; ),
false,
)?,
)?
.encode();
let larger_delivery_tx_fee = let larger_delivery_tx_fee =
self.target_client.estimate_extrinsic_fee(dummy_tx).await?; self.target_client.estimate_extrinsic_fee(Bytes(dummy_tx)).await?;
compute_prepaid_messages_refund::<P::TargetChain>( compute_prepaid_messages_refund::<P::TargetChain>(
total_prepaid_nonces, total_prepaid_nonces,
@@ -406,11 +421,7 @@ where
} }
/// Make messages delivery transaction from given proof. /// Make messages delivery transaction from given proof.
#[allow(clippy::too_many_arguments)]
fn make_messages_delivery_transaction<P: SubstrateMessageLane>( fn make_messages_delivery_transaction<P: SubstrateMessageLane>(
spec_version: u32,
transaction_version: u32,
target_genesis_hash: &HashOf<P::TargetChain>,
target_transaction_params: &TransactionParams<AccountKeyPairOf<P::TargetTransactionSignScheme>>, target_transaction_params: &TransactionParams<AccountKeyPairOf<P::TargetTransactionSignScheme>>,
target_best_block_id: HeaderIdOf<P::TargetChain>, target_best_block_id: HeaderIdOf<P::TargetChain>,
transaction_nonce: IndexOf<P::TargetChain>, transaction_nonce: IndexOf<P::TargetChain>,
@@ -418,7 +429,7 @@ fn make_messages_delivery_transaction<P: SubstrateMessageLane>(
nonces: RangeInclusive<MessageNonce>, nonces: RangeInclusive<MessageNonce>,
proof: SubstrateMessagesProof<P::SourceChain>, proof: SubstrateMessagesProof<P::SourceChain>,
trace_call: bool, trace_call: bool,
) -> Result<Bytes, SubstrateError> ) -> Result<UnsignedTransaction<P::TargetChain>, SubstrateError>
where where
P::TargetTransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>, P::TargetTransactionSignScheme: TransactionSignScheme<Chain = P::TargetChain>,
{ {
@@ -431,17 +442,8 @@ where
dispatch_weight, dispatch_weight,
trace_call, trace_call,
); );
Ok(Bytes( Ok(UnsignedTransaction::new(call.into(), transaction_nonce)
P::TargetTransactionSignScheme::sign_transaction(SignParam { .era(TransactionEra::new(target_best_block_id, target_transaction_params.mortality)))
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.into(), transaction_nonce),
})?
.encode(),
))
} }
/// Prepare 'dummy' messages proof that will compose the delivery transaction. /// Prepare 'dummy' messages proof that will compose the delivery transaction.
@@ -28,6 +28,7 @@ use relay_substrate_client::{
}; };
use relay_utils::{ use relay_utils::{
metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError, metrics::MetricsParams, relay_loop::Client as RelayClient, FailedClient, MaybeConnectionError,
STALL_TIMEOUT,
}; };
use crate::{ use crate::{
@@ -37,7 +38,7 @@ use crate::{
SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT, SubstrateFinalitySyncPipeline, RECENT_FINALITY_PROOFS_LIMIT,
}, },
on_demand::OnDemandRelay, on_demand::OnDemandRelay,
TransactionParams, STALL_TIMEOUT, TransactionParams,
}; };
/// On-demand Substrate <-> Substrate header finality relay. /// On-demand Substrate <-> Substrate header finality relay.
@@ -263,7 +263,7 @@ async fn background_task<P: SubstrateParachainsPipeline>(
let stall_timeout = relay_substrate_client::transaction_stall_timeout( let stall_timeout = relay_substrate_client::transaction_stall_timeout(
target_transactions_mortality, target_transactions_mortality,
P::TargetChain::AVERAGE_BLOCK_INTERVAL, P::TargetChain::AVERAGE_BLOCK_INTERVAL,
crate::STALL_TIMEOUT, relay_utils::STALL_TIMEOUT,
); );
log::info!( log::info!(
@@ -29,7 +29,7 @@ use bp_parachains::{
}; };
use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId}; use bp_polkadot_core::parachains::{ParaHash, ParaHeadsProof, ParaId};
use bp_runtime::HeaderIdProvider; use bp_runtime::HeaderIdProvider;
use codec::{Decode, Encode}; use codec::Decode;
use parachains_relay::{ use parachains_relay::{
parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics, parachains_loop::TargetClient, parachains_loop_metrics::ParachainsLoopMetrics,
}; };
@@ -141,7 +141,7 @@ where
.and_then(|maybe_encoded_head| match maybe_encoded_head { .and_then(|maybe_encoded_head| match maybe_encoded_head {
Some(encoded_head) => Some(encoded_head) =>
HeaderOf::<P::SourceParachain>::decode(&mut &encoded_head.0[..]) HeaderOf::<P::SourceParachain>::decode(&mut &encoded_head.0[..])
.map(|head| Some(head)) .map(Some)
.map_err(Self::Error::ResponseParseFailed), .map_err(Self::Error::ResponseParseFailed),
None => Ok(None), None => Ok(None),
}) })
@@ -182,18 +182,15 @@ where
self.client self.client
.submit_signed_extrinsic( .submit_signed_extrinsic(
self.transaction_params.signer.public().into(), self.transaction_params.signer.public().into(),
SignParam::<P::TransactionSignScheme> {
spec_version,
transaction_version,
genesis_hash,
signer: transaction_params.signer,
},
move |best_block_id, transaction_nonce| { move |best_block_id, transaction_nonce| {
Ok(Bytes( Ok(UnsignedTransaction::new(call.into(), transaction_nonce)
P::TransactionSignScheme::sign_transaction(SignParam { .era(TransactionEra::new(best_block_id, transaction_params.mortality)))
spec_version,
transaction_version,
genesis_hash,
signer: transaction_params.signer,
era: TransactionEra::new(best_block_id, transaction_params.mortality),
unsigned: UnsignedTransaction::new(call.into(), transaction_nonce),
})?
.encode(),
))
}, },
) )
.await .await
@@ -94,7 +94,7 @@ pub struct MessageDeliveryParams<Strategy: RelayStrategy> {
} }
/// Message details. /// Message details.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MessageDetails<SourceChainBalance> { pub struct MessageDetails<SourceChainBalance> {
/// Message dispatch weight. /// Message dispatch weight.
pub dispatch_weight: Weight, pub dispatch_weight: Weight,
@@ -224,7 +224,7 @@ pub trait TargetClient<P: MessageLane>: RelayClient {
} }
/// State of the client. /// State of the client.
#[derive(Clone, Debug, Default, PartialEq)] #[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ClientState<SelfHeaderId, PeerHeaderId> { pub struct ClientState<SelfHeaderId, PeerHeaderId> {
/// The best header id of this chain. /// The best header id of this chain.
pub best_self: SelfHeaderId, pub best_self: SelfHeaderId,
@@ -560,7 +560,7 @@ pub(crate) mod tests {
async fn reconnect(&mut self) -> Result<(), TestError> { async fn reconnect(&mut self) -> Result<(), TestError> {
{ {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
data.is_source_reconnected = true; data.is_source_reconnected = true;
} }
Ok(()) Ok(())
@@ -571,7 +571,7 @@ pub(crate) mod tests {
impl SourceClient<TestMessageLane> for TestSourceClient { impl SourceClient<TestMessageLane> for TestSourceClient {
async fn state(&self) -> Result<SourceClientState<TestMessageLane>, TestError> { async fn state(&self) -> Result<SourceClientState<TestMessageLane>, TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
if data.is_source_fails { if data.is_source_fails {
return Err(TestError) return Err(TestError)
} }
@@ -583,7 +583,7 @@ pub(crate) mod tests {
id: SourceHeaderIdOf<TestMessageLane>, id: SourceHeaderIdOf<TestMessageLane>,
) -> Result<(SourceHeaderIdOf<TestMessageLane>, MessageNonce), TestError> { ) -> Result<(SourceHeaderIdOf<TestMessageLane>, MessageNonce), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
if data.is_source_fails { if data.is_source_fails {
return Err(TestError) return Err(TestError)
} }
@@ -595,7 +595,7 @@ pub(crate) mod tests {
id: SourceHeaderIdOf<TestMessageLane>, id: SourceHeaderIdOf<TestMessageLane>,
) -> Result<(SourceHeaderIdOf<TestMessageLane>, MessageNonce), TestError> { ) -> Result<(SourceHeaderIdOf<TestMessageLane>, MessageNonce), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
Ok((id, data.source_latest_confirmed_received_nonce)) Ok((id, data.source_latest_confirmed_received_nonce))
} }
@@ -629,7 +629,7 @@ pub(crate) mod tests {
TestError, TestError,
> { > {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
Ok(( Ok((
id, id,
nonces.clone(), nonces.clone(),
@@ -650,7 +650,7 @@ pub(crate) mod tests {
proof: TestMessagesReceivingProof, proof: TestMessagesReceivingProof,
) -> Result<(), TestError> { ) -> Result<(), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
data.source_state.best_self = data.source_state.best_self =
HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1); HeaderId(data.source_state.best_self.0 + 1, data.source_state.best_self.1 + 1);
data.source_state.best_finalized_self = data.source_state.best_self; data.source_state.best_finalized_self = data.source_state.best_self;
@@ -663,7 +663,7 @@ pub(crate) mod tests {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.target_to_source_header_required = Some(id); data.target_to_source_header_required = Some(id);
data.target_to_source_header_requirements.push(id); data.target_to_source_header_requirements.push(id);
(self.tick)(&mut *data); (self.tick)(&mut data);
} }
async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance { async fn estimate_confirmation_transaction(&self) -> TestSourceChainBalance {
@@ -693,7 +693,7 @@ pub(crate) mod tests {
async fn reconnect(&mut self) -> Result<(), TestError> { async fn reconnect(&mut self) -> Result<(), TestError> {
{ {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
data.is_target_reconnected = true; data.is_target_reconnected = true;
} }
Ok(()) Ok(())
@@ -704,7 +704,7 @@ pub(crate) mod tests {
impl TargetClient<TestMessageLane> for TestTargetClient { impl TargetClient<TestMessageLane> for TestTargetClient {
async fn state(&self) -> Result<TargetClientState<TestMessageLane>, TestError> { async fn state(&self) -> Result<TargetClientState<TestMessageLane>, TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
if data.is_target_fails { if data.is_target_fails {
return Err(TestError) return Err(TestError)
} }
@@ -716,7 +716,7 @@ pub(crate) mod tests {
id: TargetHeaderIdOf<TestMessageLane>, id: TargetHeaderIdOf<TestMessageLane>,
) -> Result<(TargetHeaderIdOf<TestMessageLane>, MessageNonce), TestError> { ) -> Result<(TargetHeaderIdOf<TestMessageLane>, MessageNonce), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
if data.is_target_fails { if data.is_target_fails {
return Err(TestError) return Err(TestError)
} }
@@ -743,7 +743,7 @@ pub(crate) mod tests {
id: TargetHeaderIdOf<TestMessageLane>, id: TargetHeaderIdOf<TestMessageLane>,
) -> Result<(TargetHeaderIdOf<TestMessageLane>, MessageNonce), TestError> { ) -> Result<(TargetHeaderIdOf<TestMessageLane>, MessageNonce), TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
if data.is_target_fails { if data.is_target_fails {
return Err(TestError) return Err(TestError)
} }
@@ -764,7 +764,7 @@ pub(crate) mod tests {
proof: TestMessagesProof, proof: TestMessagesProof,
) -> Result<RangeInclusive<MessageNonce>, TestError> { ) -> Result<RangeInclusive<MessageNonce>, TestError> {
let mut data = self.data.lock(); let mut data = self.data.lock();
(self.tick)(&mut *data); (self.tick)(&mut data);
if data.is_target_fails { if data.is_target_fails {
return Err(TestError) return Err(TestError)
} }
@@ -784,7 +784,7 @@ pub(crate) mod tests {
let mut data = self.data.lock(); let mut data = self.data.lock();
data.source_to_target_header_required = Some(id); data.source_to_target_header_required = Some(id);
data.source_to_target_header_requirements.push(id); data.source_to_target_header_requirements.push(id);
(self.tick)(&mut *data); (self.tick)(&mut data);
} }
async fn estimate_delivery_transaction_in_source_tokens( async fn estimate_delivery_transaction_in_source_tokens(
+9
View File
@@ -25,6 +25,15 @@ use futures::future::FutureExt;
use std::time::Duration; use std::time::Duration;
use thiserror::Error; use thiserror::Error;
/// Default relay loop stall timeout. If transactions generated by relay are immortal, then
/// this timeout is used.
///
/// There are no any strict requirements on block time in Substrate. But we assume here that all
/// Substrate-based chains will be designed to produce relatively fast (compared to the slowest
/// blockchains) blocks. So 1 hour seems to be a good guess for (even congested) chains to mine
/// transaction, or remove it from the pool.
pub const STALL_TIMEOUT: Duration = Duration::from_secs(60 * 60);
/// Max delay after connection-unrelated error happened before we'll try the /// Max delay after connection-unrelated error happened before we'll try the
/// same request again. /// same request again.
pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60); pub const MAX_BACKOFF_INTERVAL: Duration = Duration::from_secs(60);