gnark is a fast zk-SNARK library that offers a high-level API to design circuits. The library is open source and developed under the Apache 2.0 license
Serialization and Deserialization of the prover key leads to the an error in the Plonk Prover.
For recreation of the issue, please find the following complete example:
package main
import (
"os"
"github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark/backend/plonk"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/test"
)
// Circuit defines a simple circuit
// x**3 + x + 5 == y
type CubicCircuit struct {
// struct tags on a variable is optional
// default uses variable name and secret visibility.
X frontend.Variable `gnark:"x"`
Y frontend.Variable `gnark:",public"`
}
// Define declares the circuit constraints
// x**3 + x + 5 == y
func (circuit *CubicCircuit) Define(api frontend.API) error {
x3 := api.Mul(circuit.X, circuit.X, circuit.X)
api.AssertIsEqual(circuit.Y, api.Add(x3, circuit.X, 5))
return nil
}
func main() {
ccs, err := frontend.Compile(bn254.ID.ScalarField(), scs.NewBuilder, &CubicCircuit{})
if err != nil {
panic("Error in compilation of constraint system!")
}
srs, err := test.NewKZGSRS(ccs)
if err != nil {
panic("Error in KZG")
}
pk, _, err := plonk.Setup(ccs, srs)
if err != nil {
panic("Error in Setup")
}
// SERIALIZATION + DESERIALIZATION BEGIN
// Open the file in write mode for pk
fPK, err := os.OpenFile("pk.dat", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
panic("Failed to open file for writing: " + err.Error())
}
defer fPK.Close()
_, err = pk.WriteTo(fPK)
if err != nil {
panic("Failed to write pk to file: " + err.Error())
}
pk_deserialized := plonk.NewProvingKey(bn254.ID)
// Read PK
f, err := os.Open("pk.dat")
if err != nil {
panic("Failed to open file: " + err.Error())
}
_, err = pk_deserialized.ReadFrom(f)
if err != nil {
panic("Failed to read from file: " + err.Error())
}
// SERIALIZATION + DESERIALIZATION END
witness := CubicCircuit{}
witness.X = "3"
witness.Y = "35"
w, err := frontend.NewWitness(&witness, bn254.ID.ScalarField())
_, err = plonk.Prove(ccs, pk_deserialized, w)
if err != nil {
panic("Proving Fails! " + err.Error())
}
}
If executed with pk, it succeeds, if executed with pk_deserialized, it fails.
09:41:14 DBG constraint system solver done nbConstraints=4 took=0.092125
panic: Proving Fails! invalid polynomial size (larger than SRS or == 0)
I suppose this is related to the logic for compressed/uncompressed serialization and deserialization.
I noticed that for groth16, the API exposes both WriteTo and WriteRawTo.
With uncompressed serialization for groth16 (WriteRawTo) the above example works fine.
Serialization and Deserialization of the prover key leads to the an error in the Plonk Prover. For recreation of the issue, please find the following complete example:
If executed with
pk
, it succeeds, if executed withpk_deserialized
, it fails.For version
the following error is returned:
For the develop branch, i.e. the following version,
the error returned is
I suppose this is related to the logic for compressed/uncompressed serialization and deserialization. I noticed that for groth16, the API exposes both
WriteTo
andWriteRawTo
. With uncompressed serialization for groth16 (WriteRawTo
) the above example works fine.