Skip to content

Commit

Permalink
override conversion rate in estimate-message-fee RPC (paritytech#1189)
Browse files Browse the repository at this point in the history
  • Loading branch information
svyatonik authored and serban300 committed Apr 10, 2024
1 parent 2a64885 commit b6a5fff
Show file tree
Hide file tree
Showing 16 changed files with 85 additions and 71 deletions.
4 changes: 3 additions & 1 deletion bridges/bin/millau/runtime/src/lib.rs
Expand Up @@ -52,7 +52,7 @@ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{Block as BlockT, IdentityLookup, Keccak256, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
Expand Down Expand Up @@ -744,10 +744,12 @@ impl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
_lane_id: bp_messages::LaneId,
payload: ToRialtoMessagePayload,
rialto_to_this_conversion_rate: Option<FixedU128>,
) -> Option<Balance> {
estimate_message_dispatch_and_delivery_fee::<WithRialtoMessageBridge>(
&payload,
WithRialtoMessageBridge::RELAYER_FEE_PERCENT,
rialto_to_this_conversion_rate,
).ok()
}

Expand Down
13 changes: 8 additions & 5 deletions bridges/bin/millau/runtime/src/rialto_messages.rs
Expand Up @@ -91,11 +91,14 @@ impl MessageBridge for WithRialtoMessageBridge {
type ThisChain = Millau;
type BridgedChain = Rialto;

fn bridged_balance_to_this_balance(bridged_balance: bp_rialto::Balance) -> bp_millau::Balance {
bp_millau::Balance::try_from(
RialtoToMillauConversionRate::get().saturating_mul_int(bridged_balance),
)
.unwrap_or(bp_millau::Balance::MAX)
fn bridged_balance_to_this_balance(
bridged_balance: bp_rialto::Balance,
bridged_to_this_conversion_rate_override: Option<FixedU128>,
) -> bp_millau::Balance {
let conversion_rate = bridged_to_this_conversion_rate_override
.unwrap_or_else(|| RialtoToMillauConversionRate::get());
bp_millau::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance))
.unwrap_or(bp_millau::Balance::MAX)
}
}

Expand Down
4 changes: 3 additions & 1 deletion bridges/bin/rialto/runtime/src/lib.rs
Expand Up @@ -53,7 +53,7 @@ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, Block as BlockT, Keccak256, NumberFor, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedPointNumber, MultiSignature, MultiSigner, Perquintill,
ApplyExtrinsicResult, FixedPointNumber, FixedU128, MultiSignature, MultiSigner, Perquintill,
};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
#[cfg(feature = "std")]
Expand Down Expand Up @@ -892,10 +892,12 @@ impl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
_lane_id: bp_messages::LaneId,
payload: ToMillauMessagePayload,
millau_to_this_conversion_rate: Option<FixedU128>,
) -> Option<Balance> {
estimate_message_dispatch_and_delivery_fee::<WithMillauMessageBridge>(
&payload,
WithMillauMessageBridge::RELAYER_FEE_PERCENT,
millau_to_this_conversion_rate,
).ok()
}

Expand Down
13 changes: 8 additions & 5 deletions bridges/bin/rialto/runtime/src/millau_messages.rs
Expand Up @@ -91,11 +91,14 @@ impl MessageBridge for WithMillauMessageBridge {
type ThisChain = Rialto;
type BridgedChain = Millau;

fn bridged_balance_to_this_balance(bridged_balance: bp_millau::Balance) -> bp_rialto::Balance {
bp_rialto::Balance::try_from(
MillauToRialtoConversionRate::get().saturating_mul_int(bridged_balance),
)
.unwrap_or(bp_rialto::Balance::MAX)
fn bridged_balance_to_this_balance(
bridged_balance: bp_millau::Balance,
bridged_to_this_conversion_rate_override: Option<FixedU128>,
) -> bp_rialto::Balance {
let conversion_rate = bridged_to_this_conversion_rate_override
.unwrap_or_else(|| MillauToRialtoConversionRate::get());
bp_rialto::Balance::try_from(conversion_rate.saturating_mul_int(bridged_balance))
.unwrap_or(bp_rialto::Balance::MAX)
}
}

Expand Down
46 changes: 40 additions & 6 deletions bridges/bin/runtime-common/src/messages.rs
Expand Up @@ -70,6 +70,7 @@ pub trait MessageBridge {
/// Convert Bridged chain balance into This chain balance.
fn bridged_balance_to_this_balance(
bridged_balance: BalanceOf<BridgedChain<Self>>,
bridged_to_this_conversion_rate_override: Option<FixedU128>,
) -> BalanceOf<ThisChain<Self>>;
}

Expand Down Expand Up @@ -316,8 +317,11 @@ pub mod source {
pallet_bridge_dispatch::verify_message_origin(submitter, payload)
.map_err(|_| BAD_ORIGIN)?;

let minimal_fee_in_this_tokens =
estimate_message_dispatch_and_delivery_fee::<B>(payload, B::RELAYER_FEE_PERCENT)?;
let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::<B>(
payload,
B::RELAYER_FEE_PERCENT,
None,
)?;

// compare with actual fee paid
if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens {
Expand Down Expand Up @@ -371,6 +375,7 @@ pub mod source {
pub fn estimate_message_dispatch_and_delivery_fee<B: MessageBridge>(
payload: &FromThisChainMessagePayload<B>,
relayer_fee_percent: u32,
bridged_to_this_conversion_rate: Option<FixedU128>,
) -> Result<BalanceOf<ThisChain<B>>, &'static str> {
// the fee (in Bridged tokens) of all transactions that are made on the Bridged chain
//
Expand All @@ -391,8 +396,11 @@ pub mod source {
ThisChain::<B>::transaction_payment(confirmation_transaction);

// minimal fee (in This tokens) is a sum of all required fees
let minimal_fee = B::bridged_balance_to_this_balance(delivery_transaction_fee)
.checked_add(&confirmation_transaction_fee);
let minimal_fee = B::bridged_balance_to_this_balance(
delivery_transaction_fee,
bridged_to_this_conversion_rate,
)
.checked_add(&confirmation_transaction_fee);

// before returning, add extra fee that is paid to the relayer (relayer interest)
minimal_fee
Expand Down Expand Up @@ -798,8 +806,12 @@ mod tests {

fn bridged_balance_to_this_balance(
bridged_balance: BridgedChainBalance,
bridged_to_this_conversion_rate_override: Option<FixedU128>,
) -> ThisChainBalance {
ThisChainBalance(bridged_balance.0 * BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE as u32)
let conversion_rate = bridged_to_this_conversion_rate_override
.map(|r| r.to_float() as u32)
.unwrap_or(BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE);
ThisChainBalance(bridged_balance.0 * conversion_rate)
}
}

Expand All @@ -817,7 +829,10 @@ mod tests {
type ThisChain = BridgedChain;
type BridgedChain = ThisChain;

fn bridged_balance_to_this_balance(_this_balance: ThisChainBalance) -> BridgedChainBalance {
fn bridged_balance_to_this_balance(
_this_balance: ThisChainBalance,
_bridged_to_this_conversion_rate_override: Option<FixedU128>,
) -> BridgedChainBalance {
unreachable!()
}
}
Expand Down Expand Up @@ -1095,6 +1110,7 @@ mod tests {
source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload,
OnThisChainBridge::RELAYER_FEE_PERCENT,
None,
),
Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)),
);
Expand All @@ -1106,6 +1122,7 @@ mod tests {
source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload_with_pay_on_target,
OnThisChainBridge::RELAYER_FEE_PERCENT,
None,
)
.expect(
"estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message",
Expand Down Expand Up @@ -1572,4 +1589,21 @@ mod tests {
100 + 50 * 10 + 777,
);
}

#[test]
fn conversion_rate_override_works() {
let payload = regular_outbound_message_payload();
let regular_fee = source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload,
OnThisChainBridge::RELAYER_FEE_PERCENT,
None,
);
let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::<OnThisChainBridge>(
&payload,
OnThisChainBridge::RELAYER_FEE_PERCENT,
Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)),
);

assert!(regular_fee < overrided_fee);
}
}
2 changes: 2 additions & 0 deletions bridges/primitives/chain-kusama/Cargo.toml
Expand Up @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false }

frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

Expand All @@ -30,6 +31,7 @@ std = [
"bp-runtime/std",
"frame-support/std",
"sp-api/std",
"sp-runtime/std",
"sp-std/std",
"sp-version/std",
]
2 changes: 2 additions & 0 deletions bridges/primitives/chain-kusama/src/lib.rs
Expand Up @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}
use frame_support::weights::{
WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
};
use sp_runtime::FixedU128;
use sp_std::prelude::*;
use sp_version::RuntimeVersion;

Expand Down Expand Up @@ -141,6 +142,7 @@ sp_api::decl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
kusama_to_this_conversion_rate: Option<FixedU128>,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
Expand Down
3 changes: 2 additions & 1 deletion bridges/primitives/chain-millau/src/lib.rs
Expand Up @@ -33,7 +33,7 @@ use scale_info::TypeInfo;
use sp_core::Hasher as HasherT;
use sp_runtime::{
traits::{Convert, IdentifyAccount, Verify},
MultiSignature, MultiSigner, Perbill,
FixedU128, MultiSignature, MultiSigner, Perbill,
};
use sp_std::prelude::*;
use sp_trie::{trie_types::Layout, TrieConfiguration};
Expand Down Expand Up @@ -319,6 +319,7 @@ sp_api::decl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
millau_to_this_conversion_rate: Option<FixedU128>,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
Expand Down
2 changes: 2 additions & 0 deletions bridges/primitives/chain-polkadot/Cargo.toml
Expand Up @@ -19,6 +19,7 @@ bp-runtime = { path = "../runtime", default-features = false }

frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-version = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }

Expand All @@ -30,6 +31,7 @@ std = [
"bp-runtime/std",
"frame-support/std",
"sp-api/std",
"sp-runtime/std",
"sp-std/std",
"sp-version/std",
]
2 changes: 2 additions & 0 deletions bridges/primitives/chain-polkadot/src/lib.rs
Expand Up @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}
use frame_support::weights::{
WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
};
use sp_runtime::FixedU128;
use sp_std::prelude::*;
use sp_version::RuntimeVersion;

Expand Down Expand Up @@ -141,6 +142,7 @@ sp_api::decl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
polkadot_to_this_conversion_rate: Option<FixedU128>,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
Expand Down
3 changes: 2 additions & 1 deletion bridges/primitives/chain-rialto/src/lib.rs
Expand Up @@ -30,7 +30,7 @@ use frame_system::limits;
use sp_core::Hasher as HasherT;
use sp_runtime::{
traits::{BlakeTwo256, Convert, IdentifyAccount, Verify},
MultiSignature, MultiSigner, Perbill,
FixedU128, MultiSignature, MultiSigner, Perbill,
};
use sp_std::prelude::*;

Expand Down Expand Up @@ -291,6 +291,7 @@ sp_api::decl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
rialto_to_this_conversion_rate: Option<FixedU128>,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
Expand Down
2 changes: 2 additions & 0 deletions bridges/primitives/chain-rococo/src/lib.rs
Expand Up @@ -24,6 +24,7 @@ use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState}
use frame_support::weights::{
Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
};
use sp_runtime::FixedU128;
use sp_std::prelude::*;
use sp_version::RuntimeVersion;

Expand Down Expand Up @@ -142,6 +143,7 @@ sp_api::decl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
rococo_to_this_conversion_rate: Option<FixedU128>,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
Expand Down
2 changes: 0 additions & 2 deletions bridges/primitives/chain-westend/Cargo.toml
Expand Up @@ -14,7 +14,6 @@ smallvec = "1.7"
# Bridge Dependencies

bp-header-chain = { path = "../header-chain", default-features = false }
bp-messages = { path = "../messages", default-features = false }
bp-polkadot-core = { path = "../polkadot-core", default-features = false }
bp-runtime = { path = "../runtime", default-features = false }

Expand All @@ -30,7 +29,6 @@ sp-version = { git = "https://github.com/paritytech/substrate", branch = "master
default = ["std"]
std = [
"bp-header-chain/std",
"bp-messages/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"frame-support/std",
Expand Down
48 changes: 0 additions & 48 deletions bridges/primitives/chain-westend/src/lib.rs
Expand Up @@ -20,7 +20,6 @@
// Runtime-generated DecodeLimit::decode_all_with_depth_limit
#![allow(clippy::unnecessary_mut_passed)]

use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState};
use frame_support::weights::{
WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial,
};
Expand Down Expand Up @@ -130,51 +129,4 @@ sp_api::decl_runtime_apis! {
/// Returns number and hash of the best finalized header known to the bridge module.
fn best_finalized() -> (BlockNumber, Hash);
}

/// Outbound message lane API for messages that are sent to Westend chain.
///
/// This API is implemented by runtimes that are sending messages to Westend chain, not the
/// Westend runtime itself.
pub trait ToWestendOutboundLaneApi<OutboundMessageFee: Parameter, OutboundPayload: Parameter> {
/// Estimate message delivery and dispatch fee that needs to be paid by the sender on
/// this chain.
///
/// Returns `None` if message is too expensive to be sent to Westend from this chain.
///
/// Please keep in mind that this method returns the lowest message fee required for message
/// to be accepted to the lane. It may be good idea to pay a bit over this price to account
/// future exchange rate changes and guarantee that relayer would deliver your message
/// to the target chain.
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
///
/// If some (or all) messages are missing from the storage, they'll also will
/// be missing from the resulting vector. The vector is ordered by the nonce.
fn message_details(
lane: LaneId,
begin: MessageNonce,
end: MessageNonce,
) -> Vec<MessageDetails<OutboundMessageFee>>;
/// Returns nonce of the latest message, received by bridged chain.
fn latest_received_nonce(lane: LaneId) -> MessageNonce;
/// Returns nonce of the latest message, generated by given lane.
fn latest_generated_nonce(lane: LaneId) -> MessageNonce;
}

/// Inbound message lane API for messages sent by Westend chain.
///
/// This API is implemented by runtimes that are receiving messages from Westend chain, not the
/// Westend runtime itself.
pub trait FromWestendInboundLaneApi {
/// Returns nonce of the latest message, received by given lane.
fn latest_received_nonce(lane: LaneId) -> MessageNonce;
/// Nonce of the latest message that has been confirmed to the bridged chain.
fn latest_confirmed_nonce(lane: LaneId) -> MessageNonce;
/// State of the unrewarded relayers set at given lane.
fn unrewarded_relayers_state(lane: LaneId) -> UnrewardedRelayersState;
}
}
2 changes: 2 additions & 0 deletions bridges/primitives/chain-wococo/src/lib.rs
Expand Up @@ -21,6 +21,7 @@
#![allow(clippy::unnecessary_mut_passed)]

use bp_messages::{LaneId, MessageDetails, MessageNonce, UnrewardedRelayersState};
use sp_runtime::FixedU128;
use sp_std::prelude::*;

pub use bp_polkadot_core::*;
Expand Down Expand Up @@ -95,6 +96,7 @@ sp_api::decl_runtime_apis! {
fn estimate_message_delivery_and_dispatch_fee(
lane_id: LaneId,
payload: OutboundPayload,
wococo_to_this_conversion_rate: Option<FixedU128>,
) -> Option<OutboundMessageFee>;
/// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all
/// messages in given inclusive range.
Expand Down

0 comments on commit b6a5fff

Please sign in to comment.