diff --git a/backend/groth16/bls12-377/marshal.go b/backend/groth16/bls12-377/marshal.go index d0e0f295c8..3d0d9ea30b 100644 --- a/backend/groth16/bls12-377/marshal.go +++ b/backend/groth16/bls12-377/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bls12-377/marshal_test.go b/backend/groth16/bls12-377/marshal_test.go index e2228b1432..4ad4a8719e 100644 --- a/backend/groth16/bls12-377/marshal_test.go +++ b/backend/groth16/bls12-377/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bls12-377/setup.go b/backend/groth16/bls12-377/setup.go index 5b6b3af78d..24efac699e 100644 --- a/backend/groth16/bls12-377/setup.go +++ b/backend/groth16/bls12-377/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/backend/groth16/bls12-381/marshal.go b/backend/groth16/bls12-381/marshal.go index 8a34d864fd..57e0af99f3 100644 --- a/backend/groth16/bls12-381/marshal.go +++ b/backend/groth16/bls12-381/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bls12-381/marshal_test.go b/backend/groth16/bls12-381/marshal_test.go index 3f8e9ab0cb..1f62e84659 100644 --- a/backend/groth16/bls12-381/marshal_test.go +++ b/backend/groth16/bls12-381/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bls12-381/setup.go b/backend/groth16/bls12-381/setup.go index 5c2f198ff9..bd0511a58e 100644 --- a/backend/groth16/bls12-381/setup.go +++ b/backend/groth16/bls12-381/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/backend/groth16/bls24-315/marshal.go b/backend/groth16/bls24-315/marshal.go index 32cbca8368..2684cca417 100644 --- a/backend/groth16/bls24-315/marshal.go +++ b/backend/groth16/bls24-315/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls24-315/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bls24-315/marshal_test.go b/backend/groth16/bls24-315/marshal_test.go index bf667dc189..849c5f684e 100644 --- a/backend/groth16/bls24-315/marshal_test.go +++ b/backend/groth16/bls24-315/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bls24-315/setup.go b/backend/groth16/bls24-315/setup.go index 6b3f193999..7f8147b3c0 100644 --- a/backend/groth16/bls24-315/setup.go +++ b/backend/groth16/bls24-315/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/backend/groth16/bls24-317/marshal.go b/backend/groth16/bls24-317/marshal.go index c1aa622e0c..d322edd46e 100644 --- a/backend/groth16/bls24-317/marshal.go +++ b/backend/groth16/bls24-317/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls24-317/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bls24-317/marshal_test.go b/backend/groth16/bls24-317/marshal_test.go index 816c340d3b..092b3beb4c 100644 --- a/backend/groth16/bls24-317/marshal_test.go +++ b/backend/groth16/bls24-317/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bls24-317/setup.go b/backend/groth16/bls24-317/setup.go index 53628f4c5e..c8db3321c2 100644 --- a/backend/groth16/bls24-317/setup.go +++ b/backend/groth16/bls24-317/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/backend/groth16/bn254/marshal.go b/backend/groth16/bn254/marshal.go index d1c6ba186f..5005269eba 100644 --- a/backend/groth16/bn254/marshal.go +++ b/backend/groth16/bn254/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bn254/marshal_test.go b/backend/groth16/bn254/marshal_test.go index 567371f1fb..65ded1d4bf 100644 --- a/backend/groth16/bn254/marshal_test.go +++ b/backend/groth16/bn254/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bn254/setup.go b/backend/groth16/bn254/setup.go index 13ddcd61d3..0af907355a 100644 --- a/backend/groth16/bn254/setup.go +++ b/backend/groth16/bn254/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/backend/groth16/bw6-633/marshal.go b/backend/groth16/bw6-633/marshal.go index d0d6ff3809..48b6ff1490 100644 --- a/backend/groth16/bw6-633/marshal.go +++ b/backend/groth16/bw6-633/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-633/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bw6-633/marshal_test.go b/backend/groth16/bw6-633/marshal_test.go index d3e7e1262d..e85f3eefcf 100644 --- a/backend/groth16/bw6-633/marshal_test.go +++ b/backend/groth16/bw6-633/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bw6-633/setup.go b/backend/groth16/bw6-633/setup.go index d26cd7c324..a569df46fb 100644 --- a/backend/groth16/bw6-633/setup.go +++ b/backend/groth16/bw6-633/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/backend/groth16/bw6-761/marshal.go b/backend/groth16/bw6-761/marshal.go index a5766ae5b3..4aebb1deb1 100644 --- a/backend/groth16/bw6-761/marshal.go +++ b/backend/groth16/bw6-761/marshal.go @@ -22,6 +22,8 @@ import ( "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/pedersen" "github.com/consensys/gnark-crypto/utils/unsafe" "github.com/consensys/gnark/internal/utils" + + "fmt" "io" ) @@ -196,35 +198,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -320,7 +326,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -344,31 +350,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -451,11 +460,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -479,57 +488,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/backend/groth16/bw6-761/marshal_test.go b/backend/groth16/bw6-761/marshal_test.go index 7538b33fd0..36e299d5c2 100644 --- a/backend/groth16/bw6-761/marshal_test.go +++ b/backend/groth16/bw6-761/marshal_test.go @@ -98,7 +98,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -175,17 +174,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any { return new(ProvingKey) }); err != nil { diff --git a/backend/groth16/bw6-761/setup.go b/backend/groth16/bw6-761/setup.go index 0988613d36..aeb2483c14 100644 --- a/backend/groth16/bw6-761/setup.go +++ b/backend/groth16/bw6-761/setup.go @@ -291,8 +291,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl index 5f11ac043b..4a839d36b1 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl @@ -3,6 +3,8 @@ import ( {{ template "import_pedersen" . }} "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark-crypto/utils/unsafe" + + "fmt" "io" ) @@ -178,35 +180,39 @@ func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) { &nbCommitments, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return dec.BytesRead(), err + return dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments) var n int64 - for i := range vk.CommitmentKeys { + for i := 0; i < int(nbCommitments); i++ { var ( m int64 err error ) + commitmentKey := pedersen.VerifyingKey{} if raw { - m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r) + m, err = commitmentKey.UnsafeReadFrom(r) } else { - m, err = vk.CommitmentKeys[i].ReadFrom(r) + m, err = commitmentKey.ReadFrom(r) } n += m if err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + vk.CommitmentKeys = append(vk.CommitmentKeys, commitmentKey) + } + if len(vk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(vk.CommitmentKeys)) } // recompute vk.e (e(α, β)) and -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("precompute: %w", err) } return n + dec.BytesRead(), nil @@ -306,7 +312,7 @@ func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) { func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) { n, err := pk.Domain.ReadFrom(r) if err != nil { - return n, err + return n, fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, decOptions...) @@ -330,31 +336,34 @@ func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return n + dec.BytesRead(), err + return n + dec.BytesRead(), fmt.Errorf("read nbCommitments: %w", err) } - - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - n2, err := pk.CommitmentKeys[i].ReadFrom(r) + for i := 0; i < int(nbCommitments); i++ { + cpkey := pedersen.ProvingKey{} + n2, err := cpkey.ReadFrom(r) n += n2 if err != nil { - return n, err + return n + dec.BytesRead(), fmt.Errorf("read commitment key %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return n + dec.BytesRead(), fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return n + dec.BytesRead(), nil @@ -438,11 +447,11 @@ func (pk *ProvingKey) WriteDump(w io.Writer) error { func (pk *ProvingKey) ReadDump(r io.Reader) error { // read the marker to fail early in case of malformed input if err := unsafe.ReadMarker(r); err != nil { - return err + return fmt.Errorf("read marker: %w", err) } if _, err := pk.Domain.ReadFrom(r); err != nil { - return err + return fmt.Errorf("read domain: %w", err) } dec := curve.NewDecoder(r, curve.NoSubgroupChecks()) @@ -466,57 +475,61 @@ func (pk *ProvingKey) ReadDump(r io.Reader) error { &pk.NbInfinityB, } - for _, v := range toDecode { + for i, v := range toDecode { if err := dec.Decode(v); err != nil { - return err + return fmt.Errorf("read field %d: %w", i, err) } } pk.InfinityA = make([]bool, nbWires) pk.InfinityB = make([]bool, nbWires) if err := dec.Decode(&pk.InfinityA); err != nil { - return err + return fmt.Errorf("read InfinityA: %w", err) } if err := dec.Decode(&pk.InfinityB); err != nil { - return err + return fmt.Errorf("read InfinityB: %w", err) } if err := dec.Decode(&nbCommitments); err != nil { - return err + return fmt.Errorf("read nbCommitments: %w", err) } // read slices of points var err error pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.A: %w", err) } pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.B: %w", err) } pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.Z: %w", err) } pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read G1.K: %w", err) } pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r) if err != nil { - return err + return fmt.Errorf("read G2.B: %w", err) } - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments) - for i := range pk.CommitmentKeys { - pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + for i := 0; i < int(nbCommitments); i++{ + cpkey := pedersen.ProvingKey{} + cpkey.Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basis %d: %w", i, err) } - pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) + cpkey.BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r) if err != nil { - return err + return fmt.Errorf("read commitment basisExpSigma %d: %w", i, err) } + pk.CommitmentKeys = append(pk.CommitmentKeys, cpkey) + } + if len(pk.CommitmentKeys) != int(nbCommitments) { + return fmt.Errorf("invalid number of commitment keys. Expected %d got %d", nbCommitments, len(pk.CommitmentKeys)) } return nil diff --git a/internal/generator/backend/template/zkpschemes/groth16/groth16.setup.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/groth16.setup.go.tmpl index ae86a7c39e..c184bb2829 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/groth16.setup.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/groth16.setup.go.tmpl @@ -273,8 +273,10 @@ func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *VerifyingKey) error { if err != nil { return err } - pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) - vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + if len(commitmentBases) > 0 { + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(commitmentBases)) + vk.CommitmentKeys = make([]pedersen.VerifyingKey, len(commitmentBases)) + } for i := range commitmentBases { comPKey, comVKey, err := pedersen.Setup(commitmentBases[i:i+1], pedersen.WithG2Point(cG2)) if err != nil { diff --git a/internal/generator/backend/template/zkpschemes/groth16/tests/groth16.marshal.go.tmpl b/internal/generator/backend/template/zkpschemes/groth16/tests/groth16.marshal.go.tmpl index 76046dc5eb..2e51218f01 100644 --- a/internal/generator/backend/template/zkpschemes/groth16/tests/groth16.marshal.go.tmpl +++ b/internal/generator/backend/template/zkpschemes/groth16/tests/groth16.marshal.go.tmpl @@ -82,7 +82,6 @@ func TestVerifyingKeySerialization(t *testing.T) { vk.G1.K[i] = p1 } - vk.CommitmentKeys = []pedersen.VerifyingKey{} if withCommitment { vk.PublicAndCommitmentCommitted = test_utils.Random2DIntSlice(5, 10) // TODO: Use gopter randomization bases := make([][]curve.G1Affine, len(vk.PublicAndCommitmentCommitted)) @@ -161,17 +160,18 @@ func TestProvingKeySerialization(t *testing.T) { pk.InfinityB = make([]bool, nbWires) pk.InfinityA[2] = true - pedersenBasis := make([]curve.G1Affine, nbCommitment) - pedersenBases := make([][]curve.G1Affine, nbCommitment) - pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitment) - for i := range pedersenBasis { - pedersenBasis[i] = p1 - pedersenBases[i] = pedersenBasis[:i+1] - } - { - var err error - pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) - require.NoError(t, err) + if nbCommitment > 0 { + pedersenBasis := make([]curve.G1Affine, nbCommitment) + pedersenBases := make([][]curve.G1Affine, nbCommitment) + for i := range pedersenBasis { + pedersenBasis[i] = p1 + pedersenBases[i] = pedersenBasis[:i+1] + } + { + var err error + pk.CommitmentKeys, _, err = pedersen.Setup(pedersenBases) + require.NoError(t, err) + } } if err := io.RoundTripCheck(&pk, func() any {return new(ProvingKey)}); err != nil {