Merge branch 'ingonyama-zk:main' into main

This commit is contained in:
liuhao230
2024-05-17 14:24:02 +08:00
committed by GitHub
90 changed files with 1865 additions and 189 deletions

View File

@@ -6,52 +6,53 @@
package main
import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
bn254_msm "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/msm"
)
func main() {
// Obtain the default MSM configuration.
cfg := bn254.GetDefaultMSMConfig()
// Obtain the default MSM configuration.
cfg := core.GetDefaultMSMConfig()
// Define the size of the problem, here 2^18.
size := 1 << 18
// Define the size of the problem, here 2^18.
size := 1 << 18
// Generate scalars and points for the MSM operation.
scalars := bn254.GenerateScalars(size)
points := bn254.GenerateAffinePoints(size)
// Generate scalars and points for the MSM operation.
scalars := bn254.GenerateScalars(size)
points := bn254.GenerateAffinePoints(size)
// Create a CUDA stream for asynchronous operations.
stream, _ := cr.CreateStream()
var p bn254.Projective
// Create a CUDA stream for asynchronous operations.
stream, _ := cr.CreateStream()
var p bn254.Projective
// Allocate memory on the device for the result of the MSM operation.
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
// Allocate memory on the device for the result of the MSM operation.
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
if e != cr.CudaSuccess {
panic(e)
}
if e != cr.CudaSuccess {
panic(e)
}
// Set the CUDA stream in the MSM configuration.
cfg.Ctx.Stream = &stream
cfg.IsAsync = true
// Set the CUDA stream in the MSM configuration.
cfg.Ctx.Stream = &stream
cfg.IsAsync = true
// Perform the MSM operation.
e = bn254.Msm(scalars, points, &cfg, out)
// Perform the MSM operation.
e = bn254_msm.Msm(scalars, points, &cfg, out)
if e != cr.CudaSuccess {
panic(e)
}
if e != cr.CudaSuccess {
panic(e)
}
// Allocate host memory for the results and copy the results from the device.
outHost := make(core.HostSlice[bn254.Projective], 1)
cr.SynchronizeStream(&stream)
outHost.CopyFromDevice(&out)
// Allocate host memory for the results and copy the results from the device.
outHost := make(core.HostSlice[bn254.Projective], 1)
cr.SynchronizeStream(&stream)
outHost.CopyFromDevice(&out)
// Free the device memory allocated for the results.
out.Free()
// Free the device memory allocated for the results.
out.Free()
}
```
@@ -169,23 +170,23 @@ This package include `G2Projective` and `G2Affine` points as well as a `G2Msm` m
package main
import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
g2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
g2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2"
)
func main() {
cfg := bn254.GetDefaultMSMConfig()
size := 1 << 12
batchSize := 3
totalSize := size * batchSize
scalars := bn254.GenerateScalars(totalSize)
points := g2.G2GenerateAffinePoints(totalSize)
cfg := core.GetDefaultMSMConfig()
size := 1 << 12
batchSize := 3
totalSize := size * batchSize
scalars := bn254.GenerateScalars(totalSize)
points := g2.G2GenerateAffinePoints(totalSize)
var p g2.G2Projective
var out core.DeviceSlice
out.Malloc(batchSize*p.Size(), p.Size())
g2.G2Msm(scalars, points, &cfg, out)
var p g2.G2Projective
var out core.DeviceSlice
out.Malloc(batchSize*p.Size(), p.Size())
g2.G2Msm(scalars, points, &cfg, out)
}
```

View File

@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.18)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
if (${CMAKE_VERSION} VERSION_LESS "3.24.0")
set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH})
else()
set(CMAKE_CUDA_ARCHITECTURES native) # on 3.24+, on earlier it is ignored, and the target is not passed
endif ()
project(example LANGUAGES CUDA CXX)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr")
set(CMAKE_CUDA_FLAGS_RELEASE "")
set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -g -G -O0")
add_executable(
example
example.cu
)
target_include_directories(example PRIVATE "../../../icicle/include")
target_link_libraries(example ${CMAKE_SOURCE_DIR}/build/icicle/lib/libingo_field_bn254.a)
set_target_properties(example PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

View File

@@ -0,0 +1,33 @@
# ICICLE best practices: Concurrent Data Transfer and NTT Computation
The [Number Theoretic Transform (NTT)](https://dev.ingonyama.com/icicle/primitives/ntt) is an integral component of many cryptographic algorithms, such as polynomial multiplication in Zero Knowledge Proofs. The performance bottleneck of NTT on GPUs is the data transfer between the host (CPU) and the device (GPU). In a typical NVIDIA GPU this transfer dominates the total NTT execution time.
## Key-Takeaway
When you have to run several NTTs, consider Concurrent Data Download, Upload, and Computation to improve data bus (PCIe) and GPU utilization, and get better total execution time.
Typically, you concurrently
1. Download the output of a previous NTT back to the host
2. Upload the input for a next NTT on the device
3. Run current NTT
> [!NOTE]
> This approach requires two on-device memory vectors, decreasing the maximum size of NTT by 2x.
## Best-Practices
1. Use three separate CUDA streams for Download, Upload, and Compute operations
2. Use pinned (page-locked) memory on host to speed data bus transfers. Calling `cudaHostAlloc` allocates pinned memory.
3. Use in-place NTT to save on device memory.
## Running the example
To change the default curve BN254, edit `compile.sh` and `CMakeLists.txt`
```sh
./compile.sh
./run.sh
```
To compare with ICICLE baseline (i.e. non-concurrent) NTT, you can run [this example](../ntt/README.md).

View File

@@ -0,0 +1,16 @@
#!/bin/bash
# Exit immediately on error
set -e
mkdir -p build/example
mkdir -p build/icicle
# Configure and build Icicle
cmake -S ../../../icicle/ -B build/icicle -DCMAKE_BUILD_TYPE=Release -DCURVE=bn254 -DG2=OFF -DMSM=OFF
cmake --build build/icicle
# Configure and build the example application
cmake -S . -B build/example
cmake --build build/example

View File

@@ -0,0 +1,142 @@
#include <stdio.h>
#include <iostream>
#include <string>
#include <chrono>
#include "curves/params/bn254.cuh"
#include "api/bn254.h"
using namespace bn254;
using namespace ntt;
const std::string curve = "BN254";
typedef scalar_t S;
typedef scalar_t E;
const unsigned max_log_ntt_size = 27;
void initialize_input(const unsigned ntt_size, const unsigned nof_ntts, E * elements ) {
for (unsigned i = 0; i < ntt_size * nof_ntts; i++) {
elements[i] = E::from(i+1);
}
}
using FpMilliseconds = std::chrono::duration<float, std::chrono::milliseconds::period>;
#define START_TIMER(timer) auto timer##_start = std::chrono::high_resolution_clock::now();
#define END_TIMER(timer, msg) printf("%s: %.0f ms\n", msg, FpMilliseconds(std::chrono::high_resolution_clock::now() - timer##_start).count());
int main(int argc, char** argv) {
cudaDeviceReset();
cudaDeviceProp deviceProperties;
int deviceId=0;
cudaGetDeviceProperties(&deviceProperties, deviceId);
std::string gpu_full_name = deviceProperties.name;
std::cout << gpu_full_name << std::endl;
std::string gpu_name = gpu_full_name;
std::cout << "Curve: " << curve << std::endl;
S basic_root = S::omega(max_log_ntt_size);
// change these parameters to match the desired NTT size and batch size
const unsigned log_ntt_size = 22;
const unsigned nof_ntts = 16;
std::cout << "log NTT size: " << log_ntt_size << std::endl;
const unsigned ntt_size = 1 << log_ntt_size;
std::cout << "Batch size: " << nof_ntts << std::endl;
// Create separate CUDA streams for overlapping data transfers and kernel execution.
cudaStream_t stream_compute, stream_h2d, stream_d2h;
cudaStreamCreate(&stream_compute);
cudaStreamCreate(&stream_h2d);
cudaStreamCreate(&stream_d2h);
// Create device context for NTT computation
auto ctx_compute = device_context::DeviceContext{
stream_compute, // stream
0, // device_id
0, // mempool
};
// Initialize NTT domain and configuration
bn254_initialize_domain(&basic_root, ctx_compute, /* fast twiddles */ true);
NTTConfig<S> config_compute = default_ntt_config<S>(ctx_compute);
config_compute.ntt_algorithm = NttAlgorithm::MixedRadix;
config_compute.batch_size = nof_ntts;
config_compute.are_inputs_on_device = true;
config_compute.are_outputs_on_device = true;
config_compute.is_async = true;
std::cout << "Concurrent Download, Upload, and Compute In-place NTT" << std::endl;
int nof_blocks = 32;
std::cout << "Number of blocks: " << nof_blocks << std::endl;
int block_size = ntt_size*nof_ntts/nof_blocks;
// on-host pinned data
E * h_inp[2];
E * h_out[2];
for (int i = 0; i < 2; i++) {
cudaHostAlloc((void**)&h_inp[i], sizeof(E)*ntt_size*nof_ntts, cudaHostAllocDefault);
cudaHostAlloc((void**)&h_out[i], sizeof(E)*ntt_size*nof_ntts, cudaHostAllocDefault);
}
// on-device in-place data
// we need two on-device vectors to overlap data transfers with NTT kernel execution
E * d_vec[2];
for (int i = 0; i < 2; i++) {
cudaMalloc((void**)&d_vec[i], sizeof(E)*ntt_size*nof_ntts);
}
// initialize input data
initialize_input(ntt_size, nof_ntts, h_inp[0]);
initialize_input(ntt_size, nof_ntts, h_inp[1]);
cudaEvent_t compute_start, compute_stop;
cudaEventCreate(&compute_start);
cudaEventCreate(&compute_stop);
for ( int run = 0; run < 10; run++ ) {
int vec_compute = run % 2;
int vec_transfer = (run + 1) % 2;
std::cout << "Run: " << run << std::endl;
std::cout << "Compute Vector: " << vec_compute << std::endl;
std::cout << "Transfer Vector: " << vec_transfer << std::endl;
START_TIMER(inplace);
cudaEventRecord(compute_start, stream_compute);
bn254_ntt_cuda(d_vec[vec_compute], ntt_size, NTTDir::kForward, config_compute, d_vec[vec_compute]);
cudaEventRecord(compute_stop, stream_compute);
// we have to delay upload to device relative to download from device by one block: preserve write after read
for (int i = 0; i <= nof_blocks; i++) {
if (i < nof_blocks) {
cudaMemcpyAsync(&h_out[vec_transfer][i*block_size], &d_vec[vec_transfer][i*block_size], sizeof(E)*block_size, cudaMemcpyDeviceToHost, stream_d2h);
}
if (i>0) {
cudaMemcpyAsync(&d_vec[vec_transfer][(i-1)*block_size], &h_inp[vec_transfer][(i-1)*block_size], sizeof(E)*block_size, cudaMemcpyHostToDevice, stream_h2d);
}
// synchronize upload and download at the end of the block to ensure data integrity
cudaStreamSynchronize(stream_d2h);
cudaStreamSynchronize(stream_h2d);
}
// synchronize compute stream with the end of the computation
cudaEventSynchronize(compute_stop);
float milliseconds = 0;
cudaEventElapsedTime(&milliseconds, compute_start, compute_stop);
END_TIMER(inplace, "Concurrent In-Place NTT");
std::cout << "NTT time: " << milliseconds << " ms" << std::endl;
};
// Clean-up
for (int i = 0; i < 2; i++) {
cudaFree(d_vec[i]);
cudaFreeHost(h_inp[i]);
cudaFreeHost(h_out[i]);
}
cudaEventDestroy(compute_start);
cudaEventDestroy(compute_stop);
cudaStreamDestroy(stream_compute);
cudaStreamDestroy(stream_d2h);
cudaStreamDestroy(stream_h2d);
return 0;
}

View File

@@ -0,0 +1,2 @@
#!/bin/bash
./build/example/example

View File

@@ -0,0 +1,34 @@
# ICICLE example: MultiScalar Multiplication (MSM) in Golang
`ICICLE` provides Golang bindings to CUDA-accelerated C++ implementation of [Multi-Scalar Multiplication](https://github.com/ingonyama-zk/ingopedia/blob/master/src/msm.md).
## Usage
```go
err := Msm(
/* Scalars input vector */ scalars,
/* Points input vector */ points,
/* MSMConfig reference */ &cfg,
/* Projective point result */ results)
```
In this example we use `BN254` and `BLS12377` curves. The function computes $result = \sum_{i=0}^{size-1} scalars[i] \cdot points[i]$, where input `points[]` uses affine coordinates, and `result` uses projective coordinates.
## What's in the example
1. Define the size of MSM.
2. Generate random inputs on-device
3. Configure MSM
4. Execute MSM on-device
5. Move the result on host
Running the example:
```sh
go run main.go
```
> [!NOTE]
> The default sizes are 2^17 - 2^22. You can change this by passing the `-l <size> -u <size>` options. To change the size range to 2^21 - 2^24, run the example like this:
> ```sh
> go run main.go -l=21 -u=24
> ```

209
examples/golang/msm/main.go Normal file
View File

@@ -0,0 +1,209 @@
package main
import (
"flag"
"fmt"
"time"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
bls12377G2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2"
bls12377Msm "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/msm"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
bn254G2 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2"
bn254Msm "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/msm"
)
func main() {
var logSizeMin int
var logSizeMax int
flag.IntVar(&logSizeMin, "l", 17, "Minimum log size")
flag.IntVar(&logSizeMax, "u", 22, "Maximum log size")
flag.Parse()
sizeMax := 1 << logSizeMax
print("Generating BN254 scalars ... ")
startTime := time.Now()
scalarsBn254Max := bn254.GenerateScalars(sizeMax)
println(time.Since(startTime).String())
print("Generating BN254 points ... ")
startTime = time.Now()
pointsBn254Max := bn254.GenerateAffinePoints(sizeMax)
println(time.Since(startTime).String())
print("Generating BN254 G2 points ... ")
startTime = time.Now()
pointsBn254G2Max := bn254G2.G2GenerateAffinePoints(sizeMax)
println(time.Since(startTime).String())
print("Generating BLS12_377 scalars ... ")
startTime = time.Now()
scalarsBls12377Max := bls12377.GenerateScalars(sizeMax)
println(time.Since(startTime).String())
print("Generating BLS12_377 points ... ")
startTime = time.Now()
pointsBls12377Max := bls12377.GenerateAffinePoints(sizeMax)
println(time.Since(startTime).String())
print("Generating BLS12_377 G2 points ... ")
startTime = time.Now()
pointsBls12377G2Max := bls12377G2.G2GenerateAffinePoints(sizeMax)
println(time.Since(startTime).String())
for logSize := logSizeMin; logSize <= logSizeMax; logSize++ {
// Define the size of the problem, here 2^18.
size := 1 << logSize
fmt.Printf("---------------------- MSM size 2^%d=%d ------------------------\n", logSize, size)
// println(scalarsBls12377, pointsBls12377, pointsBn254G2)
// println(scalarsBn254, pointsBn254, pointsBls12377G2)
print("Configuring bn254 MSM ... ")
startTime = time.Now()
scalarsBn254 := scalarsBn254Max[:size]
pointsBn254 := pointsBn254Max[:size]
pointsBn254G2 := pointsBn254G2Max[:size]
cfgBn254 := core.GetDefaultMSMConfig()
cfgBn254G2 := core.GetDefaultMSMConfig()
cfgBn254.IsAsync = true
cfgBn254G2.IsAsync = true
streamBn254, _ := cr.CreateStream()
streamBn254G2, _ := cr.CreateStream()
cfgBn254.Ctx.Stream = &streamBn254
cfgBn254G2.Ctx.Stream = &streamBn254G2
var projectiveBn254 bn254.Projective
var projectiveBn254G2 bn254G2.G2Projective
var msmResultBn254 core.DeviceSlice
var msmResultBn254G2 core.DeviceSlice
_, e := msmResultBn254.MallocAsync(projectiveBn254.Size(), projectiveBn254.Size(), streamBn254)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"Bn254 Malloc failed: ", e)
panic(errorString)
}
_, e = msmResultBn254G2.MallocAsync(projectiveBn254G2.Size(), projectiveBn254G2.Size(), streamBn254G2)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"Bn254 Malloc G2 failed: ", e)
panic(errorString)
}
println(time.Since(startTime).String())
print("Configuring Bls12377 MSM ... ")
startTime = time.Now()
scalarsBls12377 := scalarsBls12377Max[:size]
pointsBls12377 := pointsBls12377Max[:size]
pointsBls12377G2 := pointsBls12377G2Max[:size]
cfgBls12377 := core.GetDefaultMSMConfig()
cfgBls12377G2 := core.GetDefaultMSMConfig()
cfgBls12377.IsAsync = true
cfgBls12377G2.IsAsync = true
streamBls12377, _ := cr.CreateStream()
streamBls12377G2, _ := cr.CreateStream()
cfgBls12377.Ctx.Stream = &streamBls12377
cfgBls12377G2.Ctx.Stream = &streamBls12377G2
var projectiveBls12377 bls12377.Projective
var projectiveBls12377G2 bls12377G2.G2Projective
var msmResultBls12377 core.DeviceSlice
var msmResultBls12377G2 core.DeviceSlice
_, e = msmResultBls12377.MallocAsync(projectiveBls12377.Size(), projectiveBls12377.Size(), streamBls12377)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"Bls12_377 Malloc failed: ", e)
panic(errorString)
}
_, e = msmResultBls12377G2.MallocAsync(projectiveBls12377G2.Size(), projectiveBls12377G2.Size(), streamBls12377G2)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"Bls12_377 Malloc G2 failed: ", e)
panic(errorString)
}
println(time.Since(startTime).String())
print("Executing bn254 MSM on device ... ")
startTime = time.Now()
e = bn254Msm.Msm(scalarsBn254, pointsBn254, &cfgBn254, msmResultBn254)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"bn254 Msm failed: ", e)
panic(errorString)
}
e = bn254G2.G2Msm(scalarsBn254, pointsBn254G2, &cfgBn254G2, msmResultBn254G2)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"bn254 Msm G2 failed: ", e)
panic(errorString)
}
msmResultBn254Host := make(core.HostSlice[bn254.Projective], 1)
msmResultBn254G2Host := make(core.HostSlice[bn254G2.G2Projective], 1)
msmResultBn254Host.CopyFromDeviceAsync(&msmResultBn254, streamBn254)
msmResultBn254G2Host.CopyFromDeviceAsync(&msmResultBn254G2, streamBn254G2)
msmResultBn254.FreeAsync(streamBn254)
msmResultBn254G2.FreeAsync(streamBn254G2)
cr.SynchronizeStream(&streamBn254)
cr.SynchronizeStream(&streamBn254G2)
println(time.Since(startTime).String())
print("Executing Bls12377 MSM on device ... ")
startTime = time.Now()
e = bls12377Msm.Msm(scalarsBls12377, pointsBls12377, &cfgBls12377, msmResultBls12377)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"bls12_377 Msm failed: ", e)
panic(errorString)
}
e = bls12377G2.G2Msm(scalarsBls12377, pointsBls12377G2, &cfgBls12377G2, msmResultBls12377G2)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"bls12_377 Msm G2 failed: ", e)
panic(errorString)
}
msmResultBls12377Host := make(core.HostSlice[bls12377.Projective], 1)
msmResultBls12377G2Host := make(core.HostSlice[bls12377G2.G2Projective], 1)
msmResultBls12377Host.CopyFromDeviceAsync(&msmResultBls12377, streamBls12377)
msmResultBls12377G2Host.CopyFromDeviceAsync(&msmResultBls12377G2, streamBls12377G2)
msmResultBls12377.FreeAsync(streamBls12377)
msmResultBls12377G2.FreeAsync(streamBls12377G2)
cr.SynchronizeStream(&streamBls12377)
cr.SynchronizeStream(&streamBls12377G2)
println(time.Since(startTime).String())
}
}

View File

@@ -0,0 +1,39 @@
# ICICLE example: Number Theoretic Transform (NTT) in Golang
## Key-Takeaway
`ICICLE` provides Golang bindings to CUDA-accelerated C++ implementation of [Number Theoretic Transform](https://github.com/ingonyama-zk/ingopedia/blob/master/src/fft.md).
## Usage
```go
err := Ntt(
/* input slice */ scalars,
/* NTT Direction */ core.KForward,
/* NTT Configuration */ &cfg,
/* output slice */ result)
```
In this example we use the `BN254` and `BLS12377` fields.
## What's in this example
1. Define the size of NTT.
2. Generate random inputs
3. Set up the domain.
4. Configure NTT
5. Execute NTT on-device
6. Move the result on host
Running the example:
```sh
go run main.go
```
> [!NOTE]
> The default size is 2^20. You can change this by passing the `-s <size>` option. To change the size to 2^23, run the example like this:
```sh
go run main.go -s=23
```

131
examples/golang/ntt/main.go Normal file
View File

@@ -0,0 +1,131 @@
package main
import (
"flag"
"fmt"
"time"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
bls12377Ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
bn254Ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt"
bls12377Fft "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft"
bn254Fft "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft"
)
func main() {
var logSize int
flag.IntVar(&logSize, "s", 20, "Log size")
flag.Parse()
size := 1 << logSize
fmt.Printf("---------------------- NTT size 2^%d=%d ------------------------\n", logSize, size)
print("Generating BN254 scalars ... ")
startTime := time.Now()
scalarsBn254 := bn254.GenerateScalars(size)
println(time.Since(startTime).String())
cfgBn254 := bn254Ntt.GetDefaultNttConfig()
cfgBn254.IsAsync = true
print("Generating BLS12_377 scalars ... ")
startTime = time.Now()
scalarsBls12377 := bls12377.GenerateScalars(size)
println(time.Since(startTime).String())
cfgBls12377 := bls12377Ntt.GetDefaultNttConfig()
cfgBls12377.IsAsync = true
rouMontBn254, _ := bn254Fft.Generator(uint64(size))
rouBn254 := rouMontBn254.Bits()
rouIcicleBn254 := bn254.ScalarField{}
limbsBn254 := core.ConvertUint64ArrToUint32Arr(rouBn254[:])
rouIcicleBn254.FromLimbs(limbsBn254)
bn254Ntt.InitDomain(rouIcicleBn254, cfgBn254.Ctx, false)
rouMontBls12377, _ := bls12377Fft.Generator(uint64(size))
rouBls12377 := rouMontBls12377.Bits()
rouIcicleBls12377 := bls12377.ScalarField{}
limbsBls12377 := core.ConvertUint64ArrToUint32Arr(rouBls12377[:])
rouIcicleBls12377.FromLimbs(limbsBls12377)
bls12377Ntt.InitDomain(rouIcicleBls12377, cfgBls12377.Ctx, false)
print("Configuring bn254 NTT ... ")
startTime = time.Now()
streamBn254, _ := cr.CreateStream()
cfgBn254.Ctx.Stream = &streamBn254
var nttResultBn254 core.DeviceSlice
_, e := nttResultBn254.MallocAsync(size*scalarsBn254.SizeOfElement(), scalarsBn254.SizeOfElement(), streamBn254)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"Bn254 Malloc failed: ", e)
panic(errorString)
}
println(time.Since(startTime).String())
print("Configuring Bls12377 NTT ... ")
startTime = time.Now()
streamBls12377, _ := cr.CreateStream()
cfgBls12377.Ctx.Stream = &streamBls12377
var nttResultBls12377 core.DeviceSlice
_, e = nttResultBls12377.MallocAsync(size*scalarsBls12377.SizeOfElement(), scalarsBls12377.SizeOfElement(), streamBls12377)
if e != cr.CudaSuccess {
errorString := fmt.Sprint(
"Bls12_377 Malloc failed: ", e)
panic(errorString)
}
println(time.Since(startTime).String())
print("Executing bn254 NTT on device ... ")
startTime = time.Now()
err := bn254Ntt.Ntt(scalarsBn254, core.KForward, &cfgBn254, nttResultBn254)
if err.CudaErrorCode != cr.CudaSuccess {
errorString := fmt.Sprint(
"bn254 Ntt failed: ", e)
panic(errorString)
}
nttResultBn254Host := make(core.HostSlice[bn254.ScalarField], size)
nttResultBn254Host.CopyFromDeviceAsync(&nttResultBn254, streamBn254)
nttResultBn254.FreeAsync(streamBn254)
cr.SynchronizeStream(&streamBn254)
println(time.Since(startTime).String())
print("Executing Bls12377 NTT on device ... ")
startTime = time.Now()
err = bls12377Ntt.Ntt(scalarsBls12377, core.KForward, &cfgBls12377, nttResultBls12377)
if err.CudaErrorCode != cr.CudaSuccess {
errorString := fmt.Sprint(
"bls12_377 Ntt failed: ", e)
panic(errorString)
}
nttResultBls12377Host := make(core.HostSlice[bls12377.ScalarField], size)
nttResultBls12377Host.CopyFromDeviceAsync(&nttResultBls12377, streamBls12377)
nttResultBls12377.FreeAsync(streamBls12377)
cr.SynchronizeStream(&streamBls12377)
println(time.Since(startTime).String())
}

View File

@@ -0,0 +1,49 @@
# ICICLE example: Polynomials in Golang
`ICICLE` provides Golang bindings to CUDA-accelerated C++ implementation of [Polynomials](https://dev.ingonyama.com/icicle/polynomials/overview).
## Usage
### Backend Initialization
```go
InitPolyBackend()
```
### Construction
```go
poly1 := CreateFromCoeffecitients(/* Coefficients of polynomial */ coeffs)
poly2 := CreateFromROUEvaluations(/* evaluations */ evals)
poly3 := Clone(/* polynomial to clone */ poly1)
```
### Arithmetic
```go
polyAdd := poly1.Add(&poly2)
polySub := poly1.Subtract(&poly2)
polyMul := poly1.Multiply(&poly2)
polyMulScalar := MultiplyByScalar(scalar)
quotient, remainder := poly1.Divide(&poly2)
```
### Evaluation
```go
ev := poly1.Eval(scalar)
ev2 := poly1.EvalOnDomain(scalars)
```
In this example we use `BN254` and `Babybear` fields. The examples shows arithmetic operations and evaluations execution.
## What's in the example
1. Define the size of polynomials.
2. Initialize backends.
3. Generate random polynomials.
4. Execute arithmetic operations.
5. Execute evaluations.
6. Execute slicing.
Running the example:
```sh
go run main.go
```

View File

@@ -0,0 +1,114 @@
package main
import (
"flag"
"fmt"
bn254Fft "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
bn254Ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt"
bn254Polynomial "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/polynomial"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear"
babybearNtt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear/ntt"
babybearPolynomial "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear/polynomial"
)
var maxNttLogSize uint
var polyLogSize uint
func initBn254Domain() core.IcicleError {
deviceCfg, _ := cr.GetDefaultDeviceContext()
rouMontBn254, _ := bn254Fft.Generator(uint64(1 << maxNttLogSize))
rouBn254 := rouMontBn254.Bits()
rouIcicleBn254 := bn254.ScalarField{}
limbsBn254 := core.ConvertUint64ArrToUint32Arr(rouBn254[:])
rouIcicleBn254.FromLimbs(limbsBn254)
return bn254Ntt.InitDomain(rouIcicleBn254, deviceCfg, false)
}
func initBabybearDomain() core.IcicleError {
deviceCfg, _ := cr.GetDefaultDeviceContext()
rouIcicle := babybear.ScalarField{}
rouIcicle.FromUint32(1461624142)
return babybearNtt.InitDomain(rouIcicle, deviceCfg, false)
}
func init() {
flag.UintVar(&maxNttLogSize, "maxNttLogSize", 20, "")
flag.UintVar(&polyLogSize, "polyLogSize", 15, "")
e := initBn254Domain()
if e.IcicleErrorCode != core.IcicleSuccess {
errorString := fmt.Sprint(
"Bn254 Domain initialization failed: ", e)
panic(errorString)
}
e = initBabybearDomain()
if e.IcicleErrorCode != core.IcicleSuccess {
errorString := fmt.Sprint(
"Babybear Domain initialization failed: ", e)
panic(errorString)
}
bn254Polynomial.InitPolyBackend()
babybearPolynomial.InitPolyBackend()
}
func main() {
polySize := 1 << polyLogSize
// randomize three polynomials over bn254 scalar field
var fBn254 bn254Polynomial.DensePolynomial
var gBn254 bn254Polynomial.DensePolynomial
var hBn254 bn254Polynomial.DensePolynomial
fBn254.CreateFromCoeffecitients(bn254.GenerateScalars(polySize))
gBn254.CreateFromCoeffecitients(bn254.GenerateScalars(polySize / 2))
hBn254.CreateFromROUEvaluations(bn254.GenerateScalars(polySize / 4))
// randomize two polynomials over babybear field
var fBabybear babybearPolynomial.DensePolynomial
var gBabybear babybearPolynomial.DensePolynomial
fBabybear.CreateFromCoeffecitients(babybear.GenerateScalars(polySize))
gBabybear.CreateFromCoeffecitients(babybear.GenerateScalars(polySize / 2))
// Arithmetic
t0 := fBn254.Add(&gBn254)
t1 := fBn254.Multiply(&hBn254)
q, r := t1.Divide(&t0)
rBabybear := fBabybear.Add(&gBabybear)
rDegree := r.Degree()
_ = rBabybear
_ = rDegree
// evaluate in single domain point
var five bn254.ScalarField
five.FromUint32(5)
qAtFive := q.Eval(five)
var thirty bn254.ScalarField
thirty.FromUint32(30)
// evaluate on domain. Note: domain and image can be either Host or Device slice.
// in this example domain in on host and evals on device.
hostDomain := core.HostSliceFromElements([]bn254.ScalarField{five, thirty})
var deviceImage core.DeviceSlice
_, err := deviceImage.Malloc(five.Size()*hostDomain.Len(), five.Size())
if err != cr.CudaSuccess {
errorString := fmt.Sprint(
"deviceImage allocation failed: ", err)
panic(errorString)
}
t1.EvalOnDomain(hostDomain, deviceImage)
// slicing
o := hBn254.Odd()
e := hBn254.Even()
oddMult := o.MultiplyByScalar(qAtFive)
fold := e.Add(&oddMult) // e(x) + o(x)*scalar
coeff := fold.GetCoeff(2) // coeff of x^2
_ = coeff
}

View File

@@ -24,6 +24,7 @@ set(POLYNOMIAL_SOURCE_FILES
# TODO: impl poseidon for small fields. note that it needs to be defined over the extension field!
if (DEFINED CURVE)
list(APPEND FIELD_SOURCE ${SRC}/poseidon/extern.cu)
list(APPEND FIELD_SOURCE ${SRC}/poseidon/poseidon.cu)
list(APPEND FIELD_SOURCE ${SRC}/poseidon/tree/merkle.cu)
endif()

View File

@@ -1,3 +1,2 @@
test_poseidon: test.cu poseidon.cu kernels.cu constants.cu
nvcc -o test_poseidon -I../../include -DFIELD_ID=2 -DCURVE_ID=2 test.cu
./test_poseidon
test_poseidon : test.cu poseidon.cu kernels.cu constants.cu nvcc - o test_poseidon - I../../ include - DFIELD_ID =
2 - DCURVE_ID = 2 test.cu./ test_poseidon

View File

@@ -98,22 +98,4 @@ namespace poseidon {
return CHK_LAST();
}
extern "C" cudaError_t CONCAT_EXPAND(FIELD, create_optimized_poseidon_constants_cuda)(
int arity,
int full_rounds_half,
int partial_rounds,
const scalar_t* constants,
device_context::DeviceContext& ctx,
PoseidonConstants<scalar_t>* poseidon_constants)
{
return create_optimized_poseidon_constants<scalar_t>(
arity, full_rounds_half, partial_rounds, constants, ctx, poseidon_constants);
}
extern "C" cudaError_t CONCAT_EXPAND(FIELD, init_optimized_poseidon_constants_cuda)(
int arity, device_context::DeviceContext& ctx, PoseidonConstants<scalar_t>* constants)
{
return init_optimized_poseidon_constants<scalar_t>(arity, ctx, constants);
}
} // namespace poseidon

View File

@@ -0,0 +1,59 @@
#include "fields/field_config.cuh"
using namespace field_config;
#include "poseidon.cu"
#include "constants.cu"
#include "gpu-utils/device_context.cuh"
#include "utils/utils.h"
namespace poseidon {
/**
* Extern "C" version of [poseidon_hash_cuda] function with the following
* value of template parameter (where the field is given by `-DFIELD` env variable during build):
* - `S` is the [field](@ref scalar_t) - either a scalar field of the elliptic curve or a
* stand-alone "STARK field";
* @return `cudaSuccess` if the execution was successful and an error code otherwise.
*/
extern "C" cudaError_t CONCAT_EXPAND(FIELD, poseidon_hash_cuda)(
scalar_t* input,
scalar_t* output,
int number_of_states,
int arity,
const PoseidonConstants<scalar_t>& constants,
PoseidonConfig& config)
{
switch (arity) {
case 2:
return poseidon_hash<scalar_t, 3>(input, output, number_of_states, constants, config);
case 4:
return poseidon_hash<scalar_t, 5>(input, output, number_of_states, constants, config);
case 8:
return poseidon_hash<scalar_t, 9>(input, output, number_of_states, constants, config);
case 11:
return poseidon_hash<scalar_t, 12>(input, output, number_of_states, constants, config);
default:
THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, "PoseidonHash: #arity must be one of [2, 4, 8, 11]");
}
return CHK_LAST();
}
extern "C" cudaError_t CONCAT_EXPAND(FIELD, create_optimized_poseidon_constants_cuda)(
int arity,
int full_rounds_half,
int partial_rounds,
const scalar_t* constants,
device_context::DeviceContext& ctx,
PoseidonConstants<scalar_t>* poseidon_constants)
{
return create_optimized_poseidon_constants<scalar_t>(
arity, full_rounds_half, partial_rounds, constants, ctx, poseidon_constants);
}
extern "C" cudaError_t CONCAT_EXPAND(FIELD, init_optimized_poseidon_constants_cuda)(
int arity, device_context::DeviceContext& ctx, PoseidonConstants<scalar_t>* constants)
{
return init_optimized_poseidon_constants<scalar_t>(arity, ctx, constants);
}
} // namespace poseidon

View File

@@ -3,7 +3,6 @@
using namespace field_config;
#include "poseidon/poseidon.cuh"
#include "constants.cu"
#include "kernels.cu"
namespace poseidon {
@@ -88,27 +87,4 @@ namespace poseidon {
if (!config.is_async) return CHK_STICKY(cudaStreamSynchronize(stream));
return CHK_LAST();
}
extern "C" cudaError_t CONCAT_EXPAND(FIELD, poseidon_hash_cuda)(
scalar_t* input,
scalar_t* output,
int number_of_states,
int arity,
const PoseidonConstants<scalar_t>& constants,
PoseidonConfig& config)
{
switch (arity) {
case 2:
return poseidon_hash<scalar_t, 3>(input, output, number_of_states, constants, config);
case 4:
return poseidon_hash<scalar_t, 5>(input, output, number_of_states, constants, config);
case 8:
return poseidon_hash<scalar_t, 9>(input, output, number_of_states, constants, config);
case 11:
return poseidon_hash<scalar_t, 12>(input, output, number_of_states, constants, config);
default:
THROW_ICICLE_ERR(IcicleError_t::InvalidArgument, "PoseidonHash: #arity must be one of [2, 4, 8, 11]");
}
return CHK_LAST();
}
} // namespace poseidon

View File

@@ -0,0 +1,94 @@
package core
import (
"fmt"
"unsafe"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
type PoseidonConfig struct {
/// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext).
Ctx cr.DeviceContext
areInputsOnDevice bool
areOutputsOnDevice bool
///If true, input is considered to be a states vector, holding the preimages in aligned or not aligned format.
///Memory under the input pointer will be used for states. If false, fresh states memory will be allocated and input will be copied into it */
InputIsAState bool
/// If true - input should be already aligned for poseidon permutation.
///* Aligned format: [0, A, B, 0, C, D, ...] (as you might get by using loop_state)
///* not aligned format: [A, B, 0, C, D, 0, ...] (as you might get from cudaMemcpy2D) */
Aligned bool
///If true, hash results will also be copied in the input pointer in aligned format
LoopState bool
///Whether to run the Poseidon asynchronously. If set to `true`, the poseidon_hash function will be
///non-blocking and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`.
///If set to false, the poseidon_hash function will block the current CPU thread. */
IsAsync bool
}
type PoseidonConstants[T any] struct {
Arity int32
PartialRounds int32
FullRoundsHalf int32
RoundConstants unsafe.Pointer
MdsMatrix unsafe.Pointer
NonSparseMatrix unsafe.Pointer
SparseMatrices unsafe.Pointer
DomainTag T
}
func GetDefaultPoseidonConfig() PoseidonConfig {
ctx, _ := cr.GetDefaultDeviceContext()
return PoseidonConfig{
ctx, // Ctx
false, // areInputsOnDevice
false, // areOutputsOnDevice
false, // inputIsAState
false, // aligned
false, // loopState
false, // IsAsync
}
}
func PoseidonCheck[T any](input, output HostOrDeviceSlice, cfg *PoseidonConfig, constants *PoseidonConstants[T], numberOfStates int) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) {
inputLen, outputLen := input.Len(), output.Len()
arity := int(constants.Arity)
expectedInputLen := arity * numberOfStates
if cfg.InputIsAState {
expectedInputLen += numberOfStates
}
if inputLen != expectedInputLen {
errorString := fmt.Sprintf(
"input is not the right length for the given parameters: %d, should be: %d",
inputLen,
arity*numberOfStates,
)
panic(errorString)
}
if outputLen != numberOfStates {
errorString := fmt.Sprintf(
"output is not the right length for the given parameters: %d, should be: %d",
outputLen,
numberOfStates,
)
panic(errorString)
}
cfg.areInputsOnDevice = input.IsOnDevice()
cfg.areOutputsOnDevice = output.IsOnDevice()
if input.IsOnDevice() {
input.(DeviceSlice).CheckDevice()
}
if output.IsOnDevice() {
output.(DeviceSlice).CheckDevice()
}
cfgPointer := unsafe.Pointer(cfg)
return input.AsUnsafePointer(), output.AsUnsafePointer(), cfgPointer
}

View File

@@ -5,10 +5,9 @@ package g2
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,10 +5,9 @@ package msm
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,13 +5,15 @@ package ntt
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
)
import (
"unsafe"
)
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results)

View File

@@ -0,0 +1,25 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_POSEIDON_H
#define _BLS12_377_POSEIDON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PoseidonConfig PoseidonConfig;
typedef struct DeviceContext DeviceContext;
typedef struct PoseidonConstants PoseidonConstants;
cudaError_t bls12_377_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config);
cudaError_t bls12_377_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants);
cudaError_t bls12_377_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,57 @@
package poseidon
// #cgo CFLAGS: -I./include/
// #include "poseidon.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
func GetDefaultPoseidonConfig() core.PoseidonConfig {
return core.GetDefaultPoseidonConfig()
}
func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError {
scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates)
cScalars := (*C.scalar_t)(scalarsPointer)
cResults := (*C.scalar_t)(resultsPointer)
cNumberOfStates := (C.int)(numberOfStates)
cArity := (C.int)(constants.Arity)
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
cCfg := (*C.PoseidonConfig)(cfgPointer)
__ret := C.bls12_377_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cFullRoundsHalfs := (C.int)(fullRoundsHalfs)
cPartialRounds := (C.int)(partialRounds)
cConstants := (*C.scalar_t)(constants.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants))
__ret := C.bls12_377_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
__ret := C.bls12_377_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestG2AffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,7 +5,6 @@ import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/ntt"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/polynomial"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/vecOps"

View File

@@ -0,0 +1,42 @@
package tests
import (
"testing"
core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377/poseidon"
)
func TestPoseidon(t *testing.T) {
arity := 2
numberOfStates := 1
cfg := poseidon.GetDefaultPoseidonConfig()
cfg.IsAsync = true
stream, _ := cr.CreateStream()
cfg.Ctx.Stream = &stream
var constants core.PoseidonConstants[bls12_377.ScalarField]
poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants
scalars := bls12_377.GenerateScalars(numberOfStates * arity)
scalars[0] = scalars[0].Zero()
scalars[1] = scalars[0].Zero()
scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity])
var deviceInput core.DeviceSlice
scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true)
var deviceOutput core.DeviceSlice
deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function
output := make(core.HostSlice[bls12_377.ScalarField], numberOfStates)
output.CopyFromDeviceAsync(&deviceOutput, stream)
}

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,10 +5,9 @@ package g2
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,10 +5,9 @@ package msm
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,13 +5,15 @@ package ntt
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381"
)
import (
"unsafe"
)
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results)

View File

@@ -0,0 +1,25 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_POSEIDON_H
#define _BLS12_381_POSEIDON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PoseidonConfig PoseidonConfig;
typedef struct DeviceContext DeviceContext;
typedef struct PoseidonConstants PoseidonConstants;
cudaError_t bls12_381_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config);
cudaError_t bls12_381_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants);
cudaError_t bls12_381_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,57 @@
package poseidon
// #cgo CFLAGS: -I./include/
// #include "poseidon.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
func GetDefaultPoseidonConfig() core.PoseidonConfig {
return core.GetDefaultPoseidonConfig()
}
func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError {
scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates)
cScalars := (*C.scalar_t)(scalarsPointer)
cResults := (*C.scalar_t)(resultsPointer)
cNumberOfStates := (C.int)(numberOfStates)
cArity := (C.int)(constants.Arity)
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
cCfg := (*C.PoseidonConfig)(cfgPointer)
__ret := C.bls12_381_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cFullRoundsHalfs := (C.int)(fullRoundsHalfs)
cPartialRounds := (C.int)(partialRounds)
cConstants := (*C.scalar_t)(constants.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants))
__ret := C.bls12_381_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
__ret := C.bls12_381_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestG2AffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,7 +5,6 @@ import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381"
// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/ntt"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/polynomial"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/vecOps"

View File

@@ -0,0 +1,55 @@
package tests
import (
"testing"
core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381/poseidon"
"fmt"
"github.com/stretchr/testify/assert"
)
func formatOutput(x bls12_381.ScalarField) string {
r := x.GetLimbs()
return fmt.Sprintf("%08x%08x%08x%08x%08x%08x%08x%08x", r[7], r[6], r[5], r[4], r[3], r[2], r[1], r[0])
}
func TestPoseidon(t *testing.T) {
arity := 2
numberOfStates := 1
cfg := poseidon.GetDefaultPoseidonConfig()
cfg.IsAsync = true
stream, _ := cr.CreateStream()
cfg.Ctx.Stream = &stream
var constants core.PoseidonConstants[bls12_381.ScalarField]
poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants
scalars := bls12_381.GenerateScalars(numberOfStates * arity)
scalars[0] = scalars[0].Zero()
scalars[1] = scalars[0].Zero()
scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity])
var deviceInput core.DeviceSlice
scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true)
var deviceOutput core.DeviceSlice
deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function
output := make(core.HostSlice[bls12_381.ScalarField], numberOfStates)
output.CopyFromDeviceAsync(&deviceOutput, stream)
expectedString := "48fe0b1331196f6cdb33a7c6e5af61b76fd388e1ef1d3d418be5147f0e4613d4" //This result is from https://github.com/triplewz/poseidon
outputString := formatOutput(output[0])
assert.Equal(t, outputString, expectedString, "Poseidon hash does not match expected result")
}

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,10 +5,9 @@ package g2
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,10 +5,9 @@ package msm
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,13 +5,15 @@ package ntt
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
)
import (
"unsafe"
)
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results)

View File

@@ -0,0 +1,25 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BN254_POSEIDON_H
#define _BN254_POSEIDON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PoseidonConfig PoseidonConfig;
typedef struct DeviceContext DeviceContext;
typedef struct PoseidonConstants PoseidonConstants;
cudaError_t bn254_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config);
cudaError_t bn254_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants);
cudaError_t bn254_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,57 @@
package poseidon
// #cgo CFLAGS: -I./include/
// #include "poseidon.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
func GetDefaultPoseidonConfig() core.PoseidonConfig {
return core.GetDefaultPoseidonConfig()
}
func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError {
scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates)
cScalars := (*C.scalar_t)(scalarsPointer)
cResults := (*C.scalar_t)(resultsPointer)
cNumberOfStates := (C.int)(numberOfStates)
cArity := (C.int)(constants.Arity)
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
cCfg := (*C.PoseidonConfig)(cfgPointer)
__ret := C.bn254_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cFullRoundsHalfs := (C.int)(fullRoundsHalfs)
cPartialRounds := (C.int)(partialRounds)
cConstants := (*C.scalar_t)(constants.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants))
__ret := C.bn254_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
__ret := C.bn254_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestG2AffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,7 +5,6 @@ import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/ntt"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/polynomial"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/vecOps"

View File

@@ -0,0 +1,42 @@
package tests
import (
"testing"
core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254/poseidon"
)
func TestPoseidon(t *testing.T) {
arity := 2
numberOfStates := 1
cfg := poseidon.GetDefaultPoseidonConfig()
cfg.IsAsync = true
stream, _ := cr.CreateStream()
cfg.Ctx.Stream = &stream
var constants core.PoseidonConstants[bn254.ScalarField]
poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants
scalars := bn254.GenerateScalars(numberOfStates * arity)
scalars[0] = scalars[0].Zero()
scalars[1] = scalars[0].Zero()
scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity])
var deviceInput core.DeviceSlice
scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true)
var deviceOutput core.DeviceSlice
deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function
output := make(core.HostSlice[bn254.ScalarField], numberOfStates)
output.CopyFromDeviceAsync(&deviceOutput, stream)
}

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bn254 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bn254"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,10 +5,9 @@ package g2
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,10 +5,9 @@ package msm
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -5,13 +5,15 @@ package ntt
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761"
)
import (
"unsafe"
)
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results)

View File

@@ -0,0 +1,25 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BW6_761_POSEIDON_H
#define _BW6_761_POSEIDON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PoseidonConfig PoseidonConfig;
typedef struct DeviceContext DeviceContext;
typedef struct PoseidonConstants PoseidonConstants;
cudaError_t bw6_761_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config);
cudaError_t bw6_761_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants);
cudaError_t bw6_761_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,57 @@
package poseidon
// #cgo CFLAGS: -I./include/
// #include "poseidon.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
func GetDefaultPoseidonConfig() core.PoseidonConfig {
return core.GetDefaultPoseidonConfig()
}
func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError {
scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates)
cScalars := (*C.scalar_t)(scalarsPointer)
cResults := (*C.scalar_t)(resultsPointer)
cNumberOfStates := (C.int)(numberOfStates)
cArity := (C.int)(constants.Arity)
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
cCfg := (*C.PoseidonConfig)(cfgPointer)
__ret := C.bw6_761_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cFullRoundsHalfs := (C.int)(fullRoundsHalfs)
cPartialRounds := (C.int)(partialRounds)
cConstants := (*C.scalar_t)(constants.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants))
__ret := C.bw6_761_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
__ret := C.bw6_761_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestG2AffineZero(t *testing.T) {

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/g2"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,7 +5,6 @@ import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761"
// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/ntt"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/polynomial"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/vecOps"

View File

@@ -0,0 +1,42 @@
package tests
import (
"testing"
core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761/poseidon"
)
func TestPoseidon(t *testing.T) {
arity := 2
numberOfStates := 1
cfg := poseidon.GetDefaultPoseidonConfig()
cfg.IsAsync = true
stream, _ := cr.CreateStream()
cfg.Ctx.Stream = &stream
var constants core.PoseidonConstants[bw6_761.ScalarField]
poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants
scalars := bw6_761.GenerateScalars(numberOfStates * arity)
scalars[0] = scalars[0].Zero()
scalars[1] = scalars[0].Zero()
scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity])
var deviceInput core.DeviceSlice
scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true)
var deviceOutput core.DeviceSlice
deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function
output := make(core.HostSlice[bw6_761.ScalarField], numberOfStates)
output.CopyFromDeviceAsync(&deviceOutput, stream)
}

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
bw6_761 "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/bw6761"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,10 +5,9 @@ package msm
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {

View File

@@ -0,0 +1,25 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _GRUMPKIN_POSEIDON_H
#define _GRUMPKIN_POSEIDON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PoseidonConfig PoseidonConfig;
typedef struct DeviceContext DeviceContext;
typedef struct PoseidonConstants PoseidonConstants;
cudaError_t grumpkin_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config);
cudaError_t grumpkin_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants);
cudaError_t grumpkin_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,57 @@
package poseidon
// #cgo CFLAGS: -I./include/
// #include "poseidon.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
func GetDefaultPoseidonConfig() core.PoseidonConfig {
return core.GetDefaultPoseidonConfig()
}
func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError {
scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates)
cScalars := (*C.scalar_t)(scalarsPointer)
cResults := (*C.scalar_t)(resultsPointer)
cNumberOfStates := (C.int)(numberOfStates)
cArity := (C.int)(constants.Arity)
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
cCfg := (*C.PoseidonConfig)(cfgPointer)
__ret := C.grumpkin_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cFullRoundsHalfs := (C.int)(fullRoundsHalfs)
cPartialRounds := (C.int)(partialRounds)
cConstants := (*C.scalar_t)(constants.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants))
__ret := C.grumpkin_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
__ret := C.grumpkin_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -1,11 +1,10 @@
package tests
import (
"testing"
grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {

View File

@@ -0,0 +1,42 @@
package tests
import (
"testing"
core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin/poseidon"
)
func TestPoseidon(t *testing.T) {
arity := 2
numberOfStates := 1
cfg := poseidon.GetDefaultPoseidonConfig()
cfg.IsAsync = true
stream, _ := cr.CreateStream()
cfg.Ctx.Stream = &stream
var constants core.PoseidonConstants[grumpkin.ScalarField]
poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants
scalars := grumpkin.GenerateScalars(numberOfStates * arity)
scalars[0] = scalars[0].Zero()
scalars[1] = scalars[0].Zero()
scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity])
var deviceInput core.DeviceSlice
scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true)
var deviceOutput core.DeviceSlice
deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function
output := make(core.HostSlice[grumpkin.ScalarField], numberOfStates)
output.CopyFromDeviceAsync(&deviceOutput, stream)
}

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
grumpkin "github.com/ingonyama-zk/icicle/v2/wrappers/golang/curves/grumpkin"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -5,13 +5,15 @@ package ntt
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear"
)
import (
"unsafe"
)
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
scalarsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](scalars, cfg, results)

View File

@@ -6,10 +6,9 @@ import "C"
import (
"encoding/binary"
"fmt"
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
"unsafe"
)
const (

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
babybear_extension "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear/extension"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -5,7 +5,6 @@ import (
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear"
// "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear/ntt"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear/polynomial"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear/vecOps"

View File

@@ -1,12 +1,11 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
babybear "github.com/ingonyama-zk/icicle/v2/wrappers/golang/fields/babybear"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (

View File

@@ -15,6 +15,7 @@ import (
msm "github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/msm"
ntt "github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/ntt"
poly "github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/polynomial"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/poseidon"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/tests"
vecops "github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/vecOps"
)
@@ -43,6 +44,7 @@ func generateFiles() {
}
msm.Generate(curveDir, "msm", curve.Curve, "", curve.GnarkImport)
poseidon.Generate(curveDir, "", curve.Curve, scalarFieldPrefix)
if curve.SupportsG2 {
g2BaseDir := path.Join(curveDir, "g2")
packageName := "g2"

View File

@@ -0,0 +1,32 @@
package poseidon
import (
"path"
generator "github.com/ingonyama-zk/icicle/v2/wrappers/golang/internal/generator/generator_utils"
)
var poseidonTemplates = map[string]string{
"src": "poseidon/templates/poseidon.go.tmpl",
"test": "poseidon/templates/poseidon_test.go.tmpl",
"header": "poseidon/templates/poseidon.h.tmpl",
}
func Generate(baseDir, additionalDirPath, field, fieldPrefix string) {
data := struct {
PackageName string
Field string
FieldPrefix string
BaseImportPath string
}{
"poseidon",
field,
fieldPrefix,
baseDir,
}
generator.GenerateFile(poseidonTemplates["src"], path.Join(baseDir, additionalDirPath, "poseidon"), "", "", data)
generator.GenerateFile(poseidonTemplates["header"], path.Join(baseDir, additionalDirPath, "poseidon", "include"), "", "", data)
generator.GenerateFile(poseidonTemplates["test"], path.Join(baseDir, "tests"), "", "", data)
}

View File

@@ -0,0 +1,57 @@
package {{.PackageName}}
// #cgo CFLAGS: -I./include/
// #include "poseidon.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
)
func GetDefaultPoseidonConfig() core.PoseidonConfig {
return core.GetDefaultPoseidonConfig()
}
func PoseidonHash[T any](scalars, results core.HostOrDeviceSlice, numberOfStates int, cfg *core.PoseidonConfig, constants *core.PoseidonConstants[T]) core.IcicleError {
scalarsPointer, resultsPointer, cfgPointer := core.PoseidonCheck(scalars, results, cfg, constants, numberOfStates)
cScalars := (*C.scalar_t)(scalarsPointer)
cResults := (*C.scalar_t)(resultsPointer)
cNumberOfStates := (C.int)(numberOfStates)
cArity := (C.int)(constants.Arity)
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
cCfg := (*C.PoseidonConfig)(cfgPointer)
__ret := C.{{.Field}}_poseidon_hash_cuda(cScalars, cResults, cNumberOfStates, cArity, cConstants, cCfg)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func CreateOptimizedPoseidonConstants[T any](arity, fullRoundsHalfs, partialRounds int, constants core.HostOrDeviceSlice, ctx cr.DeviceContext, poseidonConstants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cFullRoundsHalfs := (C.int)(fullRoundsHalfs)
cPartialRounds := (C.int)(partialRounds)
cConstants := (*C.scalar_t)(constants.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cPoseidonConstants := (*C.PoseidonConstants)(unsafe.Pointer(poseidonConstants))
__ret := C.{{.Field}}_create_optimized_poseidon_constants_cuda(cArity, cFullRoundsHalfs, cPartialRounds, cConstants, cCtx, cPoseidonConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitOptimizedPoseidonConstantsCuda[T any](arity int, ctx cr.DeviceContext, constants *core.PoseidonConstants[T]) core.IcicleError {
cArity := (C.int)(arity)
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cConstants := (*C.PoseidonConstants)(unsafe.Pointer(constants))
__ret := C.{{.Field}}_init_optimized_poseidon_constants_cuda(cArity, cCtx, cConstants)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,25 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _{{toUpper .Field}}_POSEIDON_H
#define _{{toUpper .Field}}_POSEIDON_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PoseidonConfig PoseidonConfig;
typedef struct DeviceContext DeviceContext;
typedef struct PoseidonConstants PoseidonConstants;
cudaError_t {{.Field}}_poseidon_hash_cuda(const scalar_t* input, scalar_t* output, int number_of_states, int arity, PoseidonConstants* constants, PoseidonConfig* config);
cudaError_t {{.Field}}_create_optimized_poseidon_constants_cuda(int arity, int full_rounds_halfs, int partial_rounds, const scalar_t* constants, DeviceContext* ctx, PoseidonConstants* poseidon_constants);
cudaError_t {{.Field}}_init_optimized_poseidon_constants_cuda(int arity, DeviceContext* ctx, PoseidonConstants* constants);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,59 @@
package tests
import (
"testing"
core "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/v2/wrappers/golang/cuda_runtime"
{{.Field}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}"
poseidon "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}/poseidon"
{{if eq .Field "bls12_381"}}
"fmt"
"github.com/stretchr/testify/assert"
{{end}}
)
{{if eq .Field "bls12_381"}}
func formatOutput(x {{.Field}}.{{.FieldPrefix}}Field) string {
r := x.GetLimbs()
return fmt.Sprintf("%08x%08x%08x%08x%08x%08x%08x%08x", r[7], r[6], r[5], r[4], r[3], r[2], r[1], r[0])
}
{{end}}
func TestPoseidon(t *testing.T) {
arity := 2
numberOfStates := 1
cfg := poseidon.GetDefaultPoseidonConfig()
cfg.IsAsync = true
stream, _ := cr.CreateStream()
cfg.Ctx.Stream = &stream
var constants core.PoseidonConstants[{{.Field}}.{{.FieldPrefix}}Field]
poseidon.InitOptimizedPoseidonConstantsCuda(arity, cfg.Ctx, &constants) //generate constants
scalars := {{.Field}}.GenerateScalars(numberOfStates * arity)
scalars[0] = scalars[0].Zero()
scalars[1] = scalars[0].Zero()
scalarsCopy := core.HostSliceFromElements(scalars[:numberOfStates*arity])
var deviceInput core.DeviceSlice
scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true)
var deviceOutput core.DeviceSlice
deviceOutput.MallocAsync(numberOfStates*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
poseidon.PoseidonHash(deviceInput, deviceOutput, numberOfStates, &cfg, &constants) //run Hash function
output := make(core.HostSlice[{{.Field}}.{{.FieldPrefix}}Field], numberOfStates)
output.CopyFromDeviceAsync(&deviceOutput, stream)
{{if eq .Field "bls12_381"}}
expectedString := "48fe0b1331196f6cdb33a7c6e5af61b76fd388e1ef1d3d418be5147f0e4613d4" //This result is from https://github.com/triplewz/poseidon
outputString := formatOutput(output[0])
assert.Equal(t, outputString, expectedString, "Poseidon hash does not match expected result")
{{end}}
}

View File

@@ -17,7 +17,7 @@ exclude = [
]
[workspace.package]
version = "2.2.0"
version = "2.3.0"
edition = "2021"
authors = [ "Ingonyama" ]
homepage = "https://www.ingonyama.com"