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.
-
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