mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 15:11: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.
|
/// Millau node as messages source.
|
||||||
type MillauSourceClient =
|
type MillauSourceClient =
|
||||||
SubstrateMessagesSource<Millau, MillauMessagesToRialto, millau_runtime::WithRialtoMessagesInstance>;
|
SubstrateMessagesSource<Millau, Rialto, MillauMessagesToRialto, millau_runtime::WithRialtoMessagesInstance>;
|
||||||
|
|
||||||
/// Rialto node as messages target.
|
/// Rialto node as messages target.
|
||||||
type RialtoTargetClient =
|
type RialtoTargetClient =
|
||||||
SubstrateMessagesTarget<Rialto, MillauMessagesToRialto, rialto_runtime::WithMillauMessagesInstance>;
|
SubstrateMessagesTarget<Millau, Rialto, MillauMessagesToRialto, rialto_runtime::WithMillauMessagesInstance>;
|
||||||
|
|
||||||
/// Run Millau-to-Rialto messages sync.
|
/// Run Millau-to-Rialto messages sync.
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
|
|||||||
@@ -127,11 +127,11 @@ impl SubstrateMessageLane for RialtoMessagesToMillau {
|
|||||||
|
|
||||||
/// Rialto node as messages source.
|
/// Rialto node as messages source.
|
||||||
type RialtoSourceClient =
|
type RialtoSourceClient =
|
||||||
SubstrateMessagesSource<Rialto, RialtoMessagesToMillau, rialto_runtime::WithMillauMessagesInstance>;
|
SubstrateMessagesSource<Rialto, Millau, RialtoMessagesToMillau, rialto_runtime::WithMillauMessagesInstance>;
|
||||||
|
|
||||||
/// Millau node as messages target.
|
/// Millau node as messages target.
|
||||||
type MillauTargetClient =
|
type MillauTargetClient =
|
||||||
SubstrateMessagesTarget<Millau, RialtoMessagesToMillau, millau_runtime::WithRialtoMessagesInstance>;
|
SubstrateMessagesTarget<Rialto, Millau, RialtoMessagesToMillau, millau_runtime::WithRialtoMessagesInstance>;
|
||||||
|
|
||||||
/// Run Rialto-to-Millau messages sync.
|
/// Run Rialto-to-Millau messages sync.
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
|
|||||||
@@ -124,12 +124,20 @@ impl SubstrateMessageLane for RococoMessagesToWococo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Rococo node as messages source.
|
/// Rococo node as messages source.
|
||||||
type RococoSourceClient =
|
type RococoSourceClient = SubstrateMessagesSource<
|
||||||
SubstrateMessagesSource<Rococo, RococoMessagesToWococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
|
Rococo,
|
||||||
|
Wococo,
|
||||||
|
RococoMessagesToWococo,
|
||||||
|
relay_rococo_client::runtime::WithWococoMessagesInstance,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Wococo node as messages target.
|
/// Wococo node as messages target.
|
||||||
type WococoTargetClient =
|
type WococoTargetClient = SubstrateMessagesTarget<
|
||||||
SubstrateMessagesTarget<Wococo, RococoMessagesToWococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
|
Rococo,
|
||||||
|
Wococo,
|
||||||
|
RococoMessagesToWococo,
|
||||||
|
relay_wococo_client::runtime::WithRococoMessagesInstance,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Run Rococo-to-Wococo messages sync.
|
/// Run Rococo-to-Wococo messages sync.
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
|
|||||||
@@ -124,12 +124,20 @@ impl SubstrateMessageLane for WococoMessagesToRococo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wococo node as messages source.
|
/// Wococo node as messages source.
|
||||||
type WococoSourceClient =
|
type WococoSourceClient = SubstrateMessagesSource<
|
||||||
SubstrateMessagesSource<Wococo, WococoMessagesToRococo, relay_wococo_client::runtime::WithRococoMessagesInstance>;
|
Wococo,
|
||||||
|
Rococo,
|
||||||
|
WococoMessagesToRococo,
|
||||||
|
relay_wococo_client::runtime::WithRococoMessagesInstance,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Rococo node as messages target.
|
/// Rococo node as messages target.
|
||||||
type RococoTargetClient =
|
type RococoTargetClient = SubstrateMessagesTarget<
|
||||||
SubstrateMessagesTarget<Rococo, WococoMessagesToRococo, relay_rococo_client::runtime::WithWococoMessagesInstance>;
|
Wococo,
|
||||||
|
Rococo,
|
||||||
|
WococoMessagesToRococo,
|
||||||
|
relay_rococo_client::runtime::WithWococoMessagesInstance,
|
||||||
|
>;
|
||||||
|
|
||||||
/// Run Wococo-to-Rococo messages sync.
|
/// Run Wococo-to-Rococo messages sync.
|
||||||
pub async fn run(
|
pub async fn run(
|
||||||
|
|||||||
@@ -19,12 +19,15 @@
|
|||||||
//! <BridgedName> chain.
|
//! <BridgedName> chain.
|
||||||
|
|
||||||
use crate::messages_lane::SubstrateMessageLane;
|
use crate::messages_lane::SubstrateMessageLane;
|
||||||
|
use crate::messages_target::SubstrateMessagesReceivingProof;
|
||||||
use crate::on_demand_headers::OnDemandHeadersRelay;
|
use crate::on_demand_headers::OnDemandHeadersRelay;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bp_messages::{LaneId, MessageNonce};
|
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState};
|
||||||
use bp_runtime::{messages::DispatchFeePayment, ChainId};
|
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 codec::{Decode, Encode};
|
||||||
use frame_support::{traits::Instance, weights::Weight};
|
use frame_support::{traits::Instance, weights::Weight};
|
||||||
use messages_relay::{
|
use messages_relay::{
|
||||||
@@ -33,6 +36,7 @@ use messages_relay::{
|
|||||||
ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState,
|
ClientState, MessageDetails, MessageDetailsMap, MessageProofParameters, SourceClient, SourceClientState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use num_traits::{Bounded, Zero};
|
||||||
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf};
|
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf, HeaderIdOf};
|
||||||
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId};
|
use relay_utils::{relay_loop::Client as RelayClient, BlockNumberBase, HeaderId};
|
||||||
use sp_core::Bytes;
|
use sp_core::Bytes;
|
||||||
@@ -45,23 +49,23 @@ use std::{marker::PhantomData, ops::RangeInclusive};
|
|||||||
pub type SubstrateMessagesProof<C> = (Weight, FromBridgedChainMessagesProof<HashOf<C>>);
|
pub type SubstrateMessagesProof<C> = (Weight, FromBridgedChainMessagesProof<HashOf<C>>);
|
||||||
|
|
||||||
/// Substrate client as Substrate messages source.
|
/// Substrate client as Substrate messages source.
|
||||||
pub struct SubstrateMessagesSource<C: Chain, P: SubstrateMessageLane, I> {
|
pub struct SubstrateMessagesSource<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> {
|
||||||
client: Client<C>,
|
client: Client<SC>,
|
||||||
lane: P,
|
lane: P,
|
||||||
lane_id: LaneId,
|
lane_id: LaneId,
|
||||||
instance: ChainId,
|
instance: ChainId,
|
||||||
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
|
target_to_source_headers_relay: Option<OnDemandHeadersRelay<TC>>,
|
||||||
_phantom: PhantomData<I>,
|
_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.
|
/// Create new Substrate headers source.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: Client<C>,
|
client: Client<SC>,
|
||||||
lane: P,
|
lane: P,
|
||||||
lane_id: LaneId,
|
lane_id: LaneId,
|
||||||
instance: ChainId,
|
instance: ChainId,
|
||||||
target_to_source_headers_relay: Option<OnDemandHeadersRelay<P::TargetChain>>,
|
target_to_source_headers_relay: Option<OnDemandHeadersRelay<TC>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SubstrateMessagesSource {
|
SubstrateMessagesSource {
|
||||||
client,
|
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 {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
@@ -88,9 +92,10 @@ impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesSource<C,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[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
|
where
|
||||||
C: Chain,
|
SC: Chain,
|
||||||
|
TC: Chain,
|
||||||
P: SubstrateMessageLane,
|
P: SubstrateMessageLane,
|
||||||
I: Send + Sync + Instance,
|
I: Send + Sync + Instance,
|
||||||
{
|
{
|
||||||
@@ -102,20 +107,22 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[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
|
where
|
||||||
C: Chain,
|
SC: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber, Balance = P::SourceChainBalance>,
|
||||||
C::Header: DeserializeOwned,
|
SC::Hash: Copy,
|
||||||
C::Index: DeserializeOwned,
|
SC::BlockNumber: Copy,
|
||||||
C::BlockNumber: BlockNumberBase,
|
SC::Balance: Decode + Bounded,
|
||||||
|
SC::Header: DeserializeOwned,
|
||||||
|
SC::Index: DeserializeOwned,
|
||||||
|
SC::BlockNumber: BlockNumberBase,
|
||||||
|
TC: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
|
||||||
P: SubstrateMessageLane<
|
P: SubstrateMessageLane<
|
||||||
MessagesProof = SubstrateMessagesProof<C>,
|
MessagesProof = SubstrateMessagesProof<SC>,
|
||||||
SourceChainBalance = C::Balance,
|
MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>,
|
||||||
SourceHeaderNumber = <C::Header as HeaderT>::Number,
|
SourceChain = SC,
|
||||||
SourceHeaderHash = <C::Header as HeaderT>::Hash,
|
TargetChain = TC,
|
||||||
SourceChain = C,
|
|
||||||
>,
|
>,
|
||||||
P::TargetChain: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
|
|
||||||
P::TargetHeaderNumber: Decode,
|
P::TargetHeaderNumber: Decode,
|
||||||
P::TargetHeaderHash: Decode,
|
P::TargetHeaderHash: Decode,
|
||||||
I: Send + Sync + Instance,
|
I: Send + Sync + Instance,
|
||||||
@@ -180,7 +187,7 @@ where
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
make_message_details_map::<C>(
|
make_message_details_map::<SC>(
|
||||||
Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?,
|
Decode::decode(&mut &encoded_response.0[..]).map_err(SubstrateError::ResponseParseFailed)?,
|
||||||
nonces,
|
nonces,
|
||||||
)
|
)
|
||||||
@@ -242,10 +249,40 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn estimate_confirmation_transaction(&self) -> P::SourceChainBalance {
|
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>(
|
pub async fn read_client_state<SelfChain, BridgedHeaderHash, BridgedHeaderNumber>(
|
||||||
self_client: &Client<SelfChain>,
|
self_client: &Client<SelfChain>,
|
||||||
best_finalized_header_id_method_name: &str,
|
best_finalized_header_id_method_name: &str,
|
||||||
@@ -295,7 +332,7 @@ fn make_message_details_map<C: Chain>(
|
|||||||
) -> Result<MessageDetailsMap<C::Balance>, SubstrateError> {
|
) -> Result<MessageDetailsMap<C::Balance>, SubstrateError> {
|
||||||
let make_missing_nonce_error = |expected_nonce| {
|
let make_missing_nonce_error = |expected_nonce| {
|
||||||
Err(SubstrateError::Custom(format!(
|
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,
|
expected_nonce, nonces,
|
||||||
)))
|
)))
|
||||||
};
|
};
|
||||||
@@ -346,8 +383,7 @@ fn make_message_details_map<C: Chain>(
|
|||||||
MessageDetails {
|
MessageDetails {
|
||||||
dispatch_weight: details.dispatch_weight,
|
dispatch_weight: details.dispatch_weight,
|
||||||
size: details.size as _,
|
size: details.size as _,
|
||||||
// TODO: https://github.com/paritytech/parity-bridges-common/issues/997
|
reward: details.delivery_and_dispatch_fee,
|
||||||
reward: num_traits::Zero::zero(),
|
|
||||||
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
dispatch_fee_payment: DispatchFeePayment::AtSourceChain,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -361,6 +397,9 @@ fn make_message_details_map<C: Chain>(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use bp_runtime::messages::DispatchFeePayment;
|
||||||
|
use relay_millau_client::Millau;
|
||||||
|
use relay_rialto_client::Rialto;
|
||||||
|
|
||||||
fn message_details_from_rpc(
|
fn message_details_from_rpc(
|
||||||
nonces: RangeInclusive<MessageNonce>,
|
nonces: RangeInclusive<MessageNonce>,
|
||||||
@@ -469,4 +508,16 @@ mod tests {
|
|||||||
Err(SubstrateError::Custom(_))
|
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.
|
//! <BridgedName> chain.
|
||||||
|
|
||||||
use crate::messages_lane::SubstrateMessageLane;
|
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 crate::on_demand_headers::OnDemandHeadersRelay;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState};
|
use bp_messages::{LaneId, MessageNonce, UnrewardedRelayersState};
|
||||||
use bp_runtime::ChainId;
|
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 codec::{Decode, Encode};
|
||||||
use frame_support::{traits::Instance, weights::Weight};
|
use frame_support::{traits::Instance, weights::Weight};
|
||||||
use messages_relay::{
|
use messages_relay::{
|
||||||
message_lane::{SourceHeaderIdOf, TargetHeaderIdOf},
|
message_lane::{SourceHeaderIdOf, TargetHeaderIdOf},
|
||||||
message_lane_loop::{TargetClient, TargetClientState},
|
message_lane_loop::{TargetClient, TargetClientState},
|
||||||
};
|
};
|
||||||
|
use num_traits::{Bounded, One, Zero};
|
||||||
use relay_substrate_client::{Chain, Client, Error as SubstrateError, HashOf};
|
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_core::Bytes;
|
||||||
use sp_runtime::{traits::Header as HeaderT, DeserializeOwned};
|
use sp_runtime::{traits::Header as HeaderT, DeserializeOwned, FixedPointNumber, FixedU128};
|
||||||
use std::{marker::PhantomData, ops::RangeInclusive};
|
use std::{convert::TryFrom, marker::PhantomData, ops::RangeInclusive};
|
||||||
|
|
||||||
/// Message receiving proof returned by the target Substrate node.
|
/// Message receiving proof returned by the target Substrate node.
|
||||||
pub type SubstrateMessagesReceivingProof<C> = (
|
pub type SubstrateMessagesReceivingProof<C> = (
|
||||||
@@ -45,23 +48,23 @@ pub type SubstrateMessagesReceivingProof<C> = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// Substrate client as Substrate messages target.
|
/// Substrate client as Substrate messages target.
|
||||||
pub struct SubstrateMessagesTarget<C: Chain, P: SubstrateMessageLane, I> {
|
pub struct SubstrateMessagesTarget<SC: Chain, TC: Chain, P: SubstrateMessageLane, I> {
|
||||||
client: Client<C>,
|
client: Client<TC>,
|
||||||
lane: P,
|
lane: P,
|
||||||
lane_id: LaneId,
|
lane_id: LaneId,
|
||||||
instance: ChainId,
|
instance: ChainId,
|
||||||
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
|
source_to_target_headers_relay: Option<OnDemandHeadersRelay<SC>>,
|
||||||
_phantom: PhantomData<I>,
|
_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.
|
/// Create new Substrate headers target.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: Client<C>,
|
client: Client<TC>,
|
||||||
lane: P,
|
lane: P,
|
||||||
lane_id: LaneId,
|
lane_id: LaneId,
|
||||||
instance: ChainId,
|
instance: ChainId,
|
||||||
source_to_target_headers_relay: Option<OnDemandHeadersRelay<P::SourceChain>>,
|
source_to_target_headers_relay: Option<OnDemandHeadersRelay<SC>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SubstrateMessagesTarget {
|
SubstrateMessagesTarget {
|
||||||
client,
|
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 {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
@@ -88,9 +91,10 @@ impl<C: Chain, P: SubstrateMessageLane, I> Clone for SubstrateMessagesTarget<C,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[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
|
where
|
||||||
C: Chain,
|
SC: Chain,
|
||||||
|
TC: Chain,
|
||||||
P: SubstrateMessageLane,
|
P: SubstrateMessageLane,
|
||||||
I: Send + Sync + Instance,
|
I: Send + Sync + Instance,
|
||||||
{
|
{
|
||||||
@@ -102,19 +106,22 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[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
|
where
|
||||||
C: Chain,
|
SC: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber, Balance = P::SourceChainBalance>,
|
||||||
C::Header: DeserializeOwned,
|
SC::Balance: TryFrom<TC::Balance> + Bounded,
|
||||||
C::Index: DeserializeOwned,
|
TC: Chain<Hash = P::TargetHeaderHash, BlockNumber = P::TargetHeaderNumber>,
|
||||||
<C::Header as HeaderT>::Number: BlockNumberBase,
|
TC::Hash: Copy,
|
||||||
|
TC::BlockNumber: Copy,
|
||||||
|
TC::Header: DeserializeOwned,
|
||||||
|
TC::Index: DeserializeOwned,
|
||||||
|
<TC::Header as HeaderT>::Number: BlockNumberBase,
|
||||||
P: SubstrateMessageLane<
|
P: SubstrateMessageLane<
|
||||||
TargetChain = C,
|
MessagesProof = SubstrateMessagesProof<SC>,
|
||||||
MessagesReceivingProof = SubstrateMessagesReceivingProof<C>,
|
MessagesReceivingProof = SubstrateMessagesReceivingProof<TC>,
|
||||||
TargetHeaderNumber = <C::Header as HeaderT>::Number,
|
SourceChain = SC,
|
||||||
TargetHeaderHash = <C::Header as HeaderT>::Hash,
|
TargetChain = TC,
|
||||||
>,
|
>,
|
||||||
P::SourceChain: Chain<Hash = P::SourceHeaderHash, BlockNumber = P::SourceHeaderNumber>,
|
|
||||||
P::SourceHeaderNumber: Decode,
|
P::SourceHeaderNumber: Decode,
|
||||||
P::SourceHeaderHash: Decode,
|
P::SourceHeaderHash: Decode,
|
||||||
I: Send + Sync + Instance,
|
I: Send + Sync + Instance,
|
||||||
@@ -229,10 +236,93 @@ where
|
|||||||
|
|
||||||
async fn estimate_delivery_transaction_in_source_tokens(
|
async fn estimate_delivery_transaction_in_source_tokens(
|
||||||
&self,
|
&self,
|
||||||
_nonces: RangeInclusive<MessageNonce>,
|
nonces: RangeInclusive<MessageNonce>,
|
||||||
_total_dispatch_weight: Weight,
|
total_dispatch_weight: Weight,
|
||||||
_total_size: u32,
|
total_size: u32,
|
||||||
) -> P::SourceChainBalance {
|
) -> 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 {
|
impl Chain for Kusama {
|
||||||
const NAME: &'static str = "Kusama";
|
const NAME: &'static str = "Kusama";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
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 AccountId = bp_kusama::AccountId;
|
||||||
type Index = bp_kusama::Nonce;
|
type Index = bp_kusama::Nonce;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ relay-utils = { path = "../utils" }
|
|||||||
|
|
||||||
# Supported Chains
|
# Supported Chains
|
||||||
|
|
||||||
|
bp-millau = { path = "../../primitives/chain-millau" }
|
||||||
millau-runtime = { path = "../../bin/millau/runtime" }
|
millau-runtime = { path = "../../bin/millau/runtime" }
|
||||||
|
|
||||||
# Substrate Dependencies
|
# Substrate Dependencies
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ impl ChainBase for Millau {
|
|||||||
impl Chain for Millau {
|
impl Chain for Millau {
|
||||||
const NAME: &'static str = "Millau";
|
const NAME: &'static str = "Millau";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
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 AccountId = millau_runtime::AccountId;
|
||||||
type Index = millau_runtime::Index;
|
type Index = millau_runtime::Index;
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ impl ChainBase for Polkadot {
|
|||||||
impl Chain for Polkadot {
|
impl Chain for Polkadot {
|
||||||
const NAME: &'static str = "Polkadot";
|
const NAME: &'static str = "Polkadot";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
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 AccountId = bp_polkadot::AccountId;
|
||||||
type Index = bp_polkadot::Nonce;
|
type Index = bp_polkadot::Nonce;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ relay-utils = { path = "../utils" }
|
|||||||
|
|
||||||
# Bridge dependencies
|
# Bridge dependencies
|
||||||
|
|
||||||
|
bp-rialto = { path = "../../primitives/chain-rialto" }
|
||||||
rialto-runtime = { path = "../../bin/rialto/runtime" }
|
rialto-runtime = { path = "../../bin/rialto/runtime" }
|
||||||
|
|
||||||
# Substrate Dependencies
|
# Substrate Dependencies
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ impl ChainBase for Rialto {
|
|||||||
impl Chain for Rialto {
|
impl Chain for Rialto {
|
||||||
const NAME: &'static str = "Rialto";
|
const NAME: &'static str = "Rialto";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(5);
|
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 AccountId = rialto_runtime::AccountId;
|
||||||
type Index = rialto_runtime::Index;
|
type Index = rialto_runtime::Index;
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ impl ChainBase for Rococo {
|
|||||||
impl Chain for Rococo {
|
impl Chain for Rococo {
|
||||||
const NAME: &'static str = "Rococo";
|
const NAME: &'static str = "Rococo";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
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 AccountId = bp_rococo::AccountId;
|
||||||
type Index = bp_rococo::Index;
|
type Index = bp_rococo::Index;
|
||||||
|
|||||||
@@ -29,9 +29,12 @@ relay-utils = { path = "../utils" }
|
|||||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
frame-system = { 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-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" }
|
sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
sp-core = { 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-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-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
sp-storage = { 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" }
|
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
|||||||
@@ -17,14 +17,15 @@
|
|||||||
use bp_runtime::Chain as ChainBase;
|
use bp_runtime::Chain as ChainBase;
|
||||||
use frame_support::Parameter;
|
use frame_support::Parameter;
|
||||||
use jsonrpsee_ws_client::{DeserializeOwned, Serialize};
|
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_core::{storage::StorageKey, Pair};
|
||||||
use sp_runtime::{
|
use sp_runtime::{
|
||||||
generic::SignedBlock,
|
generic::SignedBlock,
|
||||||
traits::{
|
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};
|
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
|
/// How often blocks are produced on that chain. It's suggested to set this value
|
||||||
/// to match the block time of the chain.
|
/// to match the block time of the chain.
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration;
|
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.
|
/// The user account identifier type for the runtime.
|
||||||
type AccountId: Parameter + Member + MaybeSerializeDeserialize + Debug + MaybeDisplay + Ord + Default;
|
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
|
/// 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.
|
/// 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
|
/// Substrate-based chain with `frame_system::Config::AccountData` set to
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ use codec::Decode;
|
|||||||
use frame_system::AccountInfo;
|
use frame_system::AccountInfo;
|
||||||
use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned};
|
use jsonrpsee_ws_client::{traits::SubscriptionClient, v2::params::JsonRpcParams, DeserializeOwned};
|
||||||
use jsonrpsee_ws_client::{Subscription, WsClient as RpcClient, WsClientBuilder as RpcClientBuilder};
|
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_balances::AccountData;
|
||||||
|
use pallet_transaction_payment::InclusionFee;
|
||||||
use relay_utils::relay_loop::RECONNECT_DELAY;
|
use relay_utils::relay_loop::RECONNECT_DELAY;
|
||||||
use sp_core::{storage::StorageKey, Bytes};
|
use sp_core::{storage::StorageKey, Bytes};
|
||||||
use sp_trie::StorageProof;
|
use sp_trie::StorageProof;
|
||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities";
|
const SUB_API_GRANDPA_AUTHORITIES: &str = "GrandpaApi_grandpa_authorities";
|
||||||
const MAX_SUBSCRIPTION_CAPACITY: usize = 4096;
|
const MAX_SUBSCRIPTION_CAPACITY: usize = 4096;
|
||||||
@@ -258,6 +260,26 @@ impl<C: Chain> Client<C> {
|
|||||||
Ok(tx_hash)
|
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.
|
/// Get the GRANDPA authority set at given block.
|
||||||
pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result<OpaqueGrandpaAuthoritiesSet> {
|
pub async fn grandpa_authorities_set(&self, block: C::Hash) -> Result<OpaqueGrandpaAuthoritiesSet> {
|
||||||
let call = SUB_API_GRANDPA_AUTHORITIES.to_string();
|
let call = SUB_API_GRANDPA_AUTHORITIES.to_string();
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ mod tests {
|
|||||||
impl Chain for TestChain {
|
impl Chain for TestChain {
|
||||||
const NAME: &'static str = "Test";
|
const NAME: &'static str = "Test";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_millis(1);
|
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 AccountId = u32;
|
||||||
type Index = u32;
|
type Index = u32;
|
||||||
|
|||||||
@@ -18,11 +18,13 @@
|
|||||||
|
|
||||||
use crate::chain::Chain;
|
use crate::chain::Chain;
|
||||||
|
|
||||||
|
use pallet_transaction_payment_rpc_runtime_api::FeeDetails;
|
||||||
use sc_rpc_api::{state::ReadProof, system::Health};
|
use sc_rpc_api::{state::ReadProof, system::Health};
|
||||||
use sp_core::{
|
use sp_core::{
|
||||||
storage::{StorageData, StorageKey},
|
storage::{StorageData, StorageKey},
|
||||||
Bytes,
|
Bytes,
|
||||||
};
|
};
|
||||||
|
use sp_rpc::number::NumberOrHex;
|
||||||
use sp_version::RuntimeVersion;
|
use sp_version::RuntimeVersion;
|
||||||
|
|
||||||
jsonrpsee_proc_macros::rpc_client_api! {
|
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>;
|
fn state_prove_storage(keys: Vec<StorageKey>, hash: Option<C::Hash>) -> ReadProof<C::Hash>;
|
||||||
#[rpc(method = "state_getRuntimeVersion", positional_params)]
|
#[rpc(method = "state_getRuntimeVersion", positional_params)]
|
||||||
fn state_runtime_version() -> RuntimeVersion;
|
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 {
|
impl Chain for Westend {
|
||||||
const NAME: &'static str = "Westend";
|
const NAME: &'static str = "Westend";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
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 AccountId = bp_westend::AccountId;
|
||||||
type Index = bp_westend::Nonce;
|
type Index = bp_westend::Nonce;
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ impl ChainBase for Wococo {
|
|||||||
impl Chain for Wococo {
|
impl Chain for Wococo {
|
||||||
const NAME: &'static str = "Wococo";
|
const NAME: &'static str = "Wococo";
|
||||||
const AVERAGE_BLOCK_INTERVAL: Duration = Duration::from_secs(6);
|
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 AccountId = bp_wococo::AccountId;
|
||||||
type Index = bp_wococo::Index;
|
type Index = bp_wococo::Index;
|
||||||
|
|||||||
Reference in New Issue
Block a user