Skip to content
Snippets Groups Projects
Unverified Commit 9403a5d4 authored by Francisco Aguirre's avatar Francisco Aguirre Committed by GitHub
Browse files

Add `MAX_INSTRUCTIONS_TO_DECODE` to XCMv2 (#4978)

It was added to v4 and v3 but was missing from v2
parent 2f0e5a61
No related merge requests found
Pipeline #484504 waiting for manual action with stages
in 1 hour, 8 minutes, and 57 seconds
......@@ -62,7 +62,10 @@ use super::{
};
use alloc::{vec, vec::Vec};
use bounded_collections::{ConstU32, WeakBoundedVec};
use codec::{self, Decode, Encode, MaxEncodedLen};
use codec::{
self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
MaxEncodedLen,
};
use core::{fmt::Debug, result};
use derivative::Derivative;
use scale_info::TypeInfo;
......@@ -278,7 +281,7 @@ pub const VERSION: super::Version = 2;
pub type QueryId = u64;
/// DEPRECATED. Please use XCMv3 or XCMv4 instead.
#[derive(Derivative, Default, Encode, Decode, TypeInfo)]
#[derive(Derivative, Default, Encode, TypeInfo)]
#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
#[codec(encode_bound())]
#[codec(decode_bound())]
......@@ -286,6 +289,31 @@ pub type QueryId = u64;
#[scale_info(replace_segment("staging_xcm", "xcm"))]
pub struct Xcm<RuntimeCall>(pub Vec<Instruction<RuntimeCall>>);
environmental::environmental!(instructions_count: u8);
impl<Call> Decode for Xcm<Call> {
fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
instructions_count::using_once(&mut 0, || {
let number_of_instructions: u32 = <Compact<u32>>::decode(input)?.into();
instructions_count::with(|count| {
*count = count.saturating_add(number_of_instructions as u8);
if *count > MAX_INSTRUCTIONS_TO_DECODE {
return Err(CodecError::from("Max instructions exceeded"))
}
Ok(())
})
.unwrap_or(Ok(()))?;
let decoded_instructions = decode_vec_with_len(input, number_of_instructions as usize)?;
Ok(Self(decoded_instructions))
})
}
}
/// The maximal number of instructions in an XCM before decoding fails.
///
/// This is a deliberate limit - not a technical one.
pub const MAX_INSTRUCTIONS_TO_DECODE: u8 = 100;
impl<RuntimeCall> Xcm<RuntimeCall> {
/// Create an empty instance.
pub fn new() -> Self {
......@@ -1157,3 +1185,38 @@ impl<RuntimeCall> TryFrom<NewInstruction<RuntimeCall>> for Instruction<RuntimeCa
})
}
}
#[cfg(test)]
mod tests {
use super::{prelude::*, *};
#[test]
fn decoding_respects_limit() {
let max_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize]);
let encoded = max_xcm.encode();
assert!(Xcm::<()>::decode(&mut &encoded[..]).is_ok());
let big_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize + 1]);
let encoded = big_xcm.encode();
assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
let nested_xcm = Xcm::<()>(vec![
DepositReserveAsset {
assets: All.into(),
dest: Here.into(),
xcm: max_xcm,
max_assets: 1,
};
(MAX_INSTRUCTIONS_TO_DECODE / 2) as usize
]);
let encoded = nested_xcm.encode();
assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm); 64]);
let encoded = even_more_nested_xcm.encode();
assert_eq!(encoded.len(), 345730);
// This should not decode since the limit is 100
assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
}
}
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
title: Add MAX_INSTRUCTIONS_TO_DECODE to XCMv2
doc:
- audience: Runtime User
description: |
Added a max number of instructions to XCMv2. If using XCMv2, you'll have to take this limit into account.
It was set to 100.
- audience: Runtime Dev
description: |
Added a max number of instructions to XCMv2. If using XCMv2, you'll have to take this limit into account.
It was set to 100.
crates:
- name: staging-xcm
bump: minor
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment