diff --git a/test/WakuRlnV2.fuzz.t.sol b/test/WakuRlnV2.fuzz.t.sol index 56f10a4..ba10a5f 100644 --- a/test/WakuRlnV2.fuzz.t.sol +++ b/test/WakuRlnV2.fuzz.t.sol @@ -342,14 +342,13 @@ contract WakuRlnV2Test is Test { return current == root; } - // Fuzz Test: Merkle Tree Insertions and Proofs via Registrations + // Merkle Tree Insertions and Proofs via Registrations function testFuzz_MerkleInserts(uint8 numInserts) external { - vm.assume(numInserts > 0 && numInserts <= 32); + vm.assume(numInserts > 0 && numInserts <= 16); uint32 rateLimit = w.minMembershipRateLimit(); uint256[] memory ids = new uint256[](numInserts); uint32[] memory indices = new uint32[](numInserts); - uint256[] memory expectedRoots = new uint256[](numInserts); // Sequence: Fuzz registrations, track indices and commitments for (uint8 i = 0; i < numInserts; i++) { @@ -367,17 +366,18 @@ contract WakuRlnV2Test is Test { assertEq(rl, rateLimit); assertTrue(commitment != 0); // Inserted - // Invariant: Proof valid for leaf - uint256[20] memory proof = w.getMerkleProof(idx); - uint256 root = w.root(); - assertTrue(_verifyMerkleProof(proof, root, idx, commitment, 20)); - - expectedRoots[i] = root; // Snapshot for later + // Sampled proof verification: Only check every other for gas savings + if (i % 2 == 0) { + uint256[20] memory proof = w.getMerkleProof(idx); + uint256 root = w.root(); + assertTrue(_verifyMerkleProof(proof, root, idx, commitment, 20)); + } } - // Post-sequence invariants: Roots evolved correctly, no overwrites + // Post-sequence invariants: Roots evolved correctly, no overwrites - sampled checks assertEq(w.nextFreeIndex(), numInserts); // Filled sequentially - for (uint8 i = 0; i < numInserts; i++) { + for (uint8 i = 0; i < numInserts; i += 2) { + // Sample every other (, uint32 idx,) = w.getMembershipInfo(ids[i]); assertEq(idx, i); // Sequential indices assertEq( @@ -386,9 +386,9 @@ contract WakuRlnV2Test is Test { } } - // Fuzz Test: Merkle Tree Erasures and Reuses (Lazy/Full) + // Merkle Tree Erasures and Reuses (Lazy/Full) function testFuzz_MerkleErasures(uint8 numOps, bool fullErase) external { - vm.assume(numOps > 0 && numOps <= 16); // Small for gas + vm.assume(numOps > 0 && numOps <= 8); // Low for gas optimization uint32 rateLimit = w.minMembershipRateLimit(); uint256[] memory ids = new uint256[](numOps); @@ -412,11 +412,12 @@ contract WakuRlnV2Test is Test { uint256(w.activeDurationForNewMemberships()) + uint256(w.gracePeriodDurationForNewMemberships()) + 1; vm.warp(block.timestamp + minDelta); - // Phase 2: Erase all (lazy or full), check proofs/roots + // Phase 2: Erase all (lazy or full), check proofs/roots - sampled w.eraseMemberships(ids, fullErase); uint256 postEraseRoot = w.root(); - for (uint8 i = 0; i < numOps; i++) { + for (uint8 i = 0; i < numOps; i += 2) { + // Sample every other assertFalse(w.isInMembershipSet(ids[i])); // Erased (,, uint256 commitment) = w.getMembershipInfo(ids[i]); assertEq(commitment, 0); @@ -429,8 +430,9 @@ contract WakuRlnV2Test is Test { assertTrue(_verifyMerkleProof(proof, postEraseRoot, indices[i], expectedLeaf, 20)); } - // Phase 3: Reuse erased indices via new registrations, check no overwrite issues - for (uint8 i = 0; i < numOps; i++) { + // Phase 3: Reuse erased indices via new registrations, check no overwrite issues - sampled + for (uint8 i = 0; i < numOps; i += 2) { + // Sample every other uint256 newId = uint256(keccak256(abi.encodePacked(i + numOps, block.timestamp))) % (w.Q() - 1) + 1; vm.assume(w.currentTotalRateLimit() + rateLimit <= w.maxTotalRateLimit()); @@ -448,7 +450,7 @@ contract WakuRlnV2Test is Test { assertTrue(newRoot != postEraseRoot); // Root changed } - // Final invariant: Tree size matches ops (reuses don't grow beyond) + // Final invariant: Tree size matches ops assertEq(w.nextFreeIndex(), numOps); }