mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 12:51:02 +00:00
estimate transaction fee (#1015)
This commit is contained in:
committed by
Bastian Köcher
parent
165730a2c2
commit
db0216dabb
@@ -127,11 +127,11 @@ impl SubstrateMessageLane for MillauMessagesToRialto {
|
||||
|
||||
/// Millau node as messages source.
|
||||
type MillauSourceClient =
|
||||
SubstrateMessagesSource<Millau, MillauMessagesToRialto, millau_runtime::WithRialtoMessagesInstance>;
|
||||
SubstrateMessagesSource<Millau, Rialto, MillauMessagesToRialto, millau_runtime::WithRialtoMessagesInstance>;
|
||||
|
||||
/// Rialto node as messages target.
|
||||
type RialtoTargetClient =
|
||||
SubstrateMessagesTarget<Rialto, MillauMessagesToRialto, rialto_runtime::WithMillauMessagesInstance>;
|
||||
SubstrateMessagesTarget<Millau, Rialto, MillauMessagesToRialto, rialto_runtime::WithMillauMessagesInstance>;
|
||||
|
||||
/// Run Millau-to-Rialto messages sync.
|
||||
pub async fn run(
|
||||
|
||||
@@ -127,11 +127,11 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
|
||||
|
||||
/// Rialto node as messages source.
|
||||
type RialtoSourceClient =
|
||||
SubstrateMessagesSource<Rialto, RialtoMessagesToMillau, rialto_runtime::WithMillauMessagesInstance>;
|
||||
SubstrateMessagesSource<Rialto, Millau, RialtoMessagesToMillau, rialto_runtime::WithMillauMessagesInstance>;
|
||||
|
||||
/// Millau node as messages target.
|
||||
type MillauTargetClient =
|
||||
SubstrateMessagesTarget<Millau, RialtoMessagesToMillau, millau_runtime::WithRialtoMessagesInstance>;
|
||||
SubstrateMessagesTarget<Rialto, Millau, RialtoMessagesToMillau, millau_runtime::WithRialtoMessagesInstance>;
|
||||
|
||||
/// Run Rialto-to-Millau messages sync.
|
||||
pub async fn run(
|
||||
|
||||
@@ -124,12 +124,20 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
|
||||
}
|
||||
|
||||
/// Rococo node as messages source.
|
||||
type RococoSourceClient =
|
||||
SubstrateMessagesSource<Rococo, RococoMessagesToWococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
|
||||
type RococoSourceClient = SubstrateMessagesSource<
|
||||
Rococo,
|
||||
Wococo,
|
||||
RococoMessagesToWococo,
|
||||
relay_rococo_client::runtime::WithWococoMessagesInstance,
|
||||
>;
|
||||
|
||||
/// Wococo node as messages target.
|
||||
type WococoTargetClient =
|
||||
SubstrateMessagesTarget<Wococo, RococoMessagesToWococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
|
||||
type WococoTargetClient = SubstrateMessagesTarget<
|
||||
Rococo,
|
||||
Wococo,
|
||||
RococoMessagesToWococo,
|
||||
relay_wococo_client::runtime::WithRococoMessagesInstance,
|
||||
>;
|
||||
|
||||
/// Run Rococo-to-Wococo messages sync.
|
||||
pub async fn run(
|
||||
|
||||
@@ -124,12 +124,20 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
|
||||
}
|
||||
|
||||
/// Wococo node as messages source.
|
||||
type WococoSourceClient =
|
||||
SubstrateMessagesSource<Wococo, WococoMessagesToRococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
|
||||
type WococoSourceClient = SubstrateMessagesSource<
|
||||
Wococo,
|
||||
Rococo,
|
||||
WococoMessagesToRococo,
|
||||
relay_wococo_client::runtime::WithRococoMessagesInstance,
|
||||
>;
|
||||
|
||||
/// Rococo node as messages target.
|
||||
type RococoTargetClient =
|
||||
SubstrateMessagesTarget<Rococo, WococoMessagesToRococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
|
||||
type RococoTargetClient = SubstrateMessagesTarget<
|
||||
Wococo,
|
||||
Rococo,
|
||||
WococoMessagesToRococo,
|
||||
relay_rococo_client::runtime::WithWococoMessagesInstance,
|
||||
>;
|
||||
|
||||
/// Run Wococo-to-Rococo messages sync.
|
||||
pub async fn run(
|
||||
|
||||
@@ -19,12 +19,15 @@
|
||||
//! <BridgedName> chain.
|
||||
|
||||
use crate::messages_lane::SubstrateMessageLane;
|
||||
use crate::messages_target::SubstrateMessagesReceivingProof;
|
||||
use crate::on_demand_headers::OnDemandHeadersRelay;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use bp_messages::{LaneId, MessageNonce};
|
||||
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState};
|
||||
use bp_runtime::{messages::DispatchFeePayment, ChainId};
|
||||
use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof;
|
||||
use bridge_runtime_common::messages::{
|
||||
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{traits::Instance, weights::Weight};
|
||||
use messages_relay::{
|
||||
@@ -33,6 +36,7 @@ use messages_relay::{
|
||||
ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState,
|
||||
},
|
||||
};
|
||||
use num_traits::{Bounded, Zero};
|
||||
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf};
|
||||
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId};
|
||||
use sp_core::Bytes;
|
||||
@@ -45,23 +49,23 @@ use std::{marker::PhantomData, ops::RangeInclusive};
|
||||
pub type SubstrateMessagesProof<C> = (Weight, FromBridgedChainMessagesProof<HashOf<C>>);
|
||||
|
||||
/// Substrate client as Substrate messages source.
|
||||
pub struct SubstrateMessagesSource<C: Chain, P: SubstrateMessageLane, I> {
|
||||
client: Client<C>,
|
||||
pub struct SubstrateMessagesSource<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> {
|
||||
client: Client<SC>,
|
||||
lane: P,
|
||||
lane_id: LaneId,
|
||||
instance: ChainId,
|
||||
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
|
||||
target_to_source_headers_relay: Option<OnDemandHeadersRelay<TC>>,
|
||||
_phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<C: Chain, P: SubstrateMessageLane, I> SubstrateMessagesSource<C, P, I> {
|
||||
impl<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> SubstrateMessagesSource<SC, TC, P, I> {
|
||||
/// Create new Substrate headers source.
|
||||
pub fn new(
|
||||
client: Client<C>,
|
||||
client: Client<SC>,
|
||||
lane: P,
|
||||
lane_id: LaneId,
|
||||
instance: ChainId,
|
||||
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
|
||||
target_to_source_headers_relay: Option<OnDemandHeadersRelay<TC>>,
|
||||
) -> Self {
|
||||
SubstrateMessagesSource {
|
||||
client,
|
||||
@@ -74,7 +78,7 @@ impl<C: Chain, P: SubstrateMessageLane, I> SubstrateMessagesSource<C, P, I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesSource<C, P, I> {
|
||||
impl<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesSource<SC, TC, P, I> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
client: self.client.clone(),
|
||||
@@ -88,9 +92,10 @@ impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesSource<C,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, P, I> RelayClient for SubstrateMessagesSource<C, P, I>
|
||||
impl<SC, TC, P, I> RelayClient for SubstrateMessagesSource<SC, TC, P, I>
|
||||
where
|
||||
C: Chain,
|
||||
SC: Chain,
|
||||
TC: Chain,
|
||||
P: SubstrateMessageLane,
|
||||
I: Send + Sync + Instance,
|
||||
{
|
||||
@@ -102,20 +107,22 @@ where
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, P, I> SourceClient<P> for SubstrateMessagesSource<C, P, I>
|
||||
impl<SC, TC, P, I> SourceClient<P> for SubstrateMessagesSource<SC, TC, P, I>
|
||||
where
|
||||
C: Chain,
|
||||
C::Header: DeserializeOwned,
|
||||
C::Index: DeserializeOwned,
|
||||
C::BlockNumber: BlockNumberBase,
|
||||
SC: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber, Balance = P::SourceChainBalance>,
|
||||
SC::Hash: Copy,
|
||||
SC::BlockNumber: Copy,
|
||||
SC::Balance: Decode + Bounded,
|
||||
SC::Header: DeserializeOwned,
|
||||
SC::Index: DeserializeOwned,
|
||||
SC::BlockNumber: BlockNumberBase,
|
||||
TC: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
|
||||
P: SubstrateMessageLane<
|
||||
MessagesProof = SubstrateMessagesProof<C>,
|
||||
SourceChainBalance = C::Balance,
|
||||
SourceHeaderNumber = <C::Header as HeaderT>::Number,
|
||||
SourceHeaderHash = <C::Header as HeaderT>::Hash,
|
||||
SourceChain = C,
|
||||
MessagesProof = SubstrateMessagesProof<SC>,
|
||||
MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>,
|
||||
SourceChain = SC,
|
||||
TargetChain = TC,
|
||||
>,
|
||||
P::TargetChain: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
|
||||
P::TargetHeaderNumber: Decode,
|
||||
P::TargetHeaderHash: Decode,
|
||||
I: Send + Sync + Instance,
|
||||
@@ -180,7 +187,7 @@ where
|
||||
)
|
||||
.await?;
|
||||
|
||||
make_message_details_map::<C>(
|
||||
make_message_details_map::<SC>(
|
||||
Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?,
|
||||
nonces,
|
||||
)
|
||||
@@ -242,10 +249,40 @@ where
|
||||
}
|
||||
|
||||
async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance {
|
||||
num_traits::Zero::zero() // TODO: https://github.com/paritytech/parity-bridges-common/issues/997
|
||||
self.client
|
||||
.estimate_extrinsic_fee(self.lane.make_messages_receiving_proof_transaction(
|
||||
Zero::zero(),
|
||||
HeaderId(Default::default(), Default::default()),
|
||||
prepare_dummy_messages_delivery_proof::<SC, TC>(),
|
||||
))
|
||||
.await
|
||||
.unwrap_or_else(|_| SC::Balance::max_value())
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare 'dummy' messages delivery proof that will compose the delivery confirmation transaction.
|
||||
///
|
||||
/// We don't care about proof actually being the valid proof, because its validity doesn't
|
||||
/// affect the call weight - we only care about its size.
|
||||
fn prepare_dummy_messages_delivery_proof<SC: Chain, TC: Chain>() -> SubstrateMessagesReceivingProof<TC> {
|
||||
let single_message_confirmation_size =
|
||||
bp_messages::InboundLaneData::<()>::encoded_size_hint(SC::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE, 1, 1)
|
||||
.unwrap_or(u32::MAX);
|
||||
let proof_size = TC::STORAGE_PROOF_OVERHEAD.saturating_add(single_message_confirmation_size);
|
||||
(
|
||||
UnrewardedRelayersState {
|
||||
unrewarded_relayer_entries: 1,
|
||||
messages_in_oldest_entry: 1,
|
||||
total_messages: 1,
|
||||
},
|
||||
FromBridgedChainMessagesDeliveryProof {
|
||||
bridged_header_hash: Default::default(),
|
||||
storage_proof: vec![vec![0; proof_size as usize]],
|
||||
lane: Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn read_client_state<SelfChain, BridgedHeaderHash, BridgedHeaderNumber>(
|
||||
self_client: &Client<SelfChain>,
|
||||
best_finalized_header_id_method_name: &str,
|
||||
@@ -295,7 +332,7 @@ fn make_message_details_map<C: Chain>(
|
||||
) -> Result<MessageDetailsMap<C::Balance>, SubstrateError> {
|
||||
let make_missing_nonce_error = |expected_nonce| {
|
||||
Err(SubstrateError::Custom(format!(
|
||||
"Missing nonce {} in messages_dispatch_weight call result. Expected all nonces from {:?}",
|
||||
"Missing nonce {} in message_details call result. Expected all nonces from {:?}",
|
||||
expected_nonce, nonces,
|
||||
)))
|
||||
};
|
||||
@@ -346,8 +383,7 @@ fn make_message_details_map<C: Chain>(
|
||||
MessageDetails {
|
||||
dispatch_weight: details.dispatch_weight,
|
||||
size: details.size as _,
|
||||
// TODO: https://github.com/paritytech/parity-bridges-common/issues/997
|
||||
reward: num_traits::Zero::zero(),
|
||||
reward: details.delivery_and_dispatch_fee,
|
||||
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||
},
|
||||
);
|
||||
@@ -361,6 +397,9 @@ fn make_message_details_map<C: Chain>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bp_runtime::messages::DispatchFeePayment;
|
||||
use relay_millau_client::Millau;
|
||||
use relay_rialto_client::Rialto;
|
||||
|
||||
fn message_details_from_rpc(
|
||||
nonces: RangeInclusive<MessageNonce>,
|
||||
@@ -469,4 +508,16 @@ mod tests {
|
||||
Err(SubstrateError::Custom(_))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prepare_dummy_messages_delivery_proof_works() {
|
||||
let expected_minimal_size = Rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE + Millau::STORAGE_PROOF_OVERHEAD;
|
||||
let dummy_proof = prepare_dummy_messages_delivery_proof::<Rialto, Millau>();
|
||||
assert!(
|
||||
dummy_proof.1.encode().len() as u32 > expected_minimal_size,
|
||||
"Expected proof size at least {}. Got: {}",
|
||||
expected_minimal_size,
|
||||
dummy_proof.1.encode().len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,27 @@
|
||||
//! <BridgedName> chain.
|
||||
|
||||
use crate::messages_lane::SubstrateMessageLane;
|
||||
use crate::messages_source::read_client_state;
|
||||
use crate::messages_source::{read_client_state, SubstrateMessagesProof};
|
||||
use crate::on_demand_headers::OnDemandHeadersRelay;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState};
|
||||
use bp_runtime::ChainId;
|
||||
use bridge_runtime_common::messages::source::FromBridgedChainMessagesDeliveryProof;
|
||||
use bridge_runtime_common::messages::{
|
||||
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use frame_support::{traits::Instance, weights::Weight};
|
||||
use messages_relay::{
|
||||
message_lane::{SourceHeaderIdOf, TargetHeaderIdOf},
|
||||
message_lane_loop::{TargetClient, TargetClientState},
|
||||
};
|
||||
use num_traits::{Bounded, One, Zero};
|
||||
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf};
|
||||
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase};
|
||||
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId};
|
||||
use sp_core::Bytes;
|
||||
use sp_runtime::{traits::Header as HeaderT, DeserializeOwned};
|
||||
use std::{marker::PhantomData, ops::RangeInclusive};
|
||||
use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, FixedPointNumber, FixedU128};
|
||||
use std::{convert::TryFrom, marker::PhantomData, ops::RangeInclusive};
|
||||
|
||||
/// Message receiving proof returned by the target Substrate node.
|
||||
pub type SubstrateMessagesReceivingProof<C> = (
|
||||
@@ -45,23 +48,23 @@ pub type SubstrateMessagesReceivingProof<C> = (
|
||||
);
|
||||
|
||||
/// Substrate client as Substrate messages target.
|
||||
pub struct SubstrateMessagesTarget<C: Chain, P: SubstrateMessageLane, I> {
|
||||
client: Client<C>,
|
||||
pub struct SubstrateMessagesTarget<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> {
|
||||
client: Client<TC>,
|
||||
lane: P,
|
||||
lane_id: LaneId,
|
||||
instance: ChainId,
|
||||
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
|
||||
source_to_target_headers_relay: Option<OnDemandHeadersRelay<SC>>,
|
||||
_phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<C: Chain, P: SubstrateMessageLane, I> SubstrateMessagesTarget<C, P, I> {
|
||||
impl<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> SubstrateMessagesTarget<SC, TC, P, I> {
|
||||
/// Create new Substrate headers target.
|
||||
pub fn new(
|
||||
client: Client<C>,
|
||||
client: Client<TC>,
|
||||
lane: P,
|
||||
lane_id: LaneId,
|
||||
instance: ChainId,
|
||||
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
|
||||
source_to_target_headers_relay: Option<OnDemandHeadersRelay<SC>>,
|
||||
) -> Self {
|
||||
SubstrateMessagesTarget {
|
||||
client,
|
||||
@@ -74,7 +77,7 @@ impl<C: Chain, P: SubstrateMessageLane, I> SubstrateMessagesTarget<C, P, I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesTarget<C, P, I> {
|
||||
impl<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesTarget<SC, TC, P, I> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
client: self.client.clone(),
|
||||
@@ -88,9 +91,10 @@ impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesTarget<C,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, P, I> RelayClient for SubstrateMessagesTarget<C, P, I>
|
||||
impl<SC, TC, P, I> RelayClient for SubstrateMessagesTarget<SC, TC, P, I>
|
||||
where
|
||||
C: Chain,
|
||||
SC: Chain,
|
||||
TC: Chain,
|
||||
P: SubstrateMessageLane,
|
||||
I: Send + Sync + Instance,
|
||||
{
|
||||
@@ -102,19 +106,22 @@ where
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<C, P, I> TargetClient<P> for SubstrateMessagesTarget<C, P, I>
|
||||
impl<SC, TC, P, I> TargetClient<P> for SubstrateMessagesTarget<SC, TC, P, I>
|
||||
where
|
||||
C: Chain,
|
||||
C::Header: DeserializeOwned,
|
||||
C::Index: DeserializeOwned,
|
||||
<C::Header as HeaderT>::Number: BlockNumberBase,
|
||||
SC: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber, Balance = P::SourceChainBalance>,
|
||||
SC::Balance: TryFrom<TC::Balance> + Bounded,
|
||||
TC: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
|
||||
TC::Hash: Copy,
|
||||
TC::BlockNumber: Copy,
|
||||
TC::Header: DeserializeOwned,
|
||||
TC::Index: DeserializeOwned,
|
||||
<TC::Header as HeaderT>::Number: BlockNumberBase,
|
||||
P: SubstrateMessageLane<
|
||||
TargetChain = C,
|
||||
MessagesReceivingProof = SubstrateMessagesReceivingProof<C>,
|
||||
TargetHeaderNumber = <C::Header as HeaderT>::Number,
|
||||
TargetHeaderHash = <C::Header as HeaderT>::Hash,
|
||||
MessagesProof = SubstrateMessagesProof<SC>,
|
||||
MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>,
|
||||
SourceChain = SC,
|
||||
TargetChain = TC,
|
||||
>,
|
||||
P::SourceChain: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber>,
|
||||
P::SourceHeaderNumber: Decode,
|
||||
P::SourceHeaderHash: Decode,
|
||||
I: Send + Sync + Instance,
|
||||
@@ -229,10 +236,93 @@ where
|
||||
|
||||
async fn estimate_delivery_transaction_in_source_tokens(
|
||||
&self,
|
||||
_nonces: RangeInclusive<MessageNonce>,
|
||||
_total_dispatch_weight: Weight,
|
||||
_total_size: u32,
|
||||
nonces: RangeInclusive<MessageNonce>,
|
||||
total_dispatch_weight: Weight,
|
||||
total_size: u32,
|
||||
) -> P::SourceChainBalance {
|
||||
num_traits::Zero::zero() // TODO: https://github.com/paritytech/parity-bridges-common/issues/997
|
||||
// TODO: use actual rate (https://github.com/paritytech/parity-bridges-common/issues/997)
|
||||
convert_target_tokens_to_source_tokens::<SC, TC>(
|
||||
FixedU128::one(),
|
||||
self.client
|
||||
.estimate_extrinsic_fee(self.lane.make_messages_delivery_transaction(
|
||||
Zero::zero(),
|
||||
HeaderId(Default::default(), Default::default()),
|
||||
nonces.clone(),
|
||||
prepare_dummy_messages_proof::<SC>(nonces, total_dispatch_weight, total_size),
|
||||
))
|
||||
.await
|
||||
.unwrap_or_else(|_| TC::Balance::max_value()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare 'dummy' messages proof that will compose the delivery transaction.
|
||||
///
|
||||
/// We don't care about proof actually being the valid proof, because its validity doesn't
|
||||
/// affect the call weight - we only care about its size.
|
||||
fn prepare_dummy_messages_proof<SC: Chain>(
|
||||
nonces: RangeInclusive<MessageNonce>,
|
||||
total_dispatch_weight: Weight,
|
||||
total_size: u32,
|
||||
) -> SubstrateMessagesProof<SC> {
|
||||
(
|
||||
total_dispatch_weight,
|
||||
FromBridgedChainMessagesProof {
|
||||
bridged_header_hash: Default::default(),
|
||||
storage_proof: vec![vec![0; SC::STORAGE_PROOF_OVERHEAD.saturating_add(total_size) as usize]],
|
||||
lane: Default::default(),
|
||||
nonces_start: *nonces.start(),
|
||||
nonces_end: *nonces.end(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Given delivery transaction fee in target chain tokens and conversion rate to the source
|
||||
/// chain tokens, compute transaction cost in source chain tokens.
|
||||
fn convert_target_tokens_to_source_tokens<SC: Chain, TC: Chain>(
|
||||
target_to_source_conversion_rate: FixedU128,
|
||||
target_transaction_fee: TC::Balance,
|
||||
) -> SC::Balance
|
||||
where
|
||||
SC::Balance: TryFrom<TC::Balance>,
|
||||
{
|
||||
SC::Balance::try_from(target_to_source_conversion_rate.saturating_mul_int(target_transaction_fee))
|
||||
.unwrap_or_else(|_| SC::Balance::max_value())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use relay_millau_client::Millau;
|
||||
use relay_rialto_client::Rialto;
|
||||
|
||||
#[test]
|
||||
fn prepare_dummy_messages_proof_works() {
|
||||
const DISPATCH_WEIGHT: Weight = 1_000_000;
|
||||
const SIZE: u32 = 1_000;
|
||||
let dummy_proof = prepare_dummy_messages_proof::<Rialto>(1..=10, DISPATCH_WEIGHT, SIZE);
|
||||
assert_eq!(dummy_proof.0, DISPATCH_WEIGHT);
|
||||
assert!(
|
||||
dummy_proof.1.encode().len() as u32 > SIZE,
|
||||
"Expected proof size at least {}. Got: {}",
|
||||
SIZE,
|
||||
dummy_proof.1.encode().len(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn convert_target_tokens_to_source_tokens_works() {
|
||||
assert_eq!(
|
||||
convert_target_tokens_to_source_tokens::<Rialto, Millau>((150, 100).into(), 1_000),
|
||||
1_500
|
||||
);
|
||||
assert_eq!(
|
||||
convert_target_tokens_to_source_tokens::<Rialto, Millau>((50, 100).into(), 1_000),
|
||||
500
|
||||
);
|
||||
assert_eq!(
|
||||
convert_target_tokens_to_source_tokens::<Rialto, Millau>((100, 100).into(), 1_000),
|
||||
1_000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ impl ChainBase for Kusama {
|
||||
impl Chain for Kusama {
|
||||
const NAME: &'static str = "Kusama";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_kusama::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_kusama::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = bp_kusama::AccountId;
|
||||
type Index = bp_kusama::Nonce;
|
||||
|
||||
@@ -13,6 +13,7 @@ relay-utils = { path = "../utils" }
|
||||
|
||||
# Supported Chains
|
||||
|
||||
bp-millau = { path = "../../primitives/chain-millau" }
|
||||
millau-runtime = { path = "../../bin/millau/runtime" }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
@@ -39,6 +39,8 @@ impl ChainBase for Millau {
|
||||
impl Chain for Millau {
|
||||
const NAME: &'static str = "Millau";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_millau::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_millau::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = millau_runtime::AccountId;
|
||||
type Index = millau_runtime::Index;
|
||||
|
||||
@@ -36,6 +36,8 @@ impl ChainBase for Polkadot {
|
||||
impl Chain for Polkadot {
|
||||
const NAME: &'static str = "Polkadot";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_polkadot::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_polkadot::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = bp_polkadot::AccountId;
|
||||
type Index = bp_polkadot::Nonce;
|
||||
|
||||
@@ -13,6 +13,7 @@ relay-utils = { path = "../utils" }
|
||||
|
||||
# Bridge dependencies
|
||||
|
||||
bp-rialto = { path = "../../primitives/chain-rialto" }
|
||||
rialto-runtime = { path = "../../bin/rialto/runtime" }
|
||||
|
||||
# Substrate Dependencies
|
||||
|
||||
@@ -39,6 +39,8 @@ impl ChainBase for Rialto {
|
||||
impl Chain for Rialto {
|
||||
const NAME: &'static str = "Rialto";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rialto::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rialto::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = rialto_runtime::AccountId;
|
||||
type Index = rialto_runtime::Index;
|
||||
|
||||
@@ -44,6 +44,8 @@ impl ChainBase for Rococo {
|
||||
impl Chain for Rococo {
|
||||
const NAME: &'static str = "Rococo";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_rococo::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_rococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = bp_rococo::AccountId;
|
||||
type Index = bp_rococo::Index;
|
||||
|
||||
@@ -29,9 +29,12 @@ relay-utils = { path = "../utils" }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -17,14 +17,15 @@
|
||||
use bp_runtime::Chain as ChainBase;
|
||||
use frame_support::Parameter;
|
||||
use jsonrpsee_ws_client::{DeserializeOwned, Serialize};
|
||||
use num_traits::{CheckedSub, SaturatingAdd, Zero};
|
||||
use num_traits::{Bounded, CheckedSub, SaturatingAdd, Zero};
|
||||
use sp_core::{storage::StorageKey, Pair};
|
||||
use sp_runtime::{
|
||||
generic::SignedBlock,
|
||||
traits::{
|
||||
AtLeast32Bit, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize, MaybeSerializeDeserialize, Member,
|
||||
AtLeast32Bit, AtLeast32BitUnsigned, Block as BlockT, Dispatchable, MaybeDisplay, MaybeSerialize,
|
||||
MaybeSerializeDeserialize, Member,
|
||||
},
|
||||
EncodedJustification,
|
||||
EncodedJustification, FixedPointOperand,
|
||||
};
|
||||
use std::{fmt::Debug, time::Duration};
|
||||
|
||||
@@ -37,6 +38,10 @@ pub trait Chain: ChainBase + Clone {
|
||||
/// How often blocks are produced on that chain. It's suggested to set this value
|
||||
/// to match the block time of the chain.
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration;
|
||||
/// Maximal expected storage proof overhead (in bytes).
|
||||
const STORAGE_PROOF_OVERHEAD: u32;
|
||||
/// Maximal size (in bytes) of SCALE-encoded account id on this chain.
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32;
|
||||
|
||||
/// The user account identifier type for the runtime.
|
||||
type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default;
|
||||
@@ -58,7 +63,20 @@ pub trait Chain: ChainBase + Clone {
|
||||
///
|
||||
/// The chain may suport multiple tokens, but this particular type is for token that is used
|
||||
/// to pay for transaction dispatch, to reward different relayers (headers, messages), etc.
|
||||
type Balance: Parameter + Member + DeserializeOwned + Clone + Copy + CheckedSub + PartialOrd + SaturatingAdd + Zero;
|
||||
type Balance: AtLeast32BitUnsigned
|
||||
+ FixedPointOperand
|
||||
+ Parameter
|
||||
+ Parameter
|
||||
+ Member
|
||||
+ DeserializeOwned
|
||||
+ Clone
|
||||
+ Copy
|
||||
+ Bounded
|
||||
+ CheckedSub
|
||||
+ PartialOrd
|
||||
+ SaturatingAdd
|
||||
+ Zero
|
||||
+ std::convert::TryFrom<sp_core::U256>;
|
||||
}
|
||||
|
||||
/// Substrate-based chain with `frame_system::Config::AccountData` set to
|
||||
|
||||
@@ -25,12 +25,14 @@ use codec::Decode;
|
||||
use frame_system::AccountInfo;
|
||||
use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned};
|
||||
use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder};
|
||||
use num_traits::Zero;
|
||||
use num_traits::{Bounded, Zero};
|
||||
use pallet_balances::AccountData;
|
||||
use pallet_transaction_payment::InclusionFee;
|
||||
use relay_utils::relay_loop::RECONNECT_DELAY;
|
||||
use sp_core::{storage::StorageKey, Bytes};
|
||||
use sp_trie::StorageProof;
|
||||
use sp_version::RuntimeVersion;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities";
|
||||
const MAX_SUBSCRIPTION_CAPACITY: usize = 4096;
|
||||
@@ -258,6 +260,26 @@ impl<C: Chain> Client<C> {
|
||||
Ok(tx_hash)
|
||||
}
|
||||
|
||||
/// Estimate fee that will be spent on given extrinsic.
|
||||
pub async fn estimate_extrinsic_fee(&self, transaction: Bytes) -> Result<C::Balance> {
|
||||
let fee_details = Substrate::<C>::payment_query_fee_details(&*self.client, transaction, None).await?;
|
||||
let inclusion_fee = fee_details
|
||||
.inclusion_fee
|
||||
.map(|inclusion_fee| {
|
||||
InclusionFee {
|
||||
base_fee: C::Balance::try_from(inclusion_fee.base_fee.into_u256())
|
||||
.unwrap_or_else(|_| C::Balance::max_value()),
|
||||
len_fee: C::Balance::try_from(inclusion_fee.len_fee.into_u256())
|
||||
.unwrap_or_else(|_| C::Balance::max_value()),
|
||||
adjusted_weight_fee: C::Balance::try_from(inclusion_fee.adjusted_weight_fee.into_u256())
|
||||
.unwrap_or_else(|_| C::Balance::max_value()),
|
||||
}
|
||||
.inclusion_fee()
|
||||
})
|
||||
.unwrap_or_else(Zero::zero);
|
||||
Ok(inclusion_fee)
|
||||
}
|
||||
|
||||
/// Get the GRANDPA authority set at given block.
|
||||
pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result<OpaqueGrandpaAuthoritiesSet> {
|
||||
let call = SUB_API_GRANDPA_AUTHORITIES.to_string();
|
||||
|
||||
@@ -185,6 +185,8 @@ mod tests {
|
||||
impl Chain for TestChain {
|
||||
const NAME: &'static str = "Test";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = 0;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = 0;
|
||||
|
||||
type AccountId = u32;
|
||||
type Index = u32;
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
|
||||
use crate::chain::Chain;
|
||||
|
||||
use pallet_transaction_payment_rpc_runtime_api::FeeDetails;
|
||||
use sc_rpc_api::{state::ReadProof, system::Health};
|
||||
use sp_core::{
|
||||
storage::{StorageData, StorageKey},
|
||||
Bytes,
|
||||
};
|
||||
use sp_rpc::number::NumberOrHex;
|
||||
use sp_version::RuntimeVersion;
|
||||
|
||||
jsonrpsee_proc_macros::rpc_client_api! {
|
||||
@@ -49,5 +51,7 @@ jsonrpsee_proc_macros::rpc_client_api! {
|
||||
fn state_prove_storage(keys: Vec<StorageKey>, hash: Option<C::Hash>) -> ReadProof<C::Hash>;
|
||||
#[rpc(method = "state_getRuntimeVersion", positional_params)]
|
||||
fn state_runtime_version() -> RuntimeVersion;
|
||||
#[rpc(method = "payment_queryFeeDetails", positional_params)]
|
||||
fn payment_query_fee_details(extrinsic: Bytes, at_block: Option<C::Hash>) -> FeeDetails<NumberOrHex>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ impl ChainBase for Westend {
|
||||
impl Chain for Westend {
|
||||
const NAME: &'static str = "Westend";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_westend::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_westend::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = bp_westend::AccountId;
|
||||
type Index = bp_westend::Nonce;
|
||||
|
||||
@@ -44,6 +44,8 @@ impl ChainBase for Wococo {
|
||||
impl Chain for Wococo {
|
||||
const NAME: &'static str = "Wococo";
|
||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
||||
const STORAGE_PROOF_OVERHEAD: u32 = bp_wococo::EXTRA_STORAGE_PROOF_SIZE;
|
||||
const MAXIMAL_ENCODED_ACCOUNT_ID_SIZE: u32 = bp_wococo::MAXIMAL_ENCODED_ACCOUNT_ID_SIZE;
|
||||
|
||||
type AccountId = bp_wococo::AccountId;
|
||||
type Index = bp_wococo::Index;
|
||||
|
||||
Reference in New Issue
Block a user