diff --git a/CHANGELOG.md b/CHANGELOG.md index 64d29e56cb..54d8289e14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,60 @@ + +## [v0.7.0] - 2022-03-25 + +### Build +- go.mod: go version upgrade 1.16 --> go1.17 +- update to gnark-crpto v0.7.0 + +### Feat +- adds gnark logger. closes [#202](https://github.com/consensys/gnark/issues/202) +- added internal/stats package: measure number of constraints of circuit snippets for regression +- adds std/math/bits/ToNAF ToBinary ToTernary + +### Fix +- enables recursive hints solving [#293](https://github.com/consensys/gnark/issues/293) and +- move init() behind sync.Once. remove verbose option in stats binary +- fixes [#266](https://github.com/consensys/gnark/issues/266) by adding constant path in Lookup2 and Select +- incorrect handling of nbBits == 1 in api.ToBinary + + +### Perf +- restored frontend.WithCapacity option... +- **plonk:** IsConstant -> ConstantValue +- **sw:** no need for Lookup2 in constScalarMul +- remove offset shifts in plonk compile +- remove post-compile offset id in R1CS builder + +### Refactor +- `frontend.Compile` now takes a builder instead of backendID as parameter +- `std/signature/eddsa` `Verify` api now takes explicit hash and curve objects +- make nboutputs of a hint explicit at compile time +- std/pairing have more consistent apis +- remove StaticHint wrapper, log duplicate hints ([#289](https://github.com/consensys/gnark/issues/289)) +- backend.WithOutput -> backend.WithCircuitLogger +- remove all internal circuits from stats, keep important snippets only +- frontend: split compiler, api and builder interface into interfaces +- remove IsBoolean from R1CS variables +- moved internal/compiled to frontend/compiled + + +### Pull Requests +- Merge pull request [#295](https://github.com/consensys/gnark/issues/295) from ConsenSys/fix/test-println +- Merge pull request [#294](https://github.com/consensys/gnark/issues/294) from ConsenSys/fix/recursivehhints +- Merge pull request [#291](https://github.com/consensys/gnark/issues/291) from ConsenSys/refactor/std/pairing +- Merge pull request [#281](https://github.com/consensys/gnark/issues/281) from ConsenSys/feat/logger +- Merge pull request [#280](https://github.com/consensys/gnark/issues/280) from ConsenSys/simplify-r1cs-compile +- Merge pull request [#279](https://github.com/consensys/gnark/issues/279) from ConsenSys/feat/statistics +- Merge pull request [#276](https://github.com/consensys/gnark/issues/276) from ConsenSys/feat-math-bits +- Merge pull request [#278](https://github.com/consensys/gnark/issues/278) from ConsenSys/perf-constant-lookup2 +- Merge pull request [#272](https://github.com/consensys/gnark/issues/272) from ConsenSys/refactor-hint +- Merge pull request [#275](https://github.com/consensys/gnark/issues/275) from ConsenSys/refactor-compiler-builder +- Merge pull request [#271](https://github.com/consensys/gnark/issues/271) from ConsenSys/refactor-compiled +- Merge pull request [#267](https://github.com/consensys/gnark/issues/267) from ConsenSys/perf/tEd-add +- Merge pull request [#265](https://github.com/consensys/gnark/issues/265) from ConsenSys/perf/SW-constScalarMul + + + + ## [v0.6.4] - 2022-02-15 diff --git a/debug_test.go b/debug_test.go index 1f0992b723..f2fda2a272 100644 --- a/debug_test.go +++ b/debug_test.go @@ -1,4 +1,4 @@ -package gnark +package gnark_test import ( "bytes" diff --git a/doc.go b/doc.go index 7d091f8579..c4b35c5556 100644 --- a/doc.go +++ b/doc.go @@ -15,3 +15,10 @@ // User documentation // https://docs.gnark.consensys.net package gnark + +import "github.com/consensys/gnark-crypto/ecc" + +// Curves return the curves supported by gnark +func Curves() []ecc.ID { + return []ecc.ID{ecc.BN254, ecc.BLS12_377, ecc.BLS12_381, ecc.BW6_761, ecc.BLS24_315, ecc.BW6_633} +} diff --git a/go.mod b/go.mod index d07a8940e2..4c751ac48a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/consensys/bavard v0.1.10 - github.com/consensys/gnark-crypto v0.6.2-0.20220317143658-fb0d80a11bf4 + github.com/consensys/gnark-crypto v0.7.0 github.com/fxamacker/cbor/v2 v2.2.0 github.com/leanovate/gopter v0.2.9 github.com/rs/zerolog v1.26.1 diff --git a/go.sum b/go.sum index 94c6aeee84..d448dde776 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/consensys/bavard v0.1.10 h1:1I/IvY7bkX/O7QLNCEuV2+YBKdTetzw3gnBbvFaWiEE= github.com/consensys/bavard v0.1.10/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.6.2-0.20220317143658-fb0d80a11bf4 h1:ZsuTwNqDe83xtYP8SplQ9iOoXgOoLg9WzP04VfqOjGc= -github.com/consensys/gnark-crypto v0.6.2-0.20220317143658-fb0d80a11bf4/go.mod h1:BnexKTAHX6j7zpGXR/s6E/R0tyYtbnXlbhIMQkNdcPs= +github.com/consensys/gnark-crypto v0.7.0 h1:rwdy8+ssmLYRqKp+ryRRgQJl/rCq2uv+n83cOydm5UE= +github.com/consensys/gnark-crypto v0.7.0/go.mod h1:KPSuJzyxkJA8xZ/+CV47tyqkr9MmpZA3PXivK4VPrVg= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -33,7 +33,6 @@ github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= @@ -41,7 +40,6 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -56,7 +54,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/integration_test.go b/integration_test.go index 8a20ee246e..87ac042998 100644 --- a/integration_test.go +++ b/integration_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package gnark +package gnark_test import ( "fmt" diff --git a/internal/backend/bls12-377/plonk/prove.go b/internal/backend/bls12-377/plonk/prove.go index 6ca6e89893..ecbf54c532 100644 --- a/internal/backend/bls12-377/plonk/prove.go +++ b/internal/backend/bls12-377/plonk/prove.go @@ -62,6 +62,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bls12_377witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -109,11 +110,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bls12_377witness.Witn return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/backend/bls12-377/plonk/verify.go b/internal/backend/bls12-377/plonk/verify.go index 360576717b..e466b77cf1 100644 --- a/internal/backend/bls12-377/plonk/verify.go +++ b/internal/backend/bls12-377/plonk/verify.go @@ -49,11 +49,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls12_377witness.Witne // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -239,6 +250,47 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls12_377witness.Witne return err } +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + +} + func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { var buf [curve.SizeOfG1AffineUncompressed]byte diff --git a/internal/backend/bls12-381/plonk/prove.go b/internal/backend/bls12-381/plonk/prove.go index 0d7020cf03..e145b43352 100644 --- a/internal/backend/bls12-381/plonk/prove.go +++ b/internal/backend/bls12-381/plonk/prove.go @@ -62,6 +62,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bls12_381witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -109,11 +110,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bls12_381witness.Witn return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/backend/bls12-381/plonk/verify.go b/internal/backend/bls12-381/plonk/verify.go index 545b608861..07b645e9be 100644 --- a/internal/backend/bls12-381/plonk/verify.go +++ b/internal/backend/bls12-381/plonk/verify.go @@ -40,7 +40,7 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls12_381witness.Witness) error { - log := logger.Logger().With().Str("curve", "bls12_381").Str("backend", "plonk").Logger() + log := logger.Logger().With().Str("curve", "bls12_377").Str("backend", "plonk").Logger() start := time.Now() // pick a hash function to derive the challenge (the same as in the prover) @@ -49,11 +49,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls12_381witness.Witne // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -239,6 +250,47 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls12_381witness.Witne return err } +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + +} + func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { var buf [curve.SizeOfG1AffineUncompressed]byte diff --git a/internal/backend/bls24-315/plonk/prove.go b/internal/backend/bls24-315/plonk/prove.go index b12d9a9cb1..a3a899fceb 100644 --- a/internal/backend/bls24-315/plonk/prove.go +++ b/internal/backend/bls24-315/plonk/prove.go @@ -62,6 +62,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bls24_315witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -109,11 +110,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bls24_315witness.Witn return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/backend/bls24-315/plonk/verify.go b/internal/backend/bls24-315/plonk/verify.go index 6182f143e6..a72f21407c 100644 --- a/internal/backend/bls24-315/plonk/verify.go +++ b/internal/backend/bls24-315/plonk/verify.go @@ -40,7 +40,7 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls24_315witness.Witness) error { - log := logger.Logger().With().Str("curve", "bls24_315").Str("backend", "plonk").Logger() + log := logger.Logger().With().Str("curve", "bls12_377").Str("backend", "plonk").Logger() start := time.Now() // pick a hash function to derive the challenge (the same as in the prover) @@ -49,11 +49,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls24_315witness.Witne // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -239,6 +250,47 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bls24_315witness.Witne return err } +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + +} + func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { var buf [curve.SizeOfG1AffineUncompressed]byte diff --git a/internal/backend/bn254/plonk/prove.go b/internal/backend/bn254/plonk/prove.go index 71c1f8b022..132d3f4ee5 100644 --- a/internal/backend/bn254/plonk/prove.go +++ b/internal/backend/bn254/plonk/prove.go @@ -62,6 +62,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bn254witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -109,11 +110,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bn254witness.Witness, return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/backend/bn254/plonk/verify.go b/internal/backend/bn254/plonk/verify.go index c612dd4b63..8cc7b9c2f2 100644 --- a/internal/backend/bn254/plonk/verify.go +++ b/internal/backend/bn254/plonk/verify.go @@ -40,7 +40,7 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness bn254witness.Witness) error { - log := logger.Logger().With().Str("curve", "bn254").Str("backend", "plonk").Logger() + log := logger.Logger().With().Str("curve", "bls12_377").Str("backend", "plonk").Logger() start := time.Now() // pick a hash function to derive the challenge (the same as in the prover) @@ -49,11 +49,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bn254witness.Witness) // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -239,6 +250,47 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bn254witness.Witness) return err } +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + +} + func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { var buf [curve.SizeOfG1AffineUncompressed]byte diff --git a/internal/backend/bw6-633/plonk/prove.go b/internal/backend/bw6-633/plonk/prove.go index 168065ae66..c221fd83ea 100644 --- a/internal/backend/bw6-633/plonk/prove.go +++ b/internal/backend/bw6-633/plonk/prove.go @@ -62,6 +62,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bw6_633witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -109,11 +110,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bw6_633witness.Witnes return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/backend/bw6-633/plonk/verify.go b/internal/backend/bw6-633/plonk/verify.go index e8d2f11599..3f2a5418a4 100644 --- a/internal/backend/bw6-633/plonk/verify.go +++ b/internal/backend/bw6-633/plonk/verify.go @@ -40,7 +40,7 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness bw6_633witness.Witness) error { - log := logger.Logger().With().Str("curve", "bw6_633").Str("backend", "plonk").Logger() + log := logger.Logger().With().Str("curve", "bls12_377").Str("backend", "plonk").Logger() start := time.Now() // pick a hash function to derive the challenge (the same as in the prover) @@ -49,11 +49,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bw6_633witness.Witness // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -239,6 +250,47 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bw6_633witness.Witness return err } +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + +} + func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { var buf [curve.SizeOfG1AffineUncompressed]byte diff --git a/internal/backend/bw6-761/plonk/prove.go b/internal/backend/bw6-761/plonk/prove.go index af31f3650e..0e0ab8d599 100644 --- a/internal/backend/bw6-761/plonk/prove.go +++ b/internal/backend/bw6-761/plonk/prove.go @@ -62,6 +62,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bw6_761witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -109,11 +110,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness bw6_761witness.Witnes return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/backend/bw6-761/plonk/verify.go b/internal/backend/bw6-761/plonk/verify.go index 6788858058..083bc47bab 100644 --- a/internal/backend/bw6-761/plonk/verify.go +++ b/internal/backend/bw6-761/plonk/verify.go @@ -40,7 +40,7 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness bw6_761witness.Witness) error { - log := logger.Logger().With().Str("curve", "bw6_761").Str("backend", "plonk").Logger() + log := logger.Logger().With().Str("curve", "bls12_377").Str("backend", "plonk").Logger() start := time.Now() // pick a hash function to derive the challenge (the same as in the prover) @@ -49,11 +49,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bw6_761witness.Witness // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -239,6 +250,47 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness bw6_761witness.Witness return err } +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + +} + func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { var buf [curve.SizeOfG1AffineUncompressed]byte diff --git a/internal/backend/circuits/add.go b/internal/backend/circuits/add.go index ee9d727953..ba03fb0059 100644 --- a/internal/backend/circuits/add.go +++ b/internal/backend/circuits/add.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -39,5 +39,5 @@ func init() { bad.D = 76 bad.Z = 1 - addEntry("add", &circuit, &good, &bad, ecc.Implemented()) + addEntry("add", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/and.go b/internal/backend/circuits/and.go index ec8ab58d22..bd1450601b 100644 --- a/internal/backend/circuits/and.go +++ b/internal/backend/circuits/and.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -74,5 +74,5 @@ func init() { }, } - addNewEntry("and", &andCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("and", &andCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/assertequal.go b/internal/backend/circuits/assertequal.go index 3bd08ea6bc..8c66348729 100644 --- a/internal/backend/circuits/assertequal.go +++ b/internal/backend/circuits/assertequal.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -25,5 +25,5 @@ func init() { bad.X = (5) bad.Y = (2) - addEntry("assert_equal", &circuit, &good, &bad, ecc.Implemented()) + addEntry("assert_equal", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/assertisdifferent.go b/internal/backend/circuits/assertisdifferent.go index daa5611a54..e7bdddb3ac 100644 --- a/internal/backend/circuits/assertisdifferent.go +++ b/internal/backend/circuits/assertisdifferent.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -31,5 +31,5 @@ func init() { }, } - addNewEntry("assert_different", &assertIsDifferentCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("assert_different", &assertIsDifferentCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/boolean.go b/internal/backend/circuits/boolean.go index 927a36f83b..6671074557 100644 --- a/internal/backend/circuits/boolean.go +++ b/internal/backend/circuits/boolean.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -88,5 +88,5 @@ func init() { }, } - addNewEntry("assert_boolean", &checkAssertIsBooleanCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("assert_boolean", &checkAssertIsBooleanCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/cmp.go b/internal/backend/circuits/cmp.go index 1aecdde18c..d43dcc51a1 100644 --- a/internal/backend/circuits/cmp.go +++ b/internal/backend/circuits/cmp.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -55,5 +55,5 @@ func init() { }, } - addNewEntry("cmp", &cmpCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("cmp", &cmpCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/determinism.go b/internal/backend/circuits/determinism.go index 9c80c4060f..c013d66b81 100644 --- a/internal/backend/circuits/determinism.go +++ b/internal/backend/circuits/determinism.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -44,5 +44,5 @@ func init() { bad.X[4] = (1) bad.Z = (900) - addEntry("determinism", &circuit, &good, &bad, ecc.Implemented()) + addEntry("determinism", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/exp.go b/internal/backend/circuits/exp.go index f324642e5c..86e87dce89 100644 --- a/internal/backend/circuits/exp.go +++ b/internal/backend/circuits/exp.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -36,5 +36,5 @@ func init() { bad.E = (11) bad.Y = (4096) - addEntry("expo", &circuit, &good, &bad, ecc.Implemented()) + addEntry("expo", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/frombinary.go b/internal/backend/circuits/frombinary.go index 51bc98592c..5fc6d589f9 100644 --- a/internal/backend/circuits/frombinary.go +++ b/internal/backend/circuits/frombinary.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -37,5 +37,5 @@ func init() { bad.B3 = (1) bad.Y = (13) - addEntry("frombinary", &circuit, &good, &bad, ecc.Implemented()) + addEntry("frombinary", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/hint.go b/internal/backend/circuits/hint.go index a60f6c9e75..597bb6278a 100644 --- a/internal/backend/circuits/hint.go +++ b/internal/backend/circuits/hint.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/consensys/gnark" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/math/bits" @@ -91,7 +92,7 @@ func init() { }, } - addNewEntry("recursive_hint", &recursiveHint{}, good, bad, ecc.Implemented(), make3, bits.NBits) + addNewEntry("recursive_hint", &recursiveHint{}, good, bad, gnark.Curves(), make3, bits.NBits) } { @@ -109,7 +110,7 @@ func init() { }, } - addNewEntry("hint", &hintCircuit{}, good, bad, ecc.Implemented(), mulBy7, make3) + addNewEntry("hint", &hintCircuit{}, good, bad, gnark.Curves(), mulBy7, make3) } { @@ -134,7 +135,7 @@ func init() { }, }, } - addNewEntry("multi-output-hint", &vectorDoubleCircuit{A: make([]frontend.Variable, 8), B: make([]frontend.Variable, 8)}, good, bad, ecc.Implemented(), dvHint) + addNewEntry("multi-output-hint", &vectorDoubleCircuit{A: make([]frontend.Variable, 8), B: make([]frontend.Variable, 8)}, good, bad, gnark.Curves(), dvHint) } } diff --git a/internal/backend/circuits/iszero.go b/internal/backend/circuits/iszero.go index 432c7e783a..91f0d4fc93 100644 --- a/internal/backend/circuits/iszero.go +++ b/internal/backend/circuits/iszero.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -29,5 +29,5 @@ func init() { bad.X = (23) bad.Y = (0) - addEntry("isZero", &circuit, &good, &bad, ecc.Implemented()) + addEntry("isZero", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/lookup2.go b/internal/backend/circuits/lookup2.go index fdab2df579..9ca21f1f66 100644 --- a/internal/backend/circuits/lookup2.go +++ b/internal/backend/circuits/lookup2.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -30,5 +30,5 @@ func init() { bad = append(bad, &lookup2Circuit{v0, v1, v2, v3, tc.b0, tc.b1, tc.unexpected}) } - addNewEntry("lookup2", &lookup2Circuit{}, good, bad, ecc.Implemented()) + addNewEntry("lookup2", &lookup2Circuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/mul.go b/internal/backend/circuits/mul.go index a9437e74aa..5708d4b3a6 100644 --- a/internal/backend/circuits/mul.go +++ b/internal/backend/circuits/mul.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -38,5 +38,5 @@ func init() { bad.Z = 1 bad.ZZ = 1 - addEntry("mul", &circuit, &good, &bad, ecc.Implemented()) + addEntry("mul", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/neg.go b/internal/backend/circuits/neg.go index 8c66511804..f87eadd8f3 100644 --- a/internal/backend/circuits/neg.go +++ b/internal/backend/circuits/neg.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -28,5 +28,5 @@ func init() { bad.X = (7) bad.Z = (30) - addEntry("neg", &circuit, &good, &bad, ecc.Implemented()) + addEntry("neg", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/nocomputation.go b/internal/backend/circuits/nocomputation.go index 399702a0f0..957eb8e45e 100644 --- a/internal/backend/circuits/nocomputation.go +++ b/internal/backend/circuits/nocomputation.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -26,5 +26,5 @@ func init() { bad.A = (42) bad.B = (43) - addEntry("noComputationCircuit", &circuit, &good, &bad, ecc.Implemented()) + addEntry("noComputationCircuit", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/or.go b/internal/backend/circuits/or.go index 023e420653..0c54abc4fc 100644 --- a/internal/backend/circuits/or.go +++ b/internal/backend/circuits/or.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -74,5 +74,5 @@ func init() { }, } - addNewEntry("or", &orCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("or", &orCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/orxorandmul.go b/internal/backend/circuits/orxorandmul.go index 2a4bc488f1..86c782794c 100644 --- a/internal/backend/circuits/orxorandmul.go +++ b/internal/backend/circuits/orxorandmul.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -63,5 +63,5 @@ func init() { }, } - addNewEntry("orXoAndMulCircuit", &orXoAndMulCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("orXoAndMulCircuit", &orXoAndMulCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/backend/circuits/range.go b/internal/backend/circuits/range.go index 85ccbf5256..0acbaf7928 100644 --- a/internal/backend/circuits/range.go +++ b/internal/backend/circuits/range.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -28,7 +28,7 @@ func rangeCheckConstant() { bad.X = (11) bad.Y = (4) - addEntry("range_constant", &circuit, &good, &bad, ecc.Implemented()) + addEntry("range_constant", &circuit, &good, &bad, gnark.Curves()) } type rangeCheckCircuit struct { @@ -58,7 +58,7 @@ func rangeCheck() { bad.Y = (4) bad.Bound = (161) - addEntry("range", &circuit, &good, &bad, ecc.Implemented()) + addEntry("range", &circuit, &good, &bad, gnark.Curves()) } func init() { diff --git a/internal/backend/circuits/reference_small.go b/internal/backend/circuits/reference_small.go index 02d82adc58..034593718f 100644 --- a/internal/backend/circuits/reference_small.go +++ b/internal/backend/circuits/reference_small.go @@ -3,7 +3,7 @@ package circuits import ( "math/big" - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -40,5 +40,5 @@ func init() { bad.X = (3) bad.Y = (expectedY) - addEntry("reference_small", &circuit, &good, &bad, ecc.Implemented()) + addEntry("reference_small", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/sub.go b/internal/backend/circuits/sub.go index 8fc6c06a09..2b55309b55 100644 --- a/internal/backend/circuits/sub.go +++ b/internal/backend/circuits/sub.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -39,5 +39,5 @@ func init() { bad.E = 23820938283 bad.Res = 1 - addEntry("sub", &circuit, &good, &bad, ecc.Implemented()) + addEntry("sub", &circuit, &good, &bad, gnark.Curves()) } diff --git a/internal/backend/circuits/xor.go b/internal/backend/circuits/xor.go index 3d2d5b8b64..be2c333e4d 100644 --- a/internal/backend/circuits/xor.go +++ b/internal/backend/circuits/xor.go @@ -1,7 +1,7 @@ package circuits import ( - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/frontend" ) @@ -74,5 +74,5 @@ func init() { }, } - addNewEntry("xor", &xorCircuit{}, good, bad, ecc.Implemented()) + addNewEntry("xor", &xorCircuit{}, good, bad, gnark.Curves()) } diff --git a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl index f0a9487685..b7c7c7528b 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl @@ -19,7 +19,6 @@ import ( "github.com/consensys/gnark-crypto/fiat-shamir" ) - type Proof struct { // Commitments to the solution vectors @@ -40,6 +39,7 @@ type Proof struct { // Prove from the public data func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness {{ toLower .CurveID }}witness.Witness, opt backend.ProverConfig) (*Proof, error) { + log := logger.Logger().With().Str("curve", spr.CurveID().String()).Int("nbConstraints", len(spr.Constraints)).Str("backend", "plonk").Logger() start := time.Now() // pick a hash function that will be used to derive the challenges @@ -87,11 +87,16 @@ func Prove(spr *cs.SparseR1CS, pk *ProvingKey, fullWitness {{ toLower .CurveID } return nil, err } + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + bindPublicData(&fs, "gamma", *pk.Vk, fullWitness[:spr.NbPublicVariables]) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return nil, err } + var gamma fr.Element + gamma.SetBytes(bgamma) // Fiat Shamir this beta, err := deriveRandomness(&fs, "beta") diff --git a/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl b/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl index 38e090adb0..0f45d9b6b3 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl @@ -19,7 +19,7 @@ var ( ) func Verify(proof *Proof, vk *VerifyingKey, publicWitness {{ toLower .CurveID }}witness.Witness) error { - log := logger.Logger().With().Str("curve", "{{ toLower .CurveID }}").Str("backend", "plonk").Logger() + log := logger.Logger().With().Str("curve", "bls12_377").Str("backend", "plonk").Logger() start := time.Now() // pick a hash function to derive the challenge (the same as in the prover) @@ -28,11 +28,22 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness {{ toLower .CurveID }} // transcript to derive the challenge fs := fiatshamir.NewTranscript(hFunc, "gamma", "beta", "alpha", "zeta") - // derive gamma from Comm(l), Comm(r), Comm(o) - gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // The first challenge is derived using the public data: the commitments to the permutation, + // the coefficients of the circuit, and the public inputs. + // derive gamma from the Comm(blinded cl), Comm(blinded cr), Comm(blinded co) + bindPublicData(&fs, "gamma", *vk, publicWitness) + bgamma, err := fs.ComputeChallenge("gamma") if err != nil { return err } + var gamma fr.Element + gamma.SetBytes(bgamma) + + // derive gamma from Comm(l), Comm(r), Comm(o) + // gamma, err := deriveRandomness(&fs, "gamma", &proof.LRO[0], &proof.LRO[1], &proof.LRO[2]) + // if err != nil { + // return err + // } // derive beta from Comm(l), Comm(r), Comm(o) beta, err := deriveRandomness(&fs, "beta") @@ -215,7 +226,48 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness {{ toLower .CurveID }} log.Debug().Dur("took", time.Since(start)).Msg("verifier done") - return err + return err +} + +func bindPublicData(fs *fiatshamir.Transcript, challenge string, vk VerifyingKey, publicInputs []fr.Element) error { + + // permutation + if err := fs.Bind(challenge, vk.S[0].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[1].Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.S[2].Marshal()); err != nil { + return err + } + + // coefficients + if err := fs.Bind(challenge, vk.Ql.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qr.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qm.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qo.Marshal()); err != nil { + return err + } + if err := fs.Bind(challenge, vk.Qk.Marshal()); err != nil { + return err + } + + // public inputs + for i := 0; i < len(publicInputs); i++ { + if err := fs.Bind(challenge, publicInputs[i].Marshal()); err != nil { + return err + } + } + + return nil + } func deriveRandomness(fs *fiatshamir.Transcript, challenge string, points ...*curve.G1Affine) (fr.Element, error) { diff --git a/internal/stats/generate/main.go b/internal/stats/generate/main.go index 22c6730343..251af22562 100644 --- a/internal/stats/generate/main.go +++ b/internal/stats/generate/main.go @@ -59,7 +59,7 @@ func main() { ss := s.Stats[name] for _, curve := range c.Curves { for _, backendID := range backend.Implemented() { - cs := ss[backendID][curve] + cs := ss[backendID][stats.CurveIdx(curve)] fmt.Printf("%s,%s,%s,%d,%d\n", name, curve, backendID, cs.NbConstraints, cs.NbInternalWires) } } diff --git a/internal/stats/latest.stats b/internal/stats/latest.stats index 4959594248..2d3541f109 100644 Binary files a/internal/stats/latest.stats and b/internal/stats/latest.stats differ diff --git a/internal/stats/snippet.go b/internal/stats/snippet.go index 0c92c64155..da68348fab 100644 --- a/internal/stats/snippet.go +++ b/internal/stats/snippet.go @@ -4,6 +4,7 @@ import ( "math" "sync" + "github.com/consensys/gnark" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/std/algebra/sw_bls12377" @@ -29,7 +30,7 @@ func registerSnippet(name string, snippet snippet, curves ...ecc.ID) { panic("circuit " + name + " already registered") } if len(curves) == 0 { - curves = ecc.Implemented() + curves = gnark.Curves() } snippets[name] = Circuit{makeSnippetCircuit(snippet), curves} } diff --git a/internal/stats/stats.go b/internal/stats/stats.go index f5d774af20..0f2b2e8c31 100644 --- a/internal/stats/stats.go +++ b/internal/stats/stats.go @@ -6,6 +6,7 @@ import ( "os" "sync" + "github.com/consensys/gnark" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/frontend" @@ -13,9 +14,36 @@ import ( "github.com/consensys/gnark/frontend/cs/scs" ) +const nbCurves = 6 + +func CurveIdx(curve ecc.ID) int { + switch curve { + case ecc.BN254: + return 0 + case ecc.BLS12_377: + return 1 + case ecc.BLS12_381: + return 2 + case ecc.BLS24_315: + return 3 + case ecc.BW6_761: + return 4 + case ecc.BW6_633: + return 5 + default: + panic("not implemented") + } +} + +func init() { + if nbCurves != len(gnark.Curves()) { + panic("expected nbCurves == len(gnark.Curves())") + } +} + func NewGlobalStats() *globalStats { return &globalStats{ - Stats: make(map[string][backend.PLONK + 1][ecc.BW6_633 + 1]snippetStats), + Stats: make(map[string][backend.PLONK + 1][nbCurves + 1]snippetStats), } } @@ -71,7 +99,7 @@ func (s *globalStats) Add(curve ecc.ID, backendID backend.ID, cs snippetStats, c s.Lock() defer s.Unlock() rs := s.Stats[circuitName] - rs[backendID][curve] = cs + rs[backendID][CurveIdx(curve)] = cs s.Stats[circuitName] = rs } @@ -82,7 +110,7 @@ type Circuit struct { type globalStats struct { sync.RWMutex - Stats map[string][backend.PLONK + 1][ecc.BW6_633 + 1]snippetStats + Stats map[string][backend.PLONK + 1][nbCurves + 1]snippetStats } type snippetStats struct { diff --git a/internal/stats/stats_test.go b/internal/stats/stats_test.go index 4ed930efff..b536eda5be 100644 --- a/internal/stats/stats_test.go +++ b/internal/stats/stats_test.go @@ -33,7 +33,7 @@ func TestCircuitStatistics(t *testing.T) { // copy the circuit now in case assert calls t.Parallel() circuit := c.Circuit assert.Run(func(assert *test.Assert) { - rs := ref[backendID][curve] + rs := ref[backendID][CurveIdx(curve)] s, err := NewSnippetStats(curve, backendID, circuit) assert.NoError(err, "building stats for circuit "+name) diff --git a/test/assert.go b/test/assert.go index 9f849cd467..7c5b0e4bb8 100644 --- a/test/assert.go +++ b/test/assert.go @@ -23,6 +23,7 @@ import ( "strings" "testing" + "github.com/consensys/gnark" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16" @@ -455,7 +456,7 @@ func (assert *Assert) options(opts ...TestingOption) testingConfig { opt := testingConfig{ witnessSerialization: true, backends: backend.Implemented(), - curves: ecc.Implemented(), + curves: gnark.Curves(), } for _, option := range opts { err := option(&opt) @@ -464,7 +465,7 @@ func (assert *Assert) options(opts ...TestingOption) testingConfig { if testing.Short() { // if curves are all there, we just test with bn254 - if reflect.DeepEqual(opt.curves, ecc.Implemented()) { + if reflect.DeepEqual(opt.curves, gnark.Curves()) { opt.curves = []ecc.ID{ecc.BN254} } } diff --git a/test/engine_test.go b/test/engine_test.go index ce3a0e526f..339d5732de 100644 --- a/test/engine_test.go +++ b/test/engine_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark" "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/hint" "github.com/consensys/gnark/frontend" @@ -46,7 +46,7 @@ func (circuit *hintCircuit) Define(api frontend.API) error { } func TestBuiltinHints(t *testing.T) { - for _, curve := range ecc.Implemented() { + for _, curve := range gnark.Curves() { if err := IsSolved(&hintCircuit{}, &hintCircuit{ A: (0b1000), B: (0), diff --git a/test/fuzz.go b/test/fuzz.go index 0a60682842..df78426ba5 100644 --- a/test/fuzz.go +++ b/test/fuzz.go @@ -7,6 +7,7 @@ import ( "reflect" "time" + "github.com/consensys/gnark" "github.com/consensys/gnark-crypto/ecc" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/schema" @@ -23,7 +24,7 @@ func init() { } // moduli - for _, curve := range ecc.Implemented() { + for _, curve := range gnark.Curves() { fp := curve.Info().Fp.Modulus() fr := curve.Info().Fr.Modulus() seedCorpus = append(seedCorpus, fp)