Replies: 5 comments
-
Yes gnark supports BW6-633. It is the curve used to instantiate the SNARK that "reasons" about computations done over BLS24-315. For example in For PlonK or Groth16 implementation with BW6-633 see https://github.com/Consensys/gnark/tree/master/backend/plonk/bw6-633 and https://github.com/Consensys/gnark/tree/master/backend/groth16/bw6-633. |
Beta Was this translation helpful? Give feedback.
-
For PlonK recursion you can test it with: func TestBLS24InBW6Commit(t *testing.T) {
assert := test.NewAssert(t)
innerCcs, innerVK, innerWitness, innerProof := getInnerCommit(assert, ecc.BLS24_315.ScalarField(), ecc.BW6_633.ScalarField())
// outer proof
circuitVk, err := ValueOfVerifyingKey[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine](innerVK)
assert.NoError(err)
circuitWitness, err := ValueOfWitness[sw_bls24315.ScalarField](innerWitness)
assert.NoError(err)
circuitProof, err := ValueOfProof[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine](innerProof)
assert.NoError(err)
outerCircuit := &OuterCircuit[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine, sw_bls24315.GT]{
InnerWitness: PlaceholderWitness[sw_bls24315.ScalarField](innerCcs),
Proof: PlaceholderProof[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine](innerCcs),
VerifyingKey: circuitVk,
}
outerAssignment := &OuterCircuit[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine, sw_bls24315.GT]{
InnerWitness: circuitWitness,
Proof: circuitProof,
}
err = test.IsSolved(outerCircuit, outerAssignment, ecc.BW6_633.ScalarField())
assert.NoError(err)
} |
Beta Was this translation helpful? Give feedback.
-
I am implementing an IVC circuit, which will jump between 2-chain curve.
The following is my implementation, in the TestRecursion_Plonk_BLS12377_BW6761_BLS12377, sw_bw6761 can be used to define the outer2 circuit. while in TestRecursion_Plonk_BLS24315_BW6633_BLS24315, sw_bw6633 is not found, I suppose it should be "ithub.com/consensys/gnark/std/algebra/emulated/sw_bw6633" import (
"fmt"
"github.com/consensys/gnark-crypto/ecc"
backend_plonk "github.com/consensys/gnark/backend/plonk"
"github.com/consensys/gnark/backend/witness"
"github.com/consensys/gnark/constraint"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/std/algebra"
"github.com/consensys/gnark/std/algebra/emulated/sw_bw6761"
"github.com/consensys/gnark/std/algebra/native/sw_bls12377"
"github.com/consensys/gnark/std/algebra/native/sw_bls24315"
"github.com/consensys/gnark/std/math/bits"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/std/recursion/plonk"
"github.com/consensys/gnark/test"
"github.com/consensys/gnark/test/unsafekzg"
"math/big"
"testing"
"time"
)
/*
z0 = x0 + y0
z1 = z0 + x1
z2 = z1 + x2
z3 = z2 + x3
.....
z_n = z_{n-1} + x+n
*/
type InnerCircuit struct {
X, Y frontend.Variable
Z frontend.Variable `gnark:",public"`
}
func (c *InnerCircuit) Define(api frontend.API) error {
//make a commitment
x := api.Mul(c.X, c.X)
y := api.Mul(c.Y, c.Y)
z := api.Add(x, y)
committer, ok := api.(frontend.Committer)
if !ok {
return fmt.Errorf("builder does not implement frontend.Committer")
}
u, err := committer.Commit(x, z)
if err != nil {
return err
}
api.AssertIsDifferent(u, c.Z)
//IVC circuit
sum := api.Add(c.X, c.Y)
api.AssertIsEqual(sum, c.Z)
return nil
}
func getInnerCommit(assert *test.Assert, field, outer *big.Int) (constraint.ConstraintSystem, backend_plonk.VerifyingKey, witness.Witness, backend_plonk.Proof) {
innerCcs, err := frontend.Compile(field, scs.NewBuilder, &InnerCircuit{})
assert.NoError(err)
srs, srsLagrange, err := unsafekzg.NewSRS(innerCcs)
assert.NoError(err)
innerPK, innerVK, err := backend_plonk.Setup(innerCcs, srs, srsLagrange)
assert.NoError(err)
// inner proof
innerAssignment := &InnerCircuit{
X: 3,
Y: 5,
Z: 8,
}
innerWitness, err := frontend.NewWitness(innerAssignment, field)
assert.NoError(err)
innerProof, err := backend_plonk.Prove(innerCcs, innerPK, innerWitness, plonk.GetNativeProverOptions(outer, field))
assert.NoError(err)
innerPubWitness, err := innerWitness.Public()
assert.NoError(err)
err = backend_plonk.Verify(innerProof, innerVK, innerPubWitness, plonk.GetNativeVerifierOptions(outer, field))
assert.NoError(err)
return innerCcs, innerVK, innerPubWitness, innerProof
}
type OuterCircuit[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.GtElementT] struct {
Proof plonk.Proof[FR, G1El, G2El]
VerifyingKey plonk.VerifyingKey[FR, G1El, G2El] `gnark:"-"`
InnerWitness plonk.Witness[FR]
X frontend.Variable
Z frontend.Variable `gnark:",public"`
}
func (c *OuterCircuit[FR, G1El, G2El, GtEl]) Define(api frontend.API) error {
verifier, err := plonk.NewVerifier[FR, G1El, G2El, GtEl](api)
if err != nil {
return fmt.Errorf("new verifier: %w", err)
}
err = verifier.AssertProof(c.VerifyingKey, c.Proof, c.InnerWitness)
field, err := emulated.NewField[FR](api)
if err != nil {
return err
}
ybits := field.ToBits(&c.InnerWitness.Public[0])
y := bits.FromBinary(api, ybits)
sum := api.Add(c.X, y)
api.AssertIsEqual(sum, c.Z)
return err
}
func TestRecursion_Plonk_BLS12377_BW6761_BLS12377(t *testing.T) {
assert := test.NewAssert(t)
innerField := ecc.BLS12_377.ScalarField()
outer1Field := ecc.BW6_761.ScalarField()
outer2Field := ecc.BLS12_377.ScalarField()
innerCcs, innerVK, innerWitness, innerProof := getInnerCommit(assert, innerField, outer1Field)
//inputs for outer1
circuit1Vk, err := plonk.ValueOfVerifyingKey[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerVK)
assert.NoError(err)
circuit1Witness, err := plonk.ValueOfWitness[sw_bls12377.ScalarField](innerWitness)
assert.NoError(err)
circuit1Proof, err := plonk.ValueOfProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerProof)
assert.NoError(err)
outer1Circuit := &OuterCircuit[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
InnerWitness: plonk.PlaceholderWitness[sw_bls12377.ScalarField](innerCcs),
Proof: plonk.PlaceholderProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine](innerCcs),
VerifyingKey: circuit1Vk,
}
outer1Assignment := &OuterCircuit[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{
InnerWitness: circuit1Witness,
Proof: circuit1Proof,
X: 7,
Z: 15,
}
// compile the outer circuit
fmt.Printf("compile outer1 start...\n")
compileOuter1Start := time.Now()
outer1CCS, err := frontend.Compile(outer1Field, scs.NewBuilder, outer1Circuit)
if err != nil {
panic("compile failed: " + err.Error())
}
compileOuter1Duration := time.Since(compileOuter1Start)
fmt.Printf("compile outer1 duration:%v\n", compileOuter1Duration)
fmt.Printf("outer1 Ccs nbConstraints:%v, nbSecretWitness:%v, nbPublicInstance:%v\n", outer1CCS.GetNbConstraints(), outer1CCS.GetNbSecretVariables(), outer1CCS.GetNbPublicVariables())
// NB! UNSAFE! Use MPC.
fmt.Printf("generate start srs for outer1 circuit...\n")
generateOuter1SRSStart := time.Now()
outer1SRS, outer1SRSLagrange, err := unsafekzg.NewSRS(outer1CCS)
assert.NoError(err)
generateOuter1SRSDuration := time.Since(generateOuter1SRSStart)
fmt.Printf("generate outer1 srs duration:%v\n", generateOuter1SRSDuration)
// create PLONK setup. NB! UNSAFE
fmt.Printf("setup outer1 start...\n")
setupOuter1Start := time.Now()
outer1PK, outer1VK, err := backend_plonk.Setup(outer1CCS, outer1SRS, outer1SRSLagrange) // UNSAFE! Use MPC
assert.NoError(err)
setupOuter1Duration := time.Since(setupOuter1Start)
fmt.Printf("setup outer1 duration:%v\n", setupOuter1Duration)
// create prover witness from the assignment
outer1SecretWitness, err := frontend.NewWitness(outer1Assignment, outer1Field)
assert.NoError(err)
// create public witness from the assignment
outer1PublicWitness, err := outer1SecretWitness.Public()
assert.NoError(err)
// construct the PLONK proof of verifying PLONK proof in-circuit
fmt.Printf("prove outer1 start...\n")
proveOuter1Start := time.Now()
outer1Proof, err := backend_plonk.Prove(outer1CCS, outer1PK, outer1SecretWitness, plonk.GetNativeProverOptions(outer2Field, outer1Field))
assert.NoError(err)
proveOuter1Duration := time.Since(proveOuter1Start)
fmt.Printf("prove outer1 duration:%v\n", proveOuter1Duration)
// verify the PLONK proof
fmt.Printf("verify outer1 start...\n")
verifyOuter1Start := time.Now()
err = backend_plonk.Verify(outer1Proof, outer1VK, outer1PublicWitness, plonk.GetNativeVerifierOptions(outer2Field, outer1Field))
assert.NoError(err)
verifyOuter1Duration := time.Since(verifyOuter1Start)
fmt.Printf("verify outer1 duration:%v\n", verifyOuter1Duration)
//inputs for outer2
circuit2Vk, err := plonk.ValueOfVerifyingKey[sw_bw6761.ScalarField, sw_bw6761.G1Affine, sw_bw6761.G2Affine](outer1VK)
assert.NoError(err)
circuit2Witness, err := plonk.ValueOfWitness[sw_bw6761.ScalarField](outer1PublicWitness)
assert.NoError(err)
circuit2Proof, err := plonk.ValueOfProof[sw_bw6761.ScalarField, sw_bw6761.G1Affine, sw_bw6761.G2Affine](outer1Proof)
assert.NoError(err)
outer2Circuit := &OuterCircuit[sw_bw6761.ScalarField, sw_bw6761.G1Affine, sw_bw6761.G2Affine, sw_bw6761.GTEl]{
InnerWitness: plonk.PlaceholderWitness[sw_bw6761.ScalarField](outer1CCS),
Proof: plonk.PlaceholderProof[sw_bw6761.ScalarField, sw_bw6761.G1Affine, sw_bw6761.G2Affine](outer1CCS),
VerifyingKey: circuit2Vk,
}
outer2Assignment := &OuterCircuit[sw_bw6761.ScalarField, sw_bw6761.G1Affine, sw_bw6761.G2Affine, sw_bw6761.GTEl]{
InnerWitness: circuit2Witness,
Proof: circuit2Proof,
X: 9,
Z: 24,
}
// compile the outer circuit
fmt.Printf("compile outer2 start...\n")
compileOuter2Start := time.Now()
outer2CCS, err := frontend.Compile(outer2Field, scs.NewBuilder, outer2Circuit)
if err != nil {
panic("compile failed: " + err.Error())
}
compileOuter2Duration := time.Since(compileOuter2Start)
fmt.Printf("compile outer2 duration:%v\n", compileOuter2Duration)
fmt.Printf("outer2 CCS nbConstraints:%v, nbSecretWitness:%v, nbPublicInstance:%v\n", outer2CCS.GetNbConstraints(), outer2CCS.GetNbSecretVariables(), outer2CCS.GetNbPublicVariables())
// NB! UNSAFE! Use MPC.
fmt.Printf("generate start srs for outer2 circuit...\n")
generateOuter2SRSStart := time.Now()
outer2SRS, outer2SRSLagrange, err := unsafekzg.NewSRS(outer2CCS)
assert.NoError(err)
generateOuter2SRSDuration := time.Since(generateOuter2SRSStart)
fmt.Printf("generate outer2 srs duration:%v\n", generateOuter2SRSDuration)
// create PLONK setup. NB! UNSAFE
fmt.Printf("setup outer2 start...\n")
setupOuter2Start := time.Now()
outer2PK, outer2VK, err := backend_plonk.Setup(outer2CCS, outer2SRS, outer2SRSLagrange) // UNSAFE! Use MPC
assert.NoError(err)
setupOuter2Duration := time.Since(setupOuter2Start)
fmt.Printf("setup outer2 duration:%v\n", setupOuter2Duration)
// create prover witness from the assignment
outer2SecretWitness, err := frontend.NewWitness(outer2Assignment, outer2Field)
assert.NoError(err)
// create public witness from the assignment
outer2PublicWitness, err := outer2SecretWitness.Public()
assert.NoError(err)
// construct the PLONK proof of verifying PLONK proof in-circuit
fmt.Printf("prove outer2 start...\n")
proveOuter2Start := time.Now()
outer2Proof, err := backend_plonk.Prove(outer2CCS, outer2PK, outer2SecretWitness)
assert.NoError(err)
proveOuter2Duration := time.Since(proveOuter2Start)
fmt.Printf("prove outer2 duration:%v\n", proveOuter2Duration)
// verify the PLONK proof
fmt.Printf("verify outer2 start...\n")
verifyOuter2Start := time.Now()
err = backend_plonk.Verify(outer2Proof, outer2VK, outer2PublicWitness)
assert.NoError(err)
verifyOuter2Duration := time.Since(verifyOuter2Start)
fmt.Printf("verify outer2 duration:%v\n", verifyOuter2Duration)
}
func TestRecursion_Plonk_BLS24315_BW6633_BLS24315(t *testing.T) {
assert := test.NewAssert(t)
innerField := ecc.BLS24_315.ScalarField()
outer1Field := ecc.BW6_633.ScalarField()
outer2Field := ecc.BLS24_315.ScalarField()
innerCcs, innerVK, innerWitness, innerProof := getInnerCommit(assert, innerField, outer1Field)
//inputs for outer1
circuit1Vk, err := plonk.ValueOfVerifyingKey[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine](innerVK)
assert.NoError(err)
circuit1Witness, err := plonk.ValueOfWitness[sw_bls24315.ScalarField](innerWitness)
assert.NoError(err)
circuit1Proof, err := plonk.ValueOfProof[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine](innerProof)
assert.NoError(err)
outer1Circuit := &OuterCircuit[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine, sw_bls24315.GT]{
InnerWitness: plonk.PlaceholderWitness[sw_bls24315.ScalarField](innerCcs),
Proof: plonk.PlaceholderProof[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine](innerCcs),
VerifyingKey: circuit1Vk,
}
outer1Assignment := &OuterCircuit[sw_bls24315.ScalarField, sw_bls24315.G1Affine, sw_bls24315.G2Affine, sw_bls24315.GT]{
InnerWitness: circuit1Witness,
Proof: circuit1Proof,
X: 7,
Z: 15,
}
// compile the outer circuit
fmt.Printf("compile outer1 start...\n")
compileOuter1Start := time.Now()
outer1CCS, err := frontend.Compile(outer1Field, scs.NewBuilder, outer1Circuit)
if err != nil {
panic("compile failed: " + err.Error())
}
compileOuter1Duration := time.Since(compileOuter1Start)
fmt.Printf("compile outer1 duration:%v\n", compileOuter1Duration)
fmt.Printf("outer1 Ccs nbConstraints:%v, nbSecretWitness:%v, nbPublicInstance:%v\n", outer1CCS.GetNbConstraints(), outer1CCS.GetNbSecretVariables(), outer1CCS.GetNbPublicVariables())
// NB! UNSAFE! Use MPC.
fmt.Printf("generate start srs for outer1 circuit...\n")
generateOuter1SRSStart := time.Now()
outer1SRS, outer1SRSLagrange, err := unsafekzg.NewSRS(outer1CCS)
assert.NoError(err)
generateOuter1SRSDuration := time.Since(generateOuter1SRSStart)
fmt.Printf("generate outer1 srs duration:%v\n", generateOuter1SRSDuration)
// create PLONK setup. NB! UNSAFE
fmt.Printf("setup outer1 start...\n")
setupOuter1Start := time.Now()
outer1PK, outer1VK, err := backend_plonk.Setup(outer1CCS, outer1SRS, outer1SRSLagrange) // UNSAFE! Use MPC
assert.NoError(err)
setupOuter1Duration := time.Since(setupOuter1Start)
fmt.Printf("setup outer1 duration:%v\n", setupOuter1Duration)
// create prover witness from the assignment
outer1SecretWitness, err := frontend.NewWitness(outer1Assignment, outer1Field)
assert.NoError(err)
// create public witness from the assignment
outer1PublicWitness, err := outer1SecretWitness.Public()
assert.NoError(err)
// construct the PLONK proof of verifying PLONK proof in-circuit
fmt.Printf("prove outer1 start...\n")
proveOuter1Start := time.Now()
outer1Proof, err := backend_plonk.Prove(outer1CCS, outer1PK, outer1SecretWitness, plonk.GetNativeProverOptions(outer2Field, outer1Field))
assert.NoError(err)
proveOuter1Duration := time.Since(proveOuter1Start)
fmt.Printf("prove outer1 duration:%v\n", proveOuter1Duration)
// verify the PLONK proof
fmt.Printf("verify outer1 start...\n")
verifyOuter1Start := time.Now()
err = backend_plonk.Verify(outer1Proof, outer1VK, outer1PublicWitness, plonk.GetNativeVerifierOptions(outer2Field, outer1Field))
assert.NoError(err)
verifyOuter1Duration := time.Since(verifyOuter1Start)
fmt.Printf("verify outer1 duration:%v\n", verifyOuter1Duration)
//inputs for outer2
circuit2Vk, err := plonk.ValueOfVerifyingKey[sw_bw6633.ScalarField, sw_bw6633.G1Affine, sw_bw6633.G2Affine](outer1VK)
assert.NoError(err)
circuit2Witness, err := plonk.ValueOfWitness[sw_bw6633.ScalarField](outer1PublicWitness)
assert.NoError(err)
circuit2Proof, err := plonk.ValueOfProof[sw_bw6633.ScalarField, sw_bw6633.G1Affine, sw_bw6633.G2Affine](outer1Proof)
assert.NoError(err)
outer2Circuit := &OuterCircuit[sw_bw6633.ScalarField, sw_bw6633.G1Affine, sw_bw6633.G2Affine, sw_bw6633.GTEl]{
InnerWitness: plonk.PlaceholderWitness[sw_bw6633.ScalarField](outer1CCS),
Proof: plonk.PlaceholderProof[sw_bw6633.ScalarField, sw_bw6633.G1Affine, sw_bw6633.G2Affine](outer1CCS),
VerifyingKey: circuit2Vk,
}
outer2Assignment := &OuterCircuit[sw_bw6633.ScalarField, sw_bw6633.G1Affine, sw_bw6633.G2Affine, sw_bw6633.GTEl]{
InnerWitness: circuit2Witness,
Proof: circuit2Proof,
X: 9,
Z: 24,
}
// compile the outer circuit
fmt.Printf("compile outer2 start...\n")
compileOuter2Start := time.Now()
outer2CCS, err := frontend.Compile(outer2Field, scs.NewBuilder, outer2Circuit)
if err != nil {
panic("compile failed: " + err.Error())
}
compileOuter2Duration := time.Since(compileOuter2Start)
fmt.Printf("compile outer2 duration:%v\n", compileOuter2Duration)
fmt.Printf("outer2 CCS nbConstraints:%v, nbSecretWitness:%v, nbPublicInstance:%v\n", outer2CCS.GetNbConstraints(), outer2CCS.GetNbSecretVariables(), outer2CCS.GetNbPublicVariables())
// NB! UNSAFE! Use MPC.
fmt.Printf("generate start srs for outer2 circuit...\n")
generateOuter2SRSStart := time.Now()
outer2SRS, outer2SRSLagrange, err := unsafekzg.NewSRS(outer2CCS)
assert.NoError(err)
generateOuter2SRSDuration := time.Since(generateOuter2SRSStart)
fmt.Printf("generate outer2 srs duration:%v\n", generateOuter2SRSDuration)
// create PLONK setup. NB! UNSAFE
fmt.Printf("setup outer2 start...\n")
setupOuter2Start := time.Now()
outer2PK, outer2VK, err := backend_plonk.Setup(outer2CCS, outer2SRS, outer2SRSLagrange) // UNSAFE! Use MPC
assert.NoError(err)
setupOuter2Duration := time.Since(setupOuter2Start)
fmt.Printf("setup outer2 duration:%v\n", setupOuter2Duration)
// create prover witness from the assignment
outer2SecretWitness, err := frontend.NewWitness(outer2Assignment, outer2Field)
assert.NoError(err)
// create public witness from the assignment
outer2PublicWitness, err := outer2SecretWitness.Public()
assert.NoError(err)
// construct the PLONK proof of verifying PLONK proof in-circuit
fmt.Printf("prove outer2 start...\n")
proveOuter2Start := time.Now()
outer2Proof, err := backend_plonk.Prove(outer2CCS, outer2PK, outer2SecretWitness)
assert.NoError(err)
proveOuter2Duration := time.Since(proveOuter2Start)
fmt.Printf("prove outer2 duration:%v\n", proveOuter2Duration)
// verify the PLONK proof
fmt.Printf("verify outer2 start...\n")
verifyOuter2Start := time.Now()
err = backend_plonk.Verify(outer2Proof, outer2VK, outer2PublicWitness)
assert.NoError(err)
verifyOuter2Duration := time.Since(verifyOuter2Start)
fmt.Printf("verify outer2 duration:%v\n", verifyOuter2Duration)
} |
Beta Was this translation helpful? Give feedback.
-
Ah ok what you're looking for is the non-native implementation of BW6-633 pairing in a SNARK circuit. No indeed it's not implemented yet but you can have a shot at it! it should be similar to That is interesting! for what project are you trying to use BLS24/BW6 chain? Are you for now just trying to compare it to BLS12/BW6 chain or did identify a potential need for it? Thank you for all the issues btw @readygo67 |
Beta Was this translation helpful? Give feedback.
-
We are implementing a ZKP for ETH2, but syncCommittee + bls12-381 signature's circuit size is about 200M. It's too huge for a single circuit, so plan to use recursion to achieve our goal. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
In https://eprint.iacr.org/2021/1359, BLS24-315/BW6-633 pair is suitable for plonk recursion, I find BLS24-315 in gnark, but I can not find BW6-633 implementation in gnark/algebra.
where can I find BW6-633?
Beta Was this translation helpful? Give feedback.
All reactions