From ad4299f6c91ce4c50cb6fbc739a0c788e2920956 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 17 Dec 2021 16:54:29 +0300 Subject: [PATCH] override conversion rate in estimate-message-fee RPC (#1189) --- bridges/bin/millau/runtime/src/lib.rs | 4 +- .../bin/millau/runtime/src/rialto_messages.rs | 13 +++-- bridges/bin/rialto/runtime/src/lib.rs | 4 +- .../bin/rialto/runtime/src/millau_messages.rs | 13 +++-- bridges/bin/runtime-common/src/messages.rs | 46 +++++++++++++++--- bridges/primitives/chain-kusama/Cargo.toml | 2 + bridges/primitives/chain-kusama/src/lib.rs | 2 + bridges/primitives/chain-millau/src/lib.rs | 3 +- bridges/primitives/chain-polkadot/Cargo.toml | 2 + bridges/primitives/chain-polkadot/src/lib.rs | 2 + bridges/primitives/chain-rialto/src/lib.rs | 3 +- bridges/primitives/chain-rococo/src/lib.rs | 2 + bridges/primitives/chain-westend/Cargo.toml | 2 - bridges/primitives/chain-westend/src/lib.rs | 48 ------------------- bridges/primitives/chain-wococo/src/lib.rs | 2 + .../bin-substrate/src/cli/estimate_fee.rs | 8 +++- 16 files changed, 85 insertions(+), 71 deletions(-) diff --git a/bridges/bin/millau/runtime/src/lib.rs b/bridges/bin/millau/runtime/src/lib.rs index 4400191d940c9..f5dbab4e044a0 100644 --- a/bridges/bin/millau/runtime/src/lib.rs +++ b/bridges/bin/millau/runtime/src/lib.rs @@ -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")] @@ -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, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithRialtoMessageBridge::RELAYER_FEE_PERCENT, + rialto_to_this_conversion_rate, ).ok() } diff --git a/bridges/bin/millau/runtime/src/rialto_messages.rs b/bridges/bin/millau/runtime/src/rialto_messages.rs index d46ab4ca042a5..294b463084de1 100644 --- a/bridges/bin/millau/runtime/src/rialto_messages.rs +++ b/bridges/bin/millau/runtime/src/rialto_messages.rs @@ -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, + ) -> 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) } } diff --git a/bridges/bin/rialto/runtime/src/lib.rs b/bridges/bin/rialto/runtime/src/lib.rs index de86deb907b30..e6097adadb884 100644 --- a/bridges/bin/rialto/runtime/src/lib.rs +++ b/bridges/bin/rialto/runtime/src/lib.rs @@ -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")] @@ -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, ) -> Option { estimate_message_dispatch_and_delivery_fee::( &payload, WithMillauMessageBridge::RELAYER_FEE_PERCENT, + millau_to_this_conversion_rate, ).ok() } diff --git a/bridges/bin/rialto/runtime/src/millau_messages.rs b/bridges/bin/rialto/runtime/src/millau_messages.rs index 05935c90ea107..c6c382b43d298 100644 --- a/bridges/bin/rialto/runtime/src/millau_messages.rs +++ b/bridges/bin/rialto/runtime/src/millau_messages.rs @@ -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, + ) -> 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) } } diff --git a/bridges/bin/runtime-common/src/messages.rs b/bridges/bin/runtime-common/src/messages.rs index dd03379ce5d5d..f88ed2f4af9c4 100644 --- a/bridges/bin/runtime-common/src/messages.rs +++ b/bridges/bin/runtime-common/src/messages.rs @@ -70,6 +70,7 @@ pub trait MessageBridge { /// Convert Bridged chain balance into This chain balance. fn bridged_balance_to_this_balance( bridged_balance: BalanceOf>, + bridged_to_this_conversion_rate_override: Option, ) -> BalanceOf>; } @@ -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::(payload, B::RELAYER_FEE_PERCENT)?; + let minimal_fee_in_this_tokens = estimate_message_dispatch_and_delivery_fee::( + payload, + B::RELAYER_FEE_PERCENT, + None, + )?; // compare with actual fee paid if *delivery_and_dispatch_fee < minimal_fee_in_this_tokens { @@ -371,6 +375,7 @@ pub mod source { pub fn estimate_message_dispatch_and_delivery_fee( payload: &FromThisChainMessagePayload, relayer_fee_percent: u32, + bridged_to_this_conversion_rate: Option, ) -> Result>, &'static str> { // the fee (in Bridged tokens) of all transactions that are made on the Bridged chain // @@ -391,8 +396,11 @@ pub mod source { ThisChain::::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 @@ -798,8 +806,12 @@ mod tests { fn bridged_balance_to_this_balance( bridged_balance: BridgedChainBalance, + bridged_to_this_conversion_rate_override: Option, ) -> 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) } } @@ -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, + ) -> BridgedChainBalance { unreachable!() } } @@ -1095,6 +1110,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ), Ok(ThisChainBalance(EXPECTED_MINIMAL_FEE)), ); @@ -1106,6 +1122,7 @@ mod tests { source::estimate_message_dispatch_and_delivery_fee::( &payload_with_pay_on_target, OnThisChainBridge::RELAYER_FEE_PERCENT, + None, ) .expect( "estimate_message_dispatch_and_delivery_fee failed for pay-at-target-chain message", @@ -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::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + None, + ); + let overrided_fee = source::estimate_message_dispatch_and_delivery_fee::( + &payload, + OnThisChainBridge::RELAYER_FEE_PERCENT, + Some(FixedU128::from_float((BRIDGED_CHAIN_TO_THIS_CHAIN_BALANCE_RATE * 2) as f64)), + ); + + assert!(regular_fee < overrided_fee); + } } diff --git a/bridges/primitives/chain-kusama/Cargo.toml b/bridges/primitives/chain-kusama/Cargo.toml index 6ff860357c7c4..8d2f0e98a0117 100644 --- a/bridges/primitives/chain-kusama/Cargo.toml +++ b/bridges/primitives/chain-kusama/Cargo.toml @@ -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 } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/bridges/primitives/chain-kusama/src/lib.rs b/bridges/primitives/chain-kusama/src/lib.rs index 046323aa70091..2d798504b756d 100644 --- a/bridges/primitives/chain-kusama/src/lib.rs +++ b/bridges/primitives/chain-kusama/src/lib.rs @@ -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; @@ -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, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/bridges/primitives/chain-millau/src/lib.rs b/bridges/primitives/chain-millau/src/lib.rs index 4b2b043ed1229..45c18b72482d4 100644 --- a/bridges/primitives/chain-millau/src/lib.rs +++ b/bridges/primitives/chain-millau/src/lib.rs @@ -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}; @@ -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, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/bridges/primitives/chain-polkadot/Cargo.toml b/bridges/primitives/chain-polkadot/Cargo.toml index 917c7f9747839..710ed55e68c11 100644 --- a/bridges/primitives/chain-polkadot/Cargo.toml +++ b/bridges/primitives/chain-polkadot/Cargo.toml @@ -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 } @@ -30,6 +31,7 @@ std = [ "bp-runtime/std", "frame-support/std", "sp-api/std", + "sp-runtime/std", "sp-std/std", "sp-version/std", ] diff --git a/bridges/primitives/chain-polkadot/src/lib.rs b/bridges/primitives/chain-polkadot/src/lib.rs index 6989e6d2b641a..9f8b0ba3103d8 100644 --- a/bridges/primitives/chain-polkadot/src/lib.rs +++ b/bridges/primitives/chain-polkadot/src/lib.rs @@ -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; @@ -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, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/bridges/primitives/chain-rialto/src/lib.rs b/bridges/primitives/chain-rialto/src/lib.rs index d994b2f03f634..a6bf07c0ec786 100644 --- a/bridges/primitives/chain-rialto/src/lib.rs +++ b/bridges/primitives/chain-rialto/src/lib.rs @@ -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::*; @@ -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, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/bridges/primitives/chain-rococo/src/lib.rs b/bridges/primitives/chain-rococo/src/lib.rs index aca238358e187..94ec3af91e412 100644 --- a/bridges/primitives/chain-rococo/src/lib.rs +++ b/bridges/primitives/chain-rococo/src/lib.rs @@ -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; @@ -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, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/bridges/primitives/chain-westend/Cargo.toml b/bridges/primitives/chain-westend/Cargo.toml index 4fd1652744ed6..cc2e912cea57f 100644 --- a/bridges/primitives/chain-westend/Cargo.toml +++ b/bridges/primitives/chain-westend/Cargo.toml @@ -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 } @@ -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", diff --git a/bridges/primitives/chain-westend/src/lib.rs b/bridges/primitives/chain-westend/src/lib.rs index ffc0bf0fca109..37fe274fd3310 100644 --- a/bridges/primitives/chain-westend/src/lib.rs +++ b/bridges/primitives/chain-westend/src/lib.rs @@ -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, }; @@ -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 { - /// 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; - /// 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>; - /// 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; - } } diff --git a/bridges/primitives/chain-wococo/src/lib.rs b/bridges/primitives/chain-wococo/src/lib.rs index 20541d99a6ae5..6f586ae3fc3f9 100644 --- a/bridges/primitives/chain-wococo/src/lib.rs +++ b/bridges/primitives/chain-wococo/src/lib.rs @@ -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::*; @@ -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, ) -> Option; /// Returns dispatch weight, encoded payload size and delivery+dispatch fee of all /// messages in given inclusive range. diff --git a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs index 18e7341fc9658..42ae354564feb 100644 --- a/bridges/relays/bin-substrate/src/cli/estimate_fee.rs +++ b/bridges/relays/bin-substrate/src/cli/estimate_fee.rs @@ -21,6 +21,7 @@ use crate::{ use bp_runtime::BalanceOf; use codec::{Decode, Encode}; use relay_substrate_client::Chain; +use sp_runtime::FixedU128; use structopt::StructOpt; use strum::VariantNames; @@ -72,8 +73,13 @@ pub(crate) async fn estimate_message_delivery_and_dispatch_fee anyhow::Result { + let conversion_rate_override: Option = None; let encoded_response = client - .state_call(estimate_fee_method.into(), (lane, payload).encode().into(), None) + .state_call( + estimate_fee_method.into(), + (lane, payload, conversion_rate_override).encode().into(), + None, + ) .await?; let decoded_response: Option = Decode::decode(&mut &encoded_response.0[..]) .map_err(relay_substrate_client::Error::ResponseParseFailed)?;