Browse Source

Step test case with public inputs (#23)

* added step test case

* export solidity code

* just set proof's public input as public variables

* make serialization a command line option

* added flag to output solidity

* some changes to the benchmark file

* used gnark cherry picked bug fix

* removed fuzz testing

* added some logging

* more debug messages and test cases for the hint issue

* removed usage of goldilocks reduce

* removed prints

* removed GoldilocksReduce

* removed prints

* added a todo

* some serialization changes
main
Kevin Jue 2 years ago
committed by GitHub
parent
commit
9ce7bb7dbb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 17093 additions and 94 deletions
  1. +49
    -37
      benchmark.go
  2. +2
    -9
      field/goldilocks.go
  3. +2
    -0
      go.mod
  4. +0
    -2
      go.sum
  5. +5
    -15
      poseidon/poseidon.go
  6. +24
    -0
      poseidon/public_inputs_hash_test.go
  7. +181
    -0
      verifier/data/step/common_circuit_data.json
  8. +16697
    -0
      verifier/data/step/proof_with_public_inputs.json
  9. +21
    -0
      verifier/data/step/verifier_only_circuit_data.json
  10. +1
    -1
      verifier/internal/plonk/plonk_test.go
  11. +19
    -17
      verifier/verifier.go
  12. +92
    -13
      verifier/verifier_test.go

+ 49
- 37
benchmark.go

@ -6,22 +6,25 @@ import (
"os" "os"
"time" "time"
"github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier" "github.com/succinctlabs/gnark-plonky2-verifier/verifier"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common" "github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils" "github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
"github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend/groth16" "github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/constraint"
"github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/r1cs" "github.com/consensys/gnark/frontend/cs/r1cs"
"github.com/consensys/gnark/profile" "github.com/consensys/gnark/profile"
) )
type BenchmarkPlonky2VerifierCircuit struct { type BenchmarkPlonky2VerifierCircuit struct {
ProofWithPis common.ProofWithPublicInputs `gnark:",public"`
Proof common.Proof
PublicInputs []field.F `gnark:",public"`
verifierChip *verifier.VerifierChip
plonky2CircuitName string
verifierChip *verifier.VerifierChip `gnark:"-"`
plonky2CircuitName string `gnark:"-"`
} }
func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error { func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error {
@ -31,20 +34,21 @@ func (circuit *BenchmarkPlonky2VerifierCircuit) Define(api frontend.API) error {
circuit.verifierChip = verifier.NewVerifierChip(api, commonCircuitData) circuit.verifierChip = verifier.NewVerifierChip(api, commonCircuitData)
circuit.verifierChip.Verify(circuit.ProofWithPis, verifierOnlyCircuitData, commonCircuitData)
circuit.verifierChip.Verify(circuit.Proof, circuit.PublicInputs, verifierOnlyCircuitData, commonCircuitData)
return nil return nil
} }
func compileCircuit(plonky2Circuit string, doProfiling bool) {
func compileCircuit(plonky2Circuit string, profileCircuit bool, serialize bool, outputSolidity bool) (constraint.ConstraintSystem, groth16.ProvingKey, groth16.VerifyingKey) {
circuit := BenchmarkPlonky2VerifierCircuit{ circuit := BenchmarkPlonky2VerifierCircuit{
plonky2CircuitName: plonky2Circuit, plonky2CircuitName: plonky2Circuit,
} }
proofWithPis := utils.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json") proofWithPis := utils.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit.ProofWithPis = proofWithPis
circuit.Proof = proofWithPis.Proof
circuit.PublicInputs = proofWithPis.PublicInputs
var p *profile.Profile var p *profile.Profile
if doProfiling {
if profileCircuit {
p = profile.Start() p = profile.Start()
} }
r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
@ -53,7 +57,7 @@ func compileCircuit(plonky2Circuit string, doProfiling bool) {
os.Exit(1) os.Exit(1)
} }
if doProfiling {
if profileCircuit {
p.Stop() p.Stop()
p.Top() p.Top()
println("r1cs.GetNbCoefficients(): ", r1cs.GetNbCoefficients()) println("r1cs.GetNbCoefficients(): ", r1cs.GetNbCoefficients())
@ -63,9 +67,14 @@ func compileCircuit(plonky2Circuit string, doProfiling bool) {
println("r1cs.GetNbInternalVariables(): ", r1cs.GetNbInternalVariables()) println("r1cs.GetNbInternalVariables(): ", r1cs.GetNbInternalVariables())
} }
fR1CS, _ := os.Create("circuit")
r1cs.WriteTo(fR1CS)
fR1CS.Close()
// Don't serialize the circuit for now, since it takes up too much memory
/*
if serialize {
fR1CS, _ := os.Create("circuit")
r1cs.WriteTo(fR1CS)
fR1CS.Close()
}
*/
fmt.Println("Running circuit setup", time.Now()) fmt.Println("Running circuit setup", time.Now())
pk, vk, err := groth16.Setup(r1cs) pk, vk, err := groth16.Setup(r1cs)
@ -74,42 +83,37 @@ func compileCircuit(plonky2Circuit string, doProfiling bool) {
os.Exit(1) os.Exit(1)
} }
fPK, _ := os.Create("proving.key")
pk.WriteTo(fPK)
fPK.Close()
if serialize {
fPK, _ := os.Create("proving.key")
pk.WriteTo(fPK)
fPK.Close()
fVK, _ := os.Create("verifying.key")
vk.WriteTo(fVK)
fVK.Close()
fVK, _ := os.Create("verifying.key")
vk.WriteTo(fVK)
fVK.Close()
}
if outputSolidity {
fSolidity, _ := os.Create("proof.sol")
err = vk.ExportSolidity(fSolidity)
}
return r1cs, pk, vk
} }
func createProof(plonky2Circuit string) groth16.Proof {
func createProof(plonky2Circuit string, r1cs constraint.ConstraintSystem, pk groth16.ProvingKey, vk groth16.VerifyingKey, serialize bool) groth16.Proof {
proofWithPis := utils.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json") proofWithPis := utils.DeserializeProofWithPublicInputs("./verifier/data/" + plonky2Circuit + "/proof_with_public_inputs.json")
// Witness // Witness
assignment := &BenchmarkPlonky2VerifierCircuit{ assignment := &BenchmarkPlonky2VerifierCircuit{
ProofWithPis: proofWithPis,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
} }
fmt.Println("Generating witness", time.Now()) fmt.Println("Generating witness", time.Now())
witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField()) witness, _ := frontend.NewWitness(assignment, ecc.BN254.ScalarField())
publicWitness, _ := witness.Public() publicWitness, _ := witness.Public()
r1cs := groth16.NewCS(ecc.BN254)
fR1CS, _ := os.Open("circuit")
r1cs.ReadFrom(fR1CS)
fR1CS.Close()
var pk groth16.ProvingKey
fPK, _ := os.Open("proving.key")
pk.ReadFrom(fPK)
fPK.Close()
var vk groth16.VerifyingKey
fVK, _ := os.Open("verifying.key")
vk.ReadFrom(fVK)
fVK.Close()
fmt.Println("Creating proof", time.Now()) fmt.Println("Creating proof", time.Now())
proof, err := groth16.Prove(r1cs, pk, witness) proof, err := groth16.Prove(r1cs, pk, witness)
if err != nil { if err != nil {
@ -123,12 +127,20 @@ func createProof(plonky2Circuit string) groth16.Proof {
os.Exit(1) os.Exit(1)
} }
if serialize {
fProof, _ := os.Create("proof.proof")
proof.WriteTo(fProof)
}
return proof return proof
} }
func main() { func main() {
plonky2Circuit := flag.String("plonky2-circuit", "", "plonky2 circuit to benchmark") plonky2Circuit := flag.String("plonky2-circuit", "", "plonky2 circuit to benchmark")
doProfile := flag.Bool("profile", false, "profile the circuit")
profileCircuit := flag.Bool("profile", false, "profile the circuit")
serialize := flag.Bool("serialize", false, "serialize the circuit")
outputSolidity := flag.Bool("solidity", false, "output solidity code for the circuit")
flag.Parse() flag.Parse()
if plonky2Circuit == nil || *plonky2Circuit == "" { if plonky2Circuit == nil || *plonky2Circuit == "" {
@ -136,6 +148,6 @@ func main() {
os.Exit(1) os.Exit(1)
} }
compileCircuit(*plonky2Circuit, *doProfile)
createProof(*plonky2Circuit)
r1cs, pk, vk := compileCircuit(*plonky2Circuit, *profileCircuit, *serialize, *outputSolidity)
createProof(*plonky2Circuit, r1cs, pk, vk, *serialize)
} }

+ 2
- 9
field/goldilocks.go

@ -165,12 +165,12 @@ func GoldilocksMulAdd(api frontend.API, operand1, operand2, operand3 frontend.Va
func GoldilocksMulAddHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error { func GoldilocksMulAddHint(_ *big.Int, inputs []*big.Int, results []*big.Int) error {
if len(inputs) != 3 { if len(inputs) != 3 {
return fmt.Errorf("GoldilocksMulAddHint expects 3 input operands")
panic("GoldilocksMulAddHint expects 3 input operands")
} }
for _, operand := range inputs { for _, operand := range inputs {
if operand.Cmp(GOLDILOCKS_MODULUS) >= 0 { if operand.Cmp(GOLDILOCKS_MODULUS) >= 0 {
return fmt.Errorf("%s is not in the field", operand.String())
panic(fmt.Sprintf("%s is not in the field", operand.String()))
} }
} }
@ -184,10 +184,3 @@ func GoldilocksMulAddHint(_ *big.Int, inputs []*big.Int, results []*big.Int) err
return nil return nil
} }
func GoldilocksReduce(api frontend.API, x frontend.Variable) frontend.Variable {
// Use gnark's emulated field library.
fieldAPI := NewFieldAPI(api)
element := fieldAPI.NewElement(x)
return fieldAPI.Reduce(element).Limbs[0]
}

+ 2
- 0
go.mod

@ -27,3 +27,5 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect rsc.io/tmplfunc v0.0.3 // indirect
) )
replace github.com/consensys/gnark => /Users/kevin/succinctlabs/gnark

+ 0
- 2
go.sum

@ -2,8 +2,6 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark v0.8.0 h1:0bQ2MyDG4oNjMQpNyL8HjrrUSSL3yYJg0Elzo6LzmcU=
github.com/consensys/gnark v0.8.0/go.mod h1:aKmA7dIiLbTm0OV37xTq0z+Bpe4xER8EhRLi6necrm8=
github.com/consensys/gnark-crypto v0.9.1 h1:mru55qKdWl3E035hAoh1jj9d7hVnYY5pfb6tmovSmII= github.com/consensys/gnark-crypto v0.9.1 h1:mru55qKdWl3E035hAoh1jj9d7hVnYY5pfb6tmovSmII=
github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=

+ 5
- 15
poseidon/poseidon.go

@ -172,12 +172,11 @@ func (c *PoseidonChip) mdsRowShf(r int, v [SPONGE_WIDTH]frontend.Variable) front
for i := 0; i < 12; i++ { for i := 0; i < 12; i++ {
if i < SPONGE_WIDTH { if i < SPONGE_WIDTH {
res1 := c.api.Mul(v[(i+r)%SPONGE_WIDTH], MDS_MATRIX_CIRC_VARS[i])
res = c.api.Add(res, res1)
res = field.GoldilocksMulAdd(c.api, v[(i+r)%SPONGE_WIDTH], MDS_MATRIX_CIRC_VARS[i], res)
} }
} }
res = c.api.Add(res, c.api.Mul(v[r], MDS_MATRIX_DIAG_VARS[r]))
res = field.GoldilocksMulAdd(c.api, v[r], MDS_MATRIX_DIAG_VARS[r], res)
return res return res
} }
@ -203,15 +202,9 @@ func (c *PoseidonChip) mdsLayer(state_ PoseidonState) PoseidonState {
result[i] = frontend.Variable(0) result[i] = frontend.Variable(0)
} }
var state [SPONGE_WIDTH]frontend.Variable
for i := 0; i < SPONGE_WIDTH; i++ {
state[i] = field.GoldilocksReduce(c.api, state_[i])
}
for r := 0; r < 12; r++ { for r := 0; r < 12; r++ {
if r < SPONGE_WIDTH { if r < SPONGE_WIDTH {
sum := c.mdsRowShf(r, state)
result[r] = field.GoldilocksReduce(c.api, sum)
result[r] = c.mdsRowShf(r, state_)
} }
} }
@ -298,14 +291,11 @@ func (c *PoseidonChip) mdsPartialLayerFast(state PoseidonState, r int) PoseidonS
for i := 1; i < 12; i++ { for i := 1; i < 12; i++ {
if i < SPONGE_WIDTH { if i < SPONGE_WIDTH {
t := FAST_PARTIAL_ROUND_W_HATS_VARS[r][i-1] t := FAST_PARTIAL_ROUND_W_HATS_VARS[r][i-1]
reducedState := field.GoldilocksReduce(c.api, state[i])
dSum = c.api.Add(dSum, c.api.Mul(reducedState, t))
dSum = field.GoldilocksMulAdd(c.api, state[i], t, dSum)
} }
} }
s0 := field.GoldilocksReduce(c.api, state[0])
dSum = c.api.Add(dSum, c.api.Mul(s0, MDS0TO0_VAR))
d := field.GoldilocksReduce(c.api, dSum)
d := field.GoldilocksMulAdd(c.api, state[0], MDS0TO0_VAR, dSum)
var result PoseidonState var result PoseidonState
for i := 0; i < SPONGE_WIDTH; i++ { for i := 0; i < SPONGE_WIDTH; i++ {

+ 24
- 0
poseidon/public_inputs_hash_test.go

@ -4,6 +4,7 @@ import (
"testing" "testing"
"github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/test" "github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field" "github.com/succinctlabs/gnark-plonky2-verifier/field"
@ -58,3 +59,26 @@ func TestPublicInputsHashWitness(t *testing.T) {
copy(out[:], utils.StrArrayToFrontendVariableArray(outStr)) copy(out[:], utils.StrArrayToFrontendVariableArray(outStr))
testCase(in, out) testCase(in, out)
} }
func TestPublicInputsHashWitness2(t *testing.T) {
assert := test.NewAssert(t)
inStr := []string{"0", "1", "3736710860384812976"}
outStr := []string{"8416658900775745054", "12574228347150446423", "9629056739760131473", "3119289788404190010"}
var in [3]frontend.Variable
var out [4]frontend.Variable
copy(in[:], utils.StrArrayToFrontendVariableArray(inStr))
copy(out[:], utils.StrArrayToFrontendVariableArray(outStr))
circuit := TestPublicInputsHashCircuit{In: in, Out: out}
witness := TestPublicInputsHashCircuit{In: in, Out: out}
assert.ProverSucceeded(
&circuit,
&witness,
test.WithBackends(backend.GROTH16),
test.WithCurves(ecc.BN254),
test.NoFuzzing(),
test.NoSerialization(),
)
}

+ 181
- 0
verifier/data/step/common_circuit_data.json

@ -0,0 +1,181 @@
{
"config": {
"num_wires": 136,
"num_routed_wires": 80,
"num_constants": 2,
"use_base_arithmetic_gate": true,
"security_bits": 100,
"num_challenges": 2,
"zero_knowledge": false,
"max_quotient_degree_factor": 8,
"fri_config": {
"rate_bits": 3,
"cap_height": 4,
"proof_of_work_bits": 16,
"reduction_strategy": {
"ConstantArityBits": [
4,
5
]
},
"num_query_rounds": 28
}
},
"fri_params": {
"config": {
"rate_bits": 3,
"cap_height": 4,
"proof_of_work_bits": 16,
"reduction_strategy": {
"ConstantArityBits": [
4,
5
]
},
"num_query_rounds": 28
},
"hiding": false,
"degree_bits": 13,
"reduction_arity_bits": [
4,
4
]
},
"gates": [
"NoopGate",
"PoseidonMdsGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>",
"PublicInputGate",
"BaseSumGate { num_limbs: 63 } + Base: 2",
"ReducingExtensionGate { num_coeffs: 33 }",
"ReducingGate { num_coeffs: 44 }",
"ArithmeticExtensionGate { num_ops: 10 }",
"ArithmeticGate { num_ops: 20 }",
"MulExtensionGate { num_ops: 13 }",
"ExponentiationGate { num_power_bits: 67, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>",
"RandomAccessGate { bits: 4, num_copies: 4, num_extra_constants: 2, _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>",
"CosetInterpolationGate { subgroup_bits: 4, degree: 6, barycentric_weights: [17293822565076172801, 18374686475376656385, 18446744069413535745, 281474976645120, 17592186044416, 18446744069414584577, 18446744000695107601, 18446744065119617025, 1152921504338411520, 72057594037927936, 18446744069415632897, 18446462594437939201, 18446726477228539905, 18446744069414584065, 68719476720, 4294967296], _phantom: PhantomData<plonky2_field::goldilocks_field::GoldilocksField> }<D=2>",
"PoseidonGate(PhantomData<plonky2_field::goldilocks_field::GoldilocksField>)<WIDTH=12>"
],
"selectors_info": {
"selector_indices": [
0,
0,
0,
0,
0,
0,
1,
1,
1,
1,
2,
2,
3
],
"groups": [
{
"start": 0,
"end": 6
},
{
"start": 6,
"end": 10
},
{
"start": 10,
"end": 12
},
{
"start": 12,
"end": 13
}
]
},
"quotient_degree_factor": 8,
"num_gate_constraints": 123,
"num_constants": 6,
"num_public_inputs": 1350,
"k_is": [
1,
7,
49,
343,
2401,
16807,
117649,
823543,
5764801,
40353607,
282475249,
1977326743,
13841287201,
96889010407,
678223072849,
4747561509943,
33232930569601,
232630513987207,
1628413597910449,
11398895185373143,
79792266297612001,
558545864083284007,
3909821048582988049,
8922003270666332022,
7113790686420571191,
12903046666114829695,
16534350385145470581,
5059988279530788141,
16973173887300932666,
8131752794619022736,
1582037354089406189,
11074261478625843323,
3732854072722565977,
7683234439643377518,
16889152938674473984,
7543606154233811962,
15911754940807515092,
701820169165099718,
4912741184155698026,
15942444219675301861,
916645121239607101,
6416515848677249707,
8022122801911579307,
814627405137302186,
5702391835961115302,
3023254712898638472,
2716038920875884983,
565528376716610560,
3958698637016273920,
9264146389699333119,
9508792519651578870,
11221315429317299127,
4762231727562756605,
14888878023524711914,
11988425817600061793,
10132004445542095267,
15583798910550913906,
16852872026783475737,
7289639770996824233,
14133990258148600989,
6704211459967285318,
10035992080941828584,
14911712358349047125,
12148266161370408270,
11250886851934520606,
4969231685883306958,
16337877731768564385,
3684679705892444769,
7346013871832529062,
14528608963998534792,
9466542400916821939,
10925564598174000610,
2691975909559666986,
397087297503084581,
2779611082521592067,
1010533508236560148,
7073734557655921036,
12622653764762278610,
14571600075677612986,
9767480182670369297
],
"num_partial_products": 9
}

+ 16697
- 0
verifier/data/step/proof_with_public_inputs.json
File diff suppressed because it is too large
View File


+ 21
- 0
verifier/data/step/verifier_only_circuit_data.json

@ -0,0 +1,21 @@
{
"constants_sigmas_cap": [
"16410135397206963995867986152754239948699603273283903389293816335827918317917",
"793737431233885020076403438726099627357557537710771017261200370525509120433",
"12956281394520952097582330637773878261111274369940411254759688417761804822142",
"10577530380775003887407451820221412218265659263471194993014549768898454599785",
"13610846379681807478607563401071620391800469867382019709290833315244210704863",
"765151448660164966011013501838259753360401123903311092227424737087007538841",
"13786717651422653112944870403443265466526140408716569251322854236333823743208",
"12716088402533018234480445545939519356897157402541455414075663659898205294136",
"7714394992134137076670975536966103814585482420260383440808539140364081464561",
"21494844788603743891376885362562637287120172946709821128154824772001032728080",
"14153637094178605853060659242981358456456672896438884686797867119060652807634",
"8426523842338951741294543051254253278084158527312126154422449980067255373785",
"9336152063716553400528035177375603771317196761317425271006398060378250593421",
"19032686473689874529303788521545715886983137707759075261782048632012085567581",
"15713676428971866339564327334872368460630508652571308740737040859682008007854",
"11466448479127530610447443676955276964009242931295623425740153710621884444011"
],
"circuit_digest": "9787759494185596126611266365248694578977961103378519017707766709237231108177"
}

+ 1
- 1
verifier/internal/plonk/plonk_test.go

@ -24,7 +24,7 @@ func (circuit *TestPlonkCircuit) Define(api frontend.API) error {
verifierChip := verifier.NewVerifierChip(api, commonCircuitData) verifierChip := verifier.NewVerifierChip(api, commonCircuitData)
publicInputsHash := verifierChip.GetPublicInputsHash(proofWithPis.PublicInputs) publicInputsHash := verifierChip.GetPublicInputsHash(proofWithPis.PublicInputs)
proofChallenges := verifierChip.GetChallenges(proofWithPis, publicInputsHash, commonCircuitData, verifierOnlyCircuitData)
proofChallenges := verifierChip.GetChallenges(proofWithPis.Proof, publicInputsHash, commonCircuitData, verifierOnlyCircuitData)
fieldAPI := field.NewFieldAPI(api) fieldAPI := field.NewFieldAPI(api)
qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI) qeAPI := field.NewQuadraticExtensionAPI(api, fieldAPI)

+ 19
- 17
verifier/verifier.go

@ -47,7 +47,7 @@ func (c *VerifierChip) GetPublicInputsHash(publicInputs []field.F) poseidon.Pose
} }
func (c *VerifierChip) GetChallenges( func (c *VerifierChip) GetChallenges(
proofWithPis common.ProofWithPublicInputs,
proof common.Proof,
publicInputsHash poseidon.PoseidonHashOut, publicInputsHash poseidon.PoseidonHashOut,
commonData common.CommonCircuitData, commonData common.CommonCircuitData,
verifierData common.VerifierOnlyCircuitData, verifierData common.VerifierOnlyCircuitData,
@ -60,17 +60,17 @@ func (c *VerifierChip) GetChallenges(
challenger.ObserveBN128Hash(circuitDigest) challenger.ObserveBN128Hash(circuitDigest)
challenger.ObserveHash(publicInputsHash) challenger.ObserveHash(publicInputsHash)
challenger.ObserveCap(proofWithPis.Proof.WiresCap)
challenger.ObserveCap(proof.WiresCap)
plonkBetas := challenger.GetNChallenges(numChallenges) plonkBetas := challenger.GetNChallenges(numChallenges)
plonkGammas := challenger.GetNChallenges(numChallenges) plonkGammas := challenger.GetNChallenges(numChallenges)
challenger.ObserveCap(proofWithPis.Proof.PlonkZsPartialProductsCap)
challenger.ObserveCap(proof.PlonkZsPartialProductsCap)
plonkAlphas := challenger.GetNChallenges(numChallenges) plonkAlphas := challenger.GetNChallenges(numChallenges)
challenger.ObserveCap(proofWithPis.Proof.QuotientPolysCap)
challenger.ObserveCap(proof.QuotientPolysCap)
plonkZeta := challenger.GetExtensionChallenge() plonkZeta := challenger.GetExtensionChallenge()
challenger.ObserveOpenings(fri.ToFriOpenings(proofWithPis.Proof.Openings))
challenger.ObserveOpenings(fri.ToFriOpenings(proof.Openings))
return common.ProofChallenges{ return common.ProofChallenges{
PlonkBetas: plonkBetas, PlonkBetas: plonkBetas,
@ -78,9 +78,9 @@ func (c *VerifierChip) GetChallenges(
PlonkAlphas: plonkAlphas, PlonkAlphas: plonkAlphas,
PlonkZeta: plonkZeta, PlonkZeta: plonkZeta,
FriChallenges: challenger.GetFriChallenges( FriChallenges: challenger.GetFriChallenges(
proofWithPis.Proof.OpeningProof.CommitPhaseMerkleCaps,
proofWithPis.Proof.OpeningProof.FinalPoly,
proofWithPis.Proof.OpeningProof.PowWitness,
proof.OpeningProof.CommitPhaseMerkleCaps,
proof.OpeningProof.FinalPoly,
proof.OpeningProof.PowWitness,
commonData.DegreeBits, commonData.DegreeBits,
config.FriConfig, config.FriConfig,
), ),
@ -154,18 +154,20 @@ func (c *VerifierChip) generateProofInput(commonData common.CommonCircuitData) c
} }
*/ */
func (c *VerifierChip) Verify(proofWithPis common.ProofWithPublicInputs, verifierData common.VerifierOnlyCircuitData, commonData common.CommonCircuitData) {
func (c *VerifierChip) Verify(proof common.Proof, publicInputs []field.F, verifierData common.VerifierOnlyCircuitData, commonData common.CommonCircuitData) {
// TODO: Need to range check all the proof and public input elements to make sure they are within goldilocks field
// Generate the parts of the witness that is for the plonky2 proof input // Generate the parts of the witness that is for the plonky2 proof input
publicInputsHash := c.GetPublicInputsHash(proofWithPis.PublicInputs)
proofChallenges := c.GetChallenges(proofWithPis, publicInputsHash, commonData, verifierData)
publicInputsHash := c.GetPublicInputsHash(publicInputs)
proofChallenges := c.GetChallenges(proof, publicInputsHash, commonData, verifierData)
c.plonkChip.Verify(proofChallenges, proofWithPis.Proof.Openings, publicInputsHash)
c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
initialMerkleCaps := []common.MerkleCap{ initialMerkleCaps := []common.MerkleCap{
verifierData.ConstantSigmasCap, verifierData.ConstantSigmasCap,
proofWithPis.Proof.WiresCap,
proofWithPis.Proof.PlonkZsPartialProductsCap,
proofWithPis.Proof.QuotientPolysCap,
proof.WiresCap,
proof.PlonkZsPartialProductsCap,
proof.QuotientPolysCap,
} }
// Seems like there is a bug in the emulated field code. // Seems like there is a bug in the emulated field code.
@ -189,9 +191,9 @@ func (c *VerifierChip) Verify(proofWithPis common.ProofWithPublicInputs, verifie
c.friChip.VerifyFriProof( c.friChip.VerifyFriProof(
fri.GetFriInstance(&commonData, c.qeAPI, proofChallenges.PlonkZeta, commonData.DegreeBits), fri.GetFriInstance(&commonData, c.qeAPI, proofChallenges.PlonkZeta, commonData.DegreeBits),
fri.ToFriOpenings(proofWithPis.Proof.Openings),
fri.ToFriOpenings(proof.Openings),
&proofChallenges.FriChallenges, &proofChallenges.FriChallenges,
initialMerkleCaps, initialMerkleCaps,
&proofWithPis.Proof.OpeningProof,
&proof.OpeningProof,
) )
} }

+ 92
- 13
verifier/verifier_test.go

@ -3,42 +3,121 @@ package verifier_test
import ( import (
"testing" "testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/test" "github.com/consensys/gnark/test"
"github.com/succinctlabs/gnark-plonky2-verifier/field" "github.com/succinctlabs/gnark-plonky2-verifier/field"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier" "github.com/succinctlabs/gnark-plonky2-verifier/verifier"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/common"
"github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils" "github.com/succinctlabs/gnark-plonky2-verifier/verifier/utils"
) )
type TestVerifierCircuit struct { type TestVerifierCircuit struct {
proofWithPIsFilename string `gnark:"-"`
commonCircuitDataFilename string `gnark:"-"`
verifierOnlyCircuitDataFilename string `gnark:"-"`
Proof common.Proof
PublicInputs []field.F `gnark:",public"`
verifierChip *verifier.VerifierChip `gnark:"-"`
plonky2CircuitName string `gnark:"-"`
} }
func (c *TestVerifierCircuit) Define(api frontend.API) error { func (c *TestVerifierCircuit) Define(api frontend.API) error {
proofWithPis := utils.DeserializeProofWithPublicInputs(c.proofWithPIsFilename)
commonCircuitData := utils.DeserializeCommonCircuitData(c.commonCircuitDataFilename)
verfierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(c.verifierOnlyCircuitDataFilename)
circuitDirname := "./data/" + c.plonky2CircuitName + "/"
commonCircuitData := utils.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
verifierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(circuitDirname + "verifier_only_circuit_data.json")
c.verifierChip = verifier.NewVerifierChip(api, commonCircuitData)
c.verifierChip.Verify(c.Proof, c.PublicInputs, verifierOnlyCircuitData, commonCircuitData)
verifierChip := verifier.NewVerifierChip(api, commonCircuitData)
verifierChip.Verify(proofWithPis, verfierOnlyCircuitData, commonCircuitData)
return nil return nil
} }
func TestDecodeBlockVerifier(t *testing.T) {
func TestStepVerifier(t *testing.T) {
assert := test.NewAssert(t) assert := test.NewAssert(t)
testCase := func() { testCase := func() {
plonky2Circuit := "step"
proofWithPis := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit := TestVerifierCircuit{ circuit := TestVerifierCircuit{
proofWithPIsFilename: "./data/decode_block/proof_with_public_inputs.json",
commonCircuitDataFilename: "./data/decode_block/common_circuit_data.json",
verifierOnlyCircuitDataFilename: "./data/decode_block/verifier_only_circuit_data.json",
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
}
proofWithPis2 := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
witness := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis2.Proof,
PublicInputs: proofWithPis2.PublicInputs,
} }
witness := TestVerifierCircuit{}
err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField()) err := test.IsSolved(&circuit, &witness, field.TEST_CURVE.ScalarField())
assert.NoError(err) assert.NoError(err)
} }
testCase() testCase()
} }
func TestStepVerifier2(t *testing.T) {
assert := test.NewAssert(t)
plonky2Circuit := "step"
proofWithPis := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
circuit := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis.Proof,
PublicInputs: proofWithPis.PublicInputs,
}
proofWithPis2 := utils.DeserializeProofWithPublicInputs("./data/" + plonky2Circuit + "/proof_with_public_inputs.json")
witness := TestVerifierCircuit{
plonky2CircuitName: plonky2Circuit,
Proof: proofWithPis2.Proof,
PublicInputs: proofWithPis2.PublicInputs,
}
assert.ProverSucceeded(
&circuit,
&witness,
test.WithBackends(backend.GROTH16),
test.WithCurves(ecc.BN254),
test.NoFuzzing(),
test.NoSerialization(),
)
}
type testCircuit struct {
Arr [2]emulated.Element[emulated.Secp256k1Fp]
Expected emulated.Element[emulated.Secp256k1Fp]
}
func (circuit *testCircuit) Define(api frontend.API) error {
field, _ := emulated.NewField[emulated.Secp256k1Fp](api)
mulRes := field.Mul(&circuit.Arr[0], &circuit.Arr[1])
field.AssertIsEqual(mulRes, &circuit.Expected)
return nil
}
func TestMain(t *testing.T) {
assert := test.NewAssert(t)
var circuit testCircuit
assert.ProverSucceeded(
&circuit,
&testCircuit{
Arr: [2]emulated.Element[emulated.Secp256k1Fp]{
emulated.ValueOf[emulated.Secp256k1Fp](42),
emulated.ValueOf[emulated.Secp256k1Fp](24),
},
Expected: emulated.ValueOf[emulated.Secp256k1Fp](1008),
},
test.WithBackends(backend.GROTH16),
test.WithCurves(ecc.BN254),
test.NoFuzzing(),
test.NoSerialization(),
)
}

Loading…
Cancel
Save