From e1a44e975ed3bbb305c430031cb8875865963306 Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Mon, 9 Aug 2021 15:13:52 +1200 Subject: [PATCH 1/5] Impl WeightTrader for tuple. --- xcm/xcm-builder/src/tests.rs | 56 +++++++++++++++++++++++++++ xcm/xcm-executor/src/traits/weight.rs | 24 ++++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/xcm/xcm-builder/src/tests.rs b/xcm/xcm-builder/src/tests.rs index 31f141ab68be..0ae93a1518b7 100644 --- a/xcm/xcm-builder/src/tests.rs +++ b/xcm/xcm-builder/src/tests.rs @@ -17,6 +17,7 @@ use super::{mock::*, *}; use xcm::latest::prelude::*; use xcm_executor::{traits::*, Config, XcmExecutor}; +use frame_support::{weights::constants::WEIGHT_PER_SECOND, assert_err}; #[test] fn basic_setup_works() { @@ -372,3 +373,58 @@ fn prepaid_result_of_query_should_get_free_execution() { let r = XcmExecutor::::execute_xcm(origin.clone(), message.clone(), weight_limit); assert_eq!(r, Outcome::Incomplete(10, XcmError::Barrier)); } + +fn fungible_multi_asset(location: MultiLocation, amount: u128) -> MultiAsset { + (AssetId::from(location), Fungibility::Fungible(amount)).into() +} + +#[test] +fn weight_trader_tuple_should_work() { + pub const PARA_1: MultiLocation = X1(Parachain(1)); + pub const PARA_2: MultiLocation = X1(Parachain(2)); + + parameter_types! { + pub static HereWeightPrice: (AssetId, u128) = (Here.into(), WEIGHT_PER_SECOND.into()); + pub static PARA1WeightPrice: (AssetId, u128) = (PARA_1.into(), WEIGHT_PER_SECOND.into()); + } + + type MultiTraders = ( + // trader one + FixedRateOfFungible, + // trader two + FixedRateOfFungible, + ); + + let mut traders = MultiTraders::new(); + // trader one buys weight + assert_eq!( + traders.buy_weight(5, fungible_multi_asset(Here, 10).into()), + Ok(fungible_multi_asset(Here, 5).into()), + ); + // trader one refunds + assert_eq!( + traders.refund_weight(2), + Some(fungible_multi_asset(Here, 2)), + ); + + let mut traders = MultiTraders::new(); + // trader one failed; trader two buys weight + assert_eq!( + traders.buy_weight(5, fungible_multi_asset(PARA_1, 10).into()), + Ok(fungible_multi_asset(PARA_1, 5).into()), + ); + // trader two refunds + assert_eq!( + traders.refund_weight(2), + Some(fungible_multi_asset(PARA_1, 2)), + ); + + let mut traders = MultiTraders::new(); + // all traders fails + assert_err!( + traders.buy_weight(5, fungible_multi_asset(PARA_2, 10).into()), + XcmError::TooExpensive, + ); + // and no refund + assert_eq!(traders.refund_weight(2), None); +} diff --git a/xcm/xcm-executor/src/traits/weight.rs b/xcm/xcm-executor/src/traits/weight.rs index 8c9e6ec6366d..f6a10fd112ae 100644 --- a/xcm/xcm-executor/src/traits/weight.rs +++ b/xcm/xcm-executor/src/traits/weight.rs @@ -76,11 +76,27 @@ pub trait WeightTrader: Sized { } } -impl WeightTrader for () { +#[impl_trait_for_tuples::impl_for_tuples(30)] +impl WeightTrader for Tuple { fn new() -> Self { - () + for_tuples!( ( #( Tuple::new() ),* ) ) } - fn buy_weight(&mut self, _: Weight, _: Assets) -> Result { - Err(Error::Unimplemented) + + fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + for_tuples!( #( + if let Ok(assets) = Tuple.buy_weight(weight, payment.clone()) { + return Ok(assets); + } + )* ); + Err(Error::TooExpensive) + } + + fn refund_weight(&mut self, weight: Weight) -> Option { + for_tuples!( #( + if let Some(asset) = Tuple.refund_weight(weight) { + return Some(asset); + } + )* ); + None } } From 540787764d70181d0a7677b89b2602ba59420a52 Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Mon, 9 Aug 2021 15:16:21 +1200 Subject: [PATCH 2/5] fmt --- xcm/xcm-builder/src/tests.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/xcm/xcm-builder/src/tests.rs b/xcm/xcm-builder/src/tests.rs index 0ae93a1518b7..a8bf58aa0f5c 100644 --- a/xcm/xcm-builder/src/tests.rs +++ b/xcm/xcm-builder/src/tests.rs @@ -15,9 +15,9 @@ // along with Polkadot. If not, see . use super::{mock::*, *}; +use frame_support::{assert_err, weights::constants::WEIGHT_PER_SECOND}; use xcm::latest::prelude::*; use xcm_executor::{traits::*, Config, XcmExecutor}; -use frame_support::{weights::constants::WEIGHT_PER_SECOND, assert_err}; #[test] fn basic_setup_works() { @@ -402,10 +402,7 @@ fn weight_trader_tuple_should_work() { Ok(fungible_multi_asset(Here, 5).into()), ); // trader one refunds - assert_eq!( - traders.refund_weight(2), - Some(fungible_multi_asset(Here, 2)), - ); + assert_eq!(traders.refund_weight(2), Some(fungible_multi_asset(Here, 2))); let mut traders = MultiTraders::new(); // trader one failed; trader two buys weight @@ -414,10 +411,7 @@ fn weight_trader_tuple_should_work() { Ok(fungible_multi_asset(PARA_1, 5).into()), ); // trader two refunds - assert_eq!( - traders.refund_weight(2), - Some(fungible_multi_asset(PARA_1, 2)), - ); + assert_eq!(traders.refund_weight(2), Some(fungible_multi_asset(PARA_1, 2))); let mut traders = MultiTraders::new(); // all traders fails From 691ce7a12dbf2ce8b65b142b3f91127215f85574 Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Mon, 9 Aug 2021 15:18:45 +1200 Subject: [PATCH 3/5] Renaming. --- xcm/xcm-builder/src/tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xcm/xcm-builder/src/tests.rs b/xcm/xcm-builder/src/tests.rs index a8bf58aa0f5c..8addcb0b9e5b 100644 --- a/xcm/xcm-builder/src/tests.rs +++ b/xcm/xcm-builder/src/tests.rs @@ -388,14 +388,14 @@ fn weight_trader_tuple_should_work() { pub static PARA1WeightPrice: (AssetId, u128) = (PARA_1.into(), WEIGHT_PER_SECOND.into()); } - type MultiTraders = ( + type Traders = ( // trader one FixedRateOfFungible, // trader two FixedRateOfFungible, ); - let mut traders = MultiTraders::new(); + let mut traders = Traders::new(); // trader one buys weight assert_eq!( traders.buy_weight(5, fungible_multi_asset(Here, 10).into()), @@ -404,7 +404,7 @@ fn weight_trader_tuple_should_work() { // trader one refunds assert_eq!(traders.refund_weight(2), Some(fungible_multi_asset(Here, 2))); - let mut traders = MultiTraders::new(); + let mut traders = Traders::new(); // trader one failed; trader two buys weight assert_eq!( traders.buy_weight(5, fungible_multi_asset(PARA_1, 10).into()), @@ -413,7 +413,7 @@ fn weight_trader_tuple_should_work() { // trader two refunds assert_eq!(traders.refund_weight(2), Some(fungible_multi_asset(PARA_1, 2))); - let mut traders = MultiTraders::new(); + let mut traders = Traders::new(); // all traders fails assert_err!( traders.buy_weight(5, fungible_multi_asset(PARA_2, 10).into()), From ac73207de407dda404209aa3bd997f02072be7f1 Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Tue, 17 Aug 2021 15:46:42 +0200 Subject: [PATCH 4/5] add tracing for buy_weight --- xcm/xcm-executor/src/traits/weight.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/xcm/xcm-executor/src/traits/weight.rs b/xcm/xcm-executor/src/traits/weight.rs index f6a10fd112ae..b071c441496f 100644 --- a/xcm/xcm-executor/src/traits/weight.rs +++ b/xcm/xcm-executor/src/traits/weight.rs @@ -83,12 +83,16 @@ impl WeightTrader for Tuple { } fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result { + let mut last_error = None; for_tuples!( #( - if let Ok(assets) = Tuple.buy_weight(weight, payment.clone()) { - return Ok(assets); + match Tuple.buy_weight(weight, payment.clone()) { + Ok(assets) => return Ok(assets), + Err(e) => { last_error = Some(e) } } )* ); - Err(Error::TooExpensive) + let last_error = last_error.unwrap_or(Error::TooExpensive); + log::trace!(target: "xcm::buy_weight", "last_error: {:?}", last_error); + Err(last_error) } fn refund_weight(&mut self, weight: Weight) -> Option { From 9369beadaada834d7091425f2e0f2c1885cfb7f9 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Tue, 17 Aug 2021 14:49:55 -0700 Subject: [PATCH 5/5] Add comment clarifying the default behavior of a WeightTrader tuple --- xcm/xcm-executor/src/traits/weight.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xcm/xcm-executor/src/traits/weight.rs b/xcm/xcm-executor/src/traits/weight.rs index b071c441496f..8d962c88e5ec 100644 --- a/xcm/xcm-executor/src/traits/weight.rs +++ b/xcm/xcm-executor/src/traits/weight.rs @@ -58,6 +58,11 @@ pub trait UniversalWeigher { } /// Charge for weight in order to execute XCM. +/// +/// A `WeightTrader` may also be put into a tuple, in which case the default behavior of +/// `buy_weight` and `refund_weight` would be to attempt to call each tuple element's own +/// implementation of these two functions, in the order of which they appear in the tuple, +/// returning early when a successful result is returned. pub trait WeightTrader: Sized { /// Create a new trader instance. fn new() -> Self;