diff --git a/README.md b/README.md index 02c008f95a..229630ff94 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). **NB! ICICLE CUDA kernels are covered by a special license for now. Follow the instructions to download and set up the kernels.** +For more information about prerequisites see the [Icicle repo](https://github.com/ingonyama-zk/icicle). ## Citing diff --git a/backend/groth16/bn254/icicle/device.go b/backend/groth16/bn254/icicle/device.go deleted file mode 100644 index d6d86ea362..0000000000 --- a/backend/groth16/bn254/icicle/device.go +++ /dev/null @@ -1,29 +0,0 @@ -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 3a662b35da..a77a7fbde9 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 +package icicle_bn254 diff --git a/backend/groth16/bn254/icicle/icicle.go b/backend/groth16/bn254/icicle/icicle.go index 49133cd8b1..5b1b235d33 100644 --- a/backend/groth16/bn254/icicle/icicle.go +++ b/backend/groth16/bn254/icicle/icicle.go @@ -1,20 +1,19 @@ //go:build icicle -package icicle +package icicle_bn254 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" @@ -24,40 +23,33 @@ import ( "github.com/consensys/gnark/constraint/solver" "github.com/consensys/gnark/internal/utils" "github.com/consensys/gnark/logger" - - 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" + iciclegnark "github.com/ingonyama-zk/iciclegnark/curves/bn254" ) const HasIcicle = true -var isProfileMode bool - -func init() { - _, isProfileMode = os.LookupEnv("ICICLE_STEP_PROFILE") -} - -func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { +func (pk *ProvingKey) setupDevicePointers() error { if pk.deviceInfo != nil { return nil } pk.deviceInfo = &deviceInfo{} - 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) + 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) + + /************************* Den ***************************/ var denI, oneI fr.Element oneI.SetOne() - denI.Exp(gen, big.NewInt(int64(pk.Domain.Cardinality))) + denI.Exp(pk.Domain.FrMultiplicativeGen, big.NewInt(int64(pk.Domain.Cardinality))) denI.Sub(&denI, &oneI).Inverse(&denI) log2SizeFloor := bits.Len(uint(n)) - 1 @@ -70,165 +62,71 @@ func (pk *ProvingKey) setupDevicePointers(device *icicle_runtime.Device) error { denIcicleArr = append(denIcicleArr, denI) } - 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) - }) - - /************************* 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 ***************************/ - - /************************* 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 - - return nil -} + go iciclegnark.CopyToDevice(denIcicleArr, sizeBytes, 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())) + /************************* Twiddles and Twiddles Inv ***************************/ + twiddlesInv_d_gen, twddles_err := iciclegnark.GenerateTwiddleFactors(n, true) + if twddles_err != nil { + return twddles_err + } - var x, y, zInv fp.Element + twiddles_d_gen, twddles_err := iciclegnark.GenerateTwiddleFactors(n, false) + if twddles_err != nil { + return twddles_err + } - zInv.Inverse(&pz) - x.Mul(&px, &zInv) - y.Mul(&py, &zInv) + /************************* End Domain Device Setup ***************************/ + pk.DomainDevice.Twiddles = twiddles_d_gen + pk.DomainDevice.TwiddlesInv = twiddlesInv_d_gen - return &curve.G1Affine{X: x, Y: y} -} + pk.DomainDevice.CosetTableInv = <-copyCosetInvDone + pk.DomainDevice.CosetTable = <-copyCosetDone + pk.DenDevice = <-copyDenDone -func g1ProjectiveToG1Jac(p icicle_bn254.Projective) curve.G1Jac { - var p1 curve.G1Jac - p1.FromAffine(projectiveToGnarkAffine(p)) + /************************* 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 - return p1 -} + /************************* 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 -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, + /************************* 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) + } } -} -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) + pointsBytesK := len(pointsNoInfinity) * fp.Bytes * 2 + copyKDone := make(chan unsafe.Pointer, 1) + go iciclegnark.CopyPointsToDevice(pointsNoInfinity, pointsBytesK, copyKDone) // Make a function for points - var X curve.E2 - X.Mul(&x, &z) + /************************* 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 - var Y curve.E2 - Y.Mul(&y, &zSquared) + /************************* End G1 Device Setup ***************************/ + pk.G1Device.A = <-copyADone + pk.G1Device.B = <-copyBDone + pk.G1Device.K = <-copyKDone + pk.G1Device.Z = <-copyZDone - return curve.G2Jac{ - X: X, - Y: Y, - Z: z, - } + /************************* 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 + + /************************* End G2 Device Setup ***************************/ + return nil } // Prove generates the proof of knowledge of a r1cs with full witness (secret + public part). @@ -244,13 +142,9 @@ 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(&device); err != nil { + if err := pk.setupDevicePointers(); err != nil { return nil, fmt.Errorf("setup device pointers: %w", err) } } @@ -262,48 +156,42 @@ 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)) - 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) - } + 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 + } - 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())) + 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 } - 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 - })) + }(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))) + } _solution, err := r1cs.Solve(fullWitness, solverOpts...) if err != nil { @@ -314,66 +202,33 @@ 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()) } - 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 { + + if proof.CommitmentPok, err = pedersen.BatchProve(pk.CommitmentKeys, privateCommittedValues, commitmentsSerialized); err != nil { return nil, err } - // H (witness reduction / FFT part) - 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) + // 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) solution.A = nil solution.B = nil solution.C = nil - close(chHDone) - }) + chHDone <- struct{}{} + }() // 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 icicle_core.DeviceSlice - chWireValuesA, chWireValuesB := make(chan struct{}), make(chan struct{}) + var wireValuesADevice, wireValuesBDevice iciclegnark.OnDeviceData + chWireValuesA, chWireValuesB := make(chan struct{}, 1), make(chan struct{}, 1) - icicle_runtime.RunOnDevice(&device, func(args ...any) { + go func() { wireValuesA := make([]fr.Element, len(wireValues)-int(pk.NbInfinityA)) for i, j := 0, 0; j < len(wireValuesA); i++ { if pk.InfinityA[i] { @@ -382,18 +237,22 @@ 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 - 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())) + copyDone := make(chan unsafe.Pointer, 1) + iciclegnark.CopyToDevice(wireValuesA, scalarBytes, copyDone) + wireValuesADevicePtr := <-copyDone + + wireValuesADevice = iciclegnark.OnDeviceData{ + P: wireValuesADevicePtr, + Size: wireValuesASize, } close(chWireValuesA) - }) - - icicle_runtime.RunOnDevice(&device, func(args ...any) { + }() + go func() { wireValuesB := make([]fr.Element, len(wireValues)-int(pk.NbInfinityB)) for i, j := 0, 0; j < len(wireValuesB); i++ { if pk.InfinityB[i] { @@ -402,16 +261,21 @@ 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 - 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())) + copyDone := make(chan unsafe.Pointer, 1) + iciclegnark.CopyToDevice(wireValuesB, scalarBytes, copyDone) + wireValuesBDevicePtr := <-copyDone + + wireValuesBDevice = iciclegnark.OnDeviceData{ + P: wireValuesBDevicePtr, + Size: wireValuesBSize, } close(chWireValuesB) - }) + }() // sample random r and s var r, s big.Int @@ -431,91 +295,74 @@ 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 - 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") + if bs1, _, err = iciclegnark.MsmOnDevice(wireValuesBDevice.P, pk.G1Device.B, wireValuesBDevice.Size, true); err != nil { + return err } - bs1 = g1ProjectiveToG1Jac(res[0]) bs1.AddMixed(&pk.G1.Beta) bs1.AddMixed(&deltas[1]) - close(chBs1Done) return nil } computeAR1 := func() error { <-chWireValuesA - 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") + if ar, _, err = iciclegnark.MsmOnDevice(wireValuesADevice.P, pk.G1Device.A, wireValuesADevice.Size, true); err != nil { + return err } - 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) + sizeH := int(pk.Domain.Cardinality - 1) // comes from the fact the deg(H)=(n-1)+(n-1)-n=n-2 - 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") + // 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 + } } - 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()) - _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())) + 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:]...) } - if isProfileMode { - log.Debug().Dur("took", time.Since(start)).Msg("MSM Krs") + + 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 } - krs = g1ProjectiveToG1Jac(resKrs[0]) krs.AddMixed(&deltas[2]) krs.AddAssign(&krs2) - <-chArDone - <-chBs1Done - p1.ScalarMultiplication(&ar, &s) krs.AddAssign(&p1) @@ -532,17 +379,9 @@ func Prove(r1cs *cs.R1CS, pk *ProvingKey, fullWitness witness.Witness, opts ...b var Bs, deltaS curve.G2Jac <-chWireValuesB - - 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") + if Bs, _, err = iciclegnark.MsmG2OnDevice(wireValuesBDevice.P, pk.G2Device.B, wireValuesBDevice.Size, true); err != nil { + return err } - Bs = g2ProjectiveToG2Jac(&res[0]) deltaS.FromAffine(&pk.G2.Delta) deltaS.ScalarMultiplication(&deltaS, &s) @@ -553,51 +392,31 @@ 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 - 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 + // 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 + } log.Debug().Dur("took", time.Since(start)).Msg("prover done") // free device/GPU memory that is not needed for future proofs (scalars/hpoly) - 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()) - } - }) + go func() { + iciclegnark.FreeDevicePointer(wireValuesADevice.P) + iciclegnark.FreeDevicePointer(wireValuesBDevice.P) + iciclegnark.FreeDevicePointer(h) + }() return proof, nil } @@ -631,14 +450,13 @@ func filterHeap(slice []fr.Element, sliceFirstIndex int, toRemove []int) (r []fr return } -func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Device) icicle_core.DeviceSlice { +func computeH(a, b, c []fr.Element, pk *ProvingKey) unsafe.Pointer { // 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 @@ -648,83 +466,48 @@ func computeH(a, b, c []fr.Element, pk *ProvingKey, device *icicle_runtime.Devic c = append(c, padding...) n = len(a) - 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) - } + sizeBytes := n * fr.Bytes - icicle_runtime.RunOnDevice(device, computeInttNttOnDevice, a, computeADone) - icicle_runtime.RunOnDevice(device, computeInttNttOnDevice, b, computeBDone) - icicle_runtime.RunOnDevice(device, computeInttNttOnDevice, c, computeCDone) + /*********** 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) - aDevice := <-computeADone - bDevice := <-computeBDone - cDevice := <-computeCDone + go iciclegnark.CopyToDevice(a, sizeBytes, copyADone) + go iciclegnark.CopyToDevice(b, sizeBytes, copyBDone) + go iciclegnark.CopyToDevice(c, sizeBytes, copyCDone) - // 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())) - } + a_device := <-copyADone + b_device := <-copyBDone + c_device := <-copyCDone + /*********** Copy a,b,c to Device End ************/ - if isProfileMode { - log.Debug().Dur("took", time.Since(startTotal)).Msg("computeH: Total") + 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) } - return aDevice + + go computeInttNttOnDevice(a_device) + go computeInttNttOnDevice(b_device) + go computeInttNttOnDevice(c_device) + _, _, _ = <-computeInttNttDone, <-computeInttNttDone, <-computeInttNttDone + + iciclegnark.PolyOps(a_device, b_device, c_device, pk.DenDevice, n) + + 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) + + return h } diff --git a/backend/groth16/bn254/icicle/marshal_test.go b/backend/groth16/bn254/icicle/marshal_test.go index 114765dafe..75c5a2b57e 100644 --- a/backend/groth16/bn254/icicle/marshal_test.go +++ b/backend/groth16/bn254/icicle/marshal_test.go @@ -1,13 +1,10 @@ -//go:build icicle - -package icicle_test +package icicle_bn254_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" @@ -46,20 +43,6 @@ 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) { @@ -81,18 +64,4 @@ 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 5925dd0b11..87703339ce 100644 --- a/backend/groth16/bn254/icicle/noicicle.go +++ b/backend/groth16/bn254/icicle/noicicle.go @@ -1,6 +1,6 @@ //go:build !icicle -package icicle +package icicle_bn254 import ( "fmt" diff --git a/backend/groth16/bn254/icicle/provingkey.go b/backend/groth16/bn254/icicle/provingkey.go index ee9d170579..146a794255 100644 --- a/backend/groth16/bn254/icicle/provingkey.go +++ b/backend/groth16/bn254/icicle/provingkey.go @@ -1,26 +1,25 @@ -package icicle +package icicle_bn254 import ( - "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "unsafe" + 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 { - CosetGenerator [fr.Limbs * 2]uint32 - G1Device struct { - A, B, K, Z icicle_core.DeviceSlice + G1Device struct { + A, B, K, Z unsafe.Pointer } - G2Device struct { - B icicle_core.DeviceSlice + DomainDevice struct { + Twiddles, TwiddlesInv unsafe.Pointer + CosetTable, CosetTableInv unsafe.Pointer } - DenDevice icicle_core.DeviceSlice - - CommitmentKeysDevice struct { - Basis []icicle_core.DeviceSlice - BasisExpSigma []icicle_core.DeviceSlice // we compute in batch + G2Device struct { + B unsafe.Pointer } + DenDevice unsafe.Pointer + InfinityPointIndicesK []int } type ProvingKey struct { @@ -28,17 +27,10 @@ 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 aa27ef3f74..426621e2f6 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.NewProvingKey() + pk = &icicle_bn254.ProvingKey{} } case ecc.BLS12_377: pk = &groth16_bls12377.ProvingKey{} diff --git a/go.mod b/go.mod index a71f63c3cf..6e0371490f 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/icicle/v3 v3.1.1-0.20241118092657-fccdb2f0921b + github.com/ingonyama-zk/iciclegnark v0.1.0 github.com/leanovate/gopter v0.2.11 github.com/ronanh/intcomp v1.1.0 github.com/rs/zerolog v1.33.0 @@ -26,10 +26,12 @@ 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 4676a0a14f..5a48cfc662 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,10 @@ 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/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/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/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=