diff --git a/.github/workflows/evm-weekly-fuzzer.yml b/.github/workflows/evm-weekly-fuzzer.yml new file mode 100644 index 00000000..5c377f79 --- /dev/null +++ b/.github/workflows/evm-weekly-fuzzer.yml @@ -0,0 +1,49 @@ +name: EVM Template Fuzzer (Weekly run) + +on: + schedule: + # Runs at 00:00 UTC every Sunday + - cron: '0 0 * * 0' + workflow_dispatch: + +jobs: + generic-template-fuzzer: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + + - name: Add target + run: rustup target add wasm32-unknown-unknown + + - name: Add dependencies + run: cargo install ziggy cargo-afl honggfuzz grcov + + - name: Build AFL config + run: cargo afl config --build + working-directory: evm-template/template-fuzzer + + - name: Run Ziggy Fuzzing + run: | + AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 timeout 5h cargo ziggy fuzz -t 20 || true + working-directory: evm-template/template-fuzzer + + - name: Generate Ziggy Fuzzing Coverage Result + run: | + CARGO_HOME=.cargo cargo ziggy cover + working-directory: evm-template/template-fuzzer + + - name: Zip Artifacts + run: zip artifacts.zip evm-template/template-fuzzer/output/* -r + + - name: Save Artifacts + uses: actions/upload-artifact@v4 + with: + name: fuzzing-artifacts + path: artifacts.zip \ No newline at end of file diff --git a/.github/workflows/generic-weekly-fuzzer.yml b/.github/workflows/generic-weekly-fuzzer.yml index 2c19c9f5..2f4605e6 100644 --- a/.github/workflows/generic-weekly-fuzzer.yml +++ b/.github/workflows/generic-weekly-fuzzer.yml @@ -33,6 +33,11 @@ jobs: run: | AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 timeout 5h cargo ziggy fuzz -t 20 || true working-directory: generic-template/template-fuzzer + + - name: Generate Ziggy Fuzzing Coverage Result + run: | + CARGO_HOME=.cargo cargo ziggy cover + working-directory: generic-template/template-fuzzer - name: Zip Artifacts run: zip artifacts.zip generic-template/template-fuzzer/output/* -r diff --git a/.gitignore b/.gitignore index 5c161235..1418fcc4 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,7 @@ docs/build **/zombienet-linux-x64 **/bin-* -coverage \ No newline at end of file +coverage + +# fuzzing output +**/template-fuzzer/output \ No newline at end of file diff --git a/evm-template/Cargo.lock b/evm-template/Cargo.lock index 64756c7c..302606cf 100644 --- a/evm-template/Cargo.lock +++ b/evm-template/Cargo.lock @@ -207,6 +207,15 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "ark-bls12-377" version = "0.4.0" @@ -2579,6 +2588,17 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -10657,6 +10677,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ + "arbitrary", "bytes", "rand", "ring 0.16.20", @@ -14725,6 +14746,7 @@ dependencies = [ "pallet-whitelist", "parachains-common", "parity-scale-codec", + "quinn-proto 0.9.6", "sp-consensus-aura", "sp-runtime", "sp-state-machine", diff --git a/evm-template/template-fuzzer/Cargo.toml b/evm-template/template-fuzzer/Cargo.toml index 0af035e0..219fbcb0 100644 --- a/evm-template/template-fuzzer/Cargo.toml +++ b/evm-template/template-fuzzer/Cargo.toml @@ -15,6 +15,7 @@ workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +quinn-proto = { version = "0.9.6", features = [ "arbitrary" ] } ziggy = { workspace = true } evm-runtime-template = { path = "../runtime" } diff --git a/evm-template/template-fuzzer/src/main.rs b/evm-template/template-fuzzer/src/main.rs index ec9350ce..be755f24 100644 --- a/evm-template/template-fuzzer/src/main.rs +++ b/evm-template/template-fuzzer/src/main.rs @@ -105,7 +105,8 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { continue; } if lapse > 0 { - finalize_block(elapsed); + println!("\n time spent: {elapsed:?}"); + assert!(elapsed.as_secs() <= 2, "block execution took too much time"); block += u32::from(lapse) * 393; // 393 * 256 = 100608 which nearly corresponds to a week weight = 0.into(); @@ -126,6 +127,7 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { println!(" call: {extrinsic:?}"); let now = Instant::now(); // We get the current time for timing purposes. + #[allow(unused_variables)] let res = extrinsic.dispatch(RuntimeOrigin::signed(origin)); elapsed += now.elapsed(); @@ -133,7 +135,7 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { println!(" result: {res:?}"); } - finalize_block(elapsed); + Executive::finalize_block(); check_invariants(block, initial_total_issuance); }); @@ -142,11 +144,14 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { fn initialize_block(block: u32) { println!("\ninitializing block {}", block); - let current_timestamp = u64::from(block) * SLOT_DURATION; + let current_timestamp = u64::from(block) * SLOT_DURATION * 2; let prev_header = match block { 1 => None, - _ => Some(Executive::finalize_block()), + _ => { + println!(" finalizing block"); + Some(Executive::finalize_block()) + } }; let parent_header = &Header::new( @@ -280,14 +285,6 @@ fn recursive_call_filter(call: &RuntimeCall, origin: usize) -> bool { } } -fn finalize_block(elapsed: Duration) { - println!("\n time spent: {elapsed:?}"); - assert!(elapsed.as_secs() <= 2, "block execution took too much time"); - - println!(" finalizing block"); - Executive::finalize_block(); -} - fn check_invariants(block: u32, initial_total_issuance: Balance) { let mut counted_free = 0; let mut counted_reserved = 0; diff --git a/generic-template/Cargo.lock b/generic-template/Cargo.lock index 9c21b518..aa4defed 100644 --- a/generic-template/Cargo.lock +++ b/generic-template/Cargo.lock @@ -207,6 +207,15 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "ark-bls12-377" version = "0.4.0" @@ -2553,6 +2562,17 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -10091,6 +10111,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ + "arbitrary", "bytes", "rand", "ring 0.16.20", @@ -13967,6 +13988,7 @@ dependencies = [ "pallet-whitelist", "parachains-common", "parity-scale-codec", + "quinn-proto 0.9.6", "sp-consensus-aura", "sp-runtime", "sp-state-machine", diff --git a/generic-template/template-fuzzer/Cargo.toml b/generic-template/template-fuzzer/Cargo.toml index d157abf7..c5d206c8 100644 --- a/generic-template/template-fuzzer/Cargo.toml +++ b/generic-template/template-fuzzer/Cargo.toml @@ -15,6 +15,7 @@ workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +quinn-proto = { version = "0.9.6", features = [ "arbitrary" ] } ziggy = { workspace = true } generic-runtime-template = { path = "../runtime" } diff --git a/generic-template/template-fuzzer/src/main.rs b/generic-template/template-fuzzer/src/main.rs index eff12afd..1c74ae10 100644 --- a/generic-template/template-fuzzer/src/main.rs +++ b/generic-template/template-fuzzer/src/main.rs @@ -103,7 +103,8 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { } if lapse > 0 { - finalize_block(elapsed); + println!("\n time spent: {elapsed:?}"); + assert!(elapsed.as_secs() <= 2, "block execution took too much time"); block += u32::from(lapse) * 393; // 393 * 256 = 100608 which nearly corresponds to a week weight = 0.into(); @@ -131,7 +132,7 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { println!(" result: {res:?}"); } - finalize_block(elapsed); + Executive::finalize_block(); check_invariants(block, initial_total_issuance); }); @@ -140,7 +141,7 @@ fn process_input(accounts: &[AccountId], genesis: &Storage, data: &[u8]) { fn initialize_block(block: u32) { println!("\ninitializing block {}", block); - let current_timestamp = u64::from(block) * SLOT_DURATION; + let current_timestamp = u64::from(block) * SLOT_DURATION * 2; let prev_header = match block { 1 => None, @@ -207,14 +208,6 @@ fn initialize_block(block: u32) { // Calls that need to be called before each block starts (init_calls) go here } -fn finalize_block(elapsed: Duration) { - println!("\n time spent: {elapsed:?}"); - assert!(elapsed.as_secs() <= 2, "block execution took too much time"); - - println!(" finalizing block"); - Executive::finalize_block(); -} - fn check_invariants(block: u32, initial_total_issuance: Balance) { let mut counted_free = 0; let mut counted_reserved = 0;