Skip to content

Commit

Permalink
test: add tests for Solidity sumcheck verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
JayWhite2357 committed Oct 3, 2024
1 parent 7524301 commit 82c741f
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Sumcheck} from "./Sumcheck.sol";

library SumcheckTests {
error EvaluationPointMismatch();
error ExpectedEvaluationMismatch();
error TranscriptMismatch();

function rustTestVerification(
bytes calldata rawProof,
bytes32 transcript,
uint16 degree,
uint16 numVariables,
uint256 claimedSum,
uint256 modulus,
bytes calldata rawExpectedResult,
bytes32 expectedChallenge
) public pure {
(Sumcheck.Proof memory proof) = abi.decode(rawProof, (Sumcheck.Proof));
(Sumcheck.Subclaim memory expectedResult) = abi.decode(rawExpectedResult, (Sumcheck.Subclaim));
(Sumcheck.Subclaim memory result, bytes32 resultTranscript) =
Sumcheck.verifyWithoutEvaluation(proof, transcript, degree, numVariables, claimedSum, modulus);
if (expectedResult.evaluationPoint.length != result.evaluationPoint.length) revert EvaluationPointMismatch();
uint256 evaluationPointLength = expectedResult.evaluationPoint.length;
for (uint256 i = 0; i < evaluationPointLength; ++i) {
if (expectedResult.evaluationPoint[i] != result.evaluationPoint[i]) revert EvaluationPointMismatch();
}
if (expectedResult.expectedEvaluation != result.expectedEvaluation) revert ExpectedEvaluationMismatch();
bytes32 challenge = keccak256(abi.encode(resultTranscript));
if (expectedChallenge != challenge) revert TranscriptMismatch();
}
}
4 changes: 4 additions & 0 deletions crates/proof-of-sql/src/proof_primitive/sumcheck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ use prover_state::ProverState;
mod prover_round;
use prover_round::prove_round;

#[cfg(test)]
mod sol_test;
#[cfg(test)]
pub mod sol_types;
#[cfg(test)]
mod test_cases;
68 changes: 68 additions & 0 deletions crates/proof-of-sql/src/proof_primitive/sumcheck/sol_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use super::{
sol_types::Sumcheck::{Proof as SolProof, Subclaim as SolSubclaim},
test_cases::sumcheck_test_cases,
SumcheckProof,
};
use crate::{
base::{
polynomial::CompositePolynomialInfo,
proof::{Keccak256Transcript, Transcript},
scalar::test_scalar::{TestMontConfig, TestScalar},
},
tests::ForgeScript,
};
use alloy_sol_types::private::primitives::{B256, U256};

#[test]
#[ignore = "Because forge needs to be installed, we are ignoring this test by default. They will still be run from within the ci."]
fn we_can_correctly_verify_many_random_test_cases_with_solidity() {
let mut rng = ark_std::test_rng();

for test_case in sumcheck_test_cases::<TestScalar>(&mut rng) {
// Generate proof
let mut transcript = Keccak256Transcript::new();
transcript.extend_as_le_from_refs([b"sumchecktest"]);
let _transcript_start_hash = transcript.challenge_as_le();
let mut evaluation_point = vec![Default::default(); test_case.num_vars];
let proof = SumcheckProof::create(
&mut transcript,
&mut evaluation_point,
&test_case.polynomial,
);
let _transcript_end_hash = transcript.challenge_as_le();

// Verify with Rust verifier
let mut transcript = Keccak256Transcript::new();
transcript.extend_as_le_from_refs([b"sumchecktest"]);
let transcript_start_hash = transcript.challenge_as_le();
let subclaim = proof
.verify_without_evaluation(
&mut transcript,
CompositePolynomialInfo {
max_multiplicands: test_case.max_multiplicands,
num_variables: test_case.num_vars,
},
&test_case.sum,
)
.expect("verification should succeed with the correct setup");
let transcript_end_hash = transcript.challenge_as_le();

// Verify with Solidity verifier
ForgeScript::new(
"./sol_src/proof_primitive/sumcheck/Sumcheck.t.sol",
"rustTestVerification",
)
.arg(SolProof::from(proof.clone()))
.arg(B256::from(transcript_start_hash))
.arg(u16::try_from(test_case.max_multiplicands).unwrap())
.arg(u16::try_from(test_case.num_vars).unwrap())
.arg(U256::from_limbs(test_case.sum.into()))
.arg(U256::from_limbs(
<TestMontConfig as ark_ff::MontConfig<4>>::MODULUS.0,
))
.arg(SolSubclaim::from(subclaim))
.arg(B256::from(transcript_end_hash))
.execute()
.unwrap();
}
}
31 changes: 31 additions & 0 deletions crates/proof-of-sql/src/proof_primitive/sumcheck/sol_types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use super::{proof::Subclaim, SumcheckProof};
use crate::base::scalar::Scalar;
use alloy_sol_types::{private::primitives::U256, sol};

sol!("./sol_src/proof_primitive/sumcheck/Sumcheck.sol");

impl<S: Scalar> From<SumcheckProof<S>> for Sumcheck::Proof {
fn from(value: SumcheckProof<S>) -> Self {
Self {
coefficients: value
.coefficients
.into_iter()
.map(Into::into)
.map(U256::from_limbs)
.collect(),
}
}
}
impl<S: Scalar> From<Subclaim<S>> for Sumcheck::Subclaim {
fn from(value: Subclaim<S>) -> Self {
Self {
evaluationPoint: value
.evaluation_point
.into_iter()
.map(Into::into)
.map(U256::from_limbs)
.collect(),
expectedEvaluation: U256::from_limbs(value.expected_evaluation.into()),
}
}
}

0 comments on commit 82c741f

Please sign in to comment.