Skip to content

Commit 118cd6f

Browse files
bkonturacatangiu
andauthored
Ensure outbound XCMs are decodable with limits + add EnsureDecodableXcm router (for testing purposes) (#4186)
This PR: - adds `EnsureDecodableXcm` (testing) router that attempts to *encode* and *decode* passed XCM `message` to ensure that the receiving side will be able to decode, at least with the same XCM version. - fixes `pallet_xcm` / `pallet_xcm_benchmarks` assets data generation Relates to investigation of https://substrate.stackexchange.com/questions/11288 and missing fix #2129 which did not get into the fellows 1.1.X release. ## Questions/TODOs - [x] fix XCM benchmarks, which produces undecodable data - new router catched at least two cases - `BoundedVec exceeds its limit` - `Fungible asset of zero amount is not allowed` - [x] do we need to add `sort` to the `prepend_with` as we did for reanchor [here](#2129)? @serban300 (**created separate/follow-up PR**: #4235) - [x] We added decoding check to `XcmpQueue` -> `validate_xcm_nesting`, why not to added to the `ParentAsUmp` or `ChildParachainRouter`? @franciscoaguirre (**created separate/follow-up PR**: #4236) - [ ] `SendController::send_blob` replace `VersionedXcm::<()>::decode(` with `VersionedXcm::<()>::decode_with_depth_limit(MAX_XCM_DECODE_DEPTH, data)` ? --------- Co-authored-by: Adrian Catangiu <[email protected]>
1 parent 5f2e66f commit 118cd6f

File tree

12 files changed

+70
-50
lines changed

12 files changed

+70
-50
lines changed

Cargo.lock

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

polkadot/runtime/test-runtime/Cargo.toml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,10 @@ license.workspace = true
1111
workspace = true
1212

1313
[dependencies]
14-
bitvec = { version = "1.0.0", default-features = false, features = ["alloc"] }
1514
parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] }
1615
log = { workspace = true }
17-
rustc-hex = { version = "2.1.0", default-features = false }
1816
scale-info = { version = "2.11.1", default-features = false, features = ["derive"] }
1917
serde = { workspace = true }
20-
serde_derive = { optional = true, workspace = true }
21-
smallvec = "1.8.0"
2218

2319
authority-discovery-primitives = { package = "sp-authority-discovery", path = "../../../substrate/primitives/authority-discovery", default-features = false }
2420
babe-primitives = { package = "sp-consensus-babe", path = "../../../substrate/primitives/consensus/babe", default-features = false }
@@ -63,7 +59,6 @@ pallet-vesting = { path = "../../../substrate/frame/vesting", default-features =
6359
runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false }
6460
primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false }
6561
pallet-xcm = { path = "../../xcm/pallet-xcm", default-features = false }
66-
polkadot-parachain-primitives = { path = "../../parachain", default-features = false }
6762
polkadot-runtime-parachains = { path = "../parachains", default-features = false }
6863
xcm-builder = { package = "staging-xcm-builder", path = "../../xcm/xcm-builder", default-features = false }
6964
xcm-executor = { package = "staging-xcm-executor", path = "../../xcm/xcm-executor", default-features = false }
@@ -92,7 +87,6 @@ std = [
9287
"authority-discovery-primitives/std",
9388
"babe-primitives/std",
9489
"beefy-primitives/std",
95-
"bitvec/std",
9690
"block-builder-api/std",
9791
"frame-election-provider-support/std",
9892
"frame-executive/std",
@@ -118,14 +112,11 @@ std = [
118112
"pallet-vesting/std",
119113
"pallet-xcm/std",
120114
"parity-scale-codec/std",
121-
"polkadot-parachain-primitives/std",
122115
"polkadot-runtime-parachains/std",
123116
"primitives/std",
124117
"runtime-common/std",
125-
"rustc-hex/std",
126118
"scale-info/std",
127119
"serde/std",
128-
"serde_derive",
129120
"sp-api/std",
130121
"sp-core/std",
131122
"sp-genesis-builder/std",
@@ -157,7 +148,6 @@ runtime-benchmarks = [
157148
"pallet-timestamp/runtime-benchmarks",
158149
"pallet-vesting/runtime-benchmarks",
159150
"pallet-xcm/runtime-benchmarks",
160-
"polkadot-parachain-primitives/runtime-benchmarks",
161151
"polkadot-runtime-parachains/runtime-benchmarks",
162152
"primitives/runtime-benchmarks",
163153
"runtime-common/runtime-benchmarks",

polkadot/runtime/test-runtime/constants/Cargo.toml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,12 @@ smallvec = "1.8.0"
1414

1515
frame-support = { path = "../../../../substrate/frame/support", default-features = false }
1616
primitives = { package = "polkadot-primitives", path = "../../../primitives", default-features = false }
17-
runtime-common = { package = "polkadot-runtime-common", path = "../../common", default-features = false }
1817
sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false }
19-
sp-weights = { path = "../../../../substrate/primitives/weights", default-features = false }
20-
sp-core = { path = "../../../../substrate/primitives/core", default-features = false }
2118

2219
[features]
2320
default = ["std"]
2421
std = [
2522
"frame-support/std",
2623
"primitives/std",
27-
"runtime-common/std",
28-
"sp-core/std",
2924
"sp-runtime/std",
30-
"sp-weights/std",
3125
]

polkadot/xcm/pallet-xcm-benchmarks/src/fungible/mock.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ use frame_support::{
2323
traits::{Everything, Nothing},
2424
};
2525
use xcm::latest::prelude::*;
26-
use xcm_builder::{AllowUnpaidExecutionFrom, FrameTransactionalProcessor, MintLocation};
26+
use xcm_builder::{
27+
AllowUnpaidExecutionFrom, EnsureDecodableXcm, FrameTransactionalProcessor, MintLocation,
28+
};
2729

2830
type Block = frame_system::mocking::MockBlock<Test>;
2931

@@ -91,7 +93,7 @@ parameter_types! {
9193
pub struct XcmConfig;
9294
impl xcm_executor::Config for XcmConfig {
9395
type RuntimeCall = RuntimeCall;
94-
type XcmSender = DevNull;
96+
type XcmSender = EnsureDecodableXcm<DevNull>;
9597
type AssetTransactor = AssetTransactor;
9698
type OriginConverter = ();
9799
type IsReserve = TrustedReserves;

polkadot/xcm/pallet-xcm-benchmarks/src/generic/mock.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use xcm_builder::{
2828
AssetsInHolding, TestAssetExchanger, TestAssetLocker, TestAssetTrap,
2929
TestSubscriptionService, TestUniversalAliases,
3030
},
31-
AliasForeignAccountId32, AllowUnpaidExecutionFrom, FrameTransactionalProcessor,
31+
AliasForeignAccountId32, AllowUnpaidExecutionFrom, EnsureDecodableXcm,
32+
FrameTransactionalProcessor,
3233
};
3334
use xcm_executor::traits::ConvertOrigin;
3435

@@ -81,7 +82,7 @@ type Aliasers = AliasForeignAccountId32<OnlyParachains>;
8182
pub struct XcmConfig;
8283
impl xcm_executor::Config for XcmConfig {
8384
type RuntimeCall = RuntimeCall;
84-
type XcmSender = DevNull;
85+
type XcmSender = EnsureDecodableXcm<DevNull>;
8586
type AssetTransactor = NoAssetTransactor;
8687
type OriginConverter = AlwaysSignedByDefault<RuntimeOrigin>;
8788
type IsReserve = AllAssetLocationsPass;

polkadot/xcm/pallet-xcm/src/mock.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ use xcm::prelude::*;
3333
use xcm_builder::{
3434
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
3535
AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia,
36-
ChildSystemParachainAsSuperuser, DescribeAllTerminal, FixedRateOfFungible, FixedWeightBounds,
37-
FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, HashedDescription, IsConcrete,
38-
MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, SignedToAccountId32,
39-
SovereignSignedViaLocation, TakeWeightCredit, XcmFeeManagerFromComponents, XcmFeeToAccount,
36+
ChildSystemParachainAsSuperuser, DescribeAllTerminal, EnsureDecodableXcm, FixedRateOfFungible,
37+
FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter,
38+
HashedDescription, IsConcrete, MatchedConvertedConcreteId, NoChecking,
39+
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
40+
XcmFeeManagerFromComponents, XcmFeeToAccount,
4041
};
4142
use xcm_executor::{
4243
traits::{Identity, JustTry},
@@ -488,7 +489,8 @@ pub type Barrier = (
488489
AllowSubscriptionsFrom<Everything>,
489490
);
490491

491-
pub type XcmRouter = (TestPaidForPara3000SendXcm, TestSendXcmErrX8, TestSendXcm);
492+
pub type XcmRouter =
493+
EnsureDecodableXcm<(TestPaidForPara3000SendXcm, TestSendXcmErrX8, TestSendXcm)>;
492494

493495
pub struct XcmConfig;
494496
impl xcm_executor::Config for XcmConfig {

polkadot/xcm/xcm-builder/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ mod process_xcm_message;
119119
pub use process_xcm_message::ProcessXcmMessage;
120120

121121
mod routing;
122-
pub use routing::{EnsureDelivery, WithTopicSource, WithUniqueTopic};
122+
pub use routing::{EnsureDecodableXcm, EnsureDelivery, WithTopicSource, WithUniqueTopic};
123123

124124
mod transactional;
125125
pub use transactional::FrameTransactionalProcessor;

polkadot/xcm/xcm-builder/src/routing.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,37 @@ impl EnsureDelivery for Tuple {
139139
(None, None)
140140
}
141141
}
142+
143+
/// A wrapper router that attempts to *encode* and *decode* passed XCM `message` to ensure that the
144+
/// receiving side will be able to decode, at least with the same XCM version.
145+
///
146+
/// This is designed to be at the top-level of any routers which do the real delivery. While other
147+
/// routers can manipulate the `message`, we cannot access the final XCM due to the generic
148+
/// `Inner::Ticket`. Therefore, this router aims to validate at least the passed `message`.
149+
///
150+
/// NOTE: For use in mock runtimes which don't have the DMP/UMP/HRMP XCM validations.
151+
pub struct EnsureDecodableXcm<Inner>(sp_std::marker::PhantomData<Inner>);
152+
impl<Inner: SendXcm> SendXcm for EnsureDecodableXcm<Inner> {
153+
type Ticket = Inner::Ticket;
154+
155+
fn validate(
156+
destination: &mut Option<Location>,
157+
message: &mut Option<Xcm<()>>,
158+
) -> SendResult<Self::Ticket> {
159+
if let Some(msg) = message {
160+
let versioned_xcm = VersionedXcm::<()>::from(msg.clone());
161+
if versioned_xcm.validate_xcm_nesting().is_err() {
162+
log::error!(
163+
target: "xcm::validate_xcm_nesting",
164+
"EnsureDecodableXcm validate_xcm_nesting error for \nversioned_xcm: {versioned_xcm:?}\nbased on xcm: {msg:?}"
165+
);
166+
return Err(SendError::Transport("EnsureDecodableXcm validate_xcm_nesting error"))
167+
}
168+
}
169+
Inner::validate(destination, message)
170+
}
171+
172+
fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
173+
Inner::deliver(ticket)
174+
}
175+
}

polkadot/xcm/xcm-builder/src/tests/mock.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use crate::{
2020
barriers::{AllowSubscriptionsFrom, RespectSuspension, TrailingSetTopicAsId},
2121
test_utils::*,
22+
EnsureDecodableXcm,
2223
};
2324
pub use crate::{
2425
AliasForeignAccountId32, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
@@ -165,8 +166,8 @@ pub fn set_exporter_override(
165166
pub fn clear_exporter_override() {
166167
EXPORTER_OVERRIDE.with(|x| x.replace(None));
167168
}
168-
pub struct TestMessageSender;
169-
impl SendXcm for TestMessageSender {
169+
pub struct TestMessageSenderImpl;
170+
impl SendXcm for TestMessageSenderImpl {
170171
type Ticket = (Location, Xcm<()>, XcmHash);
171172
fn validate(
172173
dest: &mut Option<Location>,
@@ -183,6 +184,8 @@ impl SendXcm for TestMessageSender {
183184
Ok(hash)
184185
}
185186
}
187+
pub type TestMessageSender = EnsureDecodableXcm<TestMessageSenderImpl>;
188+
186189
pub struct TestMessageExporter;
187190
impl ExportXcm for TestMessageExporter {
188191
type Ticket = (NetworkId, u32, InteriorLocation, InteriorLocation, Xcm<()>, XcmHash);

polkadot/xcm/xcm-builder/tests/mock/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ use staging_xcm_builder as xcm_builder;
3535
use xcm_builder::{
3636
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
3737
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
38-
FixedRateOfFungible, FixedWeightBounds, FungibleAdapter, IsChildSystemParachain, IsConcrete,
39-
MintLocation, RespectSuspension, SignedAccountId32AsNative, SignedToAccountId32,
40-
SovereignSignedViaLocation, TakeWeightCredit,
38+
EnsureDecodableXcm, FixedRateOfFungible, FixedWeightBounds, FungibleAdapter,
39+
IsChildSystemParachain, IsConcrete, MintLocation, RespectSuspension, SignedAccountId32AsNative,
40+
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
4141
};
4242

4343
pub type AccountId = AccountId32;
@@ -68,6 +68,8 @@ impl SendXcm for TestSendXcm {
6868
}
6969
}
7070

71+
pub type TestXcmRouter = EnsureDecodableXcm<TestSendXcm>;
72+
7173
// copied from kusama constants
7274
pub const UNITS: Balance = 1_000_000_000_000;
7375
pub const CENTS: Balance = UNITS / 30_000;
@@ -180,7 +182,7 @@ pub type TrustedTeleporters = (xcm_builder::Case<KusamaForAssetHub>,);
180182
pub struct XcmConfig;
181183
impl xcm_executor::Config for XcmConfig {
182184
type RuntimeCall = RuntimeCall;
183-
type XcmSender = TestSendXcm;
185+
type XcmSender = TestXcmRouter;
184186
type AssetTransactor = LocalAssetTransactor;
185187
type OriginConverter = LocalOriginConverter;
186188
type IsReserve = ();
@@ -215,7 +217,7 @@ impl pallet_xcm::Config for Runtime {
215217
type RuntimeEvent = RuntimeEvent;
216218
type UniversalLocation = UniversalLocation;
217219
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
218-
type XcmRouter = TestSendXcm;
220+
type XcmRouter = TestXcmRouter;
219221
// Anyone can execute XCM messages locally...
220222
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
221223
type XcmExecuteFilter = Nothing;

polkadot/xcm/xcm-simulator/example/src/parachain.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ use polkadot_parachain_primitives::primitives::{
4040
use xcm::{latest::prelude::*, VersionedXcm};
4141
use xcm_builder::{
4242
Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, ConvertedConcreteId,
43-
EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor,
44-
FungibleAdapter, IsConcrete, NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset,
45-
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
46-
SovereignSignedViaLocation,
43+
EnsureDecodableXcm, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds,
44+
FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, NoChecking,
45+
NonFungiblesAdapter, ParentIsPreset, SiblingParachainConvertsVia, SignedAccountId32AsNative,
46+
SignedToAccountId32, SovereignSignedViaLocation,
4747
};
4848
use xcm_executor::{
4949
traits::{ConvertLocation, JustTry},
@@ -212,7 +212,7 @@ pub type LocalAssetTransactor = (
212212
>,
213213
);
214214

215-
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
215+
pub type XcmRouter = EnsureDecodableXcm<super::ParachainXcmRouter<MsgQueue>>;
216216
pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
217217

218218
parameter_types! {

polkadot/xcm/xcm-simulator/example/src/relay_chain.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ use xcm::latest::prelude::*;
3636
use xcm_builder::{
3737
Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex,
3838
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
39-
ConvertedConcreteId, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor,
40-
FungibleAdapter, IsConcrete, NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative,
41-
SignedToAccountId32, SovereignSignedViaLocation,
39+
ConvertedConcreteId, EnsureDecodableXcm, FixedRateOfFungible, FixedWeightBounds,
40+
FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NoChecking, NonFungiblesAdapter,
41+
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
4242
};
4343
use xcm_executor::{traits::JustTry, Config, XcmExecutor};
4444

@@ -168,7 +168,7 @@ parameter_types! {
168168
pub const MaxAssetsIntoHolding: u32 = 64;
169169
}
170170

171-
pub type XcmRouter = super::RelayChainXcmRouter;
171+
pub type XcmRouter = EnsureDecodableXcm<super::RelayChainXcmRouter>;
172172
pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
173173

174174
pub struct XcmConfig;

0 commit comments

Comments
 (0)