From 28584767a5f4af755508d88221fcc200b60e041b Mon Sep 17 00:00:00 2001 From: Gautam Botrel Date: Thu, 16 Nov 2023 18:57:46 -0600 Subject: [PATCH] refactor: simplify hint overloading for api.Commit (#919) * refactor: remove hintwithname * fix: in test engine, commit should not return 0 with tiny field * style: remove some dead code * fix: fixes #918 incorrect hash Sum usage --- backend/groth16/bls12-377/prove.go | 57 +++++++------- backend/groth16/bls12-381/prove.go | 57 +++++++------- backend/groth16/bls24-315/prove.go | 57 +++++++------- backend/groth16/bls24-317/prove.go | 57 +++++++------- backend/groth16/bn254/prove.go | 57 +++++++------- backend/groth16/bw6-633/prove.go | 57 +++++++------- backend/groth16/bw6-761/prove.go | 57 +++++++------- backend/plonk/bls12-377/prove.go | 73 +++++++++--------- backend/plonk/bls12-377/verify.go | 3 +- backend/plonk/bls12-381/prove.go | 73 +++++++++--------- backend/plonk/bls12-381/verify.go | 3 +- backend/plonk/bls24-315/prove.go | 73 +++++++++--------- backend/plonk/bls24-315/verify.go | 3 +- backend/plonk/bls24-317/prove.go | 73 +++++++++--------- backend/plonk/bls24-317/verify.go | 3 +- backend/plonk/bn254/prove.go | 73 +++++++++--------- backend/plonk/bn254/verify.go | 3 +- backend/plonk/bw6-633/prove.go | 73 +++++++++--------- backend/plonk/bw6-633/verify.go | 3 +- backend/plonk/bw6-761/prove.go | 73 +++++++++--------- backend/plonk/bw6-761/verify.go | 3 +- constraint/commitment.go | 3 - frontend/builder.go | 1 - frontend/cs/commitment.go | 37 +++------ frontend/cs/r1cs/api.go | 24 +++--- frontend/cs/scs/api.go | 11 +-- frontend/cs/scs/builder.go | 4 - .../zkpschemes/groth16/groth16.prove.go.tmpl | 53 ++++++------- .../zkpschemes/plonk/plonk.prove.go.tmpl | 75 +++++++++---------- .../zkpschemes/plonk/plonk.verify.go.tmpl | 3 +- std/recursion/groth16/verifier_test.go | 7 -- test/commitments_test.go | 6 +- test/end_to_end.go | 25 +------ test/engine.go | 5 ++ test/hint_test.go | 58 -------------- 35 files changed, 568 insertions(+), 675 deletions(-) delete mode 100644 test/hint_test.go diff --git a/backend/groth16/bls12-377/prove.go b/backend/groth16/bls12-377/prove.go index d1ee7d1103..823fbb9b7d 100644 --- a/backend/groth16/bls12-377/prove.go +++ b/backend/groth16/bls12-377/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/groth16/bls12-381/prove.go b/backend/groth16/bls12-381/prove.go index c96394908d..eb62ff616d 100644 --- a/backend/groth16/bls12-381/prove.go +++ b/backend/groth16/bls12-381/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/groth16/bls24-315/prove.go b/backend/groth16/bls24-315/prove.go index 88b8218711..725fea3202 100644 --- a/backend/groth16/bls24-315/prove.go +++ b/backend/groth16/bls24-315/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/groth16/bls24-317/prove.go b/backend/groth16/bls24-317/prove.go index de4230d50c..56a20d7f12 100644 --- a/backend/groth16/bls24-317/prove.go +++ b/backend/groth16/bls24-317/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/groth16/bn254/prove.go b/backend/groth16/bn254/prove.go index b20b6c7cae..8913a933ff 100644 --- a/backend/groth16/bn254/prove.go +++ b/backend/groth16/bn254/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/groth16/bw6-633/prove.go b/backend/groth16/bw6-633/prove.go index 6d0ee420f0..eb261d2b5b 100644 --- a/backend/groth16/bw6-633/prove.go +++ b/backend/groth16/bw6-633/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/groth16/bw6-761/prove.go b/backend/groth16/bw6-761/prove.go index 203d1be898..940a7efd5b 100644 --- a/backend/groth16/bw6-761/prove.go +++ b/backend/groth16/bw6-761/prove.go @@ -35,6 +35,8 @@ import ( "math/big" "runtime" "time" + + fcs "github.com/consensys/gnark/frontend/cs" ) // Proof represents a Groth16 proof that was encoded with a ProvingKey and can be verified @@ -76,35 +78,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) - return err - } - }(i))) - } + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { + return err + } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData diff --git a/backend/plonk/bls12-377/prove.go b/backend/plonk/bls12-377/prove.go index 46346775c5..41fc836692 100644 --- a/backend/plonk/bls12-377/prove.go +++ b/backend/plonk/bls12-377/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bls12-377" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bls12-377/verify.go b/backend/plonk/bls12-377/verify.go index 8b7fbdf3a4..70b76c39d3 100644 --- a/backend/plonk/bls12-377/verify.go +++ b/backend/plonk/bls12-377/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/backend/plonk/bls12-381/prove.go b/backend/plonk/bls12-381/prove.go index cd6282fcdf..544844cdc5 100644 --- a/backend/plonk/bls12-381/prove.go +++ b/backend/plonk/bls12-381/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bls12-381" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bls12-381/verify.go b/backend/plonk/bls12-381/verify.go index 2b3eeef6c1..567be1b01b 100644 --- a/backend/plonk/bls12-381/verify.go +++ b/backend/plonk/bls12-381/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/backend/plonk/bls24-315/prove.go b/backend/plonk/bls24-315/prove.go index 09f0643a47..373a94b4b9 100644 --- a/backend/plonk/bls24-315/prove.go +++ b/backend/plonk/bls24-315/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bls24-315" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bls24-315/verify.go b/backend/plonk/bls24-315/verify.go index 446c95ff42..d2a23f820b 100644 --- a/backend/plonk/bls24-315/verify.go +++ b/backend/plonk/bls24-315/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/backend/plonk/bls24-317/prove.go b/backend/plonk/bls24-317/prove.go index 49412d739a..6792644a72 100644 --- a/backend/plonk/bls24-317/prove.go +++ b/backend/plonk/bls24-317/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bls24-317" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bls24-317/verify.go b/backend/plonk/bls24-317/verify.go index ab64624d7c..907eeceb23 100644 --- a/backend/plonk/bls24-317/verify.go +++ b/backend/plonk/bls24-317/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/backend/plonk/bn254/prove.go b/backend/plonk/bn254/prove.go index 1a237418d6..819e9728ae 100644 --- a/backend/plonk/bn254/prove.go +++ b/backend/plonk/bn254/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bn254/verify.go b/backend/plonk/bn254/verify.go index 1e0d7ca4de..42c2415268 100644 --- a/backend/plonk/bn254/verify.go +++ b/backend/plonk/bn254/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/backend/plonk/bw6-633/prove.go b/backend/plonk/bw6-633/prove.go index 77d1a48644..d7b07a1160 100644 --- a/backend/plonk/bw6-633/prove.go +++ b/backend/plonk/bw6-633/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bw6-633" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bw6-633/verify.go b/backend/plonk/bw6-633/verify.go index 71e7c2cc72..1d80b9d256 100644 --- a/backend/plonk/bw6-633/verify.go +++ b/backend/plonk/bw6-633/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/backend/plonk/bw6-761/prove.go b/backend/plonk/bw6-761/prove.go index 35d89a6e73..8a7c7dd437 100644 --- a/backend/plonk/bw6-761/prove.go +++ b/backend/plonk/bw6-761/prove.go @@ -47,6 +47,7 @@ import ( "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bw6-761" "github.com/consensys/gnark/constraint/solver" + fcs "github.com/consensys/gnark/frontend/cs" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" ) @@ -307,49 +308,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { diff --git a/backend/plonk/bw6-761/verify.go b/backend/plonk/bw6-761/verify.go index e8b4ecd4c6..701fde89cb 100644 --- a/backend/plonk/bw6-761/verify.go +++ b/backend/plonk/bw6-761/verify.go @@ -127,7 +127,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -135,7 +134,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/constraint/commitment.go b/constraint/commitment.go index 2e812ce906..076f80f55e 100644 --- a/constraint/commitment.go +++ b/constraint/commitment.go @@ -1,7 +1,6 @@ package constraint import ( - "github.com/consensys/gnark/constraint/solver" "math/big" ) @@ -11,14 +10,12 @@ type Groth16Commitment struct { PublicAndCommitmentCommitted []int // PublicAndCommitmentCommitted sorted list of id's of public and commitment committed wires PrivateCommitted []int // PrivateCommitted sorted list of id's of private/internal committed wires CommitmentIndex int // CommitmentIndex the wire index of the commitment - HintID solver.HintID NbPublicCommitted int } type PlonkCommitment struct { Committed []int // sorted list of id's of committed variables in groth16. in plonk, list of indexes of constraints defining committed values CommitmentIndex int // CommitmentIndex index of the constraint defining the commitment - HintID solver.HintID } type Commitment interface{} diff --git a/frontend/builder.go b/frontend/builder.go index 717dbfca7a..f39262be1e 100644 --- a/frontend/builder.go +++ b/frontend/builder.go @@ -39,7 +39,6 @@ type Compiler interface { // // If nbOutputs is specified, it must be >= 1 and <= f.NbOutputs NewHint(f solver.Hint, nbOutputs int, inputs ...Variable) ([]Variable, error) - NewHintForId(id solver.HintID, nbOutputs int, inputs ...Variable) ([]Variable, error) // ConstantValue returns the big.Int value of v and true if op is a success. // nil and false if failure. This API returns a boolean to allow for future refactoring diff --git a/frontend/cs/commitment.go b/frontend/cs/commitment.go index e8b92478f9..776f4790c4 100644 --- a/frontend/cs/commitment.go +++ b/frontend/cs/commitment.go @@ -3,15 +3,13 @@ package cs import ( "crypto/rand" "fmt" - "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/debug" - "github.com/consensys/gnark/logger" - "hash/fnv" "math/big" "os" - "strconv" "strings" - "sync" + + "github.com/consensys/gnark/constraint/solver" + "github.com/consensys/gnark/debug" + "github.com/consensys/gnark/logger" ) func Bsb22CommitmentComputePlaceholder(mod *big.Int, _ []*big.Int, output []*big.Int) (err error) { @@ -20,33 +18,16 @@ func Bsb22CommitmentComputePlaceholder(mod *big.Int, _ []*big.Int, output []*big log := logger.Logger() log.Error().Msg("Augmented commitment hint not replaced. Proof will not be sound and verification will fail!") output[0], err = rand.Int(rand.Reader, mod) + if output[0].Sign() == 0 { + // a commit == 0 is unlikely; happens quite often in tests + // with tinyfield + output[0].SetUint64(1) + } return } return fmt.Errorf("placeholder function: to be replaced by commitment computation") } -var maxNbCommitments int -var m sync.Mutex - -func RegisterBsb22CommitmentComputePlaceholder(index int) (hintId solver.HintID, err error) { - - hintName := "bsb22 commitment #" + strconv.Itoa(index) - // mimic solver.GetHintID - hf := fnv.New32a() - if _, err = hf.Write([]byte(hintName)); err != nil { - return - } - hintId = solver.HintID(hf.Sum32()) - - m.Lock() - if maxNbCommitments == index { - maxNbCommitments++ - solver.RegisterNamedHint(Bsb22CommitmentComputePlaceholder, hintId) - } - m.Unlock() - - return -} func init() { solver.RegisterHint(Bsb22CommitmentComputePlaceholder) } diff --git a/frontend/cs/r1cs/api.go b/frontend/cs/r1cs/api.go index bef33307ae..6b6eeeb633 100644 --- a/frontend/cs/r1cs/api.go +++ b/frontend/cs/r1cs/api.go @@ -775,33 +775,27 @@ func (builder *builder) Commit(v ...frontend.Variable) (frontend.Variable, error // hint is used at solving time to compute the actual value of the commitment // it is going to be dynamically replaced at solving time. - - var ( - hintOut []frontend.Variable - err error + commitmentDepth := len(commitments) + inputs := builder.wireIDsToVars( + commitment.PublicAndCommitmentCommitted, + commitment.PrivateCommitted, ) + inputs = append([]frontend.Variable{commitmentDepth}, inputs...) - commitment.HintID, err = cs.RegisterBsb22CommitmentComputePlaceholder(len(commitments)) + hintOut, err := builder.NewHint(cs.Bsb22CommitmentComputePlaceholder, 1, inputs...) if err != nil { return nil, err } - if hintOut, err = builder.NewHintForId(commitment.HintID, 1, builder.wireIDsToVars( - commitment.PublicAndCommitmentCommitted, - commitment.PrivateCommitted, - )...); err != nil { - return nil, err - } - - cVar := hintOut[0] + res := hintOut[0] - commitment.CommitmentIndex = (cVar.(expr.LinearExpression))[0].WireID() + commitment.CommitmentIndex = (res.(expr.LinearExpression))[0].WireID() if err := builder.cs.AddCommitment(commitment); err != nil { return nil, err } - return cVar, nil + return res, nil } func (builder *builder) wireIDsToVars(wireIDs ...[]int) []frontend.Variable { diff --git a/frontend/cs/scs/api.go b/frontend/cs/scs/api.go index 0fec685f94..4471f54f4e 100644 --- a/frontend/cs/scs/api.go +++ b/frontend/cs/scs/api.go @@ -635,23 +635,20 @@ func (builder *builder) Commit(v ...frontend.Variable) (frontend.Variable, error builder.addPlonkConstraint(sparseR1C{xa: vINeg.VID, qL: vINeg.Coeff, commitment: constraint.COMMITTED}) } - hintId, err := cs.RegisterBsb22CommitmentComputePlaceholder(len(commitments)) + inputs := make([]frontend.Variable, len(v)+1) + inputs[0] = len(commitments) // commitment depth + copy(inputs[1:], v) + outs, err := builder.NewHint(cs.Bsb22CommitmentComputePlaceholder, 1, inputs...) if err != nil { return nil, err } - var outs []frontend.Variable - if outs, err = builder.NewHintForId(hintId, 1, v...); err != nil { - return nil, err - } - commitmentVar := builder.Neg(outs[0]).(expr.Term) commitmentConstraintIndex := builder.cs.GetNbConstraints() // RHS will be provided by both prover and verifier independently, as for a public wire builder.addPlonkConstraint(sparseR1C{xa: commitmentVar.VID, qL: commitmentVar.Coeff, commitment: constraint.COMMITMENT}) // value will be injected later return outs[0], builder.cs.AddCommitment(constraint.PlonkCommitment{ - HintID: hintId, CommitmentIndex: commitmentConstraintIndex, Committed: committed, }) diff --git a/frontend/cs/scs/builder.go b/frontend/cs/scs/builder.go index 1e6f1efb62..32a036e6a3 100644 --- a/frontend/cs/scs/builder.go +++ b/frontend/cs/scs/builder.go @@ -345,10 +345,6 @@ func (builder *builder) NewHint(f solver.Hint, nbOutputs int, inputs ...frontend return builder.newHint(f, solver.GetHintID(f), nbOutputs, inputs...) } -func (builder *builder) NewHintForId(id solver.HintID, nbOutputs int, inputs ...frontend.Variable) ([]frontend.Variable, error) { - return builder.newHint(nil, id, nbOutputs, inputs...) -} - func (builder *builder) newHint(f solver.Hint, id solver.HintID, nbOutputs int, inputs ...frontend.Variable) ([]frontend.Variable, error) { hintInputs := builder.hintBuffer(len(inputs)) diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl index 635f71c8cf..bbb9fd1bf5 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.prove.go.tmpl @@ -18,6 +18,8 @@ import ( "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/backend/witness" "github.com/consensys/gnark/logger" + + fcs "github.com/consensys/gnark/frontend/cs" ) @@ -60,35 +62,36 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b solverOpts := opt.SolverOpts[:len(opt.SolverOpts):len(opt.SolverOpts)] privateCommittedValues := make([][]fr.Element, len(commitmentInfo)) - for i := range commitmentInfo { - solverOpts = append(solverOpts, solver.OverrideHint(commitmentInfo[i].HintID, func(i int) solver.Hint { - return func(_ *big.Int, in []*big.Int, out []*big.Int) error { - privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) - hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] - committed := in[len(hashed):] - for j, inJ := range committed { - privateCommittedValues[i][j].SetBigInt(inJ) - } - var err error - if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { - return err - } + // override hints + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + solverOpts = append(solverOpts, solver.OverrideHint(bsb22ID, func(_ *big.Int, in []*big.Int, out []*big.Int) error { + i := int(in[0].Int64()) + in = in[1:] + privateCommittedValues[i] = make([]fr.Element, len(commitmentInfo[i].PrivateCommitted)) + hashed := in[:len(commitmentInfo[i].PublicAndCommitmentCommitted)] + committed := in[+len(hashed):] + for j, inJ := range committed { + privateCommittedValues[i][j].SetBigInt(inJ) + } - opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) - hashBts := opt.HashToFieldFn.Sum(nil) - opt.HashToFieldFn.Reset() - nbBuf := fr.Bytes - if opt.HashToFieldFn.Size() < fr.Bytes { - nbBuf = opt.HashToFieldFn.Size() - } - var res fr.Element - res.SetBytes(hashBts[:nbBuf]) - res.BigInt(out[0]) + var err error + if proof.Commitments[i], err = pk.CommitmentKeys[i].Commit(privateCommittedValues[i]); err != nil { return err } - }(i))) - } + + opt.HashToFieldFn.Write(constraint.SerializeCommitment(proof.Commitments[i].Marshal(), hashed, (fr.Bits-1)/8+1)) + hashBts := opt.HashToFieldFn.Sum(nil) + opt.HashToFieldFn.Reset() + nbBuf := fr.Bytes + if opt.HashToFieldFn.Size() < fr.Bytes { + nbBuf = opt.HashToFieldFn.Size() + } + var res fr.Element + res.SetBytes(hashBts[:nbBuf]) + res.BigInt(out[0]) + return nil + })) if r1cs.GkrInfo.Is() { var gkrData cs.GkrSolvingData 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 7ac814c65d..bbe0201c88 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.prove.go.tmpl @@ -26,6 +26,7 @@ import ( "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" + fcs "github.com/consensys/gnark/frontend/cs" ) // TODO in gnark-crypto: @@ -285,49 +286,47 @@ func (s *instance) initBSB22Commitments() { s.proof.Bsb22Commitments = make([]kzg.Digest, len(s.commitmentInfo)) // override the hint for the commitment constraints - for i := range s.commitmentInfo { - s.opt.SolverOpts = append(s.opt.SolverOpts, - solver.OverrideHint(s.commitmentInfo[i].HintID, s.bsb22Hint(i))) - } + bsb22ID := solver.GetHintID(fcs.Bsb22CommitmentComputePlaceholder) + s.opt.SolverOpts = append(s.opt.SolverOpts, solver.OverrideHint(bsb22ID, s.bsb22Hint)) } // Computing and verifying Bsb22 multi-commits explained in https://hackmd.io/x8KsadW3RRyX7YTCFJIkHg -func (s *instance) bsb22Hint(commDepth int) solver.Hint { - return func(_ *big.Int, ins, outs []*big.Int) error { - var err error - - res := &s.commitmentVal[commDepth] - - commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] - committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) - offset := s.spr.GetNbPublicVariables() - for i := range ins { - committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) - } - if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. - return err - } - if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding - return err - } - s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) - if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { - return err - } - s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() - - s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) - hashBts := s.htfFunc.Sum(nil) - s.htfFunc.Reset() - nbBuf := fr.Bytes - if s.htfFunc.Size() < fr.Bytes { - nbBuf = s.htfFunc.Size() - } - res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses - res.BigInt(outs[0]) +func (s *instance) bsb22Hint(_ *big.Int, ins, outs []*big.Int) error { + var err error + commDepth := int(ins[0].Int64()) + ins = ins[1:] + + res := &s.commitmentVal[commDepth] - return nil + commitmentInfo := s.spr.CommitmentInfo.(constraint.PlonkCommitments)[commDepth] + committedValues := make([]fr.Element, s.pk.Domain[0].Cardinality) + offset := s.spr.GetNbPublicVariables() + for i := range ins { + committedValues[offset+commitmentInfo.Committed[i]].SetBigInt(ins[i]) } + if _, err = committedValues[offset+commitmentInfo.CommitmentIndex].SetRandom(); err != nil { // Commitment injection constraint has qcp = 0. Safe to use for blinding. + return err + } + if _, err = committedValues[offset+s.spr.GetNbConstraints()-1].SetRandom(); err != nil { // Last constraint has qcp = 0. Safe to use for blinding + return err + } + s.cCommitments[commDepth] = iop.NewPolynomial(&committedValues, iop.Form{Basis: iop.Lagrange, Layout: iop.Regular}) + if s.proof.Bsb22Commitments[commDepth], err = kzg.Commit(s.cCommitments[commDepth].Coefficients(), s.pk.KzgLagrange); err != nil { + return err + } + s.cCommitments[commDepth].ToCanonical(&s.pk.Domain[0]).ToRegular() + + s.htfFunc.Write(s.proof.Bsb22Commitments[commDepth].Marshal()) + hashBts := s.htfFunc.Sum(nil) + s.htfFunc.Reset() + nbBuf := fr.Bytes + if s.htfFunc.Size() < fr.Bytes { + nbBuf = s.htfFunc.Size() + } + res.SetBytes(hashBts[:nbBuf]) // TODO @Tabaie use CommitmentIndex for this; create a new variable CommitmentConstraintIndex for other uses + res.BigInt(outs[0]) + + return nil } func (s *instance) setupGKRHints() { 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 04fa61b042..709610b9d6 100644 --- a/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/plonk/plonk.verify.go.tmpl @@ -111,7 +111,6 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac if cfg.HashToFieldFn == nil { cfg.HashToFieldFn = hash_to_field.New([]byte("BSB22-Plonk")) } - var hashBts []byte var hashedCmt fr.Element nbBuf := fr.Bytes if cfg.HashToFieldFn.Size() < fr.Bytes { @@ -119,7 +118,7 @@ func Verify(proof *Proof, vk *VerifyingKey, publicWitness fr.Vector, opts ...bac } for i := range vk.CommitmentConstraintIndexes { cfg.HashToFieldFn.Write(proof.Bsb22Commitments[i].Marshal()) - hashBts = cfg.HashToFieldFn.Sum(hashBts[0:]) + hashBts := cfg.HashToFieldFn.Sum(nil) cfg.HashToFieldFn.Reset() hashedCmt.SetBytes(hashBts[:nbBuf]) diff --git a/std/recursion/groth16/verifier_test.go b/std/recursion/groth16/verifier_test.go index 79d00e0d91..50c1544469 100644 --- a/std/recursion/groth16/verifier_test.go +++ b/std/recursion/groth16/verifier_test.go @@ -1,7 +1,6 @@ package groth16 import ( - "crypto/sha256" "fmt" "math/big" "testing" @@ -175,12 +174,6 @@ func TestBLS12InBW6(t *testing.T) { assert.CheckCircuit(outerCircuit, test.WithValidAssignment(outerAssignment), test.WithCurves(ecc.BW6_761)) } -func getPreimageAndDigest() (preimage [9]byte, digest [32]byte) { - copy(preimage[:], []byte("recursion")) - digest = sha256.Sum256(preimage[:]) - return -} - type WitnessCircut struct { A emulated.Element[emparams.Secp256k1Fr] `gnark:",public"` } diff --git a/test/commitments_test.go b/test/commitments_test.go index 504d95dfa0..8a8102b3f2 100644 --- a/test/commitments_test.go +++ b/test/commitments_test.go @@ -203,8 +203,10 @@ func init() { func TestCommitment(t *testing.T) { t.Parallel() - for _, assignment := range commitmentTestCircuits { - NewAssert(t).ProverSucceeded(hollow(assignment), assignment, WithBackends(backend.GROTH16, backend.PLONK)) + assert := NewAssert(t) + for i, assignment := range commitmentTestCircuits { + t.Log("circuit", i, removePackageName(reflect.TypeOf(assignment).String())) + assert.CheckCircuit(hollow(assignment), WithValidAssignment(assignment), WithBackends(backend.GROTH16, backend.PLONK)) } } diff --git a/test/end_to_end.go b/test/end_to_end.go index 5da06b75c9..96dfba0c9a 100644 --- a/test/end_to_end.go +++ b/test/end_to_end.go @@ -1,32 +1,11 @@ package test import ( - "github.com/consensys/gnark-crypto/ecc" - "github.com/consensys/gnark/backend" - "github.com/consensys/gnark/frontend" "reflect" "strings" - "testing" -) - -func makeOpts(opt TestingOption, curves []ecc.ID) []TestingOption { - if len(curves) > 0 { - return []TestingOption{opt, WithCurves(curves[0], curves[1:]...)} - } - return []TestingOption{opt} -} - -func testPlonk(t *testing.T, assignment frontend.Circuit, curves ...ecc.ID) { - NewAssert(t).ProverSucceeded(hollow(assignment), assignment, makeOpts(WithBackends(backend.PLONK), curves)...) -} - -func testGroth16(t *testing.T, assignment frontend.Circuit, curves ...ecc.ID) { - NewAssert(t).ProverSucceeded(hollow(assignment), assignment, makeOpts(WithBackends(backend.GROTH16), curves)...) -} -func testAll(t *testing.T, assignment frontend.Circuit) { - NewAssert(t).ProverSucceeded(hollow(assignment), assignment, WithBackends(backend.GROTH16, backend.PLONK)) -} + "github.com/consensys/gnark/frontend" +) // hollow takes a gnark circuit and removes all the witness data. The resulting circuit can be used for compilation purposes // Its purpose is to make testing more convenient. For example, as opposed to SolvingSucceeded(circuit, assignment), diff --git a/test/engine.go b/test/engine.go index 2d543267db..5702832bdb 100644 --- a/test/engine.go +++ b/test/engine.go @@ -678,6 +678,11 @@ func (e *engine) Commit(v ...frontend.Variable) (frontend.Variable, error) { hasher.Read(buf) res := new(big.Int).SetBytes(buf) res.Mod(res, e.modulus()) + if res.Sign() == 0 { + // a commit == 0 is unlikely; happens quite often in tests + // with tinyfield + res.SetUint64(1) + } return res, nil } diff --git a/test/hint_test.go b/test/hint_test.go deleted file mode 100644 index d2c6650f7f..0000000000 --- a/test/hint_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package test - -import ( - "fmt" - "github.com/consensys/gnark/constraint/solver" - "github.com/consensys/gnark/frontend" - "math/big" - "testing" -) - -const id = solver.HintID(123454321) - -func identityHint(_ *big.Int, in, out []*big.Int) error { - if len(in) != len(out) { - return fmt.Errorf("len(in) = %d ≠ %d = len(out)", len(in), len(out)) - } - for i := range in { - out[i].Set(in[i]) - } - return nil -} - -type customNamedHintCircuit struct { - X []frontend.Variable -} - -func (c *customNamedHintCircuit) Define(api frontend.API) error { - y, err := api.Compiler().NewHintForId(id, len(c.X), c.X...) - - if err != nil { - return err - } - for i := range y { - api.AssertIsEqual(c.X[i], y[i]) - } - - return nil -} - -var assignment customNamedHintCircuit - -func init() { - solver.RegisterNamedHint(identityHint, id) - assignment = customNamedHintCircuit{X: []frontend.Variable{1, 2, 3, 4, 5}} -} - -func TestHintWithCustomNamePlonk(t *testing.T) { - testPlonk(t, &assignment) -} - -func TestHintWithCustomNameGroth16(t *testing.T) { - testGroth16(t, &assignment) -} - -func TestHintWithCustomNameEngine(t *testing.T) { - circuit := hollow(&assignment) - NewAssert(t).SolvingSucceeded(circuit, &assignment) -}