-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add tests for Solidity sumcheck verifier
- Loading branch information
1 parent
7524301
commit 82c741f
Showing
4 changed files
with
137 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
crates/proof-of-sql/sol_src/proof_primitive/sumcheck/Sumcheck.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
crates/proof-of-sql/src/proof_primitive/sumcheck/sol_test.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
31
crates/proof-of-sql/src/proof_primitive/sumcheck/sol_types.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()), | ||
} | ||
} | ||
} |