-
Notifications
You must be signed in to change notification settings - Fork 400
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug: cannot recursively create a witness (of inner circuit) in the production engine #1079
Comments
The lines that panic was trying to compile the outer circuit:
Which was trying to recursively create another witness for inner circuit verification within the Define() function of the outer circuit:
|
Have a look at the full written PLONK recursion example: https://pkg.go.dev/github.com/consensys/[email protected]/std/recursion/plonk#example-package-Emulated For the inner circuit witness assignment, we need to use Rather, you should use package main
import (
"fmt"
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend/plonk"
cs "github.com/consensys/gnark/constraint/bn254"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/std/algebra/emulated/sw_bn254"
recursive_plonk "github.com/consensys/gnark/std/recursion/plonk"
"github.com/consensys/gnark/test/unsafekzg"
)
type innerCircuit struct {
X frontend.Variable
Y frontend.Variable `gnark:",public"`
}
func (c *innerCircuit) Define(api frontend.API) error {
api.AssertIsEqual(c.X, c.Y)
return nil
}
type outerCircuit struct {
VKey recursive_plonk.VerifyingKey[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine]
Proof recursive_plonk.Proof[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine]
InnerWitness recursive_plonk.Witness[sw_bn254.ScalarField]
}
func (c *outerCircuit) Define(api frontend.API) error {
verifier, err := recursive_plonk.NewVerifier[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine, sw_bn254.GTEl](api)
if err != nil {
panic(err)
}
return verifier.AssertProof(c.VKey, c.Proof, c.InnerWitness, recursive_plonk.WithCompleteArithmetic())
}
func testBody() {
inner := innerCircuit{}
ccsInner, _ := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &inner)
scsInner := ccsInner.(*cs.SparseR1CS)
srs, srsLagrange, err := unsafekzg.NewSRS(scsInner, unsafekzg.WithFSCache())
if err != nil {
panic(err)
}
pkInner, vkInner, err := plonk.Setup(ccsInner, srs, srsLagrange)
if err != nil {
panic(err)
}
wInner := innerCircuit{X: 5, Y: 5}
witnessInner, err := frontend.NewWitness(&wInner, ecc.BN254.ScalarField())
if err != nil {
panic(err)
}
proofInner, err := plonk.Prove(ccsInner, pkInner, witnessInner,
recursive_plonk.GetNativeProverOptions(ecc.BN254.ScalarField(), ecc.BN254.ScalarField()))
if err != nil {
panic(err)
}
witnessInnerPublic, err := witnessInner.Public()
if err != nil {
panic(err)
}
err = plonk.Verify(proofInner, vkInner, witnessInnerPublic,
recursive_plonk.GetNativeVerifierOptions(ecc.BN254.ScalarField(), ecc.BN254.ScalarField()))
if err != nil {
panic(err)
}
recursiveProof, err := recursive_plonk.ValueOfProof[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine](proofInner)
if err != nil {
panic(err)
}
recursiveVK, err := recursive_plonk.ValueOfVerifyingKey[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine](vkInner)
if err != nil {
panic(err)
}
outer := outerCircuit{
VKey: recursive_plonk.PlaceholderVerifyingKey[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine](ccsInner),
Proof: recursive_plonk.PlaceholderProof[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine](ccsInner),
InnerWitness: recursive_plonk.PlaceholderWitness[sw_bn254.ScalarField](ccsInner),
}
innerWitness, err := recursive_plonk.ValueOfWitness[sw_bn254.ScalarField](witnessInnerPublic)
if err != nil {
panic(err)
}
outerW := outerCircuit{
VKey: recursiveVK,
Proof: recursiveProof,
InnerWitness: innerWitness,
}
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &outer)
if err != nil {
panic(err)
}
srs2, srsLagrange2, err := unsafekzg.NewSRS(ccs, unsafekzg.WithFSCache())
if err != nil {
panic(err)
}
pk, vk, err := plonk.Setup(ccs, srs2, srsLagrange2)
if err != nil {
panic(err)
}
fmt.Println("proving ...")
outerWitess, err := frontend.NewWitness(&outerW, ecc.BN254.ScalarField())
if err != nil {
panic(err)
}
proof, err := plonk.Prove(ccs, pk, outerWitess,
recursive_plonk.GetNativeProverOptions(ecc.BN254.ScalarField(), ecc.BN254.ScalarField()))
if err != nil {
panic(err)
}
fmt.Println("verifying ...")
pubOuterWitness, err := outerWitess.Public()
if err != nil {
panic(err)
}
err = plonk.Verify(proof, vk, pubOuterWitness,
recursive_plonk.GetNativeVerifierOptions(ecc.BN254.ScalarField(), ecc.BN254.ScalarField()))
if err != nil {
panic(err)
}
}
func TestMain(t *testing.T) {
testBody()
} NB, the inner circuit is simple and brings out some edge cases which usually do not happen (for complex inner circuits, due to randomization). This requires using |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Description
During recursive verification, sometimes we need to use the witness/public input values of the outer circuit to assemble a witness to be verified by the inner circuit. However, this does not work: the outer circuit cannot compile, reporting
can't set fr.Element from type expr.Term
Codes below:
Expected Behavior
That running the test should pass the outer circuit proving and verification.
Actual Behavior
Possible Fix
Maybe some data are kept during circuit parsing?
Steps to Reproduce
Run the above codes.
Context
We are trying to create a library called chainark, which could be used to prove a chain-like structure recursively, and provides a validity proof for each element in the chain, basing its validity on its valid linking to its predecessor and all the way back to the genesis element.
In this project, we need to assemble some witness values for the inner circuit within the Define() function of the outer circuit. And we encountered the reported issue. The above codes is much simplified just to illustrated the issue.
Your Environment
HEAD@master
, plus some commits from New Feature: compute the fingerprint of a Plonk verification key for recursive verification #1062, which shall not impact the issue.HEAD@master
, plus some commits from feat: added HashToG2 circuit for BLS12-381 gnark-crypto#481, which shall not impact the issue.The text was updated successfully, but these errors were encountered: