Add environmental variable to track decoded instructions (#1320)

* Add environmental variable to track decoded instructions

* Fix doc tests

* Fix manifest formatting

* ".git/.scripts/commands/fmt/fmt.sh"

* Add one more test

* Add SetAppendix in test

---------

Co-authored-by: command-bot <>
This commit is contained in:
Francisco Aguirre
2023-08-31 13:42:32 -03:00
committed by GitHub
parent aedd280874
commit 995d81fd84
14 changed files with 71 additions and 38 deletions
Generated
+1
View File
@@ -17910,6 +17910,7 @@ version = "1.0.0"
dependencies = [
"bounded-collections",
"derivative",
"environmental",
"hex",
"hex-literal 0.4.1",
"impl-trait-for-tuples",
+2
View File
@@ -16,6 +16,7 @@ scale-info = { version = "2.5.0", default-features = false, features = ["derive"
sp-weights = { path = "../../substrate/primitives/weights", default-features = false, features = ["serde"] }
serde = { version = "1.0.188", default-features = false, features = ["alloc", "derive"] }
xcm-procedural = { path = "procedural" }
environmental = { version = "1.1.4", default-features = false }
[dev-dependencies]
sp-io = { path = "../../substrate/primitives/io" }
@@ -27,6 +28,7 @@ default = [ "std" ]
wasm-api = []
std = [
"bounded-collections/std",
"environmental/std",
"parity-scale-codec/std",
"scale-info/std",
"serde/std",
+2 -1
View File
@@ -20,7 +20,8 @@
// necessarily related to FRAME or even Substrate.
//
// Hence, `no_std` rather than sp-runtime.
#![no_std]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use derivative::Derivative;
+6 -6
View File
@@ -238,7 +238,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # fn main() {
/// let mut m = MultiLocation::new(1, X2(PalletInstance(3), OnlyChild));
/// assert_eq!(
@@ -260,7 +260,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// let m = MultiLocation::new(1, X3(PalletInstance(3), OnlyChild, OnlyChild));
/// assert!(m.starts_with(&MultiLocation::new(1, X1(PalletInstance(3)))));
/// assert!(!m.starts_with(&MultiLocation::new(1, X1(GeneralIndex(99)))));
@@ -279,7 +279,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # fn main() {
/// let mut m = MultiLocation::new(1, X1(Parachain(21)));
/// assert_eq!(m.append_with(X1(PalletInstance(3))), Ok(()));
@@ -302,7 +302,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # use staging_xcm::v2::{Junctions::*, Junction::*, MultiLocation};
/// # fn main() {
/// let mut m = MultiLocation::new(2, X1(PalletInstance(3)));
/// assert_eq!(m.prepend_with(MultiLocation::new(1, X2(Parachain(21), OnlyChild))), Ok(()));
@@ -839,7 +839,7 @@ impl Junctions {
///
/// # Example
/// ```rust
/// # use xcm::v2::{Junctions::*, Junction::*};
/// # use staging_xcm::v2::{Junctions::*, Junction::*};
/// # fn main() {
/// let mut m = X3(Parachain(2), PalletInstance(3), OnlyChild);
/// assert_eq!(m.match_and_split(&X2(Parachain(2), PalletInstance(3))), Some(&OnlyChild));
@@ -857,7 +857,7 @@ impl Junctions {
///
/// # Example
/// ```rust
/// # use xcm::v2::{Junctions::*, Junction::*};
/// # use staging_xcm::v2::{Junctions::*, Junction::*};
/// let mut j = X3(Parachain(2), PalletInstance(3), OnlyChild);
/// assert!(j.starts_with(&X2(Parachain(2), PalletInstance(3))));
/// assert!(j.starts_with(&j));
+1 -1
View File
@@ -278,7 +278,7 @@ pub type SendResult = result::Result<(), SendError>;
///
/// # Example
/// ```rust
/// # use xcm::v2::prelude::*;
/// # use staging_xcm::v2::prelude::*;
/// # use parity_scale_codec::Encode;
///
/// /// A sender that only passes the message through and does nothing.
+2 -2
View File
@@ -437,7 +437,7 @@ impl Junctions {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation};
/// # use staging_xcm::v3::{Junctions::*, Junction::*, MultiLocation};
/// # fn main() {
/// let mut m = X1(Parachain(21));
/// assert_eq!(m.append_with(X1(PalletInstance(3))), Ok(()));
@@ -568,7 +568,7 @@ impl Junctions {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*};
/// # use staging_xcm::v3::{Junctions::*, Junction::*};
/// # fn main() {
/// let mut m = X3(Parachain(2), PalletInstance(3), OnlyChild);
/// assert_eq!(m.match_and_split(&X2(Parachain(2), PalletInstance(3))), Some(&OnlyChild));
+44 -15
View File
@@ -22,7 +22,7 @@ use super::v2::{
};
use crate::DoubleEncoded;
use alloc::{vec, vec::Vec};
use bounded_collections::{parameter_types, BoundedVec, ConstU32};
use bounded_collections::{parameter_types, BoundedVec};
use core::{
convert::{TryFrom, TryInto},
fmt::Debug,
@@ -30,7 +30,8 @@ use core::{
};
use derivative::Derivative;
use parity_scale_codec::{
self, Decode, Encode, Error as CodecError, Input as CodecInput, MaxEncodedLen,
self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
MaxEncodedLen,
};
use scale_info::TypeInfo;
@@ -69,13 +70,25 @@ pub type QueryId = u64;
#[scale_info(bounds(), skip_type_params(Call))]
pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
const MAX_INSTRUCTIONS_TO_DECODE: u32 = 100;
const MAX_INSTRUCTIONS_TO_DECODE: u8 = 100;
environmental::environmental!(instructions_count: u8);
impl<Call> Decode for Xcm<Call> {
fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
let bounded_instructions =
BoundedVec::<Instruction<Call>, ConstU32<MAX_INSTRUCTIONS_TO_DECODE>>::decode(input)?;
Ok(Self(bounded_instructions.into_inner()))
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))
})
}
}
@@ -1441,15 +1454,31 @@ mod tests {
}
#[test]
fn decoding_fails_when_too_many_instructions() {
let small_xcm = Xcm::<()>(vec![ClearOrigin; 20]);
let bytes = small_xcm.encode();
let decoded_xcm = Xcm::<()>::decode(&mut &bytes[..]);
assert!(matches!(decoded_xcm, Ok(_)));
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; 64_000]);
let bytes = big_xcm.encode();
let decoded_xcm = Xcm::<()>::decode(&mut &bytes[..]);
assert!(matches!(decoded_xcm, Err(CodecError { .. })));
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_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(), 342530);
// This should not decode since the limit is 100
assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
}
}
+5 -5
View File
@@ -265,7 +265,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation};
/// # use staging_xcm::v3::{Junctions::*, Junction::*, MultiLocation};
/// # fn main() {
/// let mut m = MultiLocation::new(1, X2(PalletInstance(3), OnlyChild));
/// assert_eq!(
@@ -292,7 +292,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # use staging_xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # fn main() {
/// let mut m: MultiLocation = (Parent, Parachain(21), 69u64).into();
/// assert_eq!(m.append_with((Parent, PalletInstance(3))), Ok(()));
@@ -313,7 +313,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # use staging_xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # fn main() {
/// let mut m: MultiLocation = (Parent, Parachain(21), 69u64).into();
/// let r = m.appended_with((Parent, PalletInstance(3))).unwrap();
@@ -333,7 +333,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # use staging_xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # fn main() {
/// let mut m: MultiLocation = (Parent, Parent, PalletInstance(3)).into();
/// assert_eq!(m.prepend_with((Parent, Parachain(21), OnlyChild)), Ok(()));
@@ -382,7 +382,7 @@ impl MultiLocation {
///
/// # Example
/// ```rust
/// # use xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # use staging_xcm::v3::{Junctions::*, Junction::*, MultiLocation, Parent};
/// # fn main() {
/// let m: MultiLocation = (Parent, Parent, PalletInstance(3)).into();
/// let r = m.prepended_with((Parent, Parachain(21), OnlyChild)).unwrap();
+2 -2
View File
@@ -449,8 +449,8 @@ pub type SendResult<T> = result::Result<(T, MultiAssets), SendError>;
/// # Example
/// ```rust
/// # use parity_scale_codec::Encode;
/// # use xcm::v3::{prelude::*, Weight};
/// # use xcm::VersionedXcm;
/// # use staging_xcm::v3::{prelude::*, Weight};
/// # use staging_xcm::VersionedXcm;
/// # use std::convert::Infallible;
///
/// /// A sender that only passes the message through and does nothing.
@@ -53,7 +53,7 @@ impl From<Error> for XcmError {
/// use frame_support::{parameter_types, PalletId};
/// use sp_runtime::traits::{AccountIdConversion, TrailingZeroInput};
/// use xcm::latest::prelude::*;
/// use xcm_builder::{ParentIsPreset, CurrencyAdapter, IsConcrete};
/// use staging_xcm_builder::{ParentIsPreset, CurrencyAdapter, IsConcrete};
///
/// /// Our chain's account id.
/// type AccountId = sp_runtime::AccountId32;
+1 -1
View File
@@ -50,7 +50,7 @@ impl<'a, Call> CreateMatcher for &'a mut [Instruction<Call>] {
/// ```rust
/// use frame_support::traits::ProcessMessageError;
/// use xcm::latest::Instruction;
/// use xcm_builder::{CreateMatcher, MatchXcm};
/// use staging_xcm_builder::{CreateMatcher, MatchXcm};
///
/// let mut msg = [Instruction::<()>::ClearOrigin];
/// let res = msg
@@ -33,7 +33,7 @@ use xcm_executor::traits::{MatchesFungible, MatchesNonFungible};
///
/// ```
/// use xcm::latest::{MultiLocation, Parent};
/// use xcm_builder::IsConcrete;
/// use staging_xcm_builder::IsConcrete;
/// use xcm_executor::traits::MatchesFungible;
///
/// frame_support::parameter_types! {
@@ -71,7 +71,7 @@ impl<T: Get<MultiLocation>, I: TryFrom<AssetInstance>> MatchesNonFungible<I> for
///
/// ```
/// use xcm::latest::prelude::*;
/// use xcm_builder::IsAbstract;
/// use staging_xcm_builder::IsAbstract;
/// use xcm_executor::traits::{MatchesFungible, MatchesNonFungible};
///
/// frame_support::parameter_types! {
+1 -1
View File
@@ -446,7 +446,7 @@ impl Assets {
/// Example:
///
/// ```
/// use xcm_executor::Assets;
/// use staging_xcm_executor::Assets;
/// use xcm::latest::prelude::*;
/// let assets_i_have: Assets = vec![ (Here, 100).into(), ([0; 32], 100).into() ].into();
/// let assets_they_want: MultiAssetFilter = vec![ (Here, 200).into(), ([0; 32], 50).into() ].into();
@@ -46,7 +46,7 @@ impl<AccountId> ConvertLocation<AccountId> for Tuple {
///
/// ```rust
/// # use xcm::latest::{MultiLocation, Junctions, Junction, OriginKind};
/// # use xcm_executor::traits::ConvertOrigin;
/// # use staging_xcm_executor::traits::ConvertOrigin;
/// // A convertor that will bump the para id and pass it to the next one.
/// struct BumpParaId;
/// impl ConvertOrigin<u32> for BumpParaId {