Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add try_state and integrity_test to XCM simulator fuzzer #3222

Merged
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions polkadot/xcm/xcm-simulator/fuzzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ scale-info = { version = "2.10.0", features = ["derive"] }

frame-system = { path = "../../../../substrate/frame/system" }
frame-support = { path = "../../../../substrate/frame/support" }
frame-executive = { path = "../../../../substrate/frame/executive" }
frame-try-runtime = { path = "../../../../substrate/frame/try-runtime" }
pallet-balances = { path = "../../../../substrate/frame/balances" }
pallet-message-queue = { path = "../../../../substrate/frame/message-queue" }
sp-std = { path = "../../../../substrate/primitives/std" }
sp-core = { path = "../../../../substrate/primitives/core" }
sp-runtime = { path = "../../../../substrate/primitives/runtime" }
sp-io = { path = "../../../../substrate/primitives/io" }
sp-api = { path = "../../../../substrate/primitives/api" }
sp-version = { path = "../../../../substrate/primitives/version" }

xcm = { package = "staging-xcm", path = "../.." }
xcm-simulator = { path = ".." }
Expand All @@ -35,6 +39,18 @@ polkadot-runtime-parachains = { path = "../../../runtime/parachains" }
polkadot-parachain-primitives = { path = "../../../parachain" }

[features]
default = ["try-runtime"]
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
try-runtime = [
"frame-support/try-runtime",
"frame-try-runtime/try-runtime",
"frame-executive/try-runtime",
"frame-system/try-runtime",
"pallet-balances/try-runtime",
"pallet-message-queue/try-runtime",
"pallet-xcm/try-runtime",
"polkadot-runtime-parachains/try-runtime",
"sp-runtime/try-runtime",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
Expand Down
47 changes: 44 additions & 3 deletions polkadot/xcm/xcm-simulator/fuzzer/src/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ use polkadot_parachain_primitives::primitives::Id as ParaId;
use sp_runtime::{traits::AccountIdConversion, BuildStorage};
use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt};

use frame_support::assert_ok;
use frame_support::{
assert_ok,
traits::{IntegrityTest, TryState, TryStateSelect::All},
};
use xcm::{latest::prelude::*, MAX_XCM_DECODE_DEPTH};

use arbitrary::{Arbitrary, Error, Unstructured};
Expand Down Expand Up @@ -98,7 +101,7 @@ impl<'a> Arbitrary<'a> for XcmMessage {
if let Ok(message) =
DecodeLimit::decode_with_depth_limit(MAX_XCM_DECODE_DEPTH, &mut encoded_message)
{
return Ok(XcmMessage { source, destination, message })
return Ok(XcmMessage { source, destination, message });
}
Err(Error::IncorrectFormat)
}
Expand Down Expand Up @@ -148,13 +151,39 @@ pub fn relay_ext() -> sp_io::TestExternalities {
pub type RelayChainPalletXcm = pallet_xcm::Pallet<relay_chain::Runtime>;
pub type ParachainPalletXcm = pallet_xcm::Pallet<parachain::Runtime>;

// We check XCM messages recursively for blocklisted messages
fn recursively_matches_blocklisted_messages(message: &mut Instruction<()>) -> bool {
match message {
DepositReserveAsset { xcm, .. } |
ExportMessage { xcm, .. } |
InitiateReserveWithdraw { xcm, .. } |
InitiateTeleport { xcm, .. } |
TransferReserveAsset { xcm, .. } |
SetErrorHandler(xcm) |
SetAppendix(xcm) =>
Vec::from(xcm.inner()).iter_mut().any(recursively_matches_blocklisted_messages),
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
// The blocklisted message is the Transact instruction.
m => matches!(m, Transact { .. }),
}
}

fn run_input(xcm_messages: [XcmMessage; 5]) {
MockNet::reset();

#[cfg(not(fuzzing))]
println!();

for xcm_message in xcm_messages {
if xcm_message
.message
.clone()
.iter_mut()
.any(recursively_matches_blocklisted_messages)
{
println!(" skipping message\n");
continue;
}

if xcm_message.source % 4 == 0 {
// We get the destination for the message
let parachain_id = (xcm_message.destination % 3) + 1;
Expand Down Expand Up @@ -197,8 +226,20 @@ fn run_input(xcm_messages: [XcmMessage; 5]) {
}
#[cfg(not(fuzzing))]
println!();
// We run integrity tests and try_runtime invariants
[ParaA::execute_with, ParaB::execute_with, ParaC::execute_with].iter().for_each(
|execute_with| {
execute_with(|| {
parachain::AllPalletsWithSystem::try_state(Default::default(), All).unwrap();
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
parachain::AllPalletsWithSystem::integrity_test();
});
},
);
Relay::execute_with(|| {
relay_chain::AllPalletsWithSystem::try_state(Default::default(), All).unwrap();
relay_chain::AllPalletsWithSystem::integrity_test();
});
}
Relay::execute_with(|| {});
}

fn main() {
Expand Down
107 changes: 80 additions & 27 deletions polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ use frame_support::{
};

use frame_system::EnsureRoot;
use sp_core::{ConstU32, H256};
use sp_core::ConstU32;
use sp_runtime::{
traits::{Hash, IdentityLookup},
AccountId32,
create_runtime_str, generic,
traits::{AccountIdLookup, BlakeTwo256, Hash, IdentifyAccount, Verify},
MultiAddress, MultiSignature,
};
use sp_std::prelude::*;

Expand All @@ -36,6 +37,7 @@ use polkadot_core_primitives::BlockNumber as RelayBlockNumber;
use polkadot_parachain_primitives::primitives::{
DmpMessageHandler, Id as ParaId, Sibling, XcmpMessageFormat, XcmpMessageHandler,
};
use sp_version::RuntimeVersion;
use xcm::{latest::prelude::*, VersionedXcm};
#[allow(deprecated)]
use xcm_builder::CurrencyAdapter as XcmCurrencyAdapter;
Expand All @@ -47,38 +49,41 @@ use xcm_builder::{
};
use xcm_executor::{Config, XcmExecutor};

pub type AccountId = AccountId32;
pub type SignedExtra = (frame_system::CheckNonZeroSender<Runtime>,);

pub type BlockNumber = u64;
pub type Address = MultiAddress<AccountId, ()>;
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
pub type UncheckedExtrinsic =
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;

pub type Signature = MultiSignature;
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
pub type Balance = u128;

#[allow(unused_parens)]
type Migrations = ();

pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
Migrations,
>;

parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const BlockHashCount: u32 = 250;
}

#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = ::sp_runtime::traits::BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Lookup = AccountIdLookup<AccountId, ()>;
ggwpez marked this conversation as resolved.
Show resolved Hide resolved
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type BlockWeights = ();
type BlockLength = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<Balance>;
type OnNewAccount = ();
type OnKilledAccount = ();
type DbWeight = ();
type BaseCallFilter = Everything;
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}

parameter_types! {
Expand Down Expand Up @@ -356,8 +361,6 @@ impl pallet_xcm::Config for Runtime {
type AdminOrigin = EnsureRoot<AccountId>;
}

type Block = frame_system::mocking::MockBlock<Runtime>;

construct_runtime!(
pub enum Runtime
{
Expand All @@ -367,3 +370,53 @@ construct_runtime!(
PolkadotXcm: pallet_xcm,
}
);

#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node-template"),
impl_name: create_runtime_str!("node-template"),
authoring_version: 1,
spec_version: 100,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
state_version: 1,
};

sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}

fn execute_block(block: Block) {
Executive::execute_block(block);
}

fn initialize_block(header: &<Block as sp_runtime::traits::Block>::Header) {
Executive::initialize_block(header)
}
}

#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here. If any of the pre/post migration checks fail, we shall stop
// right here and right now.
let weight = Executive::try_runtime_upgrade(checks).unwrap();
(weight, 0.into())
}

fn execute_block(
block: Block,
state_root_check: bool,
signature_check: bool,
select: frame_try_runtime::TryStateSelect
) -> Weight {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here.
Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
}
}
}
Loading
Loading