2023-05-19 19:49:14 -07:00
package verifier
2022-10-10 16:41:42 -07:00
2022-10-10 20:45:34 -07:00
import (
"github.com/consensys/gnark/frontend"
2023-07-24 16:08:17 -07:00
"github.com/succinctlabs/gnark-plonky2-verifier/challenger"
"github.com/succinctlabs/gnark-plonky2-verifier/fri"
gl "github.com/succinctlabs/gnark-plonky2-verifier/goldilocks"
"github.com/succinctlabs/gnark-plonky2-verifier/plonk"
2023-05-19 19:49:14 -07:00
"github.com/succinctlabs/gnark-plonky2-verifier/poseidon"
2023-07-24 16:08:17 -07:00
"github.com/succinctlabs/gnark-plonky2-verifier/types"
2022-10-10 20:45:34 -07:00
)
type VerifierChip struct {
2023-07-24 16:18:37 -07:00
api frontend . API ` gnark:"-" `
2023-10-10 22:32:54 -07:00
glChip * gl . GoldilocksApi ` gnark:"-" `
2023-07-24 16:18:37 -07:00
poseidonGlChip * poseidon . GoldilocksChip ` gnark:"-" `
poseidonBN254Chip * poseidon . BN254Chip ` gnark:"-" `
plonkChip * plonk . PlonkChip ` gnark:"-" `
friChip * fri . Chip ` gnark:"-" `
2022-11-21 14:49:54 -08:00
}
2023-07-24 16:08:17 -07:00
func NewVerifierChip ( api frontend . API , commonCircuitData types . CommonCircuitData ) * VerifierChip {
2023-10-10 22:32:54 -07:00
glChip := gl . NewGoldilocksApi ( api )
2023-07-24 16:08:17 -07:00
friChip := fri . NewChip ( api , & commonCircuitData . FriParams )
plonkChip := plonk . NewPlonkChip ( api , commonCircuitData )
poseidonGlChip := poseidon . NewGoldilocksChip ( api )
poseidonBN254Chip := poseidon . NewBN254Chip ( api )
2022-11-21 14:49:54 -08:00
return & VerifierChip {
2023-06-06 17:36:51 -07:00
api : api ,
2023-07-24 16:18:37 -07:00
glChip : glChip ,
2023-07-24 16:08:17 -07:00
poseidonGlChip : poseidonGlChip ,
poseidonBN254Chip : poseidonBN254Chip ,
2023-06-06 17:36:51 -07:00
plonkChip : plonkChip ,
friChip : friChip ,
2022-11-21 14:49:54 -08:00
}
2022-10-10 20:45:34 -07:00
}
2023-10-11 11:37:45 -07:00
func ( c * VerifierChip ) GetPublicInputsHash ( publicInputs [ ] gl . Variable ) poseidon . GoldilocksHashOut {
2023-07-24 16:08:17 -07:00
return c . poseidonGlChip . HashNoPad ( publicInputs )
2022-10-10 20:45:34 -07:00
}
2023-05-19 19:49:14 -07:00
func ( c * VerifierChip ) GetChallenges (
2023-07-24 16:08:17 -07:00
proof types . Proof ,
publicInputsHash poseidon . GoldilocksHashOut ,
commonData types . CommonCircuitData ,
verifierData types . VerifierOnlyCircuitData ,
) types . ProofChallenges {
2022-10-10 20:45:34 -07:00
config := commonData . Config
numChallenges := config . NumChallenges
2023-07-24 16:08:17 -07:00
challenger := challenger . NewChip ( c . api )
2022-10-10 20:45:34 -07:00
2023-05-01 10:26:45 -07:00
var circuitDigest = verifierData . CircuitDigest
2022-10-10 22:44:59 -07:00
2023-07-24 16:08:17 -07:00
challenger . ObserveBN254Hash ( circuitDigest )
2022-10-10 20:45:34 -07:00
challenger . ObserveHash ( publicInputsHash )
2023-06-17 19:44:20 -07:00
challenger . ObserveCap ( proof . WiresCap )
2022-10-10 20:45:34 -07:00
plonkBetas := challenger . GetNChallenges ( numChallenges )
plonkGammas := challenger . GetNChallenges ( numChallenges )
2023-06-17 19:44:20 -07:00
challenger . ObserveCap ( proof . PlonkZsPartialProductsCap )
2022-10-10 20:45:34 -07:00
plonkAlphas := challenger . GetNChallenges ( numChallenges )
2023-06-17 19:44:20 -07:00
challenger . ObserveCap ( proof . QuotientPolysCap )
2022-10-10 20:45:34 -07:00
plonkZeta := challenger . GetExtensionChallenge ( )
2023-07-24 16:08:17 -07:00
challenger . ObserveOpenings ( fri . ToOpenings ( proof . Openings ) )
2022-10-10 20:45:34 -07:00
2023-07-24 16:08:17 -07:00
return types . ProofChallenges {
2022-10-10 20:45:34 -07:00
PlonkBetas : plonkBetas ,
PlonkGammas : plonkGammas ,
PlonkAlphas : plonkAlphas ,
PlonkZeta : plonkZeta ,
FriChallenges : challenger . GetFriChallenges (
2023-06-17 19:44:20 -07:00
proof . OpeningProof . CommitPhaseMerkleCaps ,
proof . OpeningProof . FinalPoly ,
proof . OpeningProof . PowWitness ,
2022-10-10 21:23:30 -07:00
commonData . DegreeBits ,
config . FriConfig ,
2022-10-10 20:45:34 -07:00
) ,
}
}
2023-05-25 07:39:06 -07:00
/ *
func ( c * VerifierChip ) generateProofInput ( commonData common . CommonCircuitData ) common . ProofWithPublicInputs {
// Generate the parts of the witness that is for the plonky2 proof input
capHeight := commonData . Config . FriConfig . CapHeight
friCommitPhaseMerkleCaps := [ ] common . MerkleCap { }
for i := 0 ; i < len ( commonData . FriParams . ReductionArityBits ) ; i ++ {
friCommitPhaseMerkleCaps = append ( friCommitPhaseMerkleCaps , common . NewMerkleCap ( capHeight ) )
}
salt := commonData . SaltSize ( )
numLeavesPerOracle := [ ] uint {
commonData . NumPreprocessedPolys ( ) ,
commonData . Config . NumWires + salt ,
commonData . NumZsPartialProductsPolys ( ) + salt ,
commonData . NumQuotientPolys ( ) + salt ,
}
friQueryRoundProofs := [ ] common . FriQueryRound { }
for i := uint64 ( 0 ) ; i < commonData . FriParams . Config . NumQueryRounds ; i ++ {
evalProofs := [ ] common . EvalProof { }
merkleProofLen := commonData . FriParams . LDEBits ( ) - capHeight
for _ , numLeaves := range numLeavesPerOracle {
leaves := make ( [ ] field . F , numLeaves )
merkleProof := common . NewMerkleProof ( merkleProofLen )
evalProofs = append ( evalProofs , common . NewEvalProof ( leaves , merkleProof ) )
}
initialTreesProof := common . NewFriInitialTreeProof ( evalProofs )
steps := [ ] common . FriQueryStep { }
for _ , arityBit := range commonData . FriParams . ReductionArityBits {
if merkleProofLen < arityBit {
panic ( "merkleProofLen < arityBits" )
}
steps = append ( steps , common . NewFriQueryStep ( arityBit , merkleProofLen ) )
}
friQueryRoundProofs = append ( friQueryRoundProofs , common . NewFriQueryRound ( steps , initialTreesProof ) )
}
proofInput := common . ProofWithPublicInputs {
Proof : common . Proof {
WiresCap : common . NewMerkleCap ( capHeight ) ,
PlonkZsPartialProductsCap : common . NewMerkleCap ( capHeight ) ,
QuotientPolysCap : common . NewMerkleCap ( capHeight ) ,
Openings : common . NewOpeningSet (
commonData . Config . NumConstants ,
commonData . Config . NumRoutedWires ,
commonData . Config . NumWires ,
commonData . Config . NumChallenges ,
commonData . NumPartialProducts ,
commonData . QuotientDegreeFactor ,
) ,
OpeningProof : common . FriProof {
CommitPhaseMerkleCaps : friCommitPhaseMerkleCaps ,
QueryRoundProofs : friQueryRoundProofs ,
FinalPoly : common . NewPolynomialCoeffs ( commonData . FriParams . FinalPolyLen ( ) ) ,
} ,
} ,
PublicInputs : make ( [ ] field . F , commonData . NumPublicInputs ) ,
}
2022-11-01 16:35:21 -07:00
2023-05-25 07:39:06 -07:00
return proofInput
}
* /
2023-07-24 16:18:37 -07:00
func ( c * VerifierChip ) rangeCheckProof ( proof types . Proof ) {
// Need to verify the plonky2 proof's openings, openings proof (other than the sibling elements), fri's final poly, pow witness.
// Note that this is NOT range checking the public inputs (first 32 elements should be no more than 8 bits and the last 4 elements should be no more than 64 bits). Since this is currently being inputted via the smart contract,
// we will assume that caller is doing that check.
// Range check the proof's openings.
for _ , constant := range proof . Openings . Constants {
c . glChip . RangeCheckQE ( constant )
}
for _ , plonkSigma := range proof . Openings . PlonkSigmas {
c . glChip . RangeCheckQE ( plonkSigma )
}
for _ , wire := range proof . Openings . Wires {
c . glChip . RangeCheckQE ( wire )
}
for _ , plonkZ := range proof . Openings . PlonkZs {
c . glChip . RangeCheckQE ( plonkZ )
}
for _ , plonkZNext := range proof . Openings . PlonkZsNext {
c . glChip . RangeCheckQE ( plonkZNext )
}
for _ , partialProduct := range proof . Openings . PartialProducts {
c . glChip . RangeCheckQE ( partialProduct )
}
for _ , quotientPoly := range proof . Openings . QuotientPolys {
c . glChip . RangeCheckQE ( quotientPoly )
}
// Range check the openings proof.
for _ , queryRound := range proof . OpeningProof . QueryRoundProofs {
for _ , initialTreesElement := range queryRound . InitialTreesProof . EvalsProofs [ 0 ] . Elements {
c . glChip . RangeCheck ( initialTreesElement )
}
for _ , queryStep := range queryRound . Steps {
for _ , eval := range queryStep . Evals {
c . glChip . RangeCheckQE ( eval )
}
}
}
// Range check the fri's final poly.
for _ , coeff := range proof . OpeningProof . FinalPoly . Coeffs {
c . glChip . RangeCheckQE ( coeff )
}
// Range check the pow witness.
c . glChip . RangeCheck ( proof . OpeningProof . PowWitness )
}
2023-07-24 16:08:17 -07:00
func ( c * VerifierChip ) Verify (
proof types . Proof ,
2023-10-11 11:37:45 -07:00
publicInputs [ ] gl . Variable ,
2023-07-24 16:08:17 -07:00
verifierData types . VerifierOnlyCircuitData ,
commonData types . CommonCircuitData ,
) {
2023-07-24 16:18:37 -07:00
c . rangeCheckProof ( proof )
2023-06-17 19:44:20 -07:00
2023-05-25 07:39:06 -07:00
// Generate the parts of the witness that is for the plonky2 proof input
2023-06-17 19:44:20 -07:00
publicInputsHash := c . GetPublicInputsHash ( publicInputs )
proofChallenges := c . GetChallenges ( proof , publicInputsHash , commonData , verifierData )
2022-11-21 14:49:54 -08:00
2023-06-17 19:44:20 -07:00
c . plonkChip . Verify ( proofChallenges , proof . Openings , publicInputsHash )
2022-11-21 14:49:54 -08:00
2023-07-24 16:08:17 -07:00
initialMerkleCaps := [ ] types . FriMerkleCap {
2022-11-21 14:49:54 -08:00
verifierData . ConstantSigmasCap ,
2023-06-17 19:44:20 -07:00
proof . WiresCap ,
proof . PlonkZsPartialProductsCap ,
proof . QuotientPolysCap ,
2022-11-21 14:49:54 -08:00
}
c . friChip . VerifyFriProof (
2023-07-24 16:18:37 -07:00
fri . GetInstance ( & commonData , c . glChip , proofChallenges . PlonkZeta , commonData . DegreeBits ) ,
2023-07-24 16:08:17 -07:00
fri . ToOpenings ( proof . Openings ) ,
2022-11-21 14:49:54 -08:00
& proofChallenges . FriChallenges ,
initialMerkleCaps ,
2023-06-17 19:44:20 -07:00
& proof . OpeningProof ,
2022-11-21 14:49:54 -08:00
)
2022-10-10 20:45:34 -07:00
}