mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-17 21:51:06 +00:00
Add validate_xcm_nesting to the ParentAsUmp and ChildParachainRouter (#4236)
This PR: - moves `validate_xcm_nesting` from `XcmpQueue` into the `VersionedXcm` - adds `validate_xcm_nesting` to the `ParentAsUmp` - adds `validate_xcm_nesting` to the `ChildParachainRouter` Based on discussion [here](https://github.com/paritytech/polkadot-sdk/pull/4186#discussion_r1571344270) and/or [here](https://github.com/paritytech/polkadot-sdk/pull/4186#discussion_r1572076666) and/or [here]() ## Question/TODO - [x] To the [comment](https://github.com/paritytech/polkadot-sdk/pull/4186#discussion_r1572072295) - Why was `validate_xcm_nesting` added just to the `XcmpQueue` router and nowhere else? What kind of problem `MAX_XCM_DECODE_DEPTH` is solving? (see [comment](https://github.com/paritytech/polkadot-sdk/pull/4236#discussion_r1574605191))
This commit is contained in:
@@ -916,7 +916,8 @@ impl<T: Config> SendXcm for Pallet<T> {
|
||||
let price = T::PriceForSiblingDelivery::price_for_delivery(id, &xcm);
|
||||
let versioned_xcm = T::VersionWrapper::wrap_version(&d, xcm)
|
||||
.map_err(|()| SendError::DestinationUnsupported)?;
|
||||
validate_xcm_nesting(&versioned_xcm)
|
||||
versioned_xcm
|
||||
.validate_xcm_nesting()
|
||||
.map_err(|()| SendError::ExceedsMaxMessageSize)?;
|
||||
|
||||
Ok(((id, versioned_xcm), price))
|
||||
@@ -932,10 +933,6 @@ impl<T: Config> SendXcm for Pallet<T> {
|
||||
|
||||
fn deliver((id, xcm): (ParaId, VersionedXcm<()>)) -> Result<XcmHash, SendError> {
|
||||
let hash = xcm.using_encoded(sp_io::hashing::blake2_256);
|
||||
defensive_assert!(
|
||||
validate_xcm_nesting(&xcm).is_ok(),
|
||||
"Tickets are valid prior to delivery by trait XCM; qed"
|
||||
);
|
||||
|
||||
match Self::send_fragment(id, XcmpMessageFormat::ConcatenatedVersionedXcm, xcm) {
|
||||
Ok(_) => {
|
||||
@@ -950,16 +947,6 @@ impl<T: Config> SendXcm for Pallet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the XCM is decodable with `MAX_XCM_DECODE_DEPTH`.
|
||||
///
|
||||
/// Note that this uses the limit of the sender - not the receiver. It it best effort.
|
||||
pub(crate) fn validate_xcm_nesting(xcm: &VersionedXcm<()>) -> Result<(), ()> {
|
||||
xcm.using_encoded(|mut enc| {
|
||||
VersionedXcm::<()>::decode_all_with_depth_limit(MAX_XCM_DECODE_DEPTH, &mut enc).map(|_| ())
|
||||
})
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
||||
impl<T: Config> FeeTracker for Pallet<T> {
|
||||
type Id = ParaId;
|
||||
|
||||
|
||||
@@ -1519,27 +1519,23 @@ impl_runtime_apis! {
|
||||
fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets {
|
||||
// A mix of fungible, non-fungible, and concrete assets.
|
||||
let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count;
|
||||
let holding_fungibles = holding_non_fungibles.saturating_sub(1);
|
||||
let holding_fungibles = holding_non_fungibles.saturating_sub(2); // -2 for two `iter::once` bellow
|
||||
let fungibles_amount: u128 = 100;
|
||||
let mut assets = (0..holding_fungibles)
|
||||
(0..holding_fungibles)
|
||||
.map(|i| {
|
||||
Asset {
|
||||
id: GeneralIndex(i as u128).into(),
|
||||
fun: Fungible(fungibles_amount * i as u128),
|
||||
fun: Fungible(fungibles_amount * (i + 1) as u128), // non-zero amount
|
||||
}
|
||||
})
|
||||
.chain(core::iter::once(Asset { id: Here.into(), fun: Fungible(u128::MAX) }))
|
||||
.chain(core::iter::once(Asset { id: AssetId(TokenLocation::get()), fun: Fungible(1_000_000 * UNITS) }))
|
||||
.chain((0..holding_non_fungibles).map(|i| Asset {
|
||||
id: GeneralIndex(i as u128).into(),
|
||||
fun: NonFungible(asset_instance_from(i)),
|
||||
}))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assets.push(Asset {
|
||||
id: AssetId(TokenLocation::get()),
|
||||
fun: Fungible(1_000_000 * UNITS),
|
||||
});
|
||||
assets.into()
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1610,27 +1610,23 @@ impl_runtime_apis! {
|
||||
fn worst_case_holding(depositable_count: u32) -> xcm::v4::Assets {
|
||||
// A mix of fungible, non-fungible, and concrete assets.
|
||||
let holding_non_fungibles = MaxAssetsIntoHolding::get() / 2 - depositable_count;
|
||||
let holding_fungibles = holding_non_fungibles - 1;
|
||||
let holding_fungibles = holding_non_fungibles - 2; // -2 for two `iter::once` bellow
|
||||
let fungibles_amount: u128 = 100;
|
||||
let mut assets = (0..holding_fungibles)
|
||||
(0..holding_fungibles)
|
||||
.map(|i| {
|
||||
Asset {
|
||||
id: AssetId(GeneralIndex(i as u128).into()),
|
||||
fun: Fungible(fungibles_amount * i as u128),
|
||||
fun: Fungible(fungibles_amount * (i + 1) as u128), // non-zero amount
|
||||
}
|
||||
})
|
||||
.chain(core::iter::once(Asset { id: AssetId(Here.into()), fun: Fungible(u128::MAX) }))
|
||||
.chain(core::iter::once(Asset { id: AssetId(WestendLocation::get()), fun: Fungible(1_000_000 * UNITS) }))
|
||||
.chain((0..holding_non_fungibles).map(|i| Asset {
|
||||
id: AssetId(GeneralIndex(i as u128).into()),
|
||||
fun: NonFungible(asset_instance_from(i)),
|
||||
}))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assets.push(Asset {
|
||||
id: AssetId(WestendLocation::get()),
|
||||
fun: Fungible(1_000_000 * UNITS),
|
||||
});
|
||||
assets.into()
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,9 @@ where
|
||||
let price = P::price_for_delivery((), &xcm);
|
||||
let versioned_xcm =
|
||||
W::wrap_version(&d, xcm).map_err(|()| SendError::DestinationUnsupported)?;
|
||||
versioned_xcm
|
||||
.validate_xcm_nesting()
|
||||
.map_err(|()| SendError::ExceedsMaxMessageSize)?;
|
||||
let data = versioned_xcm.encode();
|
||||
|
||||
Ok((data, price))
|
||||
@@ -526,6 +529,8 @@ impl<
|
||||
mod test_xcm_router {
|
||||
use super::*;
|
||||
use cumulus_primitives_core::UpwardMessage;
|
||||
use frame_support::assert_ok;
|
||||
use xcm::MAX_XCM_DECODE_DEPTH;
|
||||
|
||||
/// Validates [`validate`] for required Some(destination) and Some(message)
|
||||
struct OkFixedXcmHashWithAssertingRequiredInputsSender;
|
||||
@@ -621,6 +626,29 @@ mod test_xcm_router {
|
||||
)>(dest.into(), message)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parent_as_ump_validate_nested_xcm_works() {
|
||||
let dest = Parent;
|
||||
|
||||
type Router = ParentAsUmp<(), (), ()>;
|
||||
|
||||
// Message that is not too deeply nested:
|
||||
let mut good = Xcm(vec![ClearOrigin]);
|
||||
for _ in 0..MAX_XCM_DECODE_DEPTH - 1 {
|
||||
good = Xcm(vec![SetAppendix(good)]);
|
||||
}
|
||||
|
||||
// Check that the good message is validated:
|
||||
assert_ok!(<Router as SendXcm>::validate(&mut Some(dest.into()), &mut Some(good.clone())));
|
||||
|
||||
// Nesting the message one more time should reject it:
|
||||
let bad = Xcm(vec![SetAppendix(good)]);
|
||||
assert_eq!(
|
||||
Err(SendError::ExceedsMaxMessageSize),
|
||||
<Router as SendXcm>::validate(&mut Some(dest.into()), &mut Some(bad))
|
||||
);
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod test_trader {
|
||||
|
||||
Reference in New Issue
Block a user