Skip to content

test: e2e sp1 proof defense - #734

Open
0xOsiris wants to merge 29 commits into
mainfrom
osiris/e2e-defender-test
Open

test: e2e sp1 proof defense#734
0xOsiris wants to merge 29 commits into
mainfrom
osiris/e2e-defender-test

Conversation

@0xOsiris

@0xOsiris 0xOsiris commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Note

High Risk
Touches dispute finalization contracts, L1 devnet topology, and real SP1 proving; misconfiguration can break proof deploy or leave challenged games stuck. The committed panic.log looks like debug output and should probably be dropped before merge.

Overview
Adds an ignored, opt-in e2e test (defender_finalizes_challenged_game_with_sp1_proof) that runs the HA devnet with DEVNET_SP1_WORKER_PROVER, stakes a griefer to challenge a valid game, and waits for the in-process defender + SP1 worker to post a real Groth16 proof and finalize with proofThreshold = 1. A just defender-e2e recipe and DEFENDER_LOG / PROVING_LOG cargo env presets support running it.

The full-stack proof devnet switches L1 from anvil to reth + Lighthouse so kona witness collection gets debug_* L1 data and a real beacon API; op-node/op-challenger/SP1 worker wiring uses separate L1 EL and beacon URLs, L2 --rpc.eth-proof-window, delayed proof-system deploy (after L2 is healthy), standalone SP1 Groth16 verifier deploy, vkey computation, and richer L1 genesis funding. Proving ranges shrink to 1-block intervals when SP1 is enabled.

On-chain: new SP1ValidityVerifier, factory/game proofThreshold (replacing a fixed lib constant), deploy script env for real SP1; sp1-contracts submodule. Defender submits lane calldata as ABI (bytes, bytes) for SP1/Nitro and documents the flow; defended lanes are SP1-only for this devnet path.

Also adds world-chain-defender to the workspace members list and host-utils deps (kona-providers-alloy, L1 config path) for witness building.

Reviewed by Cursor Bugbot for commit 1aef7fa. Configure here.

@0xOsiris 0xOsiris changed the title Osiris/e2e defender test test: e2e sp1 proof defense Jun 15, 2026
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Compared on the same runner in the same workflow run.

group                                                                                              base                                   pr
-----                                                                                              ----                                   --
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_125tx                  1.00     28.0±0.25ms        ? ?/sec    1.00     28.1±0.20ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_250tx                  1.00     55.3±0.19ms        ? ?/sec    1.00     55.4±0.11ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers/stream/4fb_x_50tx                   1.00     11.7±0.06ms        ? ?/sec    1.00     11.7±0.02ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_125tx         1.00     35.6±0.62ms        ? ?/sec    1.02     36.2±0.35ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_250tx         1.02     68.6±0.32ms        ? ?/sec    1.00     67.2±0.43ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_eth_transfers_with_bal/stream/4fb_x_50tx          1.00     16.2±0.24ms        ? ?/sec    1.01     16.4±0.16ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_125tx                            1.03     27.9±1.26ms        ? ?/sec    1.00     27.0±0.16ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_250tx                            1.03     55.0±0.05ms        ? ?/sec    1.00     53.1±0.18ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib/stream/4fb_x_50tx                             1.00     10.8±0.01ms        ? ?/sec    1.03     11.1±0.03ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_125tx                   1.00     33.1±0.26ms        ? ?/sec    1.03     34.1±0.42ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_250tx                   1.00     62.7±0.14ms        ? ?/sec    1.02     63.7±0.25ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_fib_with_bal/stream/4fb_x_50tx                    1.00     15.6±0.25ms        ? ?/sec    1.05     16.3±0.32ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_10tx             1.00    135.2±0.15ms        ? ?/sec    1.00    135.2±0.32ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_12tx             1.00    162.3±0.16ms        ? ?/sec    1.00    162.3±1.14ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254/stream/4fb_x_5tx              1.00     68.2±0.05ms        ? ?/sec    1.00     67.9±0.04ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_10tx    1.02     21.4±0.65ms        ? ?/sec    1.00     21.0±0.78ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_12tx    1.01     23.7±1.60ms        ? ?/sec    1.00     23.5±2.52ms        ? ?/sec
flashblock_validation_launch_flashblock_sequence_world_id_like_bn254_with_bal/stream/4fb_x_5tx     1.01     19.3±0.88ms        ? ?/sec    1.00     19.0±0.27ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers/txs/1000                                    1.00     48.8±1.10ms        ? ?/sec    1.00     48.8±0.02ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers/txs/50                                      1.00      2.6±0.02ms        ? ?/sec    1.00      2.6±0.02ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers/txs/500                                     1.00     24.4±0.09ms        ? ?/sec    1.00     24.5±0.04ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/1000                           1.00     58.8±0.36ms        ? ?/sec    1.02     60.1±0.12ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/50                             1.00      3.8±0.04ms        ? ?/sec    1.01      3.9±0.06ms        ? ?/sec
flashblock_validation_process_flashblock_eth_transfers_with_bal/txs/500                            1.00     29.3±0.16ms        ? ?/sec    1.04     30.5±0.44ms        ? ?/sec
flashblock_validation_process_flashblock_fib/txs/1000                                              1.00     47.9±0.02ms        ? ?/sec    1.00     48.0±0.12ms        ? ?/sec
flashblock_validation_process_flashblock_fib/txs/50                                                1.00      2.5±0.03ms        ? ?/sec    1.01      2.5±0.03ms        ? ?/sec
flashblock_validation_process_flashblock_fib/txs/500                                               1.00     24.0±0.01ms        ? ?/sec    1.00     24.0±0.02ms        ? ?/sec
flashblock_validation_process_flashblock_fib_with_bal/txs/1000                                     1.00     55.8±0.16ms        ? ?/sec    1.02     57.1±0.26ms        ? ?/sec
flashblock_validation_process_flashblock_fib_with_bal/txs/50                                       1.00      3.8±0.07ms        ? ?/sec    1.01      3.8±0.04ms        ? ?/sec
flashblock_validation_process_flashblock_fib_with_bal/txs/500                                      1.00     28.0±0.07ms        ? ?/sec    1.02     28.7±0.09ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254/txs/10                                1.00     33.7±0.09ms        ? ?/sec    1.00     33.8±0.13ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254/txs/25                                1.00     84.0±0.05ms        ? ?/sec    1.00     84.1±0.05ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254/txs/50                                1.00    167.8±0.08ms        ? ?/sec    1.00    168.1±0.18ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/10                       1.01      5.5±0.31ms        ? ?/sec    1.00      5.4±0.27ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/25                       1.00      8.2±0.07ms        ? ?/sec    1.01      8.3±0.10ms        ? ?/sec
flashblock_validation_process_flashblock_world_id_like_bn254_with_bal/txs/50                       1.28     14.9±0.28ms        ? ?/sec    1.00     11.6±0.60ms        ? ?/sec

Threshold: 10% regression triggers failure

Base automatically changed from ale/add-defender to main June 15, 2026 10:17

@alessandromazza98 alessandromazza98 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally the e2e tests look good to me, I left some comments. I think you can split this PR into more than once, at least one where you add the sp1 verifier contract first.

}
}

function hasThreshold(uint8 bitmap) internal pure returns (bool) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can remove the PROOF_THRESHOLD const then (line 5)

/// @notice Verifies an SP1 Groth16 aggregation proof and binds its committed
/// outputs to the challenged game's proposal. Implements the validity-proof lane
/// of [`IWorldChainProofVerifier`].
contract SP1ValidityVerifier is IWorldChainProofVerifier {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd create a PR that only includes this Sp1ValidityVerifier contract first because this contract is critical for the proof-system. Then create the e2e tests PR on top

Comment on lines +17 to +23
/// worker exists to service the `Nitro` backend queue.
pub(crate) const DEFENDED_LANE_COUNT: usize = 1;

/// The proof lanes the defender drives, paired with the prover-service
/// backend that generates each proof.
pub(crate) const DEFENDED_LANES: [(ProofLane, ProofBackend); DEFENDED_LANE_COUNT] = [
(ProofLane::ValidityProof, ProofBackend::Sp1),
(ProofLane::TeeAttestation, ProofBackend::Nitro),
];
pub(crate) const DEFENDED_LANES: [(ProofLane, ProofBackend); DEFENDED_LANE_COUNT] =
[(ProofLane::ValidityProof, ProofBackend::Sp1)];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a TODO in both const so that we remember to change them once nitro worker exists ?


## 8. Full end-to-end sequence

```mermaid

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see an error here:

Parse error on line 39:
...n → defense complete
-----------------------^
Expecting '()', 'SOLID_OPEN_ARROW', 'DOTTED_OPEN_ARROW', 'SOLID_ARROW', 'SOLID_ARROW_TOP', 'SOLID_ARROW_BOTTOM', 'STICK_ARROW_TOP', 'STICK_ARROW_BOTTOM', 'SOLID_ARROW_TOP_DOTTED', 'SOLID_ARROW_BOTTOM_DOTTED', 'STICK_ARROW_TOP_DOTTED', 'STICK_ARROW_BOTTOM_DOTTED', 'SOLID_ARROW_TOP_REVERSE', 'SOLID_ARROW_BOTTOM_REVERSE', 'STICK_ARROW_TOP_REVERSE', 'STICK_ARROW_BOTTOM_REVERSE', 'SOLID_ARROW_TOP_REVERSE_DOTTED', 'SOLID_ARROW_BOTTOM_REVERSE_DOTTED', 'STICK_ARROW_TOP_REVERSE_DOTTED', 'STICK_ARROW_BOTTOM_REVERSE_DOTTED', 'BIDIRECTIONAL_SOLID_ARROW', 'DOTTED_ARROW', 'BIDIRECTIONAL_DOTTED_ARROW', 'SOLID_CROSS', 'DOTTED_CROSS', 'SOLID_POINT', 'DOTTED_POINT', got 'NEWLINE'

@@ -0,0 +1,252 @@
//! End-to-end test: the defender finalizes a challenged-but-valid game with a real SP1
//! Groth16 validity proof.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

further, what do you think of putting e2e tests for the proof-system inside the proofs folder such as:

/proofs
|
|-- /e2e

This way we have both e2e and integration tests for proof-system inside the proofs folder. See #744 for integration tests that I'm adding

@alessandromazza98

Copy link
Copy Markdown
Contributor

@0xOsiris
0xOsiris marked this pull request as ready for review June 17, 2026 00:03

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1aef7fa. Configure here.

Comment thread panic.log
2026-06-15T18:03:53.222368Z WARN op_batcher: msg="publishSignal channel is full, skipping signal" process=op-batcher
2026-06-15T18:03:54.218118Z WARN op_batcher: msg="publishSignal channel is full, skipping signal" process=op-batcher
2026-06-15T18:03:55.228298Z WARN op_batcher: msg="publishSignal channel is full, skipping signal" process=op-batcher
2026-06-15T18:03:56.218412Z WARN op_batcher: msg="publishSignal channel is full, skipping signal" process=op-batcher

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug panic log committed

Low Severity

A full panic.log with local stack traces and test run output is added at the repository root. It looks like a developer debug artifact from a failed defender e2e run, not production or test source code.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1aef7fa. Configure here.

Comment thread Cargo.toml
"proofs/proposer",
"proofs/challenger",
"proofs/prover-service",
"proofs/defender",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate workspace member entry

Low Severity

proofs/defender appears twice in the workspace members list. The duplicate entry is redundant and can confuse workspace maintenance or tooling that expects unique paths.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1aef7fa. Configure here.


function hasThreshold(uint8 bitmap) internal pure returns (bool) {
return proofCount(bitmap) >= PROOF_THRESHOLD;
function hasThreshold(uint8 bitmap, uint8 threshold) internal pure returns (bool) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused proof threshold constant

Low Severity

WorldChainProofLib.PROOF_THRESHOLD is no longer used after hasThreshold takes a threshold argument and games use proofThreshold immutables. The constant is dead code left behind by this refactor.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1aef7fa. Configure here.

@0xForerunner 0xForerunner left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have some solidity experts take a look at this before merging as well.

Comment thread panic.log

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is mistakenly committed.

p.rollupConfigHash = vm.envBytes32("ROLLUP_CONFIG_HASH");
p.blockInterval = vm.envOr("PROOF_SYSTEM_BLOCK_INTERVAL", uint256(10));
p.intermediateBlockInterval = vm.envOr("PROOF_SYSTEM_INTERMEDIATE_BLOCK_INTERVAL", uint256(5));
p.proofThreshold = uint8(vm.envOr("PROOF_SYSTEM_THRESHOLD", uint256(1)));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep this default at 2.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just only have 1 available prover atm, but yes it will be

@alessandromazza98

Copy link
Copy Markdown
Contributor

I'd still suggest to split this PR into at least 2: #734 (comment)

And to eventually change folder structure as: #734 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants