Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

[pallet_xcm] Customizable/extendable remote_message estimation #7424

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
74ac9c1
[pallet_xcm] Customizable/extendable `remote_message` estimation
bkontur Jun 24, 2023
25d67c6
Rename back weight->weigh
bkontur Jun 24, 2023
8297c87
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Jun 30, 2023
1120b80
DestinationWeigher used in all runtimes
bkontur Jun 30, 2023
a53930e
fmt
bkontur Jun 30, 2023
9605074
Nits
bkontur Jul 3, 2023
db5d966
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Jul 3, 2023
9477e78
Update xcm/xcm-builder/src/weight.rs
bkontur Jul 31, 2023
2e7e369
Doc
bkontur Jul 31, 2023
f9c46fe
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Jul 31, 2023
e54cddf
Fix compile
bkontur Aug 1, 2023
fcc310f
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Aug 1, 2023
4f9007e
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
Aug 3, 2023
9aec446
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Aug 16, 2023
69eae3f
".git/.scripts/commands/fmt/fmt.sh"
Aug 16, 2023
8ddc82e
Fix import
bkontur Aug 17, 2023
9e44153
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Aug 17, 2023
f571ec8
Update xcm/pallet-xcm/src/lib.rs
bkontur Aug 17, 2023
404ac44
".git/.scripts/commands/fmt/fmt.sh"
Aug 17, 2023
537361e
Adds Tuple support for `ProvideWeighableInstructions` and impl for `W…
bkontur Aug 17, 2023
90dfcfe
Merge remote-tracking branch 'origin/master' into bko-pallet-xcm-remo…
bkontur Aug 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions runtime/kusama/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ use xcm_builder::{
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative,
ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete,
MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents,
WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
MintLocation, OriginToPluralityVoice, ProvideWeighableInstructions, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId,
UniversalWeigherAdapter, UsingComponents, WeightInfoBounds, WithComputedOrigin,
WithUniqueTopic,
};
use xcm_executor::traits::WithOriginFilter;

Expand Down Expand Up @@ -383,6 +384,20 @@ pub type LocalPalletOriginToLocation = (
FellowsToPlurality,
);

/// Helper for adding more instructions to the weight estimation on destination side.
pub struct DestinationWeigherAddons;
impl ProvideWeighableInstructions<()> for DestinationWeigherAddons {
fn provide_for(
_dest: impl Into<MultiLocation>,
_message: &Xcm<()>,
) -> sp_std::vec::Vec<Instruction<()>> {
sp_std::vec![
// runtime uses `WithUniqueTopic` which (possibly) adds `SetTopic` instruction
SetTopic([3; 32])
]
}
}

impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
// We only allow the root, the council, fellows and the staking admin to send messages.
Expand All @@ -401,6 +416,11 @@ impl pallet_xcm::Config for Runtime {
// transfer.
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
bkontur marked this conversation as resolved.
Show resolved Hide resolved
type DestinationWeigher = UniversalWeigherAdapter<
// use local weight for remote message and hope for the best.
FixedWeightBounds<BaseXcmWeight, (), MaxInstructions>,
bkontur marked this conversation as resolved.
Show resolved Hide resolved
DestinationWeigherAddons,
>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
Expand Down
9 changes: 7 additions & 2 deletions runtime/polkadot/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ use xcm_builder::{
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, BackingToPlurality,
ChildParachainAsNative, ChildParachainConvertsVia, CurrencyAdapter as XcmCurrencyAdapter,
FixedWeightBounds, IsConcrete, MintLocation, OriginToPluralityVoice, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
WithComputedOrigin,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UniversalWeigherAdapter,
UsingComponents, WithComputedOrigin,
};
use xcm_executor::traits::WithOriginFilter;

Expand Down Expand Up @@ -408,6 +408,11 @@ impl pallet_xcm::Config for Runtime {
type XcmTeleportFilter = Everything; // == Allow All
type XcmReserveTransferFilter = Everything; // == Allow All
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type DestinationWeigher = UniversalWeigherAdapter<
// use local weight for remote message and hope for the best.
FixedWeightBounds<BaseXcmWeight, (), MaxInstructions>,
(),
>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
Expand Down
26 changes: 23 additions & 3 deletions runtime/rococo/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ use xcm_builder::{
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, BackingToPlurality,
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete,
MintLocation, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin,
WithUniqueTopic,
MintLocation, ProvideWeighableInstructions, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UniversalWeigherAdapter,
UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};

Expand Down Expand Up @@ -351,6 +351,21 @@ pub type LocalOriginToLocation = (
// And a usual Signed origin to be used in XCM as a corresponding AccountId32
SignedToAccountId32<RuntimeOrigin, AccountId, ThisNetwork>,
);

/// Helper for adding more instructions to the weight estimation on destination side.
pub struct DestinationWeigherAddons;
impl ProvideWeighableInstructions<()> for DestinationWeigherAddons {
fn provide_for(
_dest: impl Into<MultiLocation>,
_message: &Xcm<()>,
) -> sp_std::vec::Vec<Instruction<()>> {
sp_std::vec![
// runtime uses `WithUniqueTopic` which (possibly) adds `SetTopic` instruction
SetTopic([3; 32])
]
}
}

impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
Expand All @@ -364,6 +379,11 @@ impl pallet_xcm::Config for Runtime {
// transfer.
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type DestinationWeigher = UniversalWeigherAdapter<
// use local weight for remote message and hope for the best.
FixedWeightBounds<BaseXcmWeight, (), MaxInstructions>,
DestinationWeigherAddons,
>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
Expand Down
16 changes: 9 additions & 7 deletions runtime/test-runtime/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use frame_system::EnsureRoot;
use xcm::latest::prelude::*;
use xcm_builder::{
AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, SignedAccountId32AsNative,
SignedToAccountId32,
SignedToAccountId32, UniversalWeigherAdapter,
};
use xcm_executor::{
traits::{TransactAsset, WeightTrader},
Expand Down Expand Up @@ -127,21 +127,24 @@ impl pallet_xcm::Config for crate::Runtime {
// The config types here are entirely configurable, since the only one that is sorely needed
// is `XcmExecutor`, which will be used in unit tests located in xcm-executor.
type RuntimeEvent = crate::RuntimeEvent;
type ExecuteXcmOrigin = EnsureXcmOrigin<crate::RuntimeOrigin, LocalOriginToLocation>;
type UniversalLocation = UniversalLocation;
type Currency = crate::Balances;
type CurrencyMatcher = ();
type SendXcmOrigin = EnsureXcmOrigin<crate::RuntimeOrigin, LocalOriginToLocation>;
type Weigher = FixedWeightBounds<BaseXcmWeight, crate::RuntimeCall, MaxInstructions>;
type XcmRouter = DoNothingRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin<crate::RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Everything;
type XcmExecutor = xcm_executor::XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, crate::RuntimeCall, MaxInstructions>;
type DestinationWeigher =
UniversalWeigherAdapter<FixedWeightBounds<BaseXcmWeight, (), MaxInstructions>, ()>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = crate::RuntimeOrigin;
type RuntimeCall = crate::RuntimeCall;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
type Currency = crate::Balances;
type CurrencyMatcher = ();
type AdminOrigin = EnsureRoot<crate::AccountId>;
type TrustedLockers = ();
type SovereignAccountOf = ();
type MaxLockers = frame_support::traits::ConstU32<8>;
Expand All @@ -150,5 +153,4 @@ impl pallet_xcm::Config for crate::Runtime {
type WeightInfo = pallet_xcm::TestWeightInfo;
#[cfg(feature = "runtime-benchmarks")]
type ReachableDest = ReachableDest;
type AdminOrigin = EnsureRoot<crate::AccountId>;
}
24 changes: 22 additions & 2 deletions runtime/westend/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ use xcm_builder::{
AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, ChildParachainAsNative,
ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
CurrencyAdapter as XcmCurrencyAdapter, IsChildSystemParachain, IsConcrete, MintLocation,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
ProvideWeighableInstructions, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UniversalWeigherAdapter,
UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic,
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};

Expand Down Expand Up @@ -278,6 +279,20 @@ pub type LocalOriginToLocation = (
SignedToAccountId32<RuntimeOrigin, AccountId, ThisNetwork>,
);

/// Helper for adding more instructions to the weight estimation on destination side.
pub struct DestinationWeigherAddons;
impl ProvideWeighableInstructions<()> for DestinationWeigherAddons {
fn provide_for(
_dest: impl Into<MultiLocation>,
_message: &Xcm<()>,
) -> sp_std::vec::Vec<Instruction<()>> {
sp_std::vec![
// runtime uses `WithUniqueTopic` which (possibly) adds `SetTopic` instruction
SetTopic([3; 32])
]
}
}

impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
Expand All @@ -291,6 +306,11 @@ impl pallet_xcm::Config for Runtime {
type XcmReserveTransferFilter = Everything;
type Weigher =
WeightInfoBounds<weights::xcm::WestendXcmWeight<RuntimeCall>, RuntimeCall, MaxInstructions>;
type DestinationWeigher = UniversalWeigherAdapter<
// use local weight for remote message and hope for the best.
WeightInfoBounds<weights::xcm::WestendXcmWeight<()>, (), MaxInstructions>,
DestinationWeigherAddons,
>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
Expand Down
17 changes: 10 additions & 7 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub use pallet::*;
use xcm_executor::{
traits::{
CheckSuspension, ClaimAssets, ConvertLocation, DropAssets, MatchesFungible, OnResponse,
QueryHandler, QueryResponseStatus, VersionChangeNotifier, WeightBounds,
QueryHandler, QueryResponseStatus, UniversalWeigher, VersionChangeNotifier, WeightBounds,
},
Assets,
};
Expand Down Expand Up @@ -218,6 +218,9 @@ pub mod pallet {
/// Means of measuring the weight consumed by an XCM message locally.
type Weigher: WeightBounds<<Self as SysConfig>::RuntimeCall>;

/// Means of approximating the weight consumed by an XCM message on destination.
bkontur marked this conversation as resolved.
Show resolved Hide resolved
type DestinationWeigher: UniversalWeigher;

/// This chain's Universal Location.
type UniversalLocation: Get<InteriorMultiLocation>;

Expand Down Expand Up @@ -1218,14 +1221,14 @@ impl<T: Config> Pallet<T> {
Some(weight_limit) => weight_limit,
None => {
let fees = fees.clone();
let mut remote_message = Xcm(vec![
let remote_message = Xcm(vec![
ReserveAssetDeposited(assets.clone()),
ClearOrigin,
BuyExecution { fees, weight_limit: Limited(Weight::zero()) },
DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary },
]);
// use local weight for remote message and hope for the best.
let remote_weight = T::Weigher::weight(&mut remote_message)
// estimate remote_message weight
let remote_weight = T::DestinationWeigher::weigh(dest, remote_message)
.map_err(|()| Error::<T>::UnweighableMessage)?;
Limited(remote_weight)
},
Expand Down Expand Up @@ -1278,14 +1281,14 @@ impl<T: Config> Pallet<T> {
Some(weight_limit) => weight_limit,
None => {
let fees = fees.clone();
let mut remote_message = Xcm(vec![
let remote_message = Xcm(vec![
ReceiveTeleportedAsset(assets.clone()),
ClearOrigin,
BuyExecution { fees, weight_limit: Limited(Weight::zero()) },
DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary },
]);
// use local weight for remote message and hope for the best.
let remote_weight = T::Weigher::weight(&mut remote_message)
// estimate remote_message weight
let remote_weight = T::DestinationWeigher::weigh(dest, remote_message)
.map_err(|()| Error::<T>::UnweighableMessage)?;
Limited(remote_weight)
},
Expand Down
15 changes: 13 additions & 2 deletions xcm/pallet-xcm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia,
ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible,
FixedWeightBounds, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit,
FixedWeightBounds, IsConcrete, ProvideWeighableInstructions, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UniversalWeigherAdapter,
};
use xcm_executor::XcmExecutor;

Expand Down Expand Up @@ -324,6 +324,13 @@ parameter_types! {
pub ReachableDest: Option<MultiLocation> = Some(Parachain(1000).into());
}

pub struct AdditionalDestinationInstructions;
impl ProvideWeighableInstructions<()> for AdditionalDestinationInstructions {
fn provide_for(_dest: impl Into<MultiLocation>, _message: &Xcm<()>) -> Vec<Instruction<()>> {
sp_std::vec![SetTopic([13; 32])]
}
}

impl pallet_xcm::Config for Test {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
Expand All @@ -334,6 +341,10 @@ impl pallet_xcm::Config for Test {
type XcmTeleportFilter = Everything;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type DestinationWeigher = UniversalWeigherAdapter<
FixedWeightBounds<BaseXcmWeight, (), MaxInstructions>,
AdditionalDestinationInstructions,
>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
Expand Down
12 changes: 10 additions & 2 deletions xcm/pallet-xcm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,11 @@ fn teleport_assets_works() {
Xcm(vec![
ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()),
ClearOrigin,
buy_limited_execution((Here, SEND_AMOUNT), Weight::from_parts(4000, 4000)),
buy_limited_execution(
(Here, SEND_AMOUNT),
// 4 instruction + AdditionalDestinationInstructions adds 1 instruction
Weight::from_parts(5000, 5000)
),
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
]),
)]
Expand Down Expand Up @@ -511,7 +515,11 @@ fn reserve_transfer_assets_works() {
Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
ClearOrigin,
buy_limited_execution((Parent, SEND_AMOUNT), Weight::from_parts(4000, 4000)),
buy_limited_execution(
(Parent, SEND_AMOUNT),
// 4 instruction + AdditionalDestinationInstructions adds 1 instruction
Weight::from_parts(5000, 5000)
),
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
]),
)]
Expand Down
3 changes: 2 additions & 1 deletion xcm/xcm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ pub use nonfungibles_adapter::{

mod weight;
pub use weight::{
FixedRateOfFungible, FixedWeightBounds, TakeRevenue, UsingComponents, WeightInfoBounds,
FixedRateOfFungible, FixedWeightBounds, ProvideWeighableInstructions, TakeRevenue,
UniversalWeigherAdapter, UsingComponents, WeightInfoBounds,
};

mod matches_token;
Expand Down
35 changes: 33 additions & 2 deletions xcm/xcm-builder/src/weight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ use frame_support::{
};
use parity_scale_codec::Decode;
use sp_runtime::traits::{SaturatedConversion, Saturating, Zero};
use sp_std::{marker::PhantomData, result::Result};
use sp_std::{marker::PhantomData, result::Result, vec::Vec};
use xcm::latest::{prelude::*, Weight};
use xcm_executor::{
traits::{WeightBounds, WeightTrader},
traits::{UniversalWeigher, WeightBounds, WeightTrader},
Assets,
};

Expand Down Expand Up @@ -114,6 +114,37 @@ where
}
}

/// Adapter for `UniversalWeigher` which can estimate weights for XCM message,
bkontur marked this conversation as resolved.
Show resolved Hide resolved
/// that is executed on destination with possibility to add additional instructions on the way (e.g. SetTopic, UniversalOrigin, ...).
pub struct UniversalWeigherAdapter<Weigher, AdditionalInstructions>(
PhantomData<(Weigher, AdditionalInstructions)>,
);
impl<Weigher: WeightBounds<()>, AdditionalInstructions: ProvideWeighableInstructions<()>>
UniversalWeigher for UniversalWeigherAdapter<Weigher, AdditionalInstructions>
{
fn weigh(dest: impl Into<MultiLocation>, mut message: Xcm<()>) -> Result<Weight, ()> {
message.0.extend(AdditionalInstructions::provide_for(dest, &message));
Weigher::weight(&mut message)
}
}

/// Function trait for generating instruction for (dest, message).
pub trait ProvideWeighableInstructions<RuntimeCall> {
fn provide_for(
dest: impl Into<MultiLocation>,
message: &Xcm<RuntimeCall>,
) -> Vec<Instruction<RuntimeCall>>;
}

impl<RuntimeCall> ProvideWeighableInstructions<RuntimeCall> for () {
fn provide_for(
_dest: impl Into<MultiLocation>,
_message: &Xcm<RuntimeCall>,
) -> Vec<Instruction<RuntimeCall>> {
Vec::new()
}
}

/// 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 {
Expand Down
Loading