Fix flaky signed-context fuzz tests: constrain bounded keys, not raw inputs#480
Fix flaky signed-context fuzz tests: constrain bounded keys, not raw inputs#480thedavidmeister wants to merge 1 commit into
Conversation
boundPrivateKey is not injective over the full uint256 domain, so two distinct fuzz inputs (e.g. 0 and 1) can fold onto the same private key. The bad-signature assertions in testFlowBasicValidateMultipleSignedContexts and testFlowBasicValidateSignedContexts only hold when alice and bob have distinct keys, but the tests guarded the raw inputs via vm.assume(fuzzedKeyBob != fuzzedKeyAlice). Under the colliding case the 'bad' signature is signed by the same key it claims as signer, so it validates and the expected InvalidSignature revert never fires (deterministic under seed 0xdeadbeef at higher run counts). Move the assume onto the bounded keys (aliceKey != bobKey) so the revert path is exercised across the input domain without the degenerate collision masquerading as a failure. Closes #479 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughBoth signed-context fuzz tests in ChangesSigned-context fuzz test key collision fix
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What
testFlowBasicValidateMultipleSignedContexts(and its single-context siblingtestFlowBasicValidateSignedContexts) intest/src/concrete/Flow.signedContext.t.solare a latent/flaky red onrainix-sol-test. They pass at the configuredforge-config: default.fuzz.runs = 100under the pinnedseed = "0xdeadbeef", but fail deterministically once enough fuzz runs reach a colliding input. CI fuzzes with a random seed, so this surfaces intermittently.Root cause (broken test, not a code bug)
Both tests guarded the raw fuzz inputs:
forge-std'sboundPrivateKeyis_bound(x, 1, SECP256K1_ORDER - 1), which is not injective over the fulluint256domain — e.g.boundPrivateKey(0) == boundPrivateKey(1) == 1. So distinct raw inputs (passingvm.assume) can fold onto the same private key. When they do, the "bad" second signed contextvm.signContext(aliceKey, bobKey, ...)is actually signed by the same key it declares as signer, soLibContext.build'sSignatureChecker.isValidSignatureNowcorrectly validates it — and the expectedInvalidSignaturerevert never fires ("next call did not revert as expected").The validation code is correct; the test's distinctness precondition was asserted pre-bound but consumed post-bound. Diagnosis and repro are in #479. The captured counterexample under
0xdeadbeefisfuzzedKeyAlice = 0, fuzzedKeyBob = 1.Fix
Move the
vm.assumeonto the bounded keys (aliceKey != bobKey) in both tests, so the degenerate collision is discarded rather than asserted on, while the bad-signature revert path is still fully exercised across the input domain. The assertion itself is unchanged (not weakened).Verification
forge test --match-test testFlowBasicValidateMultipleSignedContexts --fuzz-seed 0xdeadbeef: FAIL at run 19, counterexample[..., 0, 1].runs = 100000underseed 0xdeadbeef: both tests pass (0 failed).0xdeadbeef, 0x1, 0x2, 0xc0ffee, 0xbadc0de, 0x12345at the configured 100 runs.forge fmt --checkclean. (rainix-sol-staticslither red is pre-existing and unrelated — tracked in fix: remove redundant statement flagged by slither (unblocks rainix-sol-static) #476.)Closes #479
🤖 Generated with Claude Code
Summary by CodeRabbit