Skip to content

Commit

Permalink
test: verifier: Add batch verification tests
Browse files Browse the repository at this point in the history
  • Loading branch information
joeykraut committed Feb 20, 2025
1 parent 1279491 commit e69c48f
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
104 changes: 104 additions & 0 deletions test/Verifier.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,96 @@ contract VerifierTest is VerifierTestUtils {
require(res, "Original proof verification should have succeeded");
}

/// @notice Test that batch verification fails if any proof in the batch is invalid
function testInvalidBatchVerification() public {
// First generate the verification keys for the circuits
compileRustBinary("test/rust-reference-impls/verifier/Cargo.toml");

// Generate batch test data
(PlonkProof[] memory proofs, BN254.ScalarField[][] memory publicInputs, VerificationKey[] memory vks) =
generateBatchProofData();

// Randomly select a proof to modify
uint256 proofToModify = randomUint(proofs.length);
PlonkProof memory invalidProof = clonePlonkProof(proofs[proofToModify]);

// Randomly select which part of the proof to modify
uint256 modType = randomUint(8);
BN254.G1Point memory dummyG1Point = BN254.P1();
BN254.ScalarField dummyScalar = BN254.ScalarField.wrap(1);

if (modType == 0) {
// Modify a wire commitment
uint256 randomIdx = randomUint(NUM_WIRE_TYPES);
invalidProof.wire_comms[randomIdx] = dummyG1Point;
} else if (modType == 1) {
// Modify z_comm
invalidProof.z_comm = dummyG1Point;
} else if (modType == 2) {
// Modify a quotient commitment
uint256 randomIdx = randomUint(NUM_WIRE_TYPES);
invalidProof.quotient_comms[randomIdx] = dummyG1Point;
} else if (modType == 3) {
// Modify w_zeta
invalidProof.w_zeta = dummyG1Point;
} else if (modType == 4) {
// Modify w_zeta_omega
invalidProof.w_zeta_omega = dummyG1Point;
} else if (modType == 5) {
// Modify a wire evaluation
uint256 randomIdx = randomUint(NUM_WIRE_TYPES);
invalidProof.wire_evals[randomIdx] = dummyScalar;
} else if (modType == 6) {
// Modify a sigma evaluation
uint256 randomIdx = randomUint(NUM_WIRE_TYPES - 1);
invalidProof.sigma_evals[randomIdx] = dummyScalar;
} else {
// Modify z_bar
invalidProof.z_bar = dummyScalar;
}

// Replace the selected proof with the invalid one
proofs[proofToModify] = invalidProof;

// Verify the batch - should fail
bool res = verifier.batchVerify(proofs, publicInputs, vks);
require(!res, "Proof verification should have failed");
}

/// @notice Test the case in which a public input is modified
function testModifiedPublicInput() public {
// First generate the verification keys for the circuits
compileRustBinary("test/rust-reference-impls/verifier/Cargo.toml");
VerificationKey memory vkey = getPermutationVkey();

// Generate data for the permutation circuit
uint256 randomChallenge = randomFelt();
uint256[5] memory statement;
uint256[5] memory witness;
for (uint256 i = 0; i < 5; i++) {
statement[i] = randomFelt();
witness[5 - i - 1] = statement[i];
}

// Get the proof and public input
PlonkProof memory proof = getPermutationProof(randomChallenge, statement, witness);

// Verify the proof
BN254.ScalarField[] memory publicInputs = new BN254.ScalarField[](6);
publicInputs[0] = BN254.ScalarField.wrap(randomChallenge);
for (uint256 i = 0; i < 5; i++) {
publicInputs[i + 1] = BN254.ScalarField.wrap(statement[i]);
}

// Modify the public input
uint256 randomIdx = randomUint(publicInputs.length);
publicInputs[randomIdx] = BN254.ScalarField.wrap(randomFelt());

// Verify the proof
bool res = verifier.verify(proof, publicInputs, vkey);
require(!res, "Proof verification should have failed");
}

// --- Valid Test Cases --- //

/// @notice Test the verifier against a reference implementation on the mul-two circuit
Expand Down Expand Up @@ -386,4 +476,18 @@ contract VerifierTest is VerifierTestUtils {
bool res = verifier.verify(proof, publicInputs, vkey);
require(res, "Proof verification should have succeeded");
}

/// @notice Test batch verification against all three circuits
function testBatchVerification() public {
// First generate the verification keys for the circuits
compileRustBinary("test/rust-reference-impls/verifier/Cargo.toml");

// Generate batch test data
(PlonkProof[] memory proofs, BN254.ScalarField[][] memory publicInputs, VerificationKey[] memory vks) =
generateBatchProofData();

// Verify the batch
bool res = verifier.batchVerify(proofs, publicInputs, vks);
require(res, "Proof verification should have succeeded");
}
}
49 changes: 49 additions & 0 deletions test/utils/VerifierTestUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,53 @@ contract VerifierTestUtils is TestUtils {
z_bar: original.z_bar
});
}

/// @dev Helper function to generate a batch of proofs, verification keys, and public inputs
function generateBatchProofData()
internal
returns (PlonkProof[] memory proofs, BN254.ScalarField[][] memory publicInputs, VerificationKey[] memory vks)
{
proofs = new PlonkProof[](3);
vks = new VerificationKey[](3);
publicInputs = new BN254.ScalarField[][](3);

// Generate mul-two proof and data
uint256 a = randomFelt();
uint256 b = randomFelt();
(uint256 c, PlonkProof memory mulTwoProof) = getMulTwoProof(a, b);
proofs[0] = mulTwoProof;
vks[0] = getMulTwoVkey();
publicInputs[0] = new BN254.ScalarField[](1);
publicInputs[0][0] = BN254.ScalarField.wrap(c);

// Generate sum-pow proof and data
uint256[10] memory inputs;
for (uint256 i = 0; i < 10; i++) {
inputs[i] = randomFelt();
}
(BN254.ScalarField sumPow, PlonkProof memory sumPowProof) = getSumPowProof(inputs);
proofs[1] = sumPowProof;
vks[1] = getSumPowVkey();
publicInputs[1] = new BN254.ScalarField[](1);
publicInputs[1][0] = sumPow;

// Generate permutation proof and data
uint256 randomChallenge = randomFelt();
uint256[5] memory statement;
uint256[5] memory witness;
for (uint256 i = 0; i < 5; i++) {
statement[i] = randomFelt();
witness[5 - i - 1] = statement[i];
}
PlonkProof memory permutationProof = getPermutationProof(randomChallenge, statement, witness);
proofs[2] = permutationProof;
vks[2] = getPermutationVkey();
publicInputs[2] = new BN254.ScalarField[](6);
publicInputs[2][0] = BN254.ScalarField.wrap(randomChallenge);
for (uint256 i = 0; i < 5; i++) {
publicInputs[2][i + 1] = BN254.ScalarField.wrap(statement[i]);
}

return (proofs, publicInputs, vks);
}
}

0 comments on commit e69c48f

Please sign in to comment.