mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 04:41:03 +00:00
Add XCM Origin and converter (#2896)
* Add XCM Origin and converter * IsMajority filter can be location-prefixed * Update xcm/pallet-xcm/src/lib.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/src/v0/multi_location.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Introduce UsingComponents to allow reuse of fee payment in XCM * Use Drop rather than finalize * Add errors for weight. * Apply suggestions from code review Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Fixes * Update xcm/xcm-builder/src/weight.rs Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> * Various XCM fixes and improvements * Fixes * Update xcm/xcm-builder/src/weight.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/weight.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Update xcm/xcm-builder/src/weight.rs Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> * Fixes Co-authored-by: Alexander Popiak <alexander.popiak@parity.io> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Generated
+179
-174
File diff suppressed because it is too large
Load Diff
@@ -92,7 +92,7 @@ use xcm_builder::{
|
||||
AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation,
|
||||
CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative, SignedAccountId32AsNative,
|
||||
ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete, FixedWeightBounds,
|
||||
FixedRateOfConcreteFungible, BackingToPlurality, SignedToAccountId32
|
||||
BackingToPlurality, SignedToAccountId32, UsingComponents,
|
||||
};
|
||||
use constants::{time::*, currency::*, fee::*, size::*};
|
||||
use frame_support::traits::InstanceFilter;
|
||||
@@ -110,7 +110,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
spec_name: create_runtime_str!("rococo"),
|
||||
impl_name: create_runtime_str!("parity-rococo-v1.5"),
|
||||
authoring_version: 0,
|
||||
spec_version: 231,
|
||||
spec_version: 232,
|
||||
impl_version: 0,
|
||||
#[cfg(not(feature = "disable-runtime-api"))]
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
@@ -646,7 +646,7 @@ impl xcm_executor::Config for XcmConfig {
|
||||
type LocationInverter = LocationInverter<Ancestry>;
|
||||
type Barrier = Barrier;
|
||||
type Weigher = FixedWeightBounds<BaseXcmWeight, Call>;
|
||||
type Trader = FixedRateOfConcreteFungible<RocFee>;
|
||||
type Trader = UsingComponents<WeightToFee, RocLocation, AccountId, Balances, ToAuthor<Runtime>>;
|
||||
type ResponseHandler = ();
|
||||
}
|
||||
|
||||
@@ -657,7 +657,8 @@ parameter_types! {
|
||||
/// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior location
|
||||
/// of this chain.
|
||||
pub type LocalOriginToLocation = (
|
||||
// We allow an origin from the Collective pallet to be used in XCM as a corresponding Plurality
|
||||
// We allow an origin from the Collective pallet to be used in XCM as a corresponding Plurality of the
|
||||
// `Unit` body.
|
||||
BackingToPlurality<Origin, pallet_collective::Origin<Runtime>, CollectiveBodyId>,
|
||||
// And a usual Signed origin to be used in XCM as a corresponding AccountId32
|
||||
SignedToAccountId32<Origin, AccountId, RococoNetwork>,
|
||||
@@ -881,8 +882,8 @@ impl pallet_collective::Config for Runtime {
|
||||
type Event = Event;
|
||||
type MotionDuration = MotionDuration;
|
||||
type MaxProposals = MaxProposals;
|
||||
type MaxMembers = MaxMembers;
|
||||
type DefaultVote = pallet_collective::PrimeDefaultVote;
|
||||
type MaxMembers = MaxMembers;
|
||||
type WeightInfo = ();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ frame-support = { git = "https://github.com/paritytech/substrate", default-featu
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
|
||||
|
||||
xcm = { path = "..", default-features = false }
|
||||
xcm-executor = { path = "../xcm-executor", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
use sp_std::{marker::PhantomData, convert::TryInto, boxed::Box};
|
||||
use codec::{Encode, Decode};
|
||||
use xcm::v0::{BodyId, MultiLocation::{self, X1}, Junction::Plurality};
|
||||
use xcm::v0::{BodyId, OriginKind, MultiLocation, Junction::Plurality};
|
||||
use xcm_executor::traits::ConvertOrigin;
|
||||
use sp_runtime::{RuntimeDebug, traits::BadOrigin};
|
||||
use frame_support::traits::{EnsureOrigin, OriginTrait, Filter, Get};
|
||||
|
||||
@@ -62,6 +63,7 @@ pub mod pallet {
|
||||
#[pallet::generate_deposit(pub(super) fn deposit_event)]
|
||||
pub enum Event<T: Config> {
|
||||
Attempted(xcm::v0::Outcome),
|
||||
Sent(MultiLocation, MultiLocation, Xcm<()>),
|
||||
}
|
||||
|
||||
#[pallet::error]
|
||||
@@ -78,11 +80,12 @@ pub mod pallet {
|
||||
#[pallet::weight(1_000)]
|
||||
fn send(origin: OriginFor<T>, dest: MultiLocation, message: Xcm<()>) -> DispatchResult {
|
||||
let origin_location = T::SendXcmOrigin::ensure_origin(origin)?;
|
||||
Self::send_xcm(origin_location, dest, message)
|
||||
Self::send_xcm(origin_location.clone(), dest.clone(), message.clone())
|
||||
.map_err(|e| match e {
|
||||
XcmError::CannotReachDestination(..) => Error::<T>::Unreachable,
|
||||
_ => Error::<T>::SendFailure,
|
||||
})?;
|
||||
Self::deposit_event(Event::Sent(origin_location, dest, message));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -149,10 +152,11 @@ pub fn ensure_xcm<OuterOrigin>(o: OuterOrigin) -> Result<MultiLocation, BadOrigi
|
||||
/// plurality.
|
||||
///
|
||||
/// May reasonably be used with `EnsureXcm`.
|
||||
pub struct IsMajorityOfBody<Body>(PhantomData<Body>);
|
||||
impl<Body: Get<BodyId>> Filter<MultiLocation> for IsMajorityOfBody<Body> {
|
||||
pub struct IsMajorityOfBody<Prefix, Body>(PhantomData<(Prefix, Body)>);
|
||||
impl<Prefix: Get<MultiLocation>, Body: Get<BodyId>> Filter<MultiLocation> for IsMajorityOfBody<Prefix, Body> {
|
||||
fn filter(l: &MultiLocation) -> bool {
|
||||
matches!(l, X1(Plurality { id, part }) if id == &Body::get() && part.is_majority())
|
||||
let maybe_suffix = l.match_and_split(&Prefix::get());
|
||||
matches!(maybe_suffix, Some(Plurality { id, part }) if id == &Body::get() && part.is_majority())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,3 +184,17 @@ impl<O: OriginTrait + From<Origin>, F: Filter<MultiLocation>> EnsureOrigin<O> fo
|
||||
O::from(Origin::Xcm(MultiLocation::Null))
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple passthrough where we reuse the `MultiLocation`-typed XCM origin as the inner value of
|
||||
/// this crate's `Origin::Xcm` value.
|
||||
pub struct XcmPassthrough<Origin>(PhantomData<Origin>);
|
||||
impl<
|
||||
Origin: From<crate::Origin>,
|
||||
> ConvertOrigin<Origin> for XcmPassthrough<Origin> {
|
||||
fn convert_origin(origin: MultiLocation, kind: OriginKind) -> Result<Origin, MultiLocation> {
|
||||
match (kind, origin) {
|
||||
(OriginKind::Xcm, l) => Ok(crate::Origin::Xcm(l).into()),
|
||||
(_, origin) => Err(origin),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,10 @@ pub use traits::{Error, Result, SendXcm, ExecuteXcm, Outcome};
|
||||
/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug)]
|
||||
pub enum OriginKind {
|
||||
/// Origin should just be the native origin for the sender. For Cumulus/Frame chains this is
|
||||
/// the `Parachain` origin.
|
||||
/// Origin should just be the native dispatch origin representation for the sender in the
|
||||
/// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin
|
||||
/// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a
|
||||
/// primary/native dispatch origin form.
|
||||
Native,
|
||||
|
||||
/// Origin should just be the standard account-based origin with the sovereign account of
|
||||
@@ -50,6 +52,11 @@ pub enum OriginKind {
|
||||
/// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin.
|
||||
/// This will not usually be an available option.
|
||||
Superuser,
|
||||
|
||||
/// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be
|
||||
/// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be
|
||||
/// the `pallet_xcm::Origin::Xcm` type.
|
||||
Xcm,
|
||||
}
|
||||
|
||||
/// Response data to a query.
|
||||
|
||||
@@ -442,6 +442,20 @@ impl MultiLocation {
|
||||
MultiLocationReverseIterator(self)
|
||||
}
|
||||
|
||||
/// Ensures that self begins with `prefix` and that it has a single `Junction` item following. If
|
||||
/// so, returns a reference to this `Junction` item.
|
||||
pub fn match_and_split(&self, prefix: &MultiLocation) -> Option<&Junction> {
|
||||
if prefix.len() + 1 != self.len() {
|
||||
return None
|
||||
}
|
||||
for i in 0..prefix.len() {
|
||||
if prefix.at(i) != self.at(i) {
|
||||
return None
|
||||
}
|
||||
}
|
||||
return self.at(prefix.len())
|
||||
}
|
||||
|
||||
/// Mutates `self`, suffixing it with `new`. Returns `Err` in case of overflow.
|
||||
pub fn push(&mut self, new: Junction) -> result::Result<(), ()> {
|
||||
let mut n = MultiLocation::Null;
|
||||
|
||||
@@ -72,6 +72,8 @@ pub enum Error {
|
||||
NotWithdrawable,
|
||||
/// Indicates that the consensus system cannot deposit an asset under the ownership of a particular location.
|
||||
LocationCannotHold,
|
||||
/// The assets given to purchase weight is are insufficient for the weight desired.
|
||||
TooExpensive,
|
||||
}
|
||||
|
||||
impl From<()> for Error {
|
||||
|
||||
@@ -16,6 +16,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", de
|
||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-support = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
|
||||
|
||||
# Polkadot dependencies
|
||||
polkadot-parachain = { path = "../../parachain", default-features = false }
|
||||
@@ -33,4 +34,5 @@ std = [
|
||||
"sp-runtime/std",
|
||||
"frame-support/std",
|
||||
"polkadot-parachain/std",
|
||||
"pallet-transaction-payment/std",
|
||||
]
|
||||
|
||||
@@ -46,7 +46,7 @@ mod fungibles_adapter;
|
||||
pub use fungibles_adapter::FungiblesAdapter;
|
||||
|
||||
mod weight;
|
||||
pub use weight::{FixedRateOfConcreteFungible, FixedWeightBounds};
|
||||
pub use weight::{FixedRateOfConcreteFungible, FixedWeightBounds, UsingComponents};
|
||||
|
||||
mod matches_fungible;
|
||||
pub use matches_fungible::{IsAbstract, IsConcrete};
|
||||
|
||||
@@ -272,6 +272,6 @@ impl Config for TestConfig {
|
||||
type LocationInverter = LocationInverter<TestAncestry>;
|
||||
type Barrier = TestBarrier;
|
||||
type Weigher = FixedWeightBounds<UnitWeightCost, TestCall>;
|
||||
type Trader = FixedRateOfConcreteFungible<WeightPrice>;
|
||||
type Trader = FixedRateOfConcreteFungible<WeightPrice, ()>;
|
||||
type ResponseHandler = TestResponseHandler;
|
||||
}
|
||||
|
||||
@@ -14,19 +14,22 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use sp_std::{result::Result, marker::PhantomData};
|
||||
use sp_std::{result::Result, marker::PhantomData, convert::TryInto};
|
||||
use parity_scale_codec::Decode;
|
||||
use xcm::v0::{Xcm, Order, MultiAsset, MultiLocation};
|
||||
use frame_support::{traits::Get, weights::{Weight, GetDispatchInfo}};
|
||||
use xcm::v0::{Xcm, Order, MultiAsset, MultiLocation, Error};
|
||||
use sp_runtime::traits::{Zero, Saturating, SaturatedConversion};
|
||||
use frame_support::traits::{Get, OnUnbalanced as OnUnbalancedT, tokens::currency::Currency as CurrencyT};
|
||||
use frame_support::weights::{Weight, GetDispatchInfo, WeightToFeePolynomial};
|
||||
use xcm_executor::{Assets, traits::{WeightBounds, WeightTrader}};
|
||||
|
||||
pub struct FixedWeightBounds<T, C>(PhantomData<(T, C)>);
|
||||
impl<T: Get<Weight>, C: Decode + GetDispatchInfo> WeightBounds<C> for FixedWeightBounds<T, C> {
|
||||
fn shallow(message: &mut Xcm<C>) -> Result<Weight, ()> {
|
||||
let min = match message {
|
||||
Ok(match message {
|
||||
Xcm::Transact { call, .. } => {
|
||||
call.ensure_decoded()?.get_dispatch_info().weight + T::get()
|
||||
}
|
||||
Xcm::RelayedFrom { ref mut message, .. } => T::get() + Self::shallow(message.as_mut())?,
|
||||
Xcm::WithdrawAsset { effects, .. }
|
||||
| Xcm::ReserveAssetDeposit { effects, .. }
|
||||
| Xcm::TeleportAsset { effects, .. } => {
|
||||
@@ -45,16 +48,16 @@ impl<T: Get<Weight>, C: Decode + GetDispatchInfo> WeightBounds<C> for FixedWeigh
|
||||
T::get() + inner
|
||||
}
|
||||
_ => T::get(),
|
||||
};
|
||||
Ok(min)
|
||||
})
|
||||
}
|
||||
fn deep(message: &mut Xcm<C>) -> Result<Weight, ()> {
|
||||
let mut extra = 0;
|
||||
match message {
|
||||
Xcm::Transact { .. } => {}
|
||||
Ok(match message {
|
||||
Xcm::RelayedFrom { ref mut message, .. } => Self::deep(message.as_mut())?,
|
||||
Xcm::WithdrawAsset { effects, .. }
|
||||
| Xcm::ReserveAssetDeposit { effects, .. }
|
||||
| Xcm::TeleportAsset { effects, .. } => {
|
||||
| Xcm::TeleportAsset { effects, .. }
|
||||
=> {
|
||||
let mut extra = 0;
|
||||
for effect in effects.iter_mut() {
|
||||
match effect {
|
||||
Order::BuyExecution { xcm, .. } => {
|
||||
@@ -65,34 +68,116 @@ impl<T: Get<Weight>, C: Decode + GetDispatchInfo> WeightBounds<C> for FixedWeigh
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Ok(extra)
|
||||
extra
|
||||
},
|
||||
_ => 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Function trait for handling some revenue. Similar to a negative imbalance (credit) handler, but for a
|
||||
/// `MultiAsset`. Sensible implementations will deposit the asset in some known treasury or block-author account.
|
||||
pub trait TakeRevenue {
|
||||
/// Do something with the given `revenue`, which is a single non-wildcard `MultiAsset`.
|
||||
fn take_revenue(revenue: MultiAsset);
|
||||
}
|
||||
|
||||
/// Null implementation just burns the revenue.
|
||||
impl TakeRevenue for () {
|
||||
fn take_revenue(_revenue: MultiAsset) {}
|
||||
}
|
||||
|
||||
/// Simple fee calculator that requires payment in a single concrete fungible at a fixed rate.
|
||||
///
|
||||
/// The constant `Get` type parameter should be the concrete fungible ID and the amount of it required for
|
||||
/// one second of weight.
|
||||
pub struct FixedRateOfConcreteFungible<T>(Weight, PhantomData<T>);
|
||||
impl<T: Get<(MultiLocation, u128)>> WeightTrader for FixedRateOfConcreteFungible<T> {
|
||||
fn new() -> Self { Self(0, PhantomData) }
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, ()> {
|
||||
pub struct FixedRateOfConcreteFungible<
|
||||
T: Get<(MultiLocation, u128)>,
|
||||
R: TakeRevenue,
|
||||
>(Weight, u128, PhantomData<(T, R)>);
|
||||
impl<T: Get<(MultiLocation, u128)>, R: TakeRevenue> WeightTrader for FixedRateOfConcreteFungible<T, R> {
|
||||
fn new() -> Self { Self(0, 0, PhantomData) }
|
||||
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, Error> {
|
||||
let (id, units_per_second) = T::get();
|
||||
let amount = units_per_second * (weight as u128) / 1_000_000_000_000u128;
|
||||
use frame_support::weights::constants::WEIGHT_PER_SECOND;
|
||||
let amount = units_per_second * (weight as u128) / (WEIGHT_PER_SECOND as u128);
|
||||
let required = MultiAsset::ConcreteFungible { amount, id };
|
||||
let (used, _) = payment.less(required).map_err(|_| ())?;
|
||||
let (unused, _) = payment.less(required).map_err(|_| Error::TooExpensive)?;
|
||||
self.0 = self.0.saturating_add(weight);
|
||||
Ok(used)
|
||||
self.1 = self.1.saturating_add(amount);
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight) -> MultiAsset {
|
||||
let weight = weight.min(self.0);
|
||||
self.0 -= weight;
|
||||
let (id, units_per_second) = T::get();
|
||||
let weight = weight.min(self.0);
|
||||
let amount = units_per_second * (weight as u128) / 1_000_000_000_000u128;
|
||||
self.0 -= weight;
|
||||
self.1 = self.1.saturating_sub(amount);
|
||||
let result = MultiAsset::ConcreteFungible { amount, id };
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Get<(MultiLocation, u128)>, R: TakeRevenue> Drop for FixedRateOfConcreteFungible<T, R> {
|
||||
fn drop(&mut self) {
|
||||
let revenue = MultiAsset::ConcreteFungible { amount: self.1, id: T::get().0 };
|
||||
R::take_revenue(revenue);
|
||||
}
|
||||
}
|
||||
|
||||
/// Weight trader which uses the TransactionPayment pallet to set the right price for weight and then
|
||||
/// places any weight bought into the right account.
|
||||
pub struct UsingComponents<
|
||||
WeightToFee: WeightToFeePolynomial<Balance=Currency::Balance>,
|
||||
AssetId: Get<MultiLocation>,
|
||||
AccountId,
|
||||
Currency: CurrencyT<AccountId>,
|
||||
OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
|
||||
>(Weight, Currency::Balance, PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>);
|
||||
impl<
|
||||
WeightToFee: WeightToFeePolynomial<Balance=Currency::Balance>,
|
||||
AssetId: Get<MultiLocation>,
|
||||
AccountId,
|
||||
Currency: CurrencyT<AccountId>,
|
||||
OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
|
||||
> WeightTrader for UsingComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced> {
|
||||
fn new() -> Self { Self(0, Zero::zero(), PhantomData) }
|
||||
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, Error> {
|
||||
let amount = WeightToFee::calc(&weight);
|
||||
let required = MultiAsset::ConcreteFungible {
|
||||
amount: amount.try_into().map_err(|_| Error::Overflow)?,
|
||||
id: AssetId::get(),
|
||||
};
|
||||
let (unused, _) = payment.less(required).map_err(|_| Error::TooExpensive)?;
|
||||
self.0 = self.0.saturating_add(weight);
|
||||
self.1 = self.1.saturating_add(amount);
|
||||
Ok(unused)
|
||||
}
|
||||
|
||||
fn refund_weight(&mut self, weight: Weight) -> MultiAsset {
|
||||
let weight = weight.min(self.0);
|
||||
let amount = WeightToFee::calc(&weight);
|
||||
self.0 -= weight;
|
||||
self.1 = self.1.saturating_sub(amount);
|
||||
let result = MultiAsset::ConcreteFungible {
|
||||
amount: amount.saturated_into(),
|
||||
id: AssetId::get(),
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
}
|
||||
impl<
|
||||
WeightToFee: WeightToFeePolynomial<Balance=Currency::Balance>,
|
||||
AssetId: Get<MultiLocation>,
|
||||
AccountId,
|
||||
Currency: CurrencyT<AccountId>,
|
||||
OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
|
||||
> Drop for UsingComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced> {
|
||||
fn drop(&mut self) {
|
||||
OnUnbalanced::on_unbalanced(Currency::issue(self.1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,9 @@ impl<Config: config::Config> ExecuteXcm<Config::Call> for XcmExecutor<Config> {
|
||||
return Outcome::Error(XcmError::WeightLimitReached);
|
||||
}
|
||||
let mut trader = Config::Trader::new();
|
||||
match Self::do_execute_xcm(origin, true, message, &mut 0, Some(shallow_weight), &mut trader) {
|
||||
let result = Self::do_execute_xcm(origin, true, message, &mut 0, Some(shallow_weight), &mut trader);
|
||||
drop(trader);
|
||||
match result {
|
||||
Ok(surplus) => Outcome::Complete(maximum_weight.saturating_sub(surplus)),
|
||||
// TODO: #2841 #REALWEIGHT We can do better than returning `maximum_weight` here, and we should otherwise
|
||||
// we'll needlessly be disregarding block execution time.
|
||||
@@ -76,7 +78,9 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
assets.into_assets_iter().collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Execute the XCM and return any unexpected and unknowable surplus weight.
|
||||
/// Execute the XCM and return the portion of weight of `shallow_weight + deep_weight` that `message` did not use.
|
||||
///
|
||||
/// NOTE: The amount returned must be less than `shallow_weight + deep_weight` of `message`.
|
||||
fn do_execute_xcm(
|
||||
origin: MultiLocation,
|
||||
top_level: bool,
|
||||
@@ -95,8 +99,8 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
.map_err(|()| XcmError::Barrier)?;
|
||||
|
||||
// The surplus weight, defined as the amount by which `shallow_weight` plus all nested
|
||||
// `shallow_weight` values (ensuring no double-counting) is an overestimate of the actual weight
|
||||
// consumed.
|
||||
// `shallow_weight` values (ensuring no double-counting and also known as `deep_weight`) is an
|
||||
// over-estimate of the actual weight consumed.
|
||||
let mut total_surplus: Weight = 0;
|
||||
|
||||
let maybe_holding_effects = match (origin.clone(), message) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use sp_std::result::Result;
|
||||
use xcm::v0::{Xcm, MultiAsset};
|
||||
use xcm::v0::{Xcm, MultiAsset, Error};
|
||||
use frame_support::weights::Weight;
|
||||
use crate::Assets;
|
||||
|
||||
@@ -46,14 +46,14 @@ pub trait WeightBounds<Call> {
|
||||
}
|
||||
|
||||
/// Charge for weight in order to execute XCM.
|
||||
pub trait WeightTrader {
|
||||
pub trait WeightTrader: Sized {
|
||||
/// Create a new trader instance.
|
||||
fn new() -> Self;
|
||||
|
||||
/// Purchase execution weight credit in return for up to a given `fee`. If less of the fee is required
|
||||
/// then the surplus is returned. If the `fee` cannot be used to pay for the `weight`, then an error is
|
||||
/// returned.
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, ()>;
|
||||
fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, Error>;
|
||||
|
||||
/// Attempt a refund of `weight` into some asset. The caller does not guarantee that the weight was
|
||||
/// purchased using `buy_weight`.
|
||||
|
||||
Reference in New Issue
Block a user