mirror of
https://github.com/pezkuwichain/pezkuwi-runtime-templates.git
synced 2026-06-09 20:11:03 +00:00
Fuzz Testing Integration (#275)
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
name: Generic Template Fuzzer (Weekly run)
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Runs at 00:00 UTC every Sunday
|
||||
- cron: '0 0 * * 0'
|
||||
|
||||
jobs:
|
||||
generic-template-fuzzer:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
|
||||
- name: Add dependencies
|
||||
run: cargo install ziggy cargo-afl honggfuzz grcov
|
||||
|
||||
- name: Add target
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
|
||||
- name: Run Ziggy Fuzzing
|
||||
run: |
|
||||
timeout 5h cargo ziggy fuzz -t 20 || true
|
||||
working-directory: generic-template/template-fuzzer
|
||||
|
||||
- name: Save Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: fuzzing-artifacts
|
||||
path: |
|
||||
generic-template/template-fuzzer/output
|
||||
Generated
+6
@@ -13993,7 +13993,13 @@ dependencies = [
|
||||
"frame-support",
|
||||
"frame-system",
|
||||
"pallet-balances",
|
||||
"pallet-collator-selection",
|
||||
"pallet-multisig",
|
||||
"pallet-scheduler",
|
||||
"pallet-sudo",
|
||||
"pallet-timestamp",
|
||||
"pallet-utility",
|
||||
"pallet-whitelist",
|
||||
"parachains-common",
|
||||
"parity-scale-codec",
|
||||
"sp-consensus-aura",
|
||||
|
||||
@@ -31,7 +31,13 @@ sp-runtime = { workspace = true }
|
||||
sp-state-machine = { workspace = true }
|
||||
|
||||
pallet-balances = { workspace = true }
|
||||
pallet-collator-selection = { workspace = true }
|
||||
pallet-multisig = { workspace = true }
|
||||
pallet-scheduler = { workspace = true }
|
||||
pallet-sudo = { workspace = true }
|
||||
pallet-timestamp = { workspace = true }
|
||||
pallet-utility = { workspace = true }
|
||||
pallet-whitelist = { workspace = true }
|
||||
|
||||
cumulus-pallet-parachain-system = { workspace = true }
|
||||
cumulus-primitives-core = { workspace = true }
|
||||
@@ -43,7 +49,13 @@ default = [ "std", "try-runtime" ]
|
||||
std = [
|
||||
"evm-runtime-template/std",
|
||||
"frame-support/std",
|
||||
"pallet-collator-selection/std",
|
||||
"pallet-multisig/std",
|
||||
"pallet-scheduler/std",
|
||||
"pallet-sudo/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-utility/std",
|
||||
"pallet-whitelist/std",
|
||||
"parity-scale-codec/std",
|
||||
"sp-consensus-aura/std",
|
||||
"sp-runtime/std",
|
||||
@@ -52,7 +64,13 @@ try-runtime = [
|
||||
"evm-runtime-template/try-runtime",
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"pallet-collator-selection/try-runtime",
|
||||
"pallet-multisig/try-runtime",
|
||||
"pallet-scheduler/try-runtime",
|
||||
"pallet-sudo/try-runtime",
|
||||
"pallet-timestamp/try-runtime",
|
||||
"pallet-utility/try-runtime",
|
||||
"pallet-whitelist/try-runtime",
|
||||
"sp-runtime/try-runtime",
|
||||
]
|
||||
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/zsh
|
||||
|
||||
data=0;
|
||||
for file in output/template-fuzzer/crashes/**/*(.); do
|
||||
cargo ziggy run -i $file 2>output/$data.err 1>output/$data.out
|
||||
data=$((data+1))
|
||||
done
|
||||
@@ -2,9 +2,9 @@ use std::time::{Duration, Instant};
|
||||
|
||||
use cumulus_primitives_core::relay_chain::Slot;
|
||||
use evm_runtime_template::{
|
||||
constants::SLOT_DURATION, AccountId, AllPalletsWithSystem, Balance, Balances, BlockNumber,
|
||||
EVMChainIdConfig, Executive, Runtime, RuntimeCall, RuntimeOrigin, SudoConfig,
|
||||
UncheckedExtrinsic,
|
||||
configs::MaxCandidates, constants::SLOT_DURATION, AccountId, AllPalletsWithSystem, Balance,
|
||||
Balances, BlockNumber, EVMChainIdConfig, Executive, Runtime, RuntimeCall, RuntimeOrigin,
|
||||
SudoConfig, UncheckedExtrinsic,
|
||||
};
|
||||
use frame_support::{
|
||||
dispatch::GetDispatchInfo,
|
||||
@@ -173,6 +173,10 @@ fn main() {
|
||||
externalities.execute_with(|| start_block(current_block, 0));
|
||||
|
||||
for (maybe_lapse, origin, extrinsic) in extrinsics {
|
||||
let origin_no = origin % endowed_accounts.len();
|
||||
if !recursive_call_filter(&extrinsic, origin_no) {
|
||||
continue;
|
||||
}
|
||||
// If the lapse is in the range [0, MAX_BLOCK_LAPSE] we finalize the block and initialize
|
||||
// a new one.
|
||||
if let Some(lapse) = maybe_lapse {
|
||||
@@ -201,7 +205,7 @@ fn main() {
|
||||
}
|
||||
|
||||
externalities.execute_with(|| {
|
||||
let origin_account = endowed_accounts[origin % endowed_accounts.len()];
|
||||
let origin_account = endowed_accounts[origin_no];
|
||||
{
|
||||
println!("\n origin: {origin_account:?}");
|
||||
println!(" call: {extrinsic:?}");
|
||||
@@ -287,3 +291,71 @@ fn main() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn recursive_call_filter(call: &RuntimeCall, origin: usize) -> bool {
|
||||
match call {
|
||||
//recursion
|
||||
RuntimeCall::Sudo(
|
||||
pallet_sudo::Call::sudo { call }
|
||||
| pallet_sudo::Call::sudo_unchecked_weight { call, weight: _ },
|
||||
) if origin == 0 => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Utility(
|
||||
pallet_utility::Call::with_weight { call, weight: _ }
|
||||
| pallet_utility::Call::dispatch_as { as_origin: _, call }
|
||||
| pallet_utility::Call::as_derivative { index: _, call },
|
||||
) => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Utility(
|
||||
pallet_utility::Call::force_batch { calls }
|
||||
| pallet_utility::Call::batch { calls }
|
||||
| pallet_utility::Call::batch_all { calls },
|
||||
) => calls.iter().map(|call| recursive_call_filter(call, origin)).all(|e| e),
|
||||
RuntimeCall::Scheduler(
|
||||
pallet_scheduler::Call::schedule_named_after {
|
||||
id: _,
|
||||
after: _,
|
||||
maybe_periodic: _,
|
||||
priority: _,
|
||||
call,
|
||||
}
|
||||
| pallet_scheduler::Call::schedule { when: _, maybe_periodic: _, priority: _, call }
|
||||
| pallet_scheduler::Call::schedule_named {
|
||||
when: _,
|
||||
id: _,
|
||||
maybe_periodic: _,
|
||||
priority: _,
|
||||
call,
|
||||
}
|
||||
| pallet_scheduler::Call::schedule_after {
|
||||
after: _,
|
||||
maybe_periodic: _,
|
||||
priority: _,
|
||||
call,
|
||||
},
|
||||
) => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Multisig(
|
||||
pallet_multisig::Call::as_multi_threshold_1 { other_signatories: _, call }
|
||||
| pallet_multisig::Call::as_multi {
|
||||
threshold: _,
|
||||
other_signatories: _,
|
||||
maybe_timepoint: _,
|
||||
call,
|
||||
max_weight: _,
|
||||
},
|
||||
) => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Whitelist(
|
||||
pallet_whitelist::Call::dispatch_whitelisted_call_with_preimage { call },
|
||||
) => recursive_call_filter(call, origin),
|
||||
|
||||
// restrictions
|
||||
RuntimeCall::Sudo(_) if origin != 0 => false,
|
||||
RuntimeCall::System(
|
||||
frame_system::Call::set_code { .. } | frame_system::Call::kill_prefix { .. },
|
||||
) => false,
|
||||
RuntimeCall::CollatorSelection(
|
||||
pallet_collator_selection::Call::set_desired_candidates { max },
|
||||
) => *max < MaxCandidates::get(),
|
||||
RuntimeCall::Balances(pallet_balances::Call::force_adjust_total_issuance { .. }) => false,
|
||||
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+6
@@ -13075,7 +13075,13 @@ dependencies = [
|
||||
"frame-system",
|
||||
"generic-runtime-template",
|
||||
"pallet-balances",
|
||||
"pallet-collator-selection",
|
||||
"pallet-multisig",
|
||||
"pallet-scheduler",
|
||||
"pallet-sudo",
|
||||
"pallet-timestamp",
|
||||
"pallet-utility",
|
||||
"pallet-whitelist",
|
||||
"parachains-common",
|
||||
"parity-scale-codec",
|
||||
"sp-consensus-aura",
|
||||
|
||||
@@ -31,7 +31,13 @@ sp-runtime = { workspace = true }
|
||||
sp-state-machine = { workspace = true }
|
||||
|
||||
pallet-balances = { workspace = true }
|
||||
pallet-collator-selection = { workspace = true }
|
||||
pallet-multisig = { workspace = true }
|
||||
pallet-scheduler = { workspace = true }
|
||||
pallet-sudo = { workspace = true }
|
||||
pallet-timestamp = { workspace = true }
|
||||
pallet-utility = { workspace = true }
|
||||
pallet-whitelist = { workspace = true }
|
||||
|
||||
cumulus-pallet-parachain-system = { workspace = true }
|
||||
cumulus-primitives-core = { workspace = true }
|
||||
@@ -43,16 +49,29 @@ default = [ "std", "try-runtime" ]
|
||||
std = [
|
||||
"frame-support/std",
|
||||
"generic-runtime-template/std",
|
||||
"pallet-collator-selection/std",
|
||||
"pallet-multisig/std",
|
||||
"pallet-scheduler/std",
|
||||
"pallet-sudo/std",
|
||||
"pallet-timestamp/std",
|
||||
"pallet-utility/std",
|
||||
"pallet-whitelist/std",
|
||||
"parity-scale-codec/std",
|
||||
"sp-consensus-aura/std",
|
||||
"sp-runtime/std",
|
||||
]
|
||||
fuzzing = []
|
||||
try-runtime = [
|
||||
"frame-support/try-runtime",
|
||||
"frame-system/try-runtime",
|
||||
"generic-runtime-template/try-runtime",
|
||||
"pallet-collator-selection/try-runtime",
|
||||
"pallet-multisig/try-runtime",
|
||||
"pallet-scheduler/try-runtime",
|
||||
"pallet-sudo/try-runtime",
|
||||
"pallet-timestamp/try-runtime",
|
||||
"pallet-utility/try-runtime",
|
||||
"pallet-whitelist/try-runtime",
|
||||
"sp-runtime/try-runtime",
|
||||
]
|
||||
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/zsh
|
||||
|
||||
data=0;
|
||||
for file in output/template-fuzzer/crashes/**/*(.); do
|
||||
cargo ziggy run -i $file 2>output/$data.err 1>output/$data.out
|
||||
data=$((data+1))
|
||||
done
|
||||
@@ -8,8 +8,8 @@ use frame_support::{
|
||||
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
|
||||
};
|
||||
use generic_runtime_template::{
|
||||
constants::SLOT_DURATION, AllPalletsWithSystem, Balance, Balances, BlockNumber, Executive,
|
||||
Runtime, RuntimeCall, RuntimeOrigin, SudoConfig, UncheckedExtrinsic,
|
||||
configs::MaxCandidates, constants::SLOT_DURATION, AllPalletsWithSystem, Balance, Balances,
|
||||
BlockNumber, Executive, Runtime, RuntimeCall, RuntimeOrigin, SudoConfig, UncheckedExtrinsic,
|
||||
};
|
||||
use parachains_common::AccountId;
|
||||
use sp_consensus_aura::AURA_ENGINE_ID;
|
||||
@@ -168,6 +168,10 @@ fn main() {
|
||||
for (maybe_lapse, origin, extrinsic) in extrinsics {
|
||||
// If the lapse is in the range [0, MAX_BLOCK_LAPSE] we finalize the block and initialize
|
||||
// a new one.
|
||||
let origin_no = origin % endowed_accounts.len();
|
||||
if !recursive_call_filter(&extrinsic, origin_no) {
|
||||
continue;
|
||||
}
|
||||
if let Some(lapse) = maybe_lapse {
|
||||
// We update our state variables
|
||||
current_weight = Weight::zero();
|
||||
@@ -194,7 +198,7 @@ fn main() {
|
||||
}
|
||||
|
||||
externalities.execute_with(|| {
|
||||
let origin_account = endowed_accounts[origin % endowed_accounts.len()].clone();
|
||||
let origin_account = endowed_accounts[origin_no].clone();
|
||||
{
|
||||
println!("\n origin: {origin_account:?}");
|
||||
println!(" call: {extrinsic:?}");
|
||||
@@ -280,3 +284,74 @@ fn main() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn recursive_call_filter(call: &RuntimeCall, origin: usize) -> bool {
|
||||
match call {
|
||||
//recursion
|
||||
RuntimeCall::Sudo(
|
||||
pallet_sudo::Call::sudo { call }
|
||||
| pallet_sudo::Call::sudo_unchecked_weight { call, weight: _ },
|
||||
) if origin == 0 => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Utility(
|
||||
pallet_utility::Call::with_weight { call, weight: _ }
|
||||
| pallet_utility::Call::dispatch_as { as_origin: _, call }
|
||||
| pallet_utility::Call::as_derivative { index: _, call },
|
||||
) => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Utility(
|
||||
pallet_utility::Call::force_batch { calls }
|
||||
| pallet_utility::Call::batch { calls }
|
||||
| pallet_utility::Call::batch_all { calls },
|
||||
) => calls
|
||||
.iter()
|
||||
.map(|call| recursive_call_filter(call, origin))
|
||||
.all(|e| e),
|
||||
RuntimeCall::Scheduler(
|
||||
pallet_scheduler::Call::schedule_named_after {
|
||||
id: _,
|
||||
after: _,
|
||||
maybe_periodic: _,
|
||||
priority: _,
|
||||
call,
|
||||
}
|
||||
| pallet_scheduler::Call::schedule { when: _, maybe_periodic: _, priority: _, call }
|
||||
| pallet_scheduler::Call::schedule_named {
|
||||
when: _,
|
||||
id: _,
|
||||
maybe_periodic: _,
|
||||
priority: _,
|
||||
call,
|
||||
}
|
||||
| pallet_scheduler::Call::schedule_after {
|
||||
after: _,
|
||||
maybe_periodic: _,
|
||||
priority: _,
|
||||
call,
|
||||
},
|
||||
) => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Multisig(
|
||||
pallet_multisig::Call::as_multi_threshold_1 { other_signatories: _, call }
|
||||
| pallet_multisig::Call::as_multi {
|
||||
threshold: _,
|
||||
other_signatories: _,
|
||||
maybe_timepoint: _,
|
||||
call,
|
||||
max_weight: _,
|
||||
},
|
||||
) => recursive_call_filter(call, origin),
|
||||
RuntimeCall::Whitelist(
|
||||
pallet_whitelist::Call::dispatch_whitelisted_call_with_preimage { call },
|
||||
) => recursive_call_filter(call, origin),
|
||||
|
||||
// restrictions
|
||||
RuntimeCall::Sudo(_) if origin != 0 => false,
|
||||
RuntimeCall::System(
|
||||
frame_system::Call::set_code { .. } | frame_system::Call::kill_prefix { .. },
|
||||
) => false,
|
||||
RuntimeCall::CollatorSelection(
|
||||
pallet_collator_selection::Call::set_desired_candidates { max },
|
||||
) => *max < MaxCandidates::get(),
|
||||
RuntimeCall::Balances(pallet_balances::Call::force_adjust_total_issuance { .. }) => false,
|
||||
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user