From b04a6884de8de776f2d3803ec9f81892a8ae5886 Mon Sep 17 00:00:00 2001 From: Jeremy Felder Date: Mon, 16 Dec 2024 11:55:48 +0200 Subject: [PATCH] Update ICICLE integration to use v3 ICICLE (#1318) Co-authored-by: Ivo Kubjas --- README.md | 6 +- backend/groth16/bn254/icicle/device.go | 29 + backend/groth16/bn254/icicle/doc.go | 2 +- backend/groth16/bn254/icicle/icicle.go | 677 ++++++++++++------- backend/groth16/bn254/icicle/marshal_test.go | 33 +- backend/groth16/bn254/icicle/noicicle.go | 2 +- backend/groth16/bn254/icicle/provingkey.go | 32 +- backend/groth16/groth16.go | 2 +- go.mod | 4 +- go.sum | 6 +- 10 files changed, 537 insertions(+), 256 deletions(-) create mode 100644 backend/groth16/bn254/icicle/device.go diff --git a/README.md b/README.md index 229630ff94..02c008f95a 100644 --- a/README.md +++ b/README.md @@ -162,9 +162,9 @@ func main() { ### GPU Support -#### Icicle Library +#### ICICLE Library -The following schemes and curves support experimental use of Ingonyama's Icicle GPU library for low level zk-SNARK primitives such as MSM, NTT, and polynomial operations: +The following schemes and curves support experimental use of Ingonyama's ICICLE GPU library for low level zk-SNARK primitives such as MSM, NTT, and polynomial operations: - [x] [Groth16](https://eprint.iacr.org/2016/260) @@ -184,7 +184,7 @@ You can then toggle on or off icicle acceleration by providing the `WithIcicleAc proof, err := groth16.Prove(ccs, pk, secretWitness) ``` -For more information about prerequisites see the [Icicle repo](https://github.com/ingonyama-zk/icicle). +For more information about prerequisites see the [ICICLE repo](https://github.com/ingonyama-zk/icicle). **NB! ICICLE CUDA kernels are covered by a special license for now. Follow the instructions to download and set up the kernels.** ## Citing diff --git a/backend/groth16/bn254/icicle/device.go b/backend/groth16/bn254/icicle/device.go new file mode 100644 index 0000000000..d6d86ea362 --- /dev/null +++ b/backend/groth16/bn254/icicle/device.go @@ -0,0 +1,29 @@ +package icicle + +import ( + "fmt" + "sync" + + "github.com/consensys/gnark/logger" + icicle_runtime "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" +) + +var onceWarmUpDevice sync.Once + +func warmUpDevice() { + onceWarmUpDevice.Do(func() { + log := logger.Logger() + err := icicle_runtime.LoadBackendFromEnvOrDefault() + if err != icicle_runtime.Success { + panic(fmt.Sprintf("ICICLE backend loading error: %s", err.AsString())) + } + device := icicle_runtime.CreateDevice("CUDA", 0) + log.Debug().Int32("id", device.Id).Str("type", device.GetDeviceType()).Msg("ICICLE device created") + icicle_runtime.RunOnDevice(&device, func(args ...any) { + err := icicle_runtime.WarmUpDevice() + if err != icicle_runtime.Success { + panic(fmt.Sprintf("ICICLE device warmup error: %s", err.AsString())) + } + }) + }) +} diff --git a/backend/groth16/bn254/icicle/doc.go b/backend/groth16/bn254/icicle/doc.go index a77a7fbde9..3a662b35da 100644 --- a/backend/groth16/bn254/icicle/doc.go +++ b/backend/groth16/bn254/icicle/doc.go @@ -1,2 +1,2 @@ // Package icicle_bn254 implements ICICLE acceleration for BN254 Groth16 backend. -package icicle_bn254 +package icicle diff --git a/backend/groth16/bn254/icicle/icicle.go b/backend/groth16/bn254/icicle/icicle.go index 5b1b235d33..49133cd8b1 100644 --- a/backend/groth16/bn254/icicle/icicle.go +++ b/backend/groth16/bn254/icicle/icicle.go @@ -1,19 +1,20 @@ //go:build icicle -package icicle_bn254 +package icicle import ( "fmt" "math/big" "math/bits" + "os" "time" - "unsafe" + "github.com/consensys/gnark-crypto/ecc" curve "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" "github.com/consensys/gnark-crypto/ecc/bn254/fr/hash_to_field" - "github.com/consensys/gnark-crypto/ecc/bn254/fr/pedersen" "github.com/consensys/gnark/backend" groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254" "github.com/consensys/gnark/backend/groth16/internal" @@ -23,33 +24,40 @@ import ( "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" - iciclegnark "github.com/ingonyama-zk/iciclegnark/curves/bn254" + + icicle_core "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" + icicle_bn254 "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254" + icicle_g2 "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/g2" + icicle_msm "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/msm" + icicle_ntt "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/ntt" + icicle_vecops "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/vecOps" + icicle_runtime "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" + + fcs "github.com/consensys/gnark/frontend/cs" ) const HasIcicle = true -func (pk *ProvingKey) setupDevicePointers() error { +var isProfileMode bool + +func init() { + _, isProfileMode = os.LookupEnv("ICICLE_STEP_PROFILE") +} + +func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { if pk.deviceInfo != nil { return nil } pk.deviceInfo = &deviceInfo{} - n := int(pk.Domain.Cardinality) - sizeBytes := n * fr.Bytes - - /************************* Start Domain Device Setup ***************************/ - copyCosetInvDone := make(chan unsafe.Pointer, 1) - copyCosetDone := make(chan unsafe.Pointer, 1) - copyDenDone := make(chan unsafe.Pointer, 1) - /************************* CosetTableInv ***************************/ - go iciclegnark.CopyToDevice(pk.Domain.CosetTableInv, sizeBytes, copyCosetInvDone) - - /************************* CosetTable ***************************/ - go iciclegnark.CopyToDevice(pk.Domain.CosetTable, sizeBytes, copyCosetDone) - + gen, err := fft.Generator(2 * pk.Domain.Cardinality) + if err != nil { + return fmt.Errorf("get fft generator: %w", err) + } /************************* Den ***************************/ + n := int(pk.Domain.Cardinality) var denI, oneI fr.Element oneI.SetOne() - denI.Exp(pk.Domain.FrMultiplicativeGen, big.NewInt(int64(pk.Domain.Cardinality))) + denI.Exp(gen, big.NewInt(int64(pk.Domain.Cardinality))) denI.Sub(&denI, &oneI).Inverse(&denI) log2SizeFloor := bits.Len(uint(n)) - 1 @@ -62,71 +70,165 @@ func (pk *ProvingKey) setupDevicePointers() error { denIcicleArr = append(denIcicleArr, denI) } - go iciclegnark.CopyToDevice(denIcicleArr, sizeBytes, copyDenDone) + copyDenDone := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + denIcicleArrHost := (icicle_core.HostSlice[fr.Element])(denIcicleArr) + denIcicleArrHost.CopyToDevice(&pk.DenDevice, true) + if err := icicle_bn254.FromMontgomery(pk.DenDevice); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy den to device: %s", err.AsString())) + } + close(copyDenDone) + }) + + /************************* Init Domain Device ***************************/ + genBits := gen.Bits() + limbs := icicle_core.ConvertUint64ArrToUint32Arr(genBits[:]) + copy(pk.CosetGenerator[:], limbs[:fr.Limbs*2]) + var rouIcicle icicle_bn254.ScalarField + rouIcicle.FromLimbs(limbs) + + initDomain := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + if e := icicle_ntt.InitDomain(rouIcicle, icicle_core.GetDefaultNTTInitDomainConfig()); e != icicle_runtime.Success { + panic(fmt.Sprintf("couldn't initialize domain: %s", e.AsString())) // TODO + } + close(initDomain) + }) - /************************* Twiddles and Twiddles Inv ***************************/ - twiddlesInv_d_gen, twddles_err := iciclegnark.GenerateTwiddleFactors(n, true) - if twddles_err != nil { - return twddles_err - } + /************************* End Init Domain Device ***************************/ + /************************* Start G1 Device Setup ***************************/ + /************************* A ***************************/ + copyADone := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + g1AHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.A) + g1AHost.CopyToDevice(&pk.G1Device.A, true) + if err := icicle_bn254.AffineFromMontgomery(pk.G1Device.A); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy A to device: %s", err.AsString())) + } + close(copyADone) + }) + /************************* B ***************************/ + copyBDone := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + g1BHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.B) + g1BHost.CopyToDevice(&pk.G1Device.B, true) + if err := icicle_bn254.AffineFromMontgomery(pk.G1Device.B); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy B to device: %s", err.AsString())) + } + close(copyBDone) + }) + /************************* K ***************************/ + copyKDone := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + g1KHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.K) + g1KHost.CopyToDevice(&pk.G1Device.K, true) + if err := icicle_bn254.AffineFromMontgomery(pk.G1Device.K); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy K to device: %s", err.AsString())) + } + close(copyKDone) + }) + /************************* Z ***************************/ + copyZDone := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + g1ZHost := (icicle_core.HostSlice[curve.G1Affine])(pk.G1.Z) + g1ZHost.CopyToDevice(&pk.G1Device.Z, true) + err := icicle_bn254.AffineFromMontgomery(pk.G1Device.Z) + if err != icicle_runtime.Success { + panic(fmt.Sprintf("copy Z to device: %s", err.AsString())) + } + close(copyZDone) + }) + /************************* End G1 Device Setup ***************************/ + /************************* Start G2 Device Setup ***************************/ + copyG2BDone := make(chan struct{}) + icicle_runtime.RunOnDevice(device, func(args ...any) { + g2BHost := (icicle_core.HostSlice[curve.G2Affine])(pk.G2.B) + g2BHost.CopyToDevice(&pk.G2Device.B, true) + if err := icicle_g2.G2AffineFromMontgomery(pk.G2Device.B); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy G2 B to device: %s", err.AsString())) + } + close(copyG2BDone) + }) + /************************* End G2 Device Setup ***************************/ - twiddles_d_gen, twddles_err := iciclegnark.GenerateTwiddleFactors(n, false) - if twddles_err != nil { - return twddles_err - } + /************************* Commitment Keys Device Setup ***************************/ + + commitmentKeysDeviceDone := make(chan struct{}) + pk.CommitmentKeysDevice.Basis = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) + pk.CommitmentKeysDevice.BasisExpSigma = make([]icicle_core.DeviceSlice, len(pk.CommitmentKeys)) + icicle_runtime.RunOnDevice(device, func(args ...any) { + for i := range pk.CommitmentKeys { + commitmentKeyBasisHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].Basis) + commitmentKeyBasisExpSigmaHost := icicle_core.HostSliceFromElements(pk.CommitmentKeys[i].BasisExpSigma) + commitmentKeyBasisHost.CopyToDevice(&pk.CommitmentKeysDevice.Basis[i], true) + commitmentKeyBasisExpSigmaHost.CopyToDevice(&pk.CommitmentKeysDevice.BasisExpSigma[i], true) + } + close(commitmentKeysDeviceDone) + }) + /************************* End Commitment Keys Device Setup ***************************/ + + /************************* Wait for all data tranfsers ***************************/ + <-initDomain + <-copyDenDone + <-copyADone + <-copyBDone + <-copyKDone + <-copyZDone + <-copyG2BDone + <-commitmentKeysDeviceDone - /************************* End Domain Device Setup ***************************/ - pk.DomainDevice.Twiddles = twiddles_d_gen - pk.DomainDevice.TwiddlesInv = twiddlesInv_d_gen + return nil +} - pk.DomainDevice.CosetTableInv = <-copyCosetInvDone - pk.DomainDevice.CosetTable = <-copyCosetDone - pk.DenDevice = <-copyDenDone +func projectiveToGnarkAffine(p icicle_bn254.Projective) *curve.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(p.X.ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(p.Y.ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(p.Z.ToBytesLittleEndian())) - /************************* Start G1 Device Setup ***************************/ - /************************* A ***************************/ - pointsBytesA := len(pk.G1.A) * fp.Bytes * 2 - copyADone := make(chan unsafe.Pointer, 1) - go iciclegnark.CopyPointsToDevice(pk.G1.A, pointsBytesA, copyADone) // Make a function for points + var x, y, zInv fp.Element - /************************* B ***************************/ - pointsBytesB := len(pk.G1.B) * fp.Bytes * 2 - copyBDone := make(chan unsafe.Pointer, 1) - go iciclegnark.CopyPointsToDevice(pk.G1.B, pointsBytesB, copyBDone) // Make a function for points + zInv.Inverse(&pz) + x.Mul(&px, &zInv) + y.Mul(&py, &zInv) - /************************* K ***************************/ - var pointsNoInfinity []curve.G1Affine - for i, gnarkPoint := range pk.G1.K { - if gnarkPoint.IsInfinity() { - pk.InfinityPointIndicesK = append(pk.InfinityPointIndicesK, i) - } else { - pointsNoInfinity = append(pointsNoInfinity, gnarkPoint) - } - } + return &curve.G1Affine{X: x, Y: y} +} - pointsBytesK := len(pointsNoInfinity) * fp.Bytes * 2 - copyKDone := make(chan unsafe.Pointer, 1) - go iciclegnark.CopyPointsToDevice(pointsNoInfinity, pointsBytesK, copyKDone) // Make a function for points +func g1ProjectiveToG1Jac(p icicle_bn254.Projective) curve.G1Jac { + var p1 curve.G1Jac + p1.FromAffine(projectiveToGnarkAffine(p)) - /************************* Z ***************************/ - pointsBytesZ := len(pk.G1.Z) * fp.Bytes * 2 - copyZDone := make(chan unsafe.Pointer, 1) - go iciclegnark.CopyPointsToDevice(pk.G1.Z, pointsBytesZ, copyZDone) // Make a function for points + return p1 +} - /************************* End G1 Device Setup ***************************/ - pk.G1Device.A = <-copyADone - pk.G1Device.B = <-copyBDone - pk.G1Device.K = <-copyKDone - pk.G1Device.Z = <-copyZDone +func toGnarkE2(f icicle_g2.G2BaseField) curve.E2 { + bytes := f.ToBytesLittleEndian() + a0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(bytes[:fp.Bytes])) + a1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(bytes[fp.Bytes:])) + return curve.E2{ + A0: a0, + A1: a1, + } +} - /************************* Start G2 Device Setup ***************************/ - pointsBytesB2 := len(pk.G2.B) * fp.Bytes * 4 - copyG2BDone := make(chan unsafe.Pointer, 1) - go iciclegnark.CopyG2PointsToDevice(pk.G2.B, pointsBytesB2, copyG2BDone) // Make a function for points - pk.G2Device.B = <-copyG2BDone +func g2ProjectiveToG2Jac(p *icicle_g2.G2Projective) curve.G2Jac { + x := toGnarkE2(p.X) + y := toGnarkE2(p.Y) + z := toGnarkE2(p.Z) + var zSquared curve.E2 + zSquared.Mul(&z, &z) - /************************* End G2 Device Setup ***************************/ - return nil + var X curve.E2 + X.Mul(&x, &z) + + var Y curve.E2 + Y.Mul(&y, &zSquared) + + return curve.G2Jac{ + X: X, + Y: Y, + Z: z, + } } // Prove generates the proof of knowledge of a r1cs with full witness (secret + public part). @@ -142,9 +244,13 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return groth16_bn254.Prove(r1cs, &pk.ProvingKey, fullWitness, opts...) } log := logger.Logger().With().Str("curve", r1cs.CurveID().String()).Str("acceleration", "icicle").Int("nbConstraints", r1cs.GetNbConstraints()).Str("backend", "groth16").Logger() + + device := icicle_runtime.CreateDevice("CUDA", 0) + if pk.deviceInfo == nil { log.Debug().Msg("precomputing proving key in GPU") - if err := pk.setupDevicePointers(); err != nil { + + if err := pk.setupDevicePointers(&device); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) } } @@ -156,42 +262,48 @@ 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 - } + privateCommittedValuesDevice := make([]icicle_core.DeviceSlice, len(commitmentInfo)) + + // 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 + proofCommitmentIcicle := make(icicle_core.HostSlice[icicle_bn254.Projective], 1) + ckBasisMsmDone := make(chan struct{}) + icicle_runtime.RunOnDevice(&device, func(args ...any) { + cfg := icicle_msm.GetDefaultMSMConfig() + cfg.AreBasesMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + privateCommittedValuesHost := icicle_core.HostSliceFromElements(privateCommittedValues[i]) + privateCommittedValuesHost.CopyToDevice(&privateCommittedValuesDevice[i], true) + if err := icicle_msm.Msm(privateCommittedValuesDevice[i], pk.CommitmentKeysDevice.Basis[i], &cfg, proofCommitmentIcicle); err != icicle_runtime.Success { + panic(fmt.Sprintf("commitment: %s", err.AsString())) } - }(i))) - } - - if r1cs.GkrInfo.Is() { - var gkrData cs.GkrSolvingData - solverOpts = append(solverOpts, - solver.OverrideHint(r1cs.GkrInfo.SolveHintID, cs.GkrSolveHint(r1cs.GkrInfo, &gkrData)), - solver.OverrideHint(r1cs.GkrInfo.ProveHintID, cs.GkrProveHint(r1cs.GkrInfo.HashName, &gkrData))) - } + close(ckBasisMsmDone) + }) + <-ckBasisMsmDone + proof.Commitments[i] = *projectiveToGnarkAffine(proofCommitmentIcicle[0]) + + 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 + })) _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { @@ -202,33 +314,66 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b wireValues := []fr.Element(solution.W) start := time.Now() - + numCommitmentKeys := len(pk.CommitmentKeys) + poks := make([]curve.G1Affine, numCommitmentKeys) + + // if there are CommitmentKeys, run a batch MSM for pederson Proof of Knowledge + if numCommitmentKeys > 0 { + startPoKBatch := time.Now() + poksIcicle := make([]icicle_core.HostSlice[icicle_bn254.Projective], numCommitmentKeys) + for i := range poksIcicle { + poksIcicle[i] = make(icicle_core.HostSlice[icicle_bn254.Projective], 1) + } + ckBasisExpSigmaMsmBatchDone := make(chan struct{}) + icicle_runtime.RunOnDevice(&device, func(args ...any) { + cfg := icicle_msm.GetDefaultMSMConfig() + cfg.AreBasesMontgomeryForm = true + cfg.AreScalarsMontgomeryForm = true + for i := range pk.CommitmentKeysDevice.BasisExpSigma { + if err := icicle_msm.Msm(privateCommittedValuesDevice[i], pk.CommitmentKeysDevice.BasisExpSigma[i], &cfg, poksIcicle[i]); err != icicle_runtime.Success { + panic(fmt.Sprintf("commitment POK: %s", err.AsString())) + } + } + close(ckBasisExpSigmaMsmBatchDone) + }) + <-ckBasisExpSigmaMsmBatchDone + for i := range pk.CommitmentKeys { + poks[i] = *projectiveToGnarkAffine(poksIcicle[i][0]) + } + if isProfileMode { + log.Debug().Dur("took", time.Since(startPoKBatch)).Msg("ICICLE Batch Proof of Knowledge") + } + } + // compute challenge for folding the PoKs from the commitments commitmentsSerialized := make([]byte, fr.Bytes*len(commitmentInfo)) for i := range commitmentInfo { copy(commitmentsSerialized[fr.Bytes*i:], wireValues[commitmentInfo[i].CommitmentIndex].Marshal()) } - - if proof.CommitmentPok, err = pedersen.BatchProve(pk.CommitmentKeys, privateCommittedValues, commitmentsSerialized); err != nil { + challenge, err := fr.Hash(commitmentsSerialized, []byte("G16-BSB22"), 1) + if err != nil { + return nil, err + } + if _, err = proof.CommitmentPok.Fold(poks, challenge[0], ecc.MultiExpConfig{NbTasks: 1}); err != nil { return nil, err } - // H (witness reduction / FFT part) - var h unsafe.Pointer - chHDone := make(chan struct{}, 1) - go func() { - h = computeH(solution.A, solution.B, solution.C, pk) + var h icicle_core.DeviceSlice + chHDone := make(chan struct{}) + icicle_runtime.RunOnDevice(&device, func(args ...any) { + h = computeH(solution.A, solution.B, solution.C, pk, &device) + solution.A = nil solution.B = nil solution.C = nil - chHDone <- struct{}{} - }() + close(chHDone) + }) // we need to copy and filter the wireValues for each multi exp // as pk.G1.A, pk.G1.B and pk.G2.B may have (a significant) number of point at infinity - var wireValuesADevice, wireValuesBDevice iciclegnark.OnDeviceData - chWireValuesA, chWireValuesB := make(chan struct{}, 1), make(chan struct{}, 1) + var wireValuesADevice, wireValuesBDevice icicle_core.DeviceSlice + chWireValuesA, chWireValuesB := make(chan struct{}), make(chan struct{}) - go func() { + icicle_runtime.RunOnDevice(&device, func(args ...any) { wireValuesA := make([]fr.Element, len(wireValues)-int(pk.NbInfinityA)) for i, j := 0, 0; j < len(wireValuesA); i++ { if pk.InfinityA[i] { @@ -237,22 +382,18 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b wireValuesA[j] = wireValues[i] j++ } - wireValuesASize := len(wireValuesA) - scalarBytes := wireValuesASize * fr.Bytes // Copy scalars to the device and retain ptr to them - copyDone := make(chan unsafe.Pointer, 1) - iciclegnark.CopyToDevice(wireValuesA, scalarBytes, copyDone) - wireValuesADevicePtr := <-copyDone - - wireValuesADevice = iciclegnark.OnDeviceData{ - P: wireValuesADevicePtr, - Size: wireValuesASize, + wireValuesAHost := (icicle_core.HostSlice[fr.Element])(wireValuesA) + wireValuesAHost.CopyToDevice(&wireValuesADevice, true) + if err := icicle_bn254.FromMontgomery(wireValuesADevice); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy A to device: %s", err.AsString())) } close(chWireValuesA) - }() - go func() { + }) + + icicle_runtime.RunOnDevice(&device, func(args ...any) { wireValuesB := make([]fr.Element, len(wireValues)-int(pk.NbInfinityB)) for i, j := 0, 0; j < len(wireValuesB); i++ { if pk.InfinityB[i] { @@ -261,21 +402,16 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b wireValuesB[j] = wireValues[i] j++ } - wireValuesBSize := len(wireValuesB) - scalarBytes := wireValuesBSize * fr.Bytes // Copy scalars to the device and retain ptr to them - copyDone := make(chan unsafe.Pointer, 1) - iciclegnark.CopyToDevice(wireValuesB, scalarBytes, copyDone) - wireValuesBDevicePtr := <-copyDone - - wireValuesBDevice = iciclegnark.OnDeviceData{ - P: wireValuesBDevicePtr, - Size: wireValuesBSize, + wireValuesBHost := (icicle_core.HostSlice[fr.Element])(wireValuesB) + wireValuesBHost.CopyToDevice(&wireValuesBDevice, true) + if err := icicle_bn254.FromMontgomery(wireValuesBDevice); err != icicle_runtime.Success { + panic(fmt.Sprintf("copy B to device: %s", err.AsString())) } close(chWireValuesB) - }() + }) // sample random r and s var r, s big.Int @@ -295,74 +431,91 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b deltas := curve.BatchScalarMultiplicationG1(&pk.G1.Delta, []fr.Element{_r, _s, _kr}) var bs1, ar curve.G1Jac + chArDone, chBs1Done := make(chan struct{}), make(chan struct{}) computeBS1 := func() error { <-chWireValuesB - if bs1, _, err = iciclegnark.MsmOnDevice(wireValuesBDevice.P, pk.G1Device.B, wireValuesBDevice.Size, true); err != nil { - return err + cfg := icicle_msm.GetDefaultMSMConfig() + res := make(icicle_core.HostSlice[icicle_bn254.Projective], 1) + start := time.Now() + if err := icicle_msm.Msm(wireValuesBDevice, pk.G1Device.B, &cfg, res); err != icicle_runtime.Success { + panic(fmt.Sprintf("msm Bs1: %s", err.AsString())) + } + + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("MSM Bs1") } + bs1 = g1ProjectiveToG1Jac(res[0]) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) + close(chBs1Done) return nil } computeAR1 := func() error { <-chWireValuesA - if ar, _, err = iciclegnark.MsmOnDevice(wireValuesADevice.P, pk.G1Device.A, wireValuesADevice.Size, true); err != nil { - return err + cfg := icicle_msm.GetDefaultMSMConfig() + res := make(icicle_core.HostSlice[icicle_bn254.Projective], 1) + start := time.Now() + if err := icicle_msm.Msm(wireValuesADevice, pk.G1Device.A, &cfg, res); err != icicle_runtime.Success { + panic(fmt.Sprintf("msm Ar1: %s", err.AsString())) + } + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("MSM Ar1") } + ar = g1ProjectiveToG1Jac(res[0]) ar.AddMixed(&pk.G1.Alpha) ar.AddMixed(&deltas[0]) proof.Ar.FromJacobian(&ar) + close(chArDone) return nil } computeKRS := func() error { var krs, krs2, p1 curve.G1Jac - sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 + sizeH := int(pk.Domain.Cardinality - 1) - // check for small circuits as iciclegnark doesn't handle zero sizes well - if len(pk.G1.Z) > 0 { - if krs2, _, err = iciclegnark.MsmOnDevice(h, pk.G1Device.Z, sizeH, true); err != nil { - return err - } + cfg := icicle_msm.GetDefaultMSMConfig() + resKrs2 := make(icicle_core.HostSlice[icicle_bn254.Projective], 1) + start := time.Now() + if err := icicle_msm.Msm(h.RangeTo(sizeH, false), pk.G1Device.Z, &cfg, resKrs2); err != icicle_runtime.Success { + panic(fmt.Sprintf("msm Krs2: %s", err.AsString())) + } + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("MSM Krs2") } + krs2 = g1ProjectiveToG1Jac(resKrs2[0]) // filter the wire values if needed // TODO Perf @Tabaie worst memory allocation offender toRemove := commitmentInfo.GetPrivateCommitted() toRemove = append(toRemove, commitmentInfo.CommitmentIndexes()) - scalars := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) - - // filter zero/infinity points since icicle doesn't handle them - // See https://github.com/ingonyama-zk/icicle/issues/169 for more info - for _, indexToRemove := range pk.InfinityPointIndicesK { - scalars = append(scalars[:indexToRemove], scalars[indexToRemove+1:]...) + _wireValues := filterHeap(wireValues[r1cs.GetNbPublicVariables():], r1cs.GetNbPublicVariables(), internal.ConcatAll(toRemove...)) + _wireValuesHost := (icicle_core.HostSlice[fr.Element])(_wireValues) + resKrs := make(icicle_core.HostSlice[icicle_bn254.Projective], 1) + cfg.AreScalarsMontgomeryForm = true + start = time.Now() + if err := icicle_msm.Msm(_wireValuesHost, pk.G1Device.K, &cfg, resKrs); err != icicle_runtime.Success { + panic(fmt.Sprintf("msm Krs: %s", err.AsString())) } - - scalarBytes := len(scalars) * fr.Bytes - - copyDone := make(chan unsafe.Pointer, 1) - iciclegnark.CopyToDevice(scalars, scalarBytes, copyDone) - scalars_d := <-copyDone - - krs, _, err = iciclegnark.MsmOnDevice(scalars_d, pk.G1Device.K, len(scalars), true) - iciclegnark.FreeDevicePointer(scalars_d) - - if err != nil { - return err + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("MSM Krs") } + krs = g1ProjectiveToG1Jac(resKrs[0]) krs.AddMixed(&deltas[2]) krs.AddAssign(&krs2) + <-chArDone + <-chBs1Done + p1.ScalarMultiplication(&ar, &s) krs.AddAssign(&p1) @@ -379,9 +532,17 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b var Bs, deltaS curve.G2Jac <-chWireValuesB - if Bs, _, err = iciclegnark.MsmG2OnDevice(wireValuesBDevice.P, pk.G2Device.B, wireValuesBDevice.Size, true); err != nil { - return err + + cfg := icicle_g2.G2GetDefaultMSMConfig() + res := make(icicle_core.HostSlice[icicle_g2.G2Projective], 1) + start := time.Now() + if err := icicle_g2.G2Msm(wireValuesBDevice, pk.G2Device.B, &cfg, res); err != icicle_runtime.Success { + panic(fmt.Sprintf("msm Bs2: %s", err.AsString())) + } + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("MSM Bs2 G2") } + Bs = g2ProjectiveToG2Jac(&res[0]) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) @@ -392,31 +553,51 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b return nil } + // schedule our proof part computations + icicle_runtime.RunOnDevice(&device, func(args ...any) { + if err := computeAR1(); err != nil { + panic(fmt.Sprintf("compute AR1: %v", err)) + } + }) + + icicle_runtime.RunOnDevice(&device, func(args ...any) { + if err := computeBS1(); err != nil { + panic(fmt.Sprintf("compute BS1: %v", err)) + } + }) + + icicle_runtime.RunOnDevice(&device, func(args ...any) { + if err := computeBS2(); err != nil { + panic(fmt.Sprintf("compute BS2: %v", err)) + } + }) + // wait for FFT to end <-chHDone - // schedule our proof part computations - if err := computeAR1(); err != nil { - return nil, err - } - if err := computeBS1(); err != nil { - return nil, err - } - if err := computeKRS(); err != nil { - return nil, err - } - if err := computeBS2(); err != nil { - return nil, err - } + computeKrsDone := make(chan struct{}) + icicle_runtime.RunOnDevice(&device, func(args ...any) { + if err := computeKRS(); err != nil { + panic(fmt.Sprintf("compute KRS: %v", err)) + } + close(computeKrsDone) + }) + <-computeKrsDone log.Debug().Dur("took", time.Since(start)).Msg("prover done") // free device/GPU memory that is not needed for future proofs (scalars/hpoly) - go func() { - iciclegnark.FreeDevicePointer(wireValuesADevice.P) - iciclegnark.FreeDevicePointer(wireValuesBDevice.P) - iciclegnark.FreeDevicePointer(h) - }() + icicle_runtime.RunOnDevice(&device, func(args ...any) { + if err := wireValuesADevice.Free(); err != icicle_runtime.Success { + log.Error().Msgf("free wireValuesADevice failed: %s", err.AsString()) + } + if err := wireValuesBDevice.Free(); err != icicle_runtime.Success { + log.Error().Msgf("free wireValuesBDevice failed: %s", err.AsString()) + } + if err := h.Free(); err != icicle_runtime.Success { + log.Error().Msgf("free h failed: %s", err.AsString()) + } + }) return proof, nil } @@ -450,13 +631,14 @@ func filterHeap(slice []fr.Element, sliceFirstIndex int, toRemove []int) (r []fr return } -func computeH(a, b, c []fr.Element, pk *ProvingKey) unsafe.Pointer { +func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Device) icicle_core.DeviceSlice { // H part of Krs // Compute H (hz=ab-c, where z=-2 on ker X^n+1 (z(x)=x^n-1)) // 1 - _a = ifft(a), _b = ifft(b), _c = ifft(c) // 2 - ca = fft_coset(_a), ba = fft_coset(_b), cc = fft_coset(_c) // 3 - h = ifft_coset(ca o cb - cc) - + log := logger.Logger() + startTotal := time.Now() n := len(a) // add padding to ensure input length is domain cardinality @@ -466,48 +648,83 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey) unsafe.Pointer { c = append(c, padding...) n = len(a) - sizeBytes := n * fr.Bytes - - /*********** Copy a,b,c to Device Start ************/ - // Individual channels are necessary to know which device pointers - // point to which vector - copyADone := make(chan unsafe.Pointer, 1) - copyBDone := make(chan unsafe.Pointer, 1) - copyCDone := make(chan unsafe.Pointer, 1) - - go iciclegnark.CopyToDevice(a, sizeBytes, copyADone) - go iciclegnark.CopyToDevice(b, sizeBytes, copyBDone) - go iciclegnark.CopyToDevice(c, sizeBytes, copyCDone) - - a_device := <-copyADone - b_device := <-copyBDone - c_device := <-copyCDone - /*********** Copy a,b,c to Device End ************/ - - computeInttNttDone := make(chan error, 1) - computeInttNttOnDevice := func(devicePointer unsafe.Pointer) { - a_intt_d := iciclegnark.INttOnDevice(devicePointer, pk.DomainDevice.TwiddlesInv, nil, n, sizeBytes, false) - iciclegnark.NttOnDevice(devicePointer, a_intt_d, pk.DomainDevice.Twiddles, pk.DomainDevice.CosetTable, n, n, sizeBytes, true) - computeInttNttDone <- nil - iciclegnark.FreeDevicePointer(a_intt_d) + computeADone := make(chan icicle_core.DeviceSlice) + computeBDone := make(chan icicle_core.DeviceSlice) + computeCDone := make(chan icicle_core.DeviceSlice) + + computeInttNttOnDevice := func(args ...any) { + var scalars []fr.Element = args[0].([]fr.Element) + var channel chan icicle_core.DeviceSlice = args[1].(chan icicle_core.DeviceSlice) + + cfg := icicle_ntt.GetDefaultNttConfig() + scalarsStream, _ := icicle_runtime.CreateStream() + cfg.StreamHandle = scalarsStream + cfg.Ordering = icicle_core.KNM + cfg.IsAsync = true + scalarsHost := icicle_core.HostSliceFromElements(scalars) + var scalarsDevice icicle_core.DeviceSlice + scalarsHost.CopyToDeviceAsync(&scalarsDevice, scalarsStream, true) + start := time.Now() + icicle_ntt.Ntt(scalarsDevice, icicle_core.KInverse, &cfg, scalarsDevice) + cfg.Ordering = icicle_core.KMN + cfg.CosetGen = pk.CosetGenerator + icicle_ntt.Ntt(scalarsDevice, icicle_core.KForward, &cfg, scalarsDevice) + icicle_runtime.SynchronizeStream(scalarsStream) + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("computeH: NTT + INTT") + } + channel <- scalarsDevice + close(channel) } - go computeInttNttOnDevice(a_device) - go computeInttNttOnDevice(b_device) - go computeInttNttOnDevice(c_device) - _, _, _ = <-computeInttNttDone, <-computeInttNttDone, <-computeInttNttDone + icicle_runtime.RunOnDevice(device, computeInttNttOnDevice, a, computeADone) + icicle_runtime.RunOnDevice(device, computeInttNttOnDevice, b, computeBDone) + icicle_runtime.RunOnDevice(device, computeInttNttOnDevice, c, computeCDone) - iciclegnark.PolyOps(a_device, b_device, c_device, pk.DenDevice, n) + aDevice := <-computeADone + bDevice := <-computeBDone + cDevice := <-computeCDone - h := iciclegnark.INttOnDevice(a_device, pk.DomainDevice.TwiddlesInv, pk.DomainDevice.CosetTableInv, n, sizeBytes, true) - - go func() { - iciclegnark.FreeDevicePointer(a_device) - iciclegnark.FreeDevicePointer(b_device) - iciclegnark.FreeDevicePointer(c_device) - }() - - iciclegnark.ReverseScalars(h, n) + // The following does not need to be run in a RunOnDevice call because + // computeH is being run inside a RunOnDevice call and the following is not + // being run in a different goroutine unlike the calls above to + // computeInttNttOnDevice which are running in different goroutines + vecCfg := icicle_core.DefaultVecOpsConfig() + start := time.Now() + if err := icicle_bn254.FromMontgomery(aDevice); err != icicle_runtime.Success { + panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) + } + if err := icicle_vecops.VecOp(aDevice, bDevice, aDevice, vecCfg, icicle_core.Mul); err != icicle_runtime.Success { + panic(fmt.Sprintf("mul a b in computeH: %s", err.AsString())) + } + if err := icicle_vecops.VecOp(aDevice, cDevice, aDevice, vecCfg, icicle_core.Sub); err != icicle_runtime.Success { + panic(fmt.Sprintf("sub a c in computeH: %s", err.AsString())) + } + if err := icicle_vecops.VecOp(aDevice, pk.DenDevice, aDevice, vecCfg, icicle_core.Mul); err != icicle_runtime.Success { + panic(fmt.Sprintf("mul a den in computeH: %s", err.AsString())) + } + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("computeH: vecOps") + } + defer bDevice.Free() + defer cDevice.Free() + + cfg := icicle_ntt.GetDefaultNttConfig() + cfg.CosetGen = pk.CosetGenerator + cfg.Ordering = icicle_core.KNR + start = time.Now() + if err := icicle_ntt.Ntt(aDevice, icicle_core.KInverse, &cfg, aDevice); err != icicle_runtime.Success { + panic(fmt.Sprintf("ntt a in computeH: %s", err.AsString())) + } + if isProfileMode { + log.Debug().Dur("took", time.Since(start)).Msg("computeH: INTT final") + } + if err := icicle_bn254.FromMontgomery(aDevice); err != icicle_runtime.Success { + panic(fmt.Sprintf("fromMontgomery a in computeH: %s", err.AsString())) + } - return h + if isProfileMode { + log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + } + return aDevice } diff --git a/backend/groth16/bn254/icicle/marshal_test.go b/backend/groth16/bn254/icicle/marshal_test.go index 75c5a2b57e..114765dafe 100644 --- a/backend/groth16/bn254/icicle/marshal_test.go +++ b/backend/groth16/bn254/icicle/marshal_test.go @@ -1,10 +1,13 @@ -package icicle_bn254_test +//go:build icicle + +package icicle_test import ( "bytes" "testing" "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark/backend" "github.com/consensys/gnark/backend/groth16" groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254" icicle_bn254 "github.com/consensys/gnark/backend/groth16/bn254/icicle" @@ -43,6 +46,20 @@ func TestMarshal(t *testing.T) { if pk.IsDifferent(&nativePK) { t.Error("marshal output difference") } + + assignment := circuit{A: 3, B: 5, Res: 15} + w, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + assert.NoError(err) + pw, err := w.Public() + assert.NoError(err) + proofNative, err := groth16_bn254.Prove(tCcs, &nativePK, w) + assert.NoError(err) + proofIcicle, err := groth16.Prove(tCcs, pk, w, backend.WithIcicleAcceleration()) + assert.NoError(err) + err = groth16.Verify(proofNative, &nativeVK, pw) + assert.NoError(err) + err = groth16.Verify(proofIcicle, &nativeVK, pw) + assert.NoError(err) } func TestMarshal2(t *testing.T) { @@ -64,4 +81,18 @@ func TestMarshal2(t *testing.T) { if iciPK.IsDifferent(&nativePK) { t.Error("marshal output difference") } + + assignment := circuit{A: 3, B: 5, Res: 15} + w, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) + assert.NoError(err) + pw, err := w.Public() + assert.NoError(err) + proofNative, err := groth16_bn254.Prove(tCcs, &nativePK, w) + assert.NoError(err) + proofIcicle, err := groth16.Prove(tCcs, &iciPK, w, backend.WithIcicleAcceleration()) + assert.NoError(err) + err = groth16.Verify(proofNative, &iciVK, pw) + assert.NoError(err) + err = groth16.Verify(proofIcicle, &iciVK, pw) + assert.NoError(err) } diff --git a/backend/groth16/bn254/icicle/noicicle.go b/backend/groth16/bn254/icicle/noicicle.go index 87703339ce..5925dd0b11 100644 --- a/backend/groth16/bn254/icicle/noicicle.go +++ b/backend/groth16/bn254/icicle/noicicle.go @@ -1,6 +1,6 @@ //go:build !icicle -package icicle_bn254 +package icicle import ( "fmt" diff --git a/backend/groth16/bn254/icicle/provingkey.go b/backend/groth16/bn254/icicle/provingkey.go index 146a794255..ee9d170579 100644 --- a/backend/groth16/bn254/icicle/provingkey.go +++ b/backend/groth16/bn254/icicle/provingkey.go @@ -1,25 +1,26 @@ -package icicle_bn254 +package icicle import ( - "unsafe" - + "github.com/consensys/gnark-crypto/ecc/bn254/fr" groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254" cs "github.com/consensys/gnark/constraint/bn254" + icicle_core "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" ) type deviceInfo struct { - G1Device struct { - A, B, K, Z unsafe.Pointer - } - DomainDevice struct { - Twiddles, TwiddlesInv unsafe.Pointer - CosetTable, CosetTableInv unsafe.Pointer + CosetGenerator [fr.Limbs * 2]uint32 + G1Device struct { + A, B, K, Z icicle_core.DeviceSlice } G2Device struct { - B unsafe.Pointer + B icicle_core.DeviceSlice + } + DenDevice icicle_core.DeviceSlice + + CommitmentKeysDevice struct { + Basis []icicle_core.DeviceSlice + BasisExpSigma []icicle_core.DeviceSlice // we compute in batch } - DenDevice unsafe.Pointer - InfinityPointIndicesK []int } type ProvingKey struct { @@ -27,10 +28,17 @@ type ProvingKey struct { *deviceInfo } +func NewProvingKey() *ProvingKey { + warmUpDevice() + return &ProvingKey{} +} + func Setup(r1cs *cs.R1CS, pk *ProvingKey, vk *groth16_bn254.VerifyingKey) error { + warmUpDevice() return groth16_bn254.Setup(r1cs, &pk.ProvingKey, vk) } func DummySetup(r1cs *cs.R1CS, pk *ProvingKey) error { + warmUpDevice() return groth16_bn254.DummySetup(r1cs, &pk.ProvingKey) } diff --git a/backend/groth16/groth16.go b/backend/groth16/groth16.go index 426621e2f6..aa27ef3f74 100644 --- a/backend/groth16/groth16.go +++ b/backend/groth16/groth16.go @@ -347,7 +347,7 @@ func NewProvingKey(curveID ecc.ID) ProvingKey { case ecc.BN254: pk = &groth16_bn254.ProvingKey{} if icicle_bn254.HasIcicle { - pk = &icicle_bn254.ProvingKey{} + pk = icicle_bn254.NewProvingKey() } case ecc.BLS12_377: pk = &groth16_bls12377.ProvingKey{} diff --git a/go.mod b/go.mod index 6e0371490f..a71f63c3cf 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 github.com/icza/bitio v1.1.0 - github.com/ingonyama-zk/iciclegnark v0.1.0 + github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b github.com/leanovate/gopter v0.2.11 github.com/ronanh/intcomp v1.1.0 github.com/rs/zerolog v1.33.0 @@ -26,12 +26,10 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/ingonyama-zk/icicle v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/x448/float16 v0.8.4 // indirect golang.org/x/sys v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 5a48cfc662..4676a0a14f 100644 --- a/go.sum +++ b/go.sum @@ -184,10 +184,8 @@ github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k= github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/ingonyama-zk/icicle v1.1.0 h1:a2MUIaF+1i4JY2Lnb961ZMvaC8GFs9GqZgSnd9e95C8= -github.com/ingonyama-zk/icicle v1.1.0/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= -github.com/ingonyama-zk/iciclegnark v0.1.0 h1:88MkEghzjQBMjrYRJFxZ9oR9CTIpB8NG2zLeCJSvXKQ= -github.com/ingonyama-zk/iciclegnark v0.1.0/go.mod h1:wz6+IpyHKs6UhMMoQpNqz1VY+ddfKqC/gRwR/64W6WU= +github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b h1:AvQTK7l0PTHODD06PVQX1Tn2o29sRIaKIDOvTJmKurY= +github.com/ingonyama-zk/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b/go.mod h1:e0JHb27/P6WorCJS3YolbY5XffS4PGBuoW38OthLkDs= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=