mirror of
https://github.com/arnaucube/gnark-plonky2-verifier.git
synced 2026-01-12 00:51:33 +01:00
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
This commit is contained in:
86
benchmark.go
86
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
|
verifierChip *verifier.VerifierChip `gnark:"-"`
|
||||||
plonky2CircuitName string
|
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")
|
// Don't serialize the circuit for now, since it takes up too much memory
|
||||||
r1cs.WriteTo(fR1CS)
|
/*
|
||||||
fR1CS.Close()
|
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")
|
if serialize {
|
||||||
pk.WriteTo(fPK)
|
fPK, _ := os.Create("proving.key")
|
||||||
fPK.Close()
|
pk.WriteTo(fPK)
|
||||||
|
fPK.Close()
|
||||||
|
|
||||||
fVK, _ := os.Create("verifying.key")
|
fVK, _ := os.Create("verifying.key")
|
||||||
vk.WriteTo(fVK)
|
vk.WriteTo(fVK)
|
||||||
fVK.Close()
|
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)
|
r1cs, pk, vk := compileCircuit(*plonky2Circuit, *profileCircuit, *serialize, *outputSolidity)
|
||||||
createProof(*plonky2Circuit)
|
createProof(*plonky2Circuit, r1cs, pk, vk, *serialize)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
go.mod
2
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
|
||||||
|
|||||||
2
go.sum
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=
|
||||||
|
|||||||
@@ -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 = field.GoldilocksMulAdd(c.api, v[(i+r)%SPONGE_WIDTH], MDS_MATRIX_CIRC_VARS[i], res)
|
||||||
res = c.api.Add(res, res1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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] = c.mdsRowShf(r, state_)
|
||||||
result[r] = field.GoldilocksReduce(c.api, sum)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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 = field.GoldilocksMulAdd(c.api, state[i], t, dSum)
|
||||||
dSum = c.api.Add(dSum, c.api.Mul(reducedState, t))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s0 := field.GoldilocksReduce(c.api, state[0])
|
d := field.GoldilocksMulAdd(c.api, state[0], MDS0TO0_VAR, dSum)
|
||||||
dSum = c.api.Add(dSum, c.api.Mul(s0, MDS0TO0_VAR))
|
|
||||||
d := field.GoldilocksReduce(c.api, dSum)
|
|
||||||
|
|
||||||
var result PoseidonState
|
var result PoseidonState
|
||||||
for i := 0; i < SPONGE_WIDTH; i++ {
|
for i := 0; i < SPONGE_WIDTH; i++ {
|
||||||
|
|||||||
@@ -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
verifier/data/step/common_circuit_data.json
Normal file
181
verifier/data/step/common_circuit_data.json
Normal file
@@ -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
verifier/data/step/proof_with_public_inputs.json
Normal file
16697
verifier/data/step/proof_with_public_inputs.json
Normal file
File diff suppressed because it is too large
Load Diff
21
verifier/data/step/verifier_only_circuit_data.json
Normal file
21
verifier/data/step/verifier_only_circuit_data.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,
|
proof.OpeningProof.CommitPhaseMerkleCaps,
|
||||||
proofWithPis.Proof.OpeningProof.FinalPoly,
|
proof.OpeningProof.FinalPoly,
|
||||||
proofWithPis.Proof.OpeningProof.PowWitness,
|
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) {
|
||||||
// Generate the parts of the witness that is for the plonky2 proof input
|
// TODO: Need to range check all the proof and public input elements to make sure they are within goldilocks field
|
||||||
publicInputsHash := c.GetPublicInputsHash(proofWithPis.PublicInputs)
|
|
||||||
proofChallenges := c.GetChallenges(proofWithPis, publicInputsHash, commonData, verifierData)
|
|
||||||
|
|
||||||
c.plonkChip.Verify(proofChallenges, proofWithPis.Proof.Openings, publicInputsHash)
|
// Generate the parts of the witness that is for the plonky2 proof input
|
||||||
|
publicInputsHash := c.GetPublicInputsHash(publicInputs)
|
||||||
|
proofChallenges := c.GetChallenges(proof, publicInputsHash, commonData, verifierData)
|
||||||
|
|
||||||
|
c.plonkChip.Verify(proofChallenges, proof.Openings, publicInputsHash)
|
||||||
|
|
||||||
initialMerkleCaps := []common.MerkleCap{
|
initialMerkleCaps := []common.MerkleCap{
|
||||||
verifierData.ConstantSigmasCap,
|
verifierData.ConstantSigmasCap,
|
||||||
proofWithPis.Proof.WiresCap,
|
proof.WiresCap,
|
||||||
proofWithPis.Proof.PlonkZsPartialProductsCap,
|
proof.PlonkZsPartialProductsCap,
|
||||||
proofWithPis.Proof.QuotientPolysCap,
|
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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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:"-"`
|
Proof common.Proof
|
||||||
commonCircuitDataFilename string `gnark:"-"`
|
PublicInputs []field.F `gnark:",public"`
|
||||||
verifierOnlyCircuitDataFilename string `gnark:"-"`
|
|
||||||
|
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)
|
circuitDirname := "./data/" + c.plonky2CircuitName + "/"
|
||||||
commonCircuitData := utils.DeserializeCommonCircuitData(c.commonCircuitDataFilename)
|
commonCircuitData := utils.DeserializeCommonCircuitData(circuitDirname + "common_circuit_data.json")
|
||||||
verfierOnlyCircuitData := utils.DeserializeVerifierOnlyCircuitData(c.verifierOnlyCircuitDataFilename)
|
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",
|
plonky2CircuitName: plonky2Circuit,
|
||||||
commonCircuitDataFilename: "./data/decode_block/common_circuit_data.json",
|
Proof: proofWithPis.Proof,
|
||||||
verifierOnlyCircuitDataFilename: "./data/decode_block/verifier_only_circuit_data.json",
|
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(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user