ICICLE V2 Release (#492)

This PR introduces major updates for ICICLE Core, Rust and Golang
bindings

---------

Co-authored-by: Yuval Shekel <yshekel@gmail.com>
Co-authored-by: DmytroTym <dmytrotym1@gmail.com>
Co-authored-by: Otsar <122266060+Otsar-Raikou@users.noreply.github.com>
Co-authored-by: VitaliiH <vhnatyk@gmail.com>
Co-authored-by: release-bot <release-bot@ingonyama.com>
Co-authored-by: Stas <spolonsky@icloud.com>
Co-authored-by: Jeremy Felder <jeremy.felder1@gmail.com>
Co-authored-by: ImmanuelSegol <3ditds@gmail.com>
Co-authored-by: JimmyHongjichuan <45908291+JimmyHongjichuan@users.noreply.github.com>
Co-authored-by: pierre <pierreuu@gmail.com>
Co-authored-by: Leon Hibnik <107353745+LeonHibnik@users.noreply.github.com>
Co-authored-by: nonam3e <timur@ingonyama.com>
Co-authored-by: Vlad <88586482+vladfdp@users.noreply.github.com>
Co-authored-by: LeonHibnik <leon@ingonyama.com>
Co-authored-by: nonam3e <71525212+nonam3e@users.noreply.github.com>
Co-authored-by: vladfdp <vlad.heintz@gmail.com>
This commit is contained in:
ChickenLover
2024-04-23 09:26:40 +07:00
committed by GitHub
parent a1dc0539ce
commit 7265d18d48
584 changed files with 33460 additions and 8856 deletions

View File

@@ -4,57 +4,60 @@ In order to build the underlying ICICLE libraries you should run the build scrip
Build script USAGE
```
./build <curve> [G2_enabled]
```bash
./build.sh [-curve=<curve> | -field=<field>] [-cuda_version=<version>] [-g2] [-ecntt] [-devmode]
curve - The name of the curve to build or "all" to build all curves
G2_enabled - Optional - To build with G2 enabled
field - The name of the field to build or "all" to build all fields
-g2 - Optional - build with G2 enabled
-ecntt - Optional - build with ECNTT enabled
-devmode - Optional - build in devmode
```
To build ICICLE libraries for all supported curves with G2 enabled.
To build ICICLE libraries for all supported curves with G2 and ECNTT enabled.
```
./build.sh all ON
./build.sh all -g2 -ecntt
```
If you wish to build for a specific curve, for example bn254, without G2 enabled.
If you wish to build for a specific curve, for example bn254, without G2 or ECNTT enabled.
```
./build.sh bn254
```
>[!NOTE]
>Current supported curves are `bn254`, `bls12_381`, `bls12_377` and `bw6_671`
>Current supported curves are `bn254`, `bls12_381`, `bls12_377`, `bw6_671` and `grumpkin`
>Current supported fields are `babybear`
>[!NOTE]
>G2 is enabled by building your golang project with the build tag `g2`
>Make sure to add it to your build tags if you want it enabled
>G2 and ECNTT are located in nested packages
## Running golang tests
To run the tests for curve bn254.
```
```bash
go test ./wrappers/golang/curves/bn254 -count=1
```
To run all the tests in the golang bindings
```
go test --tags=g2 ./... -count=1
```bash
go test ./... -count=1
```
## How do Golang bindings work?
The libraries produced from the CUDA code compilation are used to bind Golang to ICICLE's CUDA code.
1. These libraries (named `libingo_<curve>.a`) can be imported in your Go project to leverage the GPU accelerated functionalities provided by ICICLE.
1. These libraries (named `libingo_curve_<curve>.a` and `libingo_field_<curve>.a`) can be imported in your Go project to leverage the GPU accelerated functionalities provided by ICICLE.
2. In your Go project, you can use `cgo` to link these libraries. Here's a basic example on how you can use `cgo` to link these libraries:
```go
/*
#cgo LDFLAGS: -L/path/to/shared/libs -lingo_bn254
#cgo LDFLAGS: -L$/path/to/shared/libs -lingo_curve_bn254 -L$/path/to/shared/libs -lingo_field_bn254 -lstdc++ -lm
#include "icicle.h" // make sure you use the correct header file(s)
*/
import "C"

View File

@@ -2,32 +2,106 @@
G2_DEFINED=OFF
ECNTT_DEFINED=OFF
CUDA_COMPILER_PATH=/usr/local/cuda/bin/nvcc
DEVMODE=OFF
EXT_FIELD=OFF
BUILD_CURVES=( )
BUILD_FIELDS=( )
if [[ $2 == "ON" ]]
then
G2_DEFINED=ON
SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761", "grumpkin")
SUPPORTED_FIELDS=("babybear")
if [[ $1 == "-help" ]]; then
echo "Build script for building ICICLE cpp libraries"
echo ""
echo "If more than one curve or more than one field is supplied, the last one supplied will be built"
echo ""
echo "USAGE: ./build.sh [OPTION...]"
echo ""
echo "OPTIONS:"
echo " -curve=<curve_name> The curve that should be built. If \"all\" is supplied,"
echo " all curves will be built with any other supplied curve options"
echo " -g2 Builds the curve lib with G2 enabled"
echo " -ecntt Builds the curve lib with ECNTT enabled"
echo " -field=<field_name> The field that should be built. If \"all\" is supplied,"
echo " all fields will be built with any other supplied field options"
echo " -field-ext Builds the field lib with the extension field enabled"
echo " -devmode Enables devmode debugging and fast build times"
echo " -cuda_version=<version> The version of cuda to use for compiling"
echo ""
exit 0
fi
if [[ $3 ]]
then
ECNTT_DEFINED=ON
fi
for arg in "$@"
do
arg_lower=$(echo "$arg" | tr '[:upper:]' '[:lower:]')
case "$arg_lower" in
-cuda_version=*)
cuda_version=$(echo "$arg" | cut -d'=' -f2)
CUDA_COMPILER_PATH=/usr/local/cuda-$cuda_version/bin/nvcc
;;
-ecntt)
ECNTT_DEFINED=ON
;;
-g2)
G2_DEFINED=ON
;;
-curve=*)
curve=$(echo "$arg_lower" | cut -d'=' -f2)
if [[ $curve == "all" ]]
then
BUILD_CURVES=("${SUPPORTED_CURVES[@]}")
else
BUILD_CURVES=( $curve )
fi
;;
-field=*)
field=$(echo "$arg_lower" | cut -d'=' -f2)
if [[ $field == "all" ]]
then
BUILD_FIELDS=("${SUPPORTED_FIELDS[@]}")
else
BUILD_FIELDS=( $field )
fi
;;
-field-ext)
EXT_FIELD=ON
;;
-devmode)
DEVMODE=ON
;;
*)
echo "Unknown argument: $arg"
exit 1
;;
esac
done
BUILD_DIR=$(realpath "$PWD/../../icicle/build")
SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761")
if [[ $1 == "all" ]]
then
BUILD_CURVES=("${SUPPORTED_CURVES[@]}")
else
BUILD_CURVES=( $1 )
fi
cd ../../icicle
mkdir -p build
rm -f "$BUILD_DIR/CMakeCache.txt"
for CURVE in "${BUILD_CURVES[@]}"
do
cmake -DCURVE=$CURVE -DG2_DEFINED=$G2_DEFINED -DECNTT_DEFINED=$ECNTT_DEFINED -DCMAKE_BUILD_TYPE=Release -S . -B build
cmake --build build -j8
done
echo "CURVE=${CURVE}" > build_config.txt
echo "ECNTT=${ECNTT_DEFINED}" >> build_config.txt
echo "G2=${G2_DEFINED}" >> build_config.txt
echo "DEVMODE=${DEVMODE}" >> build_config.txt
cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DCURVE=$CURVE -DG2=$G2_DEFINED -DECNTT=$ECNTT_DEFINED -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build
cmake --build build -j8 && rm build_config.txt
done
# Needs to remove the CMakeCache.txt file to allow building fields after curves
# have been built since CURVE and FIELD cannot both be defined
rm -f "$BUILD_DIR/CMakeCache.txt"
for FIELD in "${BUILD_FIELDS[@]}"
do
echo "FIELD=${FIELD}" > build_config.txt
echo "DEVMODE=${DEVMODE}" >> build_config.txt
cmake -DCMAKE_CUDA_COMPILER=$CUDA_COMPILER_PATH -DFIELD=$FIELD -DEXT_FIELD=$EXT_FIELD -DDEVMODE=$DEVMODE -DCMAKE_BUILD_TYPE=Release -S . -B build
cmake --build build -j8 && rm build_config.txt
done

View File

@@ -1,101 +0,0 @@
package internal
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestMockAffineZero(t *testing.T) {
var fieldZero = MockField{}
var affineZero MockAffine
assert.Equal(t, affineZero.X, fieldZero)
assert.Equal(t, affineZero.Y, fieldZero)
x := generateRandomLimb(int(BASE_LIMBS))
y := generateRandomLimb(int(BASE_LIMBS))
var affine MockAffine
affine.FromLimbs(x, y)
affine.Zero()
assert.Equal(t, affine.X, fieldZero)
assert.Equal(t, affine.Y, fieldZero)
}
func TestMockAffineFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
var affine MockAffine
affine.FromLimbs(randLimbs, randLimbs2)
assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs())
assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs())
}
func TestMockAffineToProjective(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
var fieldOne MockField
fieldOne.One()
var expected MockProjective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var affine MockAffine
affine.FromLimbs(randLimbs, randLimbs2)
projectivePoint := affine.ToProjective()
assert.Equal(t, expected, projectivePoint)
}
func TestMockProjectiveZero(t *testing.T) {
var projectiveZero MockProjective
projectiveZero.Zero()
var fieldZero = MockField{}
var fieldOne MockField
fieldOne.One()
assert.Equal(t, projectiveZero.X, fieldZero)
assert.Equal(t, projectiveZero.Y, fieldOne)
assert.Equal(t, projectiveZero.Z, fieldZero)
randLimbs := generateRandomLimb(int(BASE_LIMBS))
var projective MockProjective
projective.FromLimbs(randLimbs, randLimbs, randLimbs)
projective.Zero()
assert.Equal(t, projective.X, fieldZero)
assert.Equal(t, projective.Y, fieldOne)
assert.Equal(t, projective.Z, fieldZero)
}
func TestMockProjectiveFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
randLimbs3 := generateRandomLimb(int(BASE_LIMBS))
var projective MockProjective
projective.FromLimbs(randLimbs, randLimbs2, randLimbs3)
assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs())
assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs())
assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs())
}
func TestMockProjectiveFromAffine(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
var fieldOne MockField
fieldOne.One()
var expected MockProjective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var affine MockAffine
affine.FromLimbs(randLimbs, randLimbs2)
var projectivePoint MockProjective
projectivePoint.FromAffine(affine)
assert.Equal(t, expected, projectivePoint)
}

View File

@@ -1,82 +0,0 @@
package internal
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestMockFieldFromLimbs(t *testing.T) {
emptyField := MockField{}
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the MockField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.limbs)
}
func TestMockFieldGetLimbs(t *testing.T) {
emptyField := MockField{}
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the MockField's limbs")
}
func TestMockFieldOne(t *testing.T) {
var emptyField MockField
emptyField.One()
limbOne := generateLimbOne(int(BASE_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "MockField with limbs to field one did not work")
}
func TestMockFieldZero(t *testing.T) {
var emptyField MockField
emptyField.Zero()
limbsZero := make([]uint32, BASE_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "MockField with limbs to field zero failed")
}
func TestMockFieldSize(t *testing.T) {
var emptyField MockField
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestMockFieldAsPointer(t *testing.T) {
var emptyField MockField
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestMockFieldFromBytes(t *testing.T) {
var emptyField MockField
bytes, expected := generateBytesArray(int(BASE_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
}
func TestMockFieldToBytes(t *testing.T) {
var emptyField MockField
expected, limbs := generateBytesArray(int(BASE_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
}

View File

@@ -1,31 +0,0 @@
package internal
import (
"math/rand"
)
func generateRandomLimb(size int) []uint32 {
limbs := make([]uint32, size)
for i := range limbs {
limbs[i] = rand.Uint32()
}
return limbs
}
func generateLimbOne(size int) []uint32 {
limbs := make([]uint32, size)
limbs[0] = 1
return limbs
}
func generateBytesArray(size int) ([]byte, []uint32) {
baseBytes := []byte{1, 2, 3, 4}
var bytes []byte
var limbs []uint32
for i := 0; i < size; i++ {
bytes = append(bytes, baseBytes...)
limbs = append(limbs, 67305985)
}
return bytes, limbs
}

View File

@@ -1,7 +1,7 @@
package internal
type MockProjective struct {
X, Y, Z MockField
X, Y, Z MockBaseField
}
func (p MockProjective) Size() int {
@@ -29,7 +29,7 @@ func (p *MockProjective) FromLimbs(x, y, z []uint32) MockProjective {
}
func (p *MockProjective) FromAffine(a MockAffine) MockProjective {
z := MockField{}
z := MockBaseField{}
z.One()
p.X = a.X
@@ -40,7 +40,7 @@ func (p *MockProjective) FromAffine(a MockAffine) MockProjective {
}
type MockAffine struct {
X, Y MockField
X, Y MockBaseField
}
func (a MockAffine) Size() int {
@@ -66,7 +66,7 @@ func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine {
}
func (a MockAffine) ToProjective() MockProjective {
var z MockField
var z MockBaseField
return MockProjective{
X: a.X,

View File

@@ -0,0 +1,84 @@
package internal
import (
"encoding/binary"
"fmt"
)
const (
MOCKBASE_LIMBS int = 4
)
type MockBaseField struct {
limbs [MOCKBASE_LIMBS]uint32
}
func (f MockBaseField) Len() int {
return int(MOCKBASE_LIMBS)
}
func (f MockBaseField) Size() int {
return int(MOCKBASE_LIMBS * 4)
}
func (f MockBaseField) GetLimbs() []uint32 {
return f.limbs[:]
}
func (f MockBaseField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *MockBaseField) FromUint32(v uint32) MockBaseField {
f.limbs[0] = v
return *f
}
func (f *MockBaseField) FromLimbs(limbs []uint32) MockBaseField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")
}
for i := range f.limbs {
f.limbs[i] = limbs[i]
}
return *f
}
func (f *MockBaseField) Zero() MockBaseField {
for i := range f.limbs {
f.limbs[i] = 0
}
return *f
}
func (f *MockBaseField) One() MockBaseField {
for i := range f.limbs {
f.limbs[i] = 0
}
f.limbs[0] = 1
return *f
}
func (f *MockBaseField) FromBytesLittleEndian(bytes []byte) MockBaseField {
if len(bytes)/4 != f.Len() {
panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes)))
}
for i := range f.limbs {
f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4])
}
return *f
}
func (f MockBaseField) ToBytesLittleEndian() []byte {
bytes := make([]byte, f.Len()*4)
for i, v := range f.limbs {
binary.LittleEndian.PutUint32(bytes[i*4:], v)
}
return bytes
}

View File

@@ -2,6 +2,7 @@ package core
import (
"fmt"
"unsafe"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
@@ -75,7 +76,7 @@ func GetDefaultMSMConfig() MSMConfig {
}
}
func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfig, results HostOrDeviceSlice) {
func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfig, results HostOrDeviceSlice) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, int, unsafe.Pointer) {
scalarsLength, pointsLength, resultsLength := scalars.Len(), points.Len()/int(cfg.PrecomputeFactor), results.Len()
if scalarsLength%pointsLength != 0 {
errorString := fmt.Sprintf(
@@ -98,9 +99,24 @@ func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfi
cfg.areScalarsOnDevice = scalars.IsOnDevice()
cfg.arePointsOnDevice = points.IsOnDevice()
cfg.areResultsOnDevice = results.IsOnDevice()
if scalars.IsOnDevice() {
scalars.(DeviceSlice).CheckDevice()
}
if points.IsOnDevice() {
points.(DeviceSlice).CheckDevice()
}
if results.IsOnDevice() {
results.(DeviceSlice).CheckDevice()
}
size := scalars.Len() / results.Len()
return scalars.AsUnsafePointer(), points.AsUnsafePointer(), results.AsUnsafePointer(), size, unsafe.Pointer(cfg)
}
func PrecomputeBasesCheck(points HostOrDeviceSlice, precomputeFactor int32, outputBases DeviceSlice) {
func PrecomputeBasesCheck(points HostOrDeviceSlice, precomputeFactor int32, outputBases DeviceSlice) (unsafe.Pointer, unsafe.Pointer) {
outputBasesLength, pointsLength := outputBases.Len(), points.Len()
if outputBasesLength != pointsLength*int(precomputeFactor) {
errorString := fmt.Sprintf(
@@ -110,4 +126,10 @@ func PrecomputeBasesCheck(points HostOrDeviceSlice, precomputeFactor int32, outp
)
panic(errorString)
}
if points.IsOnDevice() {
points.(DeviceSlice).CheckDevice()
}
return points.AsUnsafePointer(), outputBases.AsUnsafePointer()
}

View File

@@ -36,19 +36,19 @@ func TestMSMDefaultConfig(t *testing.T) {
func TestMSMCheckHostSlices(t *testing.T) {
cfg := GetDefaultMSMConfig()
randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8}
rawScalars := make([]internal.MockField, 10)
rawScalars := make([]internal.MockBaseField, 10)
for i := range rawScalars {
var emptyField internal.MockField
emptyField.FromLimbs(randLimbs)
var emptyField internal.MockBaseField
emptyField.One()
rawScalars[i] = emptyField
}
scalars := HostSliceFromElements[internal.MockField](rawScalars)
scalars := HostSliceFromElements[internal.MockBaseField](rawScalars)
affine := internal.MockAffine{}
limbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8}
affine.FromLimbs(limbs, limbs)
var emptyField internal.MockBaseField
emptyField.One()
affine.FromLimbs(emptyField.GetLimbs(), emptyField.GetLimbs())
rawAffinePoints := make([]internal.MockAffine, 10)
for i := range rawAffinePoints {
rawAffinePoints[i] = affine
@@ -69,21 +69,21 @@ func TestMSMCheckHostSlices(t *testing.T) {
func TestMSMCheckDeviceSlices(t *testing.T) {
cfg := GetDefaultMSMConfig()
randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8}
rawScalars := make([]internal.MockField, 10)
rawScalars := make([]internal.MockBaseField, 10)
for i := range rawScalars {
var emptyField internal.MockField
emptyField.FromLimbs(randLimbs)
var emptyField internal.MockBaseField
emptyField.One()
rawScalars[i] = emptyField
}
scalars := HostSliceFromElements[internal.MockField](rawScalars)
scalars := HostSliceFromElements[internal.MockBaseField](rawScalars)
var scalarsOnDevice DeviceSlice
scalars.CopyToDevice(&scalarsOnDevice, true)
affine := internal.MockAffine{}
limbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8}
affine.FromLimbs(limbs, limbs)
var emptyField internal.MockBaseField
emptyField.One()
affine.FromLimbs(emptyField.GetLimbs(), emptyField.GetLimbs())
rawAffinePoints := make([]internal.MockAffine, 10)
for i := range rawAffinePoints {
rawAffinePoints[i] = affine

View File

@@ -2,6 +2,7 @@ package core
import (
"fmt"
"unsafe"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
@@ -67,7 +68,7 @@ func GetDefaultNTTConfig[T any](cosetGen T) NTTConfig[T] {
}
}
func NttCheck[T any](input HostOrDeviceSlice, cfg *NTTConfig[T], output HostOrDeviceSlice) {
func NttCheck[T any](input HostOrDeviceSlice, cfg *NTTConfig[T], output HostOrDeviceSlice) (unsafe.Pointer, unsafe.Pointer, int, unsafe.Pointer) {
inputLen, outputLen := input.Len(), output.Len()
if inputLen != outputLen {
errorString := fmt.Sprintf(
@@ -79,4 +80,17 @@ func NttCheck[T any](input HostOrDeviceSlice, cfg *NTTConfig[T], output HostOrDe
}
cfg.areInputsOnDevice = input.IsOnDevice()
cfg.areOutputsOnDevice = output.IsOnDevice()
if input.IsOnDevice() {
input.(DeviceSlice).CheckDevice()
}
if output.IsOnDevice() {
output.(DeviceSlice).CheckDevice()
}
size := input.Len() / int(cfg.BatchSize)
cfgPointer := unsafe.Pointer(cfg)
return input.AsUnsafePointer(), output.AsUnsafePointer(), size, cfgPointer
}

View File

@@ -1,7 +1,6 @@
package core
import (
// "unsafe"
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core/internal"
@@ -10,7 +9,7 @@ import (
)
func TestNTTDefaultConfig(t *testing.T) {
var cosetGenField internal.MockField
var cosetGenField internal.MockBaseField
cosetGenField.One()
var cosetGen [1]uint32
copy(cosetGen[:], cosetGenField.GetLimbs())
@@ -33,56 +32,52 @@ func TestNTTDefaultConfig(t *testing.T) {
}
func TestNTTCheckHostScalars(t *testing.T) {
randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8}
var cosetGen internal.MockField
cosetGen.FromLimbs(randLimbs)
var cosetGen internal.MockBaseField
cosetGen.One()
cfg := GetDefaultNTTConfig(&cosetGen)
rawInput := make([]internal.MockField, 10)
var emptyField internal.MockField
emptyField.FromLimbs(randLimbs)
rawInput := make([]internal.MockBaseField, 10)
var emptyField internal.MockBaseField
emptyField.One()
for i := range rawInput {
rawInput[i] = emptyField
}
input := HostSliceFromElements[internal.MockField](rawInput)
output := HostSliceFromElements[internal.MockField](rawInput)
input := HostSliceFromElements[internal.MockBaseField](rawInput)
output := HostSliceFromElements[internal.MockBaseField](rawInput)
assert.NotPanics(t, func() { NttCheck(input, &cfg, output) })
assert.False(t, cfg.areInputsOnDevice)
assert.False(t, cfg.areOutputsOnDevice)
rawInputLarger := make([]internal.MockField, 11)
rawInputLarger := make([]internal.MockBaseField, 11)
for i := range rawInputLarger {
rawInputLarger[i] = emptyField
}
output2 := HostSliceFromElements[internal.MockField](rawInputLarger)
output2 := HostSliceFromElements[internal.MockBaseField](rawInputLarger)
assert.Panics(t, func() { NttCheck(input, &cfg, output2) })
}
func TestNTTCheckDeviceScalars(t *testing.T) {
randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8}
var cosetGen internal.MockField
cosetGen.FromLimbs(randLimbs)
var cosetGen internal.MockBaseField
cosetGen.One()
cfg := GetDefaultNTTConfig(cosetGen)
fieldBytesSize := 16
numFields := 10
rawInput := make([]internal.MockField, numFields)
rawInput := make([]internal.MockBaseField, numFields)
for i := range rawInput {
var emptyField internal.MockField
emptyField.FromLimbs(randLimbs)
var emptyField internal.MockBaseField
emptyField.One()
rawInput[i] = emptyField
}
hostElements := HostSliceFromElements[internal.MockField](rawInput)
hostElements := HostSliceFromElements[internal.MockBaseField](rawInput)
var input DeviceSlice
hostElements.CopyToDevice(&input, true)
fieldBytesSize := hostElements.SizeOfElement()
var output DeviceSlice
output.Malloc(numFields*fieldBytesSize, fieldBytesSize)

View File

@@ -11,6 +11,7 @@ type HostOrDeviceSlice interface {
Cap() int
IsEmpty() bool
IsOnDevice() bool
AsUnsafePointer() unsafe.Pointer
}
type DevicePointer = unsafe.Pointer
@@ -35,7 +36,7 @@ func (d DeviceSlice) IsEmpty() bool {
return d.length == 0
}
func (d DeviceSlice) AsPointer() unsafe.Pointer {
func (d DeviceSlice) AsUnsafePointer() unsafe.Pointer {
return d.inner
}
@@ -188,6 +189,14 @@ func (h HostSlice[T]) SizeOfElement() int {
return int(unsafe.Sizeof(h[0]))
}
func (h HostSlice[T]) AsPointer() *T {
return &h[0]
}
func (h HostSlice[T]) AsUnsafePointer() unsafe.Pointer {
return unsafe.Pointer(&h[0])
}
func (h HostSlice[T]) CopyToDevice(dst *DeviceSlice, shouldAllocate bool) *DeviceSlice {
size := h.Len() * h.SizeOfElement()
if shouldAllocate {
@@ -198,8 +207,7 @@ func (h HostSlice[T]) CopyToDevice(dst *DeviceSlice, shouldAllocate bool) *Devic
panic("Number of bytes to copy is too large for destination")
}
hostSrc := unsafe.Pointer(&h[0])
cr.CopyToDevice(dst.inner, hostSrc, uint(size))
cr.CopyToDevice(dst.inner, h.AsUnsafePointer(), uint(size))
dst.length = h.Len()
return dst
}
@@ -214,8 +222,7 @@ func (h HostSlice[T]) CopyToDeviceAsync(dst *DeviceSlice, stream cr.CudaStream,
panic("Number of bytes to copy is too large for destination")
}
hostSrc := unsafe.Pointer(&h[0])
cr.CopyToDeviceAsync(dst.inner, hostSrc, uint(size), stream)
cr.CopyToDeviceAsync(dst.inner, h.AsUnsafePointer(), uint(size), stream)
dst.length = h.Len()
return dst
}
@@ -226,7 +233,7 @@ func (h HostSlice[T]) CopyFromDevice(src *DeviceSlice) {
panic("destination and source slices have different lengths")
}
bytesSize := src.Len() * h.SizeOfElement()
cr.CopyFromDevice(unsafe.Pointer(&h[0]), src.inner, uint(bytesSize))
cr.CopyFromDevice(h.AsUnsafePointer(), src.inner, uint(bytesSize))
}
func (h HostSlice[T]) CopyFromDeviceAsync(src *DeviceSlice, stream cr.Stream) {
@@ -235,5 +242,5 @@ func (h HostSlice[T]) CopyFromDeviceAsync(src *DeviceSlice, stream cr.Stream) {
panic("destination and source slices have different lengths")
}
bytesSize := src.Len() * h.SizeOfElement()
cr.CopyFromDeviceAsync(unsafe.Pointer(&h[0]), src.inner, uint(bytesSize), stream)
cr.CopyFromDeviceAsync(h.AsUnsafePointer(), src.inner, uint(bytesSize), stream)
}

View File

@@ -9,20 +9,20 @@ import (
"github.com/stretchr/testify/assert"
)
func randomField(size int) internal.MockField {
func randomField(size int) internal.MockBaseField {
limbs := make([]uint32, size)
for i := range limbs {
limbs[i] = rand.Uint32()
}
var field internal.MockField
var field internal.MockBaseField
field.FromLimbs(limbs)
return field
}
func randomFields(numFields, fieldSize int) []internal.MockField {
var randFields []internal.MockField
func randomFields(numFields, fieldSize int) []internal.MockBaseField {
var randFields []internal.MockBaseField
for i := 0; i < numFields; i++ {
randFields = append(randFields, randomField(fieldSize))
@@ -67,12 +67,12 @@ func randomAffinePoints(numPoints, fieldSize int) []internal.MockAffine {
const (
numPoints = 4
numFields = 4
fieldSize = 8
fieldSize = 4
fieldBytesSize = fieldSize * 4
)
func TestHostSlice(t *testing.T) {
var emptyHostSlice HostSlice[internal.MockField]
var emptyHostSlice HostSlice[internal.MockBaseField]
assert.Equal(t, emptyHostSlice.Len(), 0)
assert.Equal(t, emptyHostSlice.Cap(), 0)
@@ -82,13 +82,13 @@ func TestHostSlice(t *testing.T) {
assert.Equal(t, hostSlice.Len(), 4)
assert.Equal(t, hostSlice.Cap(), 4)
hostSliceCasted := (HostSlice[internal.MockField])(randFields)
hostSliceCasted := (HostSlice[internal.MockBaseField])(randFields)
assert.Equal(t, hostSliceCasted.Len(), 4)
assert.Equal(t, hostSliceCasted.Cap(), 4)
}
func TestHostSliceIsEmpty(t *testing.T) {
var emptyHostSlice HostSlice[*internal.MockField]
var emptyHostSlice HostSlice[*internal.MockBaseField]
assert.True(t, emptyHostSlice.IsEmpty())
randFields := randomFields(numFields, fieldSize)
@@ -98,7 +98,7 @@ func TestHostSliceIsEmpty(t *testing.T) {
}
func TestHostSliceIsOnDevice(t *testing.T) {
var emptyHostSlice HostSlice[*internal.MockField]
var emptyHostSlice HostSlice[*internal.MockBaseField]
assert.False(t, emptyHostSlice.IsOnDevice())
}
@@ -112,17 +112,17 @@ func TestDeviceSlice(t *testing.T) {
var emptyDeviceSlice DeviceSlice
assert.Equal(t, 0, emptyDeviceSlice.Len())
assert.Equal(t, 0, emptyDeviceSlice.Cap())
assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsPointer())
assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsUnsafePointer())
emptyDeviceSlice.Malloc(numFields*fieldBytesSize, fieldBytesSize)
assert.Equal(t, numFields, emptyDeviceSlice.Len())
assert.Equal(t, numFields*fieldBytesSize, emptyDeviceSlice.Cap())
assert.NotEqual(t, unsafe.Pointer(nil), emptyDeviceSlice.AsPointer())
assert.NotEqual(t, unsafe.Pointer(nil), emptyDeviceSlice.AsUnsafePointer())
emptyDeviceSlice.Free()
assert.Equal(t, 0, emptyDeviceSlice.Len())
assert.Equal(t, 0, emptyDeviceSlice.Cap())
assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsPointer())
assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsUnsafePointer())
}
func TestDeviceSliceIsEmpty(t *testing.T) {

View File

@@ -2,6 +2,7 @@ package core
import (
"fmt"
"unsafe"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
@@ -23,8 +24,6 @@ type VecOpsConfig struct {
isBOnDevice bool
/* If true, output is preserved on device, otherwise on host. Default value: false. */
isResultOnDevice bool
/* True if `result` vector should be in Montgomery form and false otherwise. Default value: false. */
IsResultMontgomeryForm bool
/* Whether to run the vector operations asynchronously. If set to `true`, the function will be
* non-blocking and you'll need to synchronize it explicitly by calling
* `SynchronizeStream`. If set to false, the function will block the current CPU thread. */
@@ -42,14 +41,13 @@ func DefaultVecOpsConfig() VecOpsConfig {
false, // isAOnDevice
false, // isBOnDevice
false, // isResultOnDevice
false, // IsResultMontgomeryForm
false, // IsAsync
}
return config
}
func VecOpCheck(a, b, out HostOrDeviceSlice, cfg *VecOpsConfig) {
func VecOpCheck(a, b, out HostOrDeviceSlice, cfg *VecOpsConfig) (unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, unsafe.Pointer, int) {
aLen, bLen, outLen := a.Len(), b.Len(), out.Len()
if aLen != bLen {
errorString := fmt.Sprintf(
@@ -68,7 +66,45 @@ func VecOpCheck(a, b, out HostOrDeviceSlice, cfg *VecOpsConfig) {
panic(errorString)
}
if a.IsOnDevice() {
a.(DeviceSlice).CheckDevice()
}
if b.IsOnDevice() {
b.(DeviceSlice).CheckDevice()
}
if out.IsOnDevice() {
out.(DeviceSlice).CheckDevice()
}
cfg.isAOnDevice = a.IsOnDevice()
cfg.isBOnDevice = b.IsOnDevice()
cfg.isResultOnDevice = out.IsOnDevice()
return a.AsUnsafePointer(), b.AsUnsafePointer(), out.AsUnsafePointer(), unsafe.Pointer(cfg), a.Len()
}
func TransposeCheck(in, out HostOrDeviceSlice, onDevice bool) {
inLen, outLen := in.Len(), out.Len()
if inLen != outLen {
errorString := fmt.Sprintf(
"in and out vector lengths %d; %d are not equal",
inLen,
outLen,
)
panic(errorString)
}
if (onDevice != in.IsOnDevice()) || (onDevice != out.IsOnDevice()) {
errorString := fmt.Sprintf(
"onDevice is set to %t, but in.IsOnDevice():%t and out.IsOnDevice():%t",
onDevice,
in.IsOnDevice(),
out.IsOnDevice(),
)
panic(errorString)
}
if onDevice {
in.(DeviceSlice).CheckDevice()
out.(DeviceSlice).CheckDevice()
}
}

View File

@@ -1,9 +1,10 @@
package core
import (
"testing"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/stretchr/testify/assert"
"testing"
)
func TestVecOpsDefaultConfig(t *testing.T) {
@@ -13,7 +14,6 @@ func TestVecOpsDefaultConfig(t *testing.T) {
false, // isAOnDevice
false, // isBOnDevice
false, // isResultOnDevice
false, // IsResultMontgomeryForm
false, // IsAsync
}

View File

@@ -6,7 +6,7 @@ import (
)
const (
BASE_LIMBS int8 = 12
BASE_LIMBS int = 12
)
type BaseField struct {
@@ -29,6 +29,11 @@ func (f BaseField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *BaseField) FromUint32(v uint32) BaseField {
f.limbs[0] = v
return *f
}
func (f *BaseField) FromLimbs(limbs []uint32) BaseField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")

View File

@@ -1,4 +0,0 @@
package bls12377
// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_bls12_377 -lstdc++ -lm
import "C"

View File

@@ -53,7 +53,7 @@ func (p *Projective) FromAffine(a Affine) Projective {
func (p Projective) ProjectiveEq(p2 *Projective) bool {
cP := (*C.projective_t)(unsafe.Pointer(&p))
cP2 := (*C.projective_t)(unsafe.Pointer(&p2))
__ret := C.bls12_377Eq(cP, cP2)
__ret := C.bls12_377_eq(cP, cP2)
return __ret == (C._Bool)(true)
}
@@ -62,7 +62,7 @@ func (p *Projective) ProjectiveToAffine() Affine {
cA := (*C.affine_t)(unsafe.Pointer(&a))
cP := (*C.projective_t)(unsafe.Pointer(&p))
C.bls12_377ToAffine(cP, cA)
C.bls12_377_to_affine(cP, cA)
return a
}
@@ -75,7 +75,7 @@ func GenerateProjectivePoints(size int) core.HostSlice[Projective] {
pointsSlice := core.HostSliceFromElements[Projective](points)
pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bls12_377GenerateProjectivePoints(pPoints, cSize)
C.bls12_377_generate_projective_points(pPoints, cSize)
return pointsSlice
}
@@ -129,18 +129,18 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] {
pointsSlice := core.HostSliceFromElements[Affine](points)
cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bls12_377GenerateAffinePoints(cPoints, cSize)
C.bls12_377_generate_affine_points(cPoints, cSize)
return pointsSlice
}
func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.affine_t)(points.AsPointer())
cValues := (*C.affine_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_377AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_377_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}
@@ -156,12 +156,12 @@ func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError {
}
func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.projective_t)(points.AsPointer())
cValues := (*C.projective_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_377ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_377_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -0,0 +1,24 @@
package ecntt
// #cgo CFLAGS: -I./include/
// #include "ecntt.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results)
cPoints := (*C.projective_t)(pointsPointer)
cSize := (C.int)(size)
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(cfgPointer)
cResults := (*C.projective_t)(resultsPointer)
__ret := C.bls12_377_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,19 @@
#include <cuda_runtime.h>
#ifndef _BLS12_377_ECNTT_H
#define _BLS12_377_ECNTT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct NTTConfig NTTConfig;
typedef struct projective_t projective_t;
cudaError_t bls12_377_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,9 +1,7 @@
//go:build g2
package bls12381
package g2
// #cgo CFLAGS: -I./include/
// #include "g2_curve.h"
// #include "curve.h"
import "C"
import (
@@ -55,7 +53,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective {
func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool {
cP := (*C.g2_projective_t)(unsafe.Pointer(&p))
cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2))
__ret := C.bls12_381G2Eq(cP, cP2)
__ret := C.bls12_377_g2_eq(cP, cP2)
return __ret == (C._Bool)(true)
}
@@ -64,7 +62,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine {
cA := (*C.g2_affine_t)(unsafe.Pointer(&a))
cP := (*C.g2_projective_t)(unsafe.Pointer(&p))
C.bls12_381G2ToAffine(cP, cA)
C.bls12_377_g2_to_affine(cP, cA)
return a
}
@@ -77,7 +75,7 @@ func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] {
pointsSlice := core.HostSliceFromElements[G2Projective](points)
pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bls12_381G2GenerateProjectivePoints(pPoints, cSize)
C.bls12_377_g2_generate_projective_points(pPoints, cSize)
return pointsSlice
}
@@ -131,18 +129,18 @@ func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] {
pointsSlice := core.HostSliceFromElements[G2Affine](points)
cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bls12_381G2GenerateAffinePoints(cPoints, cSize)
C.bls12_377_g2_generate_affine_points(cPoints, cSize)
return pointsSlice
}
func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.g2_affine_t)(points.AsPointer())
cValues := (*C.g2_affine_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_381G2AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_377_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}
@@ -158,12 +156,12 @@ func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError {
}
func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.g2_projective_t)(points.AsPointer())
cValues := (*C.g2_projective_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_381G2ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_377_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,6 +1,4 @@
//go:build g2
package bn254
package g2
import (
"encoding/binary"
@@ -8,19 +6,19 @@ import (
)
const (
G2_BASE_LIMBS int8 = 16
G2BASE_LIMBS int = 24
)
type G2BaseField struct {
limbs [G2_BASE_LIMBS]uint32
limbs [G2BASE_LIMBS]uint32
}
func (f G2BaseField) Len() int {
return int(G2_BASE_LIMBS)
return int(G2BASE_LIMBS)
}
func (f G2BaseField) Size() int {
return int(G2_BASE_LIMBS * 4)
return int(G2BASE_LIMBS * 4)
}
func (f G2BaseField) GetLimbs() []uint32 {
@@ -31,6 +29,11 @@ func (f G2BaseField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *G2BaseField) FromUint32(v uint32) G2BaseField {
f.limbs[0] = v
return *f
}
func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")

View File

@@ -0,0 +1,26 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_G2CURVE_H
#define _BLS12_377_G2CURVE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct g2_projective_t g2_projective_t;
typedef struct g2_affine_t g2_affine_t;
typedef struct DeviceContext DeviceContext;
bool bls12_377_g2_eq(g2_projective_t* point1, g2_projective_t* point2);
void bls12_377_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out);
void bls12_377_g2_generate_projective_points(g2_projective_t* points, int size);
void bls12_377_g2_generate_affine_points(g2_affine_t* points, int size);
cudaError_t bls12_377_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_377_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,24 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_G2MSM_H
#define _BLS12_377_G2MSM_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct g2_projective_t g2_projective_t;
typedef struct g2_affine_t g2_affine_t;
typedef struct MSMConfig MSMConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_377_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bls12_377_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,21 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_FIELD_H
#define _BLS12_377_FIELD_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct DeviceContext DeviceContext;
void bls12_377_generate_scalars(scalar_t* scalars, int size);
cudaError_t bls12_377_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
package g2
// #cgo CFLAGS: -I./include/
// #include "msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results)
cScalars := (*C.scalar_t)(scalarsPointer)
cPoints := (*C.g2_affine_t)(pointsPointer)
cResults := (*C.g2_projective_t)(resultsPointer)
cSize := (C.int)(size)
cCfg := (*C.MSMConfig)(cfgPointer)
__ret := C.bls12_377_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bls12_377_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,82 +0,0 @@
//go:build g2
package bls12377
// #cgo CFLAGS: -I./include/
// #include "g2_msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
core.MsmCheck(scalars, points, cfg, results)
var scalarsPointer unsafe.Pointer
if scalars.IsOnDevice() {
scalarsDevice := scalars.(core.DeviceSlice)
scalarsDevice.CheckDevice()
scalarsPointer = scalarsDevice.AsPointer()
} else {
scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0])
}
cScalars := (*C.scalar_t)(scalarsPointer)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsDevice := points.(core.DeviceSlice)
pointsDevice.CheckDevice()
pointsPointer = pointsDevice.AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0])
}
cPoints := (*C.g2_affine_t)(pointsPointer)
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsDevice := results.(core.DeviceSlice)
resultsDevice.CheckDevice()
resultsPointer = resultsDevice.AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[G2Projective])[0])
}
cResults := (*C.g2_projective_t)(resultsPointer)
cSize := (C.int)(scalars.Len() / results.Len())
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
__ret := C.bls12_377G2MSMCuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsPointer = points.(core.DeviceSlice).AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0])
}
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
outputBasesPointer := outputBases.AsPointer()
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bls12_377G2PrecomputeMSMBases(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,31 +0,0 @@
package bls12377
import (
"math/rand"
)
func generateRandomLimb(size int) []uint32 {
limbs := make([]uint32, size)
for i := range limbs {
limbs[i] = rand.Uint32()
}
return limbs
}
func generateLimbOne(size int) []uint32 {
limbs := make([]uint32, size)
limbs[0] = 1
return limbs
}
func generateBytesArray(size int) ([]byte, []uint32) {
baseBytes := []byte{1, 2, 3, 4}
var bytes []byte
var limbs []uint32
for i := 0; i < size; i++ {
bytes = append(bytes, baseBytes...)
limbs = append(limbs, 67305985)
}
return bytes, limbs
}

View File

@@ -1,5 +1,4 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_CURVE_H
@@ -9,12 +8,16 @@
extern "C" {
#endif
bool bls12_377Eq(projective_t* point1, projective_t* point2);
void bls12_377ToAffine(projective_t* point, affine_t* point_out);
void bls12_377GenerateProjectivePoints(projective_t* points, int size);
void bls12_377GenerateAffinePoints(affine_t* points, int size);
cudaError_t bls12_377AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_377ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
typedef struct projective_t projective_t;
typedef struct affine_t affine_t;
typedef struct DeviceContext DeviceContext;
bool bls12_377_eq(projective_t* point1, projective_t* point2);
void bls12_377_to_affine(projective_t* point, affine_t* point_out);
void bls12_377_generate_projective_points(projective_t* points, int size);
void bls12_377_generate_affine_points(affine_t* points, int size);
cudaError_t bls12_377_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_377_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}

View File

@@ -1,23 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_G2CURVE_H
#define _BLS12_377_G2CURVE_H
#ifdef __cplusplus
extern "C" {
#endif
bool bls12_377G2Eq(g2_projective_t* point1, g2_projective_t* point2);
void bls12_377G2ToAffine(g2_projective_t* point, g2_affine_t* point_out);
void bls12_377G2GenerateProjectivePoints(g2_projective_t* points, int size);
void bls12_377G2GenerateAffinePoints(g2_affine_t* points, int size);
cudaError_t bls12_377G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_377G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,19 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_G2MSM_H
#define _BLS12_377_G2MSM_H
#ifdef __cplusplus
extern "C" {
#endif
cudaError_t bls12_377G2MSMCuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bls12_377G2PrecomputeMSMBases(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,19 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_MSM_H
#define _BLS12_377_MSM_H
#ifdef __cplusplus
extern "C" {
#endif
cudaError_t bls12_377MSMCuda(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bls12_377PrecomputeMSMBases(affine_t* points, int bases_size, int precompute_factor, int _c, bool are_bases_on_device, DeviceContext* ctx, affine_t* output_bases);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,21 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_NTT_H
#define _BLS12_377_NTT_H
#ifdef __cplusplus
extern "C" {
#endif
cudaError_t bls12_377NTTCuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output);
cudaError_t bls12_377ECNTTCuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output);
cudaError_t bls12_377InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles);
cudaError_t bls12_377ReleaseDomain(DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,5 +1,4 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_FIELD_H
@@ -9,8 +8,11 @@
extern "C" {
#endif
void bls12_377GenerateScalars(scalar_t* scalars, int size);
cudaError_t bls12_377ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx);
typedef struct scalar_t scalar_t;
typedef struct DeviceContext DeviceContext;
void bls12_377_generate_scalars(scalar_t* scalars, int size);
cudaError_t bls12_377_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}

View File

@@ -0,0 +1,4 @@
package bls12377
// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bls12_377 -lingo_field_bls12_377 -lstdc++ -lm
import "C"

View File

@@ -1,80 +0,0 @@
package bls12377
// #cgo CFLAGS: -I./include/
// #include "msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
core.MsmCheck(scalars, points, cfg, results)
var scalarsPointer unsafe.Pointer
if scalars.IsOnDevice() {
scalarsDevice := scalars.(core.DeviceSlice)
scalarsDevice.CheckDevice()
scalarsPointer = scalarsDevice.AsPointer()
} else {
scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0])
}
cScalars := (*C.scalar_t)(scalarsPointer)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsDevice := points.(core.DeviceSlice)
pointsDevice.CheckDevice()
pointsPointer = pointsDevice.AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0])
}
cPoints := (*C.affine_t)(pointsPointer)
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsDevice := results.(core.DeviceSlice)
resultsDevice.CheckDevice()
resultsPointer = resultsDevice.AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0])
}
cResults := (*C.projective_t)(resultsPointer)
cSize := (C.int)(scalars.Len() / results.Len())
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
__ret := C.bls12_377MSMCuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsPointer = points.(core.DeviceSlice).AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0])
}
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
outputBasesPointer := outputBases.AsPointer()
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bls12_377PrecomputeMSMBases(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -0,0 +1,24 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_MSM_H
#define _BLS12_377_MSM_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct projective_t projective_t;
typedef struct affine_t affine_t;
typedef struct MSMConfig MSMConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_377_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bls12_377_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
package msm
// #cgo CFLAGS: -I./include/
// #include "msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results)
cScalars := (*C.scalar_t)(scalarsPointer)
cPoints := (*C.affine_t)(pointsPointer)
cResults := (*C.projective_t)(resultsPointer)
cSize := (C.int)(size)
cCfg := (*C.MSMConfig)(cfgPointer)
__ret := C.bls12_377_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bls12_377_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,97 +0,0 @@
package bls12377
// #cgo CFLAGS: -I./include/
// #include "ntt.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] {
cosetGenField := ScalarField{}
cosetGenField.One()
var cosetGen [SCALAR_LIMBS]uint32
for i, v := range cosetGenField.GetLimbs() {
cosetGen[i] = v
}
return core.GetDefaultNTTConfig(cosetGen)
}
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
core.NttCheck[T](scalars, cfg, results)
var scalarsPointer unsafe.Pointer
if scalars.IsOnDevice() {
scalarsDevice := scalars.(core.DeviceSlice)
scalarsDevice.CheckDevice()
scalarsPointer = scalarsDevice.AsPointer()
} else {
scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0])
}
cScalars := (*C.scalar_t)(scalarsPointer)
cSize := (C.int)(scalars.Len() / int(cfg.BatchSize))
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg))
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsDevice := results.(core.DeviceSlice)
resultsDevice.CheckDevice()
resultsPointer = resultsDevice.AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0])
}
cResults := (*C.scalar_t)(resultsPointer)
__ret := C.bls12_377NTTCuda(cScalars, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
core.NttCheck[T](points, cfg, results)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsPointer = points.(core.DeviceSlice).AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Projective])[0])
}
cPoints := (*C.projective_t)(pointsPointer)
cSize := (C.int)(points.Len() / int(cfg.BatchSize))
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg))
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsPointer = results.(core.DeviceSlice).AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0])
}
cResults := (*C.projective_t)(resultsPointer)
__ret := C.bls12_377ECNTTCuda(cPoints, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError {
cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer()))
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cFastTwiddles := (C._Bool)(fastTwiddles)
__ret := C.bls12_377InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError {
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
__ret := C.bls12_377ReleaseDomain(cCtx)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,23 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_NTT_H
#define _BLS12_377_NTT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct NTTConfig NTTConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_377_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output);
cudaError_t bls12_377_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles);
cudaError_t bls12_377_release_domain(DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,56 @@
package ntt
// #cgo CFLAGS: -I./include/
// #include "ntt.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
bls12_377 "github.com/ingonyama-zk/icicle/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)
cScalars := (*C.scalar_t)(scalarsPointer)
cSize := (C.int)(size)
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(cfgPointer)
cResults := (*C.scalar_t)(resultsPointer)
__ret := C.bls12_377_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func GetDefaultNttConfig() core.NTTConfig[[bls12_377.SCALAR_LIMBS]uint32] {
cosetGenField := bls12_377.ScalarField{}
cosetGenField.One()
var cosetGen [bls12_377.SCALAR_LIMBS]uint32
for i, v := range cosetGenField.GetLimbs() {
cosetGen[i] = v
}
return core.GetDefaultNTTConfig(cosetGen)
}
func InitDomain(primitiveRoot bls12_377.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError {
cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer()))
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cFastTwiddles := (C._Bool)(fastTwiddles)
__ret := C.bls12_377_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError {
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
__ret := C.bls12_377_release_domain(cCtx)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,51 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_377_POLY_H
#define _BLS12_377_POLY_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PolynomialInst PolynomialInst;
typedef struct IntegrityPointer IntegrityPointer;
bool bls12_377_polynomial_init_cuda_backend();
PolynomialInst* bls12_377_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size);
PolynomialInst* bls12_377_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size);
PolynomialInst* bls12_377_polynomial_clone(const PolynomialInst* p);
void bls12_377_polynomial_print(PolynomialInst* p);
void bls12_377_polynomial_delete(PolynomialInst* instance);
PolynomialInst* bls12_377_polynomial_add(const PolynomialInst* a, const PolynomialInst* b);
void bls12_377_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_377_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_377_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_377_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar);
void bls12_377_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/);
PolynomialInst* bls12_377_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_377_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_377_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree);
void bls12_377_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial);
void bls12_377_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial);
void bls12_377_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/);
size_t bls12_377_polynomial_degree(PolynomialInst* p);
size_t bls12_377_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx);
PolynomialInst* bls12_377_polynomial_even(PolynomialInst* p);
PolynomialInst* bls12_377_polynomial_odd(PolynomialInst* p);
// scalar_t* bls12_377_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/);
// PolynomialInst* bls12_377_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size);
// IntegrityPointer* bls12_377_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/);
// IntegrityPointer* bls12_377_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/);
// const scalar_t* bls12_377_polynomial_intergrity_ptr_get(IntegrityPointer* p);
// bool bls12_377_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p);
// void bls12_377_polynomial_intergrity_ptr_destroy(IntegrityPointer* p);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,176 @@
package polynomial
// #cgo CFLAGS: -I./include/
// #include "polynomial.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
)
type PolynomialHandle = C.struct_PolynomialInst
type DensePolynomial struct {
handle *PolynomialHandle
}
func InitPolyBackend() bool {
return (bool)(C.bls12_377_polynomial_init_cuda_backend())
}
func (up *DensePolynomial) Print() {
C.bls12_377_polynomial_print(up.handle)
}
func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial {
if coeffs.IsOnDevice() {
coeffs.(core.DeviceSlice).CheckDevice()
}
coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer())
cSize := (C.size_t)(coeffs.Len())
up.handle = C.bls12_377_polynomial_create_from_coefficients(coeffsPointer, cSize)
return *up
}
func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial {
evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer())
cSize := (C.size_t)(evals.Len())
up.handle = C.bls12_377_polynomial_create_from_coefficients(evalsPointer, cSize)
return *up
}
func (up *DensePolynomial) Clone() DensePolynomial {
return DensePolynomial{
handle: C.bls12_377_polynomial_clone(up.handle),
}
}
// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions?
func (up *DensePolynomial) Delete() {
C.bls12_377_polynomial_delete(up.handle)
}
func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_377_polynomial_add(up.handle, b.handle),
}
}
func (up *DensePolynomial) AddInplace(b *DensePolynomial) {
C.bls12_377_polynomial_add_inplace(up.handle, b.handle)
}
func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_377_polynomial_subtract(up.handle, b.handle),
}
}
func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_377_polynomial_multiply(up.handle, b.handle),
}
}
func (up *DensePolynomial) MultiplyByScalar(scalar bls12_377.ScalarField) DensePolynomial {
cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer()))
return DensePolynomial{
handle: C.bls12_377_polynomial_multiply_by_scalar(up.handle, cScalar),
}
}
func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) {
var q, r *PolynomialHandle
C.bls12_377_polynomial_division(up.handle, b.handle, &q, &r)
return DensePolynomial{
handle: q,
}, DensePolynomial{
handle: r,
}
}
func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_377_polynomial_quotient(up.handle, b.handle),
}
}
func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_377_polynomial_remainder(up.handle, b.handle),
}
}
func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial {
cVanishingDegree := (C.ulong)(vanishing_degree)
return DensePolynomial{
handle: C.bls12_377_polynomial_divide_by_vanishing(up.handle, cVanishingDegree),
}
}
func (up *DensePolynomial) AddMonomial(monomialCoeff bls12_377.ScalarField, monomial uint64) DensePolynomial {
hs := core.HostSliceFromElements([]bls12_377.ScalarField{monomialCoeff})
cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer())
cMonomial := (C.ulong)(monomial)
C.bls12_377_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial)
return *up
}
func (up *DensePolynomial) SubMonomial(monomialCoeff bls12_377.ScalarField, monomial uint64) DensePolynomial {
hs := core.HostSliceFromElements([]bls12_377.ScalarField{monomialCoeff})
cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer())
cMonomial := (C.ulong)(monomial)
C.bls12_377_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial)
return *up
}
func (up *DensePolynomial) Eval(x bls12_377.ScalarField) bls12_377.ScalarField {
domains := make(core.HostSlice[bls12_377.ScalarField], 1)
domains[0] = x
evals := make(core.HostSlice[bls12_377.ScalarField], 1)
up.EvalOnDomain(domains, evals)
return evals[0]
}
func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice {
cDomain := (*C.scalar_t)(domain.AsUnsafePointer())
cDomainSize := (C.size_t)(domain.Len())
cEvals := (*C.scalar_t)(evals.AsUnsafePointer())
C.bls12_377_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals)
return evals
}
func (up *DensePolynomial) Degree() int {
return int(C.bls12_377_polynomial_degree(up.handle))
}
func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) {
cStart := (C.size_t)(start)
cEnd := (C.size_t)(end)
cScalarOut := (*C.scalar_t)(out.AsUnsafePointer())
__cNumCoeffsRead := C.bls12_377_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd)
return int(__cNumCoeffsRead), out
}
func (up *DensePolynomial) GetCoeff(idx int) bls12_377.ScalarField {
out := make(core.HostSlice[bls12_377.ScalarField], 1)
up.CopyCoeffsRange(idx, idx, out)
return out[0]
}
func (up *DensePolynomial) Even() DensePolynomial {
evenPoly := C.bls12_377_polynomial_even(up.handle)
return DensePolynomial{
handle: evenPoly,
}
}
func (up *DensePolynomial) Odd() DensePolynomial {
oddPoly := C.bls12_377_polynomial_odd(up.handle)
return DensePolynomial{
handle: oddPoly,
}
}

View File

@@ -12,7 +12,7 @@ import (
)
const (
SCALAR_LIMBS int8 = 8
SCALAR_LIMBS int = 8
)
type ScalarField struct {
@@ -35,6 +35,11 @@ func (f ScalarField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *ScalarField) FromUint32(v uint32) ScalarField {
f.limbs[0] = v
return *f
}
func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")
@@ -89,18 +94,18 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] {
cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0]))
cSize := (C.int)(size)
C.bls12_377GenerateScalars(cScalars, cSize)
C.bls12_377_generate_scalars(cScalars, cSize)
return scalarSlice
}
func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.scalar_t)(scalars.AsPointer())
cValues := (*C.scalar_t)(scalars.AsUnsafePointer())
cSize := (C.size_t)(scalars.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_377ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_377_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,34 +1,40 @@
package bw6761
package tests
import (
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (
BASE_LIMBS = bls12_377.BASE_LIMBS
)
func TestBaseFieldFromLimbs(t *testing.T) {
emptyField := BaseField{}
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField := bls12_377.BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the BaseField's limbs")
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.limbs)
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}
func TestBaseFieldGetLimbs(t *testing.T) {
emptyField := BaseField{}
randLimbs := generateRandomLimb(int(BASE_LIMBS))
emptyField := bls12_377.BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
}
func TestBaseFieldOne(t *testing.T) {
var emptyField BaseField
var emptyField bls12_377.BaseField
emptyField.One()
limbOne := generateLimbOne(int(BASE_LIMBS))
limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
@@ -36,12 +42,12 @@ func TestBaseFieldOne(t *testing.T) {
}
func TestBaseFieldZero(t *testing.T) {
var emptyField BaseField
var emptyField bls12_377.BaseField
emptyField.Zero()
limbsZero := make([]uint32, BASE_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
@@ -49,24 +55,24 @@ func TestBaseFieldZero(t *testing.T) {
}
func TestBaseFieldSize(t *testing.T) {
var emptyField BaseField
randLimbs := generateRandomLimb(int(BASE_LIMBS))
var emptyField bls12_377.BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestBaseFieldAsPointer(t *testing.T) {
var emptyField BaseField
randLimbs := generateRandomLimb(int(BASE_LIMBS))
var emptyField bls12_377.BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestBaseFieldFromBytes(t *testing.T) {
var emptyField BaseField
bytes, expected := generateBytesArray(int(BASE_LIMBS))
var emptyField bls12_377.BaseField
bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
@@ -74,8 +80,8 @@ func TestBaseFieldFromBytes(t *testing.T) {
}
func TestBaseFieldToBytes(t *testing.T) {
var emptyField BaseField
expected, limbs := generateBytesArray(int(BASE_LIMBS))
var emptyField bls12_377.BaseField
expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")

View File

@@ -1,20 +1,22 @@
package bn254
package tests
import (
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {
var fieldZero = BaseField{}
var fieldZero = bls12_377.BaseField{}
var affineZero Affine
var affineZero bls12_377.Affine
assert.Equal(t, affineZero.X, fieldZero)
assert.Equal(t, affineZero.Y, fieldZero)
x := generateRandomLimb(int(BASE_LIMBS))
y := generateRandomLimb(int(BASE_LIMBS))
var affine Affine
x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var affine bls12_377.Affine
affine.FromLimbs(x, y)
affine.Zero()
@@ -23,10 +25,10 @@ func TestAffineZero(t *testing.T) {
}
func TestAffineFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var affine Affine
var affine bls12_377.Affine
affine.FromLimbs(randLimbs, randLimbs2)
assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs())
@@ -34,15 +36,15 @@ func TestAffineFromLimbs(t *testing.T) {
}
func TestAffineToProjective(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
var fieldOne BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var fieldOne bls12_377.BaseField
fieldOne.One()
var expected Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var expected bls12_377.Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine Affine
var affine bls12_377.Affine
affine.FromLimbs(randLimbs, randLimbs2)
projectivePoint := affine.ToProjective()
@@ -50,18 +52,18 @@ func TestAffineToProjective(t *testing.T) {
}
func TestProjectiveZero(t *testing.T) {
var projectiveZero Projective
var projectiveZero bls12_377.Projective
projectiveZero.Zero()
var fieldZero = BaseField{}
var fieldOne BaseField
var fieldZero = bls12_377.BaseField{}
var fieldOne bls12_377.BaseField
fieldOne.One()
assert.Equal(t, projectiveZero.X, fieldZero)
assert.Equal(t, projectiveZero.Y, fieldOne)
assert.Equal(t, projectiveZero.Z, fieldZero)
randLimbs := generateRandomLimb(int(BASE_LIMBS))
var projective Projective
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var projective bls12_377.Projective
projective.FromLimbs(randLimbs, randLimbs, randLimbs)
projective.Zero()
@@ -71,11 +73,11 @@ func TestProjectiveZero(t *testing.T) {
}
func TestProjectiveFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
randLimbs3 := generateRandomLimb(int(BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var projective Projective
var projective bls12_377.Projective
projective.FromLimbs(randLimbs, randLimbs2, randLimbs3)
assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs())
@@ -84,18 +86,18 @@ func TestProjectiveFromLimbs(t *testing.T) {
}
func TestProjectiveFromAffine(t *testing.T) {
randLimbs := generateRandomLimb(int(BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(BASE_LIMBS))
var fieldOne BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var fieldOne bls12_377.BaseField
fieldOne.One()
var expected Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var expected bls12_377.Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine Affine
var affine bls12_377.Affine
affine.FromLimbs(randLimbs, randLimbs2)
var projectivePoint Projective
var projectivePoint bls12_377.Projective
projectivePoint.FromAffine(affine)
assert.Equal(t, expected, projectivePoint)
}

View File

@@ -0,0 +1,30 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
ecntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/ecntt"
ntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/ntt"
"github.com/stretchr/testify/assert"
)
func TestECNtt(t *testing.T) {
cfg := ntt.GetDefaultNttConfig()
points := bls12_377.GenerateProjectivePoints(1 << largestTestSize)
for _, size := range []int{4, 5, 6, 7, 8} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
pointsCopy := core.HostSliceFromElements[bls12_377.Projective](points[:testSize])
cfg.Ordering = v
cfg.NttAlgorithm = core.Radix2
output := make(core.HostSlice[bls12_377.Projective], testSize)
e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output)
assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed")
}
}
}

View File

@@ -1,22 +1,22 @@
//go:build g2
package bw6761
package tests
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/g2"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestG2AffineZero(t *testing.T) {
var fieldZero = G2BaseField{}
var fieldZero = g2.G2BaseField{}
var affineZero G2Affine
var affineZero g2.G2Affine
assert.Equal(t, affineZero.X, fieldZero)
assert.Equal(t, affineZero.Y, fieldZero)
x := generateRandomLimb(int(G2_BASE_LIMBS))
y := generateRandomLimb(int(G2_BASE_LIMBS))
var affine G2Affine
x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var affine g2.G2Affine
affine.FromLimbs(x, y)
affine.Zero()
@@ -25,10 +25,10 @@ func TestG2AffineZero(t *testing.T) {
}
func TestG2AffineFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var affine G2Affine
var affine g2.G2Affine
affine.FromLimbs(randLimbs, randLimbs2)
assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs())
@@ -36,15 +36,15 @@ func TestG2AffineFromLimbs(t *testing.T) {
}
func TestG2AffineToProjective(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
var fieldOne G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var fieldOne g2.G2BaseField
fieldOne.One()
var expected G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var expected g2.G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine G2Affine
var affine g2.G2Affine
affine.FromLimbs(randLimbs, randLimbs2)
projectivePoint := affine.ToProjective()
@@ -52,18 +52,18 @@ func TestG2AffineToProjective(t *testing.T) {
}
func TestG2ProjectiveZero(t *testing.T) {
var projectiveZero G2Projective
var projectiveZero g2.G2Projective
projectiveZero.Zero()
var fieldZero = G2BaseField{}
var fieldOne G2BaseField
var fieldZero = g2.G2BaseField{}
var fieldOne g2.G2BaseField
fieldOne.One()
assert.Equal(t, projectiveZero.X, fieldZero)
assert.Equal(t, projectiveZero.Y, fieldOne)
assert.Equal(t, projectiveZero.Z, fieldZero)
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
var projective G2Projective
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var projective g2.G2Projective
projective.FromLimbs(randLimbs, randLimbs, randLimbs)
projective.Zero()
@@ -73,11 +73,11 @@ func TestG2ProjectiveZero(t *testing.T) {
}
func TestG2ProjectiveFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs3 := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var projective G2Projective
var projective g2.G2Projective
projective.FromLimbs(randLimbs, randLimbs2, randLimbs3)
assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs())
@@ -86,18 +86,18 @@ func TestG2ProjectiveFromLimbs(t *testing.T) {
}
func TestG2ProjectiveFromAffine(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
var fieldOne G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var fieldOne g2.G2BaseField
fieldOne.One()
var expected G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var expected g2.G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine G2Affine
var affine g2.G2Affine
affine.FromLimbs(randLimbs, randLimbs2)
var projectivePoint G2Projective
var projectivePoint g2.G2Projective
projectivePoint.FromAffine(affine)
assert.Equal(t, expected, projectivePoint)
}

View File

@@ -1,36 +1,40 @@
//go:build g2
package bn254
package tests
import (
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/g2"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (
G2BASE_LIMBS = bls12_377.G2BASE_LIMBS
)
func TestG2BaseFieldFromLimbs(t *testing.T) {
emptyField := G2BaseField{}
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
emptyField := bls12_377.G2BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the G2BaseField's limbs")
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.limbs)
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}
func TestG2BaseFieldGetLimbs(t *testing.T) {
emptyField := G2BaseField{}
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
emptyField := bls12_377.G2BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs")
}
func TestG2BaseFieldOne(t *testing.T) {
var emptyField G2BaseField
var emptyField bls12_377.G2BaseField
emptyField.One()
limbOne := generateLimbOne(int(G2_BASE_LIMBS))
limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
@@ -38,12 +42,12 @@ func TestG2BaseFieldOne(t *testing.T) {
}
func TestG2BaseFieldZero(t *testing.T) {
var emptyField G2BaseField
var emptyField bls12_377.G2BaseField
emptyField.Zero()
limbsZero := make([]uint32, G2_BASE_LIMBS)
limbsZero := make([]uint32, G2BASE_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
@@ -51,24 +55,24 @@ func TestG2BaseFieldZero(t *testing.T) {
}
func TestG2BaseFieldSize(t *testing.T) {
var emptyField G2BaseField
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
var emptyField bls12_377.G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestG2BaseFieldAsPointer(t *testing.T) {
var emptyField G2BaseField
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
var emptyField bls12_377.G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestG2BaseFieldFromBytes(t *testing.T) {
var emptyField G2BaseField
bytes, expected := generateBytesArray(int(G2_BASE_LIMBS))
var emptyField bls12_377.G2BaseField
bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
@@ -76,8 +80,8 @@ func TestG2BaseFieldFromBytes(t *testing.T) {
}
func TestG2BaseFieldToBytes(t *testing.T) {
var emptyField G2BaseField
expected, limbs := generateBytesArray(int(G2_BASE_LIMBS))
var emptyField bls12_377.G2BaseField
expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")

View File

@@ -1,6 +1,4 @@
//go:build g2
package bls12377
package tests
import (
"fmt"
@@ -9,16 +7,18 @@ import (
"github.com/stretchr/testify/assert"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bls12-377"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
icicleBls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/g2"
)
func projectiveToGnarkAffineG2(p G2Projective) bls12377.G2Affine {
func projectiveToGnarkAffineG2(p g2.G2Projective) bls12377.G2Affine {
pxBytes := p.X.ToBytesLittleEndian()
pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes]))
pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:]))
@@ -62,7 +62,7 @@ func projectiveToGnarkAffineG2(p G2Projective) bls12377.G2Affine {
return *g2Affine.FromJacobian(&g2Jac)
}
func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points core.HostSlice[G2Affine], out G2Projective) bool {
func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool {
scalarsFr := make([]fr.Element, len(scalars))
for i, v := range scalars {
slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian()))
@@ -73,6 +73,11 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points cor
for i, v := range points {
pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective())
}
return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out)
}
func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G2Affine], out g2.G2Projective) bool {
var msmRes bls12377.G2Jac
msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{})
@@ -83,54 +88,117 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points cor
return msmRes.Equal(&icicleResAsJac)
}
func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12377.G2Affine {
points := make([]bls12377.G2Affine, len(iciclePoints))
for index, iciclePoint := range iciclePoints {
xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian())
xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes])
xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:])
xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes)
xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes)
yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian())
yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes])
yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:])
yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes)
yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes)
points[index] = bls12377.G2Affine{
X: bls12377.E2{
A0: xA0Elem,
A1: xA1Elem,
},
Y: bls12377.E2{
A0: yA0Elem,
A1: yA1Elem,
},
}
}
return points
}
func TestMSMG2(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := G2GenerateAffinePoints(size)
scalars := icicleBls12_377.GenerateScalars(size)
points := g2.G2GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], 1)
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)
cr.SynchronizeStream(&stream)
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0]))
}
}
func TestMSMG2GnarkCryptoTypes(t *testing.T) {
cfg := g2.G2GetDefaultMSMConfig()
for _, power := range []int{3} {
size := 1 << power
scalars := make([]fr.Element, size)
var x fr.Element
for i := 0; i < size; i++ {
x.SetRandom()
scalars[i] = x
}
scalarsHost := (core.HostSlice[fr.Element])(scalars)
points := g2.G2GenerateAffinePoints(size)
pointsGnark := convertIcicleG2AffineToG2Affine(points)
pointsHost := (core.HostSlice[bls12377.G2Affine])(pointsGnark)
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.ArePointsMontgomeryForm = true
cfg.AreScalarsMontgomeryForm = true
e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0]))
}
}
func TestMSMG2Batch(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := G2GenerateAffinePoints(totalSize)
scalars := icicleBls12_377.GenerateScalars(totalSize)
points := g2.G2GenerateAffinePoints(totalSize)
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], batchSize)
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -143,36 +211,35 @@ func TestMSMG2Batch(t *testing.T) {
}
func TestPrecomputeBaseG2(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
const precomputeFactor = 8
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := G2GenerateAffinePoints(totalSize)
scalars := icicleBls12_377.GenerateScalars(totalSize)
points := g2.G2GenerateAffinePoints(totalSize)
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
e = G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
e = g2.G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
e = G2Msm(scalars, precomputeOut, &cfg, out)
e = g2.G2Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], batchSize)
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
precomputeOut.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -185,30 +252,29 @@ func TestPrecomputeBaseG2(t *testing.T) {
}
func TestMSMG2SkewedDistribution(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
scalars := icicleBls12_377.GenerateScalars(size)
for i := size / 4; i < size; i++ {
scalars[i].One()
}
points := G2GenerateAffinePoints(size)
points := g2.G2GenerateAffinePoints(size)
for i := 0; i < size/4; i++ {
points[i].Zero()
}
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], 1)
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0]))
}
@@ -225,23 +291,23 @@ func TestMSMG2MultiDevice(t *testing.T) {
wg.Add(1)
cr.RunOnDevice(i, func(args ...any) {
defer wg.Done()
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := G2GenerateAffinePoints(size)
scalars := icicleBls12_377.GenerateScalars(size)
points := g2.G2GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], 1)
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)

View File

@@ -0,0 +1,48 @@
package tests
import (
"os"
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
ntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/ntt"
poly "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/polynomial"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft"
)
const (
largestTestSize = 20
)
func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError {
rouMont, _ := fft.Generator(uint64(1 << largestTestSize))
rou := rouMont.Bits()
rouIcicle := bls12_377.ScalarField{}
limbs := core.ConvertUint64ArrToUint32Arr(rou[:])
rouIcicle.FromLimbs(limbs)
e := ntt.InitDomain(rouIcicle, cfg.Ctx, false)
return e
}
func TestMain(m *testing.M) {
poly.InitPolyBackend()
// setup domain
cfg := ntt.GetDefaultNttConfig()
e := initDomain(largestTestSize, cfg)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("initDomain failed")
}
// execute tests
os.Exit(m.Run())
// release domain
e = ntt.ReleaseDomain(cfg.Ctx)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("ReleaseDomain failed")
}
}

View File

@@ -1,4 +1,4 @@
package bls12377
package tests
import (
"fmt"
@@ -7,16 +7,18 @@ import (
"github.com/stretchr/testify/assert"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bls12-377"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
icicleBls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/msm"
)
func projectiveToGnarkAffine(p Projective) bls12377.G1Affine {
func projectiveToGnarkAffine(p icicleBls12_377.Projective) bls12377.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()))
@@ -33,7 +35,7 @@ func projectiveToGnarkAffine(p Projective) bls12377.G1Affine {
return bls12377.G1Affine{X: *x, Y: *y}
}
func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.HostSlice[Affine], out Projective) bool {
func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_377.ScalarField], points core.HostSlice[icicleBls12_377.Affine], out icicleBls12_377.Projective) bool {
scalarsFr := make([]fr.Element, len(scalars))
for i, v := range scalars {
slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian()))
@@ -44,6 +46,11 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.
for i, v := range points {
pointsFp[i] = projectiveToGnarkAffine(v.ToProjective())
}
return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out)
}
func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12377.G1Affine], out icicleBls12_377.Projective) bool {
var msmRes bls12377.G1Jac
msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{})
@@ -54,54 +61,104 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.
return msmRes.Equal(&icicleResAsJac)
}
func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_377.Affine) []bls12377.G1Affine {
points := make([]bls12377.G1Affine, len(iciclePoints))
for index, iciclePoint := range iciclePoints {
xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian())
fpXElem, _ := fp.LittleEndian.Element(&xBytes)
yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian())
fpYElem, _ := fp.LittleEndian.Element(&yBytes)
points[index] = bls12377.G1Affine{
X: fpXElem,
Y: fpYElem,
}
}
return points
}
func TestMSM(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := GenerateAffinePoints(size)
scalars := icicleBls12_377.GenerateScalars(size)
points := icicleBls12_377.GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p Projective
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], 1)
outHost := make(core.HostSlice[icicleBls12_377.Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)
cr.SynchronizeStream(&stream)
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0]))
}
}
func TestMSMGnarkCryptoTypes(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
for _, power := range []int{3} {
size := 1 << power
scalars := make([]fr.Element, size)
var x fr.Element
for i := 0; i < size; i++ {
x.SetRandom()
scalars[i] = x
}
scalarsHost := (core.HostSlice[fr.Element])(scalars)
points := icicleBls12_377.GenerateAffinePoints(size)
pointsGnark := convertIcicleAffineToG1Affine(points)
pointsHost := (core.HostSlice[bls12377.G1Affine])(pointsGnark)
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.ArePointsMontgomeryForm = true
cfg.AreScalarsMontgomeryForm = true
e = msm.Msm(scalarsHost, pointsHost, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[icicleBls12_377.Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0]))
}
}
func TestMSMBatch(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := GenerateAffinePoints(totalSize)
scalars := icicleBls12_377.GenerateScalars(totalSize)
points := icicleBls12_377.GenerateAffinePoints(totalSize)
var p Projective
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e := out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], batchSize)
outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -114,36 +171,35 @@ func TestMSMBatch(t *testing.T) {
}
func TestPrecomputeBase(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := GenerateAffinePoints(totalSize)
scalars := icicleBls12_377.GenerateScalars(totalSize)
points := icicleBls12_377.GenerateAffinePoints(totalSize)
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
e = PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
var p Projective
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
e = Msm(scalars, precomputeOut, &cfg, out)
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], batchSize)
outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
precomputeOut.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -156,30 +212,29 @@ func TestPrecomputeBase(t *testing.T) {
}
func TestMSMSkewedDistribution(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
scalars := icicleBls12_377.GenerateScalars(size)
for i := size / 4; i < size; i++ {
scalars[i].One()
}
points := GenerateAffinePoints(size)
points := icicleBls12_377.GenerateAffinePoints(size)
for i := 0; i < size/4; i++ {
points[i].Zero()
}
var p Projective
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], 1)
outHost := make(core.HostSlice[icicleBls12_377.Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0]))
}
@@ -196,23 +251,23 @@ func TestMSMMultiDevice(t *testing.T) {
wg.Add(1)
cr.RunOnDevice(i, func(args ...any) {
defer wg.Done()
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := GenerateAffinePoints(size)
scalars := icicleBls12_377.GenerateScalars(size)
points := icicleBls12_377.GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p Projective
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], 1)
outHost := make(core.HostSlice[icicleBls12_377.Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)

View File

@@ -1,40 +1,20 @@
package bls12377
package tests
import (
"os"
"reflect"
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
ntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/ntt"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
)
const (
largestTestSize = 17
)
func init() {
cfg := GetDefaultNttConfig()
initDomain(largestTestSize, cfg)
}
func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError {
rouMont, _ := fft.Generator(uint64(1 << largestTestSize))
rou := rouMont.Bits()
rouIcicle := ScalarField{}
limbs := core.ConvertUint64ArrToUint32Arr(rou[:])
rouIcicle.FromLimbs(limbs)
e := InitDomain(rouIcicle, cfg.Ctx, false)
return e
}
func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool {
domainWithPrecompute := fft.NewDomain(uint64(size))
func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_377.ScalarField], output core.HostSlice[bls12_377.ScalarField], order core.Ordering, direction core.NTTDir) bool {
scalarsFr := make([]fr.Element, size)
for i, v := range scalars {
slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian()))
@@ -46,6 +26,11 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], ou
outputAsFr[i] = slice64
}
return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction)
}
func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool {
domainWithPrecompute := fft.NewDomain(uint64(size))
// DIT + BitReverse == Ordering.kRR
// DIT == Ordering.kRN
// DIF + BitReverse == Ordering.kNN
@@ -68,72 +53,77 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], ou
}
return reflect.DeepEqual(scalarsFr, outputAsFr)
}
func TestNTTGetDefaultConfig(t *testing.T) {
actual := GetDefaultNttConfig()
expected := generateLimbOne(int(SCALAR_LIMBS))
actual := ntt.GetDefaultNttConfig()
expected := test_helpers.GenerateLimbOne(int(bls12_377.SCALAR_LIMBS))
assert.Equal(t, expected, actual.CosetGen[:])
cosetGenField := ScalarField{}
cosetGenField := bls12_377.ScalarField{}
cosetGenField.One()
assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen)
}
func TestInitDomain(t *testing.T) {
t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function")
cfg := GetDefaultNttConfig()
cfg := ntt.GetDefaultNttConfig()
assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) })
}
func TestNtt(t *testing.T) {
cfg := GetDefaultNttConfig()
scalars := GenerateScalars(1 << largestTestSize)
cfg := ntt.GetDefaultNttConfig()
scalars := bls12_377.GenerateScalars(1 << largestTestSize)
for _, size := range []int{4, largestTestSize} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize])
scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize])
cfg.Ordering = v
// run ntt
output := make(core.HostSlice[ScalarField], testSize)
Ntt(scalarsCopy, core.KForward, &cfg, output)
output := make(core.HostSlice[bls12_377.ScalarField], testSize)
ntt.Ntt(scalarsCopy, core.KForward, &cfg, output)
// Compare with gnark-crypto
assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward))
}
}
}
func TestNttFrElement(t *testing.T) {
cfg := ntt.GetDefaultNttConfig()
scalars := make([]fr.Element, 4)
var x fr.Element
for i := 0; i < 4; i++ {
x.SetRandom()
scalars[i] = x
}
func TestECNtt(t *testing.T) {
cfg := GetDefaultNttConfig()
points := GenerateProjectivePoints(1 << largestTestSize)
for _, size := range []int{4} {
for _, v := range [1]core.Ordering{core.KNN} {
testSize := size
for _, size := range []int{4, 5, 6, 7, 8} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
pointsCopy := core.HostSliceFromElements[Projective](points[:testSize])
scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize])
cfg.Ordering = v
cfg.NttAlgorithm = core.Radix2
output := make(core.HostSlice[Projective], testSize)
e := ECNtt(pointsCopy, core.KForward, &cfg, output)
assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed")
// run ntt
output := make(core.HostSlice[fr.Element], testSize)
ntt.Ntt(scalarsCopy, core.KForward, &cfg, output)
// Compare with gnark-crypto
assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward))
}
}
}
func TestNttDeviceAsync(t *testing.T) {
cfg := GetDefaultNttConfig()
scalars := GenerateScalars(1 << largestTestSize)
cfg := ntt.GetDefaultNttConfig()
scalars := bls12_377.GenerateScalars(1 << largestTestSize)
for _, size := range []int{1, 10, largestTestSize} {
for _, direction := range []core.NTTDir{core.KForward, core.KInverse} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize])
scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:testSize])
stream, _ := cr.CreateStream()
@@ -147,12 +137,11 @@ func TestNttDeviceAsync(t *testing.T) {
deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
// run ntt
Ntt(deviceInput, direction, &cfg, deviceOutput)
output := make(core.HostSlice[ScalarField], testSize)
ntt.Ntt(deviceInput, direction, &cfg, deviceOutput)
output := make(core.HostSlice[bls12_377.ScalarField], testSize)
output.CopyFromDeviceAsync(&deviceOutput, stream)
cr.SynchronizeStream(&stream)
// Compare with gnark-crypto
assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction))
}
@@ -161,22 +150,22 @@ func TestNttDeviceAsync(t *testing.T) {
}
func TestNttBatch(t *testing.T) {
cfg := GetDefaultNttConfig()
cfg := ntt.GetDefaultNttConfig()
largestBatchSize := 100
scalars := GenerateScalars(1 << largestTestSize * largestBatchSize)
scalars := bls12_377.GenerateScalars(1 << largestTestSize * largestBatchSize)
for _, size := range []int{4, largestTestSize} {
for _, batchSize := range []int{1, 16, largestBatchSize} {
testSize := 1 << size
totalSize := testSize * batchSize
scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize])
scalarsCopy := core.HostSliceFromElements[bls12_377.ScalarField](scalars[:totalSize])
cfg.Ordering = core.KNN
cfg.BatchSize = int32(batchSize)
// run ntt
output := make(core.HostSlice[ScalarField], totalSize)
Ntt(scalarsCopy, core.KForward, &cfg, output)
output := make(core.HostSlice[bls12_377.ScalarField], totalSize)
ntt.Ntt(scalarsCopy, core.KForward, &cfg, output)
// Compare with gnark-crypto
domainWithPrecompute := fft.NewDomain(uint64(testSize))
@@ -205,36 +194,18 @@ func TestNttBatch(t *testing.T) {
func TestReleaseDomain(t *testing.T) {
t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function")
cfg := GetDefaultNttConfig()
e := ReleaseDomain(cfg.Ctx)
cfg := ntt.GetDefaultNttConfig()
e := ntt.ReleaseDomain(cfg.Ctx)
assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed")
}
func TestMain(m *testing.M) {
// setup domain
cfg := GetDefaultNttConfig()
e := initDomain(largestTestSize, cfg)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("initDomain failed")
}
// execute tests
os.Exit(m.Run())
// release domain
e = ReleaseDomain(cfg.Ctx)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("ReleaseDomain failed")
}
}
// func TestNttArbitraryCoset(t *testing.T) {
// for _, size := range []int{20} {
// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
// testSize := 1 << size
// scalars := GenerateScalars(testSize)
// cfg := GetDefaultNttConfig()
// cfg := ntt.GetDefaultNttConfig()
// var scalarsCopy core.HostSlice[ScalarField]
// for _, v := range scalars {

View File

@@ -0,0 +1,229 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
// "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/ntt"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/polynomial"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/vecOps"
"github.com/stretchr/testify/assert"
)
var one, two, three, four, five bls12_377.ScalarField
func init() {
one.One()
two.FromUint32(2)
three.FromUint32(3)
four.FromUint32(4)
five.FromUint32(5)
}
func rand() bls12_377.ScalarField {
return bls12_377.GenerateScalars(1)[0]
}
func randomPoly(size int) (f polynomial.DensePolynomial) {
f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_377.GenerateScalars(size)))
return f
}
func vecOp(a, b bls12_377.ScalarField, op core.VecOps) bls12_377.ScalarField {
ahost := core.HostSliceWithValue(a, 1)
bhost := core.HostSliceWithValue(b, 1)
out := make(core.HostSlice[bls12_377.ScalarField], 1)
cfg := core.DefaultVecOpsConfig()
vecOps.VecOp(ahost, bhost, out, cfg, op)
return out[0]
}
func TestPolyCreateFromCoefficients(t *testing.T) {
scalars := bls12_377.GenerateScalars(33)
var uniPoly polynomial.DensePolynomial
poly := uniPoly.CreateFromCoeffecitients(scalars)
poly.Print()
}
func TestPolyEval(t *testing.T) {
// testing correct evaluation of f(8) for f(x)=4x^2+2x+5
coeffs := core.HostSliceFromElements([]bls12_377.ScalarField{five, two, four})
var f polynomial.DensePolynomial
f.CreateFromCoeffecitients(coeffs)
var x bls12_377.ScalarField
x.FromUint32(8)
domains := make(core.HostSlice[bls12_377.ScalarField], 1)
domains[0] = x
evals := make(core.HostSlice[bls12_377.ScalarField], 1)
fEvaled := f.EvalOnDomain(domains, evals)
var expected bls12_377.ScalarField
assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[bls12_377.ScalarField])[0])
}
func TestPolyClone(t *testing.T) {
f := randomPoly(8)
x := rand()
fx := f.Eval(x)
g := f.Clone()
fg := f.Add(&g)
gx := g.Eval(x)
fgx := fg.Eval(x)
assert.Equal(t, fx, gx)
assert.Equal(t, vecOp(fx, gx, core.Add), fgx)
}
func TestPolyAddSubMul(t *testing.T) {
testSize := 1 << 10
f := randomPoly(testSize)
g := randomPoly(testSize)
x := rand()
fx := f.Eval(x)
gx := g.Eval(x)
polyAdd := f.Add(&g)
fxAddgx := vecOp(fx, gx, core.Add)
assert.Equal(t, polyAdd.Eval(x), fxAddgx)
polySub := f.Subtract(&g)
fxSubgx := vecOp(fx, gx, core.Sub)
assert.Equal(t, polySub.Eval(x), fxSubgx)
polyMul := f.Multiply(&g)
fxMulgx := vecOp(fx, gx, core.Mul)
assert.Equal(t, polyMul.Eval(x), fxMulgx)
s1 := rand()
polMulS1 := f.MultiplyByScalar(s1)
assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul))
s2 := rand()
polMulS2 := f.MultiplyByScalar(s2)
assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul))
}
func TestPolyMonomials(t *testing.T) {
var zero bls12_377.ScalarField
var f polynomial.DensePolynomial
f.CreateFromCoeffecitients(core.HostSliceFromElements([]bls12_377.ScalarField{one, zero, two}))
x := rand()
fx := f.Eval(x)
f.AddMonomial(three, 1)
fxAdded := f.Eval(x)
assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add))
f.SubMonomial(one, 0)
fxSub := f.Eval(x)
assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub))
}
func TestPolyReadCoeffs(t *testing.T) {
var f polynomial.DensePolynomial
coeffs := core.HostSliceFromElements([]bls12_377.ScalarField{one, two, three, four})
f.CreateFromCoeffecitients(coeffs)
coeffsCopied := make(core.HostSlice[bls12_377.ScalarField], coeffs.Len())
_, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied)
assert.ElementsMatch(t, coeffs, coeffsCopied)
var coeffsDevice core.DeviceSlice
coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size())
_, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice)
coeffsHost := make(core.HostSlice[bls12_377.ScalarField], coeffs.Len())
coeffsHost.CopyFromDevice(&coeffsDevice)
assert.ElementsMatch(t, coeffs, coeffsHost)
}
func TestPolyOddEvenSlicing(t *testing.T) {
size := 1<<10 - 3
f := randomPoly(size)
even := f.Even()
odd := f.Odd()
assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1)
x := rand()
var evenExpected, oddExpected bls12_377.ScalarField
for i := size; i >= 0; i-- {
if i%2 == 0 {
mul := vecOp(evenExpected, x, core.Mul)
evenExpected = vecOp(mul, f.GetCoeff(i), core.Add)
} else {
mul := vecOp(oddExpected, x, core.Mul)
oddExpected = vecOp(mul, f.GetCoeff(i), core.Add)
}
}
evenEvaled := even.Eval(x)
assert.Equal(t, evenExpected, evenEvaled)
oddEvaled := odd.Eval(x)
assert.Equal(t, oddExpected, oddEvaled)
}
func TestPolynomialDivision(t *testing.T) {
// divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x)
var f, g polynomial.DensePolynomial
f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_377.GenerateScalars(1 << 4)))
g.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_377.GenerateScalars(1 << 2)))
q, r := f.Divide(&g)
qMulG := q.Multiply(&g)
fRecon := qMulG.Add(&r)
x := bls12_377.GenerateScalars(1)[0]
fEval := f.Eval(x)
fReconEval := fRecon.Eval(x)
assert.Equal(t, fEval, fReconEval)
}
func TestDivideByVanishing(t *testing.T) {
// poly of x^4-1 vanishes ad 4th rou
var zero bls12_377.ScalarField
minus_one := vecOp(zero, one, core.Sub)
coeffs := core.HostSliceFromElements([]bls12_377.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1
var v polynomial.DensePolynomial
v.CreateFromCoeffecitients(coeffs)
f := randomPoly(1 << 3)
fv := f.Multiply(&v)
fDegree := f.Degree()
fvDegree := fv.Degree()
assert.Equal(t, fDegree+4, fvDegree)
fReconstructed := fv.DivideByVanishing(4)
assert.Equal(t, fDegree, fReconstructed.Degree())
x := rand()
assert.Equal(t, f.Eval(x), fReconstructed.Eval(x))
}
// func TestPolySlice(t *testing.T) {
// size := 4
// coeffs := bls12_377.GenerateScalars(size)
// var f DensePolynomial
// f.CreateFromCoeffecitients(coeffs)
// fSlice := f.AsSlice()
// assert.True(t, fSlice.IsOnDevice())
// assert.Equal(t, size, fSlice.Len())
// hostSlice := make(core.HostSlice[bls12_377.ScalarField], size)
// hostSlice.CopyFromDevice(fSlice)
// assert.Equal(t, coeffs, hostSlice)
// cfg := ntt.GetDefaultNttConfig()
// res := make(core.HostSlice[bls12_377.ScalarField], size)
// ntt.Ntt(fSlice, core.KForward, cfg, res)
// assert.Equal(t, f.Eval(one), res[0])
// }

View File

@@ -0,0 +1,120 @@
package tests
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (
SCALAR_LIMBS = bls12_377.SCALAR_LIMBS
)
func TestScalarFieldFromLimbs(t *testing.T) {
emptyField := bls12_377.ScalarField{}
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}
func TestScalarFieldGetLimbs(t *testing.T) {
emptyField := bls12_377.ScalarField{}
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs")
}
func TestScalarFieldOne(t *testing.T) {
var emptyField bls12_377.ScalarField
emptyField.One()
limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work")
}
func TestScalarFieldZero(t *testing.T) {
var emptyField bls12_377.ScalarField
emptyField.Zero()
limbsZero := make([]uint32, SCALAR_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed")
}
func TestScalarFieldSize(t *testing.T) {
var emptyField bls12_377.ScalarField
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestScalarFieldAsPointer(t *testing.T) {
var emptyField bls12_377.ScalarField
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestScalarFieldFromBytes(t *testing.T) {
var emptyField bls12_377.ScalarField
bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
}
func TestScalarFieldToBytes(t *testing.T) {
var emptyField bls12_377.ScalarField
expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
}
func TestBls12_377GenerateScalars(t *testing.T) {
const numScalars = 8
scalars := bls12_377.GenerateScalars(numScalars)
assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars)
assert.Equal(t, numScalars, scalars.Len())
zeroScalar := bls12_377.ScalarField{}
assert.NotContains(t, scalars, zeroScalar)
}
func TestBls12_377MongtomeryConversion(t *testing.T) {
size := 1 << 15
scalars := bls12_377.GenerateScalars(size)
var deviceScalars core.DeviceSlice
scalars.CopyToDevice(&deviceScalars, true)
bls12_377.ToMontgomery(&deviceScalars)
scalarsMontHost := bls12_377.GenerateScalars(size)
scalarsMontHost.CopyFromDevice(&deviceScalars)
assert.NotEqual(t, scalars, scalarsMontHost)
bls12_377.FromMontgomery(&deviceScalars)
scalarsMontHost.CopyFromDevice(&deviceScalars)
assert.Equal(t, scalars, scalarsMontHost)
}

View File

@@ -0,0 +1,69 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
bls12_377 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12377/vecOps"
"github.com/stretchr/testify/assert"
)
func TestBls12_377VecOps(t *testing.T) {
testSize := 1 << 14
a := bls12_377.GenerateScalars(testSize)
b := bls12_377.GenerateScalars(testSize)
var scalar bls12_377.ScalarField
scalar.One()
ones := core.HostSliceWithValue(scalar, testSize)
out := make(core.HostSlice[bls12_377.ScalarField], testSize)
out2 := make(core.HostSlice[bls12_377.ScalarField], testSize)
out3 := make(core.HostSlice[bls12_377.ScalarField], testSize)
cfg := core.DefaultVecOpsConfig()
vecOps.VecOp(a, b, out, cfg, core.Add)
vecOps.VecOp(out, b, out2, cfg, core.Sub)
assert.Equal(t, a, out2)
vecOps.VecOp(a, ones, out3, cfg, core.Mul)
assert.Equal(t, a, out3)
}
func TestBls12_377Transpose(t *testing.T) {
rowSize := 1 << 6
columnSize := 1 << 8
onDevice := false
isAsync := false
matrix := bls12_377.GenerateScalars(rowSize * columnSize)
out := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize)
out2 := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize)
ctx, _ := cr.GetDefaultDeviceContext()
vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync)
vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync)
assert.Equal(t, matrix, out2)
var dMatrix, dOut, dOut2 core.DeviceSlice
onDevice = true
matrix.CopyToDevice(&dMatrix, true)
dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement())
dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement())
vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync)
vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync)
output := make(core.HostSlice[bls12_377.ScalarField], rowSize*columnSize)
output.CopyFromDevice(&dOut2)
assert.Equal(t, matrix, output)
}

View File

@@ -1,5 +1,5 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_377_VEC_OPS_H
#define _BLS12_377_VEC_OPS_H
@@ -8,7 +8,11 @@
extern "C" {
#endif
cudaError_t bls12_377MulCuda(
typedef struct scalar_t scalar_t;
typedef struct VecOpsConfig VecOpsConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_377_mul_cuda(
scalar_t* vec_a,
scalar_t* vec_b,
int n,
@@ -16,7 +20,7 @@ cudaError_t bls12_377MulCuda(
scalar_t* result
);
cudaError_t bls12_377AddCuda(
cudaError_t bls12_377_add_cuda(
scalar_t* vec_a,
scalar_t* vec_b,
int n,
@@ -24,7 +28,7 @@ cudaError_t bls12_377AddCuda(
scalar_t* result
);
cudaError_t bls12_377SubCuda(
cudaError_t bls12_377_sub_cuda(
scalar_t* vec_a,
scalar_t* vec_b,
int n,
@@ -32,6 +36,16 @@ cudaError_t bls12_377SubCuda(
scalar_t* result
);
cudaError_t bls12_377_transpose_matrix_cuda(
scalar_t* mat_in,
int row_size,
int column_size,
scalar_t* mat_out,
DeviceContext* ctx,
bool on_device,
bool is_async
);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,48 @@
package vecOps
// #cgo CFLAGS: -I./include/
// #include "vec_ops.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) {
aPointer, bPointer, outPointer, cfgPointer, size := core.VecOpCheck(a, b, out, &config)
cA := (*C.scalar_t)(aPointer)
cB := (*C.scalar_t)(bPointer)
cOut := (*C.scalar_t)(outPointer)
cConfig := (*C.VecOpsConfig)(cfgPointer)
cSize := (C.int)(size)
switch op {
case core.Sub:
ret = (cr.CudaError)(C.bls12_377_sub_cuda(cA, cB, cSize, cConfig, cOut))
case core.Add:
ret = (cr.CudaError)(C.bls12_377_add_cuda(cA, cB, cSize, cConfig, cOut))
case core.Mul:
ret = (cr.CudaError)(C.bls12_377_mul_cuda(cA, cB, cSize, cConfig, cOut))
}
return ret
}
func TransposeMatrix(in, out core.HostOrDeviceSlice, columnSize, rowSize int, ctx cr.DeviceContext, onDevice, isAsync bool) (ret core.IcicleError) {
core.TransposeCheck(in, out, onDevice)
cIn := (*C.scalar_t)(in.AsUnsafePointer())
cOut := (*C.scalar_t)(out.AsUnsafePointer())
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cRowSize := (C.int)(rowSize)
cColumnSize := (C.int)(columnSize)
cOnDevice := (C._Bool)(onDevice)
cIsAsync := (C._Bool)(isAsync)
err := (cr.CudaError)(C.bls12_377_transpose_matrix_cuda(cIn, cRowSize, cColumnSize, cOut, cCtx, cOnDevice, cIsAsync))
return core.FromCudaError(err)
}

View File

@@ -1,55 +0,0 @@
package bls12377
// #cgo CFLAGS: -I./include/
// #include "vec_ops.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
func VecOp(a, b, out core.HostOrDeviceSlice, config core.VecOpsConfig, op core.VecOps) (ret cr.CudaError) {
core.VecOpCheck(a, b, out, &config)
var cA, cB, cOut *C.scalar_t
if a.IsOnDevice() {
aDevice := a.(core.DeviceSlice)
aDevice.CheckDevice()
cA = (*C.scalar_t)(aDevice.AsPointer())
} else {
cA = (*C.scalar_t)(unsafe.Pointer(&a.(core.HostSlice[ScalarField])[0]))
}
if b.IsOnDevice() {
bDevice := b.(core.DeviceSlice)
bDevice.CheckDevice()
cB = (*C.scalar_t)(bDevice.AsPointer())
} else {
cB = (*C.scalar_t)(unsafe.Pointer(&b.(core.HostSlice[ScalarField])[0]))
}
if out.IsOnDevice() {
outDevice := out.(core.DeviceSlice)
outDevice.CheckDevice()
cOut = (*C.scalar_t)(outDevice.AsPointer())
} else {
cOut = (*C.scalar_t)(unsafe.Pointer(&out.(core.HostSlice[ScalarField])[0]))
}
cConfig := (*C.VecOpsConfig)(unsafe.Pointer(&config))
cSize := (C.int)(a.Len())
switch op {
case core.Sub:
ret = (cr.CudaError)(C.bls12_377SubCuda(cA, cB, cSize, cConfig, cOut))
case core.Add:
ret = (cr.CudaError)(C.bls12_377AddCuda(cA, cB, cSize, cConfig, cOut))
case core.Mul:
ret = (cr.CudaError)(C.bls12_377MulCuda(cA, cB, cSize, cConfig, cOut))
}
return ret
}

View File

@@ -1,33 +0,0 @@
package bls12377
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
"github.com/stretchr/testify/assert"
)
func TestVecOps(t *testing.T) {
testSize := 1 << 14
a := GenerateScalars(testSize)
b := GenerateScalars(testSize)
var scalar ScalarField
scalar.One()
ones := core.HostSliceWithValue(scalar, testSize)
out := make(core.HostSlice[ScalarField], testSize)
out2 := make(core.HostSlice[ScalarField], testSize)
out3 := make(core.HostSlice[ScalarField], testSize)
cfg := core.DefaultVecOpsConfig()
VecOp(a, b, out, cfg, core.Add)
VecOp(out, b, out2, cfg, core.Sub)
assert.Equal(t, a, out2)
VecOp(a, ones, out3, cfg, core.Mul)
assert.Equal(t, a, out3)
}

View File

@@ -6,7 +6,7 @@ import (
)
const (
BASE_LIMBS int8 = 12
BASE_LIMBS int = 12
)
type BaseField struct {
@@ -29,6 +29,11 @@ func (f BaseField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *BaseField) FromUint32(v uint32) BaseField {
f.limbs[0] = v
return *f
}
func (f *BaseField) FromLimbs(limbs []uint32) BaseField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")

View File

@@ -1,4 +0,0 @@
package bls12381
// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_bls12_381 -lstdc++ -lm
import "C"

View File

@@ -53,7 +53,7 @@ func (p *Projective) FromAffine(a Affine) Projective {
func (p Projective) ProjectiveEq(p2 *Projective) bool {
cP := (*C.projective_t)(unsafe.Pointer(&p))
cP2 := (*C.projective_t)(unsafe.Pointer(&p2))
__ret := C.bls12_381Eq(cP, cP2)
__ret := C.bls12_381_eq(cP, cP2)
return __ret == (C._Bool)(true)
}
@@ -62,7 +62,7 @@ func (p *Projective) ProjectiveToAffine() Affine {
cA := (*C.affine_t)(unsafe.Pointer(&a))
cP := (*C.projective_t)(unsafe.Pointer(&p))
C.bls12_381ToAffine(cP, cA)
C.bls12_381_to_affine(cP, cA)
return a
}
@@ -75,7 +75,7 @@ func GenerateProjectivePoints(size int) core.HostSlice[Projective] {
pointsSlice := core.HostSliceFromElements[Projective](points)
pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bls12_381GenerateProjectivePoints(pPoints, cSize)
C.bls12_381_generate_projective_points(pPoints, cSize)
return pointsSlice
}
@@ -129,18 +129,18 @@ func GenerateAffinePoints(size int) core.HostSlice[Affine] {
pointsSlice := core.HostSliceFromElements[Affine](points)
cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bls12_381GenerateAffinePoints(cPoints, cSize)
C.bls12_381_generate_affine_points(cPoints, cSize)
return pointsSlice
}
func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.affine_t)(points.AsPointer())
cValues := (*C.affine_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_381AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_381_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}
@@ -156,12 +156,12 @@ func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError {
}
func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.projective_t)(points.AsPointer())
cValues := (*C.projective_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_381ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_381_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -0,0 +1,24 @@
package ecntt
// #cgo CFLAGS: -I./include/
// #include "ecntt.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
pointsPointer, resultsPointer, size, cfgPointer := core.NttCheck[T](points, cfg, results)
cPoints := (*C.projective_t)(pointsPointer)
cSize := (C.int)(size)
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(cfgPointer)
cResults := (*C.projective_t)(resultsPointer)
__ret := C.bls12_381_ecntt_cuda(cPoints, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,19 @@
#include <cuda_runtime.h>
#ifndef _BLS12_381_ECNTT_H
#define _BLS12_381_ECNTT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct NTTConfig NTTConfig;
typedef struct projective_t projective_t;
cudaError_t bls12_381_ecntt_cuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,9 +1,7 @@
//go:build g2
package bn254
package g2
// #cgo CFLAGS: -I./include/
// #include "g2_curve.h"
// #include "curve.h"
import "C"
import (
@@ -55,7 +53,7 @@ func (p *G2Projective) FromAffine(a G2Affine) G2Projective {
func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool {
cP := (*C.g2_projective_t)(unsafe.Pointer(&p))
cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2))
__ret := C.bn254G2Eq(cP, cP2)
__ret := C.bls12_381_g2_eq(cP, cP2)
return __ret == (C._Bool)(true)
}
@@ -64,7 +62,7 @@ func (p *G2Projective) ProjectiveToAffine() G2Affine {
cA := (*C.g2_affine_t)(unsafe.Pointer(&a))
cP := (*C.g2_projective_t)(unsafe.Pointer(&p))
C.bn254G2ToAffine(cP, cA)
C.bls12_381_g2_to_affine(cP, cA)
return a
}
@@ -77,7 +75,7 @@ func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] {
pointsSlice := core.HostSliceFromElements[G2Projective](points)
pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bn254G2GenerateProjectivePoints(pPoints, cSize)
C.bls12_381_g2_generate_projective_points(pPoints, cSize)
return pointsSlice
}
@@ -131,18 +129,18 @@ func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] {
pointsSlice := core.HostSliceFromElements[G2Affine](points)
cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0]))
cSize := (C.int)(size)
C.bn254G2GenerateAffinePoints(cPoints, cSize)
C.bls12_381_g2_generate_affine_points(cPoints, cSize)
return pointsSlice
}
func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.g2_affine_t)(points.AsPointer())
cValues := (*C.g2_affine_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bn254G2AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_381_g2_affine_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}
@@ -158,12 +156,12 @@ func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError {
}
func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.g2_projective_t)(points.AsPointer())
cValues := (*C.g2_projective_t)(points.AsUnsafePointer())
cSize := (C.size_t)(points.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bn254G2ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_381_g2_projective_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,6 +1,4 @@
//go:build g2
package bls12377
package g2
import (
"encoding/binary"
@@ -8,19 +6,19 @@ import (
)
const (
G2_BASE_LIMBS int8 = 24
G2BASE_LIMBS int = 24
)
type G2BaseField struct {
limbs [G2_BASE_LIMBS]uint32
limbs [G2BASE_LIMBS]uint32
}
func (f G2BaseField) Len() int {
return int(G2_BASE_LIMBS)
return int(G2BASE_LIMBS)
}
func (f G2BaseField) Size() int {
return int(G2_BASE_LIMBS * 4)
return int(G2BASE_LIMBS * 4)
}
func (f G2BaseField) GetLimbs() []uint32 {
@@ -31,6 +29,11 @@ func (f G2BaseField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *G2BaseField) FromUint32(v uint32) G2BaseField {
f.limbs[0] = v
return *f
}
func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")

View File

@@ -0,0 +1,26 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_G2CURVE_H
#define _BLS12_381_G2CURVE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct g2_projective_t g2_projective_t;
typedef struct g2_affine_t g2_affine_t;
typedef struct DeviceContext DeviceContext;
bool bls12_381_g2_eq(g2_projective_t* point1, g2_projective_t* point2);
void bls12_381_g2_to_affine(g2_projective_t* point, g2_affine_t* point_out);
void bls12_381_g2_generate_projective_points(g2_projective_t* points, int size);
void bls12_381_g2_generate_affine_points(g2_affine_t* points, int size);
cudaError_t bls12_381_g2_affine_convert_montgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_381_g2_projective_convert_montgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,24 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_G2MSM_H
#define _BLS12_381_G2MSM_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct g2_projective_t g2_projective_t;
typedef struct g2_affine_t g2_affine_t;
typedef struct MSMConfig MSMConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_381_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bls12_381_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,21 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_FIELD_H
#define _BLS12_381_FIELD_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct DeviceContext DeviceContext;
void bls12_381_generate_scalars(scalar_t* scalars, int size);
cudaError_t bls12_381_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
package g2
// #cgo CFLAGS: -I./include/
// #include "msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results)
cScalars := (*C.scalar_t)(scalarsPointer)
cPoints := (*C.g2_affine_t)(pointsPointer)
cResults := (*C.g2_projective_t)(resultsPointer)
cSize := (C.int)(size)
cCfg := (*C.MSMConfig)(cfgPointer)
__ret := C.bls12_381_g2_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bls12_381_g2_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,82 +0,0 @@
//go:build g2
package bls12381
// #cgo CFLAGS: -I./include/
// #include "g2_msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func G2GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
core.MsmCheck(scalars, points, cfg, results)
var scalarsPointer unsafe.Pointer
if scalars.IsOnDevice() {
scalarsDevice := scalars.(core.DeviceSlice)
scalarsDevice.CheckDevice()
scalarsPointer = scalarsDevice.AsPointer()
} else {
scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0])
}
cScalars := (*C.scalar_t)(scalarsPointer)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsDevice := points.(core.DeviceSlice)
pointsDevice.CheckDevice()
pointsPointer = pointsDevice.AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0])
}
cPoints := (*C.g2_affine_t)(pointsPointer)
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsDevice := results.(core.DeviceSlice)
resultsDevice.CheckDevice()
resultsPointer = resultsDevice.AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[G2Projective])[0])
}
cResults := (*C.g2_projective_t)(resultsPointer)
cSize := (C.int)(scalars.Len() / results.Len())
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
__ret := C.bls12_381G2MSMCuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsPointer = points.(core.DeviceSlice).AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0])
}
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
outputBasesPointer := outputBases.AsPointer()
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bls12_381G2PrecomputeMSMBases(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,5 +1,4 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_381_CURVE_H
@@ -9,12 +8,16 @@
extern "C" {
#endif
bool bls12_381Eq(projective_t* point1, projective_t* point2);
void bls12_381ToAffine(projective_t* point, affine_t* point_out);
void bls12_381GenerateProjectivePoints(projective_t* points, int size);
void bls12_381GenerateAffinePoints(affine_t* points, int size);
cudaError_t bls12_381AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_381ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
typedef struct projective_t projective_t;
typedef struct affine_t affine_t;
typedef struct DeviceContext DeviceContext;
bool bls12_381_eq(projective_t* point1, projective_t* point2);
void bls12_381_to_affine(projective_t* point, affine_t* point_out);
void bls12_381_generate_projective_points(projective_t* points, int size);
void bls12_381_generate_affine_points(affine_t* points, int size);
cudaError_t bls12_381_affine_convert_montgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_381_projective_convert_montgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}

View File

@@ -1,23 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_381_G2CURVE_H
#define _BLS12_381_G2CURVE_H
#ifdef __cplusplus
extern "C" {
#endif
bool bls12_381G2Eq(g2_projective_t* point1, g2_projective_t* point2);
void bls12_381G2ToAffine(g2_projective_t* point, g2_affine_t* point_out);
void bls12_381G2GenerateProjectivePoints(g2_projective_t* points, int size);
void bls12_381G2GenerateAffinePoints(g2_affine_t* points, int size);
cudaError_t bls12_381G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx);
cudaError_t bls12_381G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,19 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_381_G2MSM_H
#define _BLS12_381_G2MSM_H
#ifdef __cplusplus
extern "C" {
#endif
cudaError_t bls12_381G2MSMCuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bls12_381G2PrecomputeMSMBases(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,19 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_381_MSM_H
#define _BLS12_381_MSM_H
#ifdef __cplusplus
extern "C" {
#endif
cudaError_t bls12_381MSMCuda(const scalar_t* scalars, const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bls12_381PrecomputeMSMBases(affine_t* points, int bases_size, int precompute_factor, int _c, bool are_bases_on_device, DeviceContext* ctx, affine_t* output_bases);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,21 +0,0 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_381_NTT_H
#define _BLS12_381_NTT_H
#ifdef __cplusplus
extern "C" {
#endif
cudaError_t bls12_381NTTCuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output);
cudaError_t bls12_381ECNTTCuda(const projective_t* input, int size, int dir, NTTConfig* config, projective_t* output);
cudaError_t bls12_381InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles);
cudaError_t bls12_381ReleaseDomain(DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,5 +1,4 @@
#include <cuda_runtime.h>
#include "../../include/types.h"
#include <stdbool.h>
#ifndef _BLS12_381_FIELD_H
@@ -9,8 +8,11 @@
extern "C" {
#endif
void bls12_381GenerateScalars(scalar_t* scalars, int size);
cudaError_t bls12_381ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx);
typedef struct scalar_t scalar_t;
typedef struct DeviceContext DeviceContext;
void bls12_381_generate_scalars(scalar_t* scalars, int size);
cudaError_t bls12_381_scalar_convert_montgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx);
#ifdef __cplusplus
}

View File

@@ -0,0 +1,4 @@
package bls12381
// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build/lib -lingo_curve_bls12_381 -lingo_field_bls12_381 -lstdc++ -lm
import "C"

View File

@@ -1,80 +0,0 @@
package bls12381
// #cgo CFLAGS: -I./include/
// #include "msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
core.MsmCheck(scalars, points, cfg, results)
var scalarsPointer unsafe.Pointer
if scalars.IsOnDevice() {
scalarsDevice := scalars.(core.DeviceSlice)
scalarsDevice.CheckDevice()
scalarsPointer = scalarsDevice.AsPointer()
} else {
scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0])
}
cScalars := (*C.scalar_t)(scalarsPointer)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsDevice := points.(core.DeviceSlice)
pointsDevice.CheckDevice()
pointsPointer = pointsDevice.AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0])
}
cPoints := (*C.affine_t)(pointsPointer)
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsDevice := results.(core.DeviceSlice)
resultsDevice.CheckDevice()
resultsPointer = resultsDevice.AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0])
}
cResults := (*C.projective_t)(resultsPointer)
cSize := (C.int)(scalars.Len() / results.Len())
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
__ret := C.bls12_381MSMCuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsPointer = points.(core.DeviceSlice).AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0])
}
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
outputBasesPointer := outputBases.AsPointer()
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bls12_381PrecomputeMSMBases(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -0,0 +1,24 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_MSM_H
#define _BLS12_381_MSM_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct projective_t projective_t;
typedef struct affine_t affine_t;
typedef struct MSMConfig MSMConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_381_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bls12_381_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
package msm
// #cgo CFLAGS: -I./include/
// #include "msm.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"unsafe"
)
func GetDefaultMSMConfig() core.MSMConfig {
return core.GetDefaultMSMConfig()
}
func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError {
scalarsPointer, pointsPointer, resultsPointer, size, cfgPointer := core.MsmCheck(scalars, points, cfg, results)
cScalars := (*C.scalar_t)(scalarsPointer)
cPoints := (*C.affine_t)(pointsPointer)
cResults := (*C.projective_t)(resultsPointer)
cSize := (C.int)(size)
cCfg := (*C.MSMConfig)(cfgPointer)
__ret := C.bls12_381_msm_cuda(cScalars, cPoints, cSize, cCfg, cResults)
err := (cr.CudaError)(__ret)
return err
}
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
cPrecomputeFactor := (C.int)(precomputeFactor)
cC := (C.int)(c)
cPointsIsOnDevice := (C._Bool)(points.IsOnDevice())
cCtx := (*C.DeviceContext)(unsafe.Pointer(ctx))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bls12_381_precompute_msm_bases_cuda(cPoints, cPointsLen, cPrecomputeFactor, cC, cPointsIsOnDevice, cCtx, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -1,97 +0,0 @@
package bls12381
// #cgo CFLAGS: -I./include/
// #include "ntt.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
)
func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] {
cosetGenField := ScalarField{}
cosetGenField.One()
var cosetGen [SCALAR_LIMBS]uint32
for i, v := range cosetGenField.GetLimbs() {
cosetGen[i] = v
}
return core.GetDefaultNTTConfig(cosetGen)
}
func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
core.NttCheck[T](scalars, cfg, results)
var scalarsPointer unsafe.Pointer
if scalars.IsOnDevice() {
scalarsDevice := scalars.(core.DeviceSlice)
scalarsDevice.CheckDevice()
scalarsPointer = scalarsDevice.AsPointer()
} else {
scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0])
}
cScalars := (*C.scalar_t)(scalarsPointer)
cSize := (C.int)(scalars.Len() / int(cfg.BatchSize))
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg))
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsDevice := results.(core.DeviceSlice)
resultsDevice.CheckDevice()
resultsPointer = resultsDevice.AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0])
}
cResults := (*C.scalar_t)(resultsPointer)
__ret := C.bls12_381NTTCuda(cScalars, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func ECNtt[T any](points core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError {
core.NttCheck[T](points, cfg, results)
var pointsPointer unsafe.Pointer
if points.IsOnDevice() {
pointsPointer = points.(core.DeviceSlice).AsPointer()
} else {
pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Projective])[0])
}
cPoints := (*C.projective_t)(pointsPointer)
cSize := (C.int)(points.Len() / int(cfg.BatchSize))
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg))
var resultsPointer unsafe.Pointer
if results.IsOnDevice() {
resultsPointer = results.(core.DeviceSlice).AsPointer()
} else {
resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0])
}
cResults := (*C.projective_t)(resultsPointer)
__ret := C.bls12_381ECNTTCuda(cPoints, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError {
cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer()))
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cFastTwiddles := (C._Bool)(fastTwiddles)
__ret := C.bls12_381InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError {
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
__ret := C.bls12_381ReleaseDomain(cCtx)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,23 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_NTT_H
#define _BLS12_381_NTT_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct NTTConfig NTTConfig;
typedef struct DeviceContext DeviceContext;
cudaError_t bls12_381_ntt_cuda(const scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output);
cudaError_t bls12_381_initialize_domain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles);
cudaError_t bls12_381_release_domain(DeviceContext* ctx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,56 @@
package ntt
// #cgo CFLAGS: -I./include/
// #include "ntt.h"
import "C"
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
bls12_381 "github.com/ingonyama-zk/icicle/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)
cScalars := (*C.scalar_t)(scalarsPointer)
cSize := (C.int)(size)
cDir := (C.int)(dir)
cCfg := (*C.NTTConfig)(cfgPointer)
cResults := (*C.scalar_t)(resultsPointer)
__ret := C.bls12_381_ntt_cuda(cScalars, cSize, cDir, cCfg, cResults)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func GetDefaultNttConfig() core.NTTConfig[[bls12_381.SCALAR_LIMBS]uint32] {
cosetGenField := bls12_381.ScalarField{}
cosetGenField.One()
var cosetGen [bls12_381.SCALAR_LIMBS]uint32
for i, v := range cosetGenField.GetLimbs() {
cosetGen[i] = v
}
return core.GetDefaultNTTConfig(cosetGen)
}
func InitDomain(primitiveRoot bls12_381.ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError {
cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer()))
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
cFastTwiddles := (C._Bool)(fastTwiddles)
__ret := C.bls12_381_initialize_domain(cPrimitiveRoot, cCtx, cFastTwiddles)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}
func ReleaseDomain(ctx cr.DeviceContext) core.IcicleError {
cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx))
__ret := C.bls12_381_release_domain(cCtx)
err := (cr.CudaError)(__ret)
return core.FromCudaError(err)
}

View File

@@ -0,0 +1,51 @@
#include <cuda_runtime.h>
#include <stdbool.h>
#ifndef _BLS12_381_POLY_H
#define _BLS12_381_POLY_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct scalar_t scalar_t;
typedef struct PolynomialInst PolynomialInst;
typedef struct IntegrityPointer IntegrityPointer;
bool bls12_381_polynomial_init_cuda_backend();
PolynomialInst* bls12_381_polynomial_create_from_coefficients(scalar_t* coeffs, size_t size);
PolynomialInst* bls12_381_polynomial_create_from_rou_evaluations(scalar_t* evals, size_t size);
PolynomialInst* bls12_381_polynomial_clone(const PolynomialInst* p);
void bls12_381_polynomial_print(PolynomialInst* p);
void bls12_381_polynomial_delete(PolynomialInst* instance);
PolynomialInst* bls12_381_polynomial_add(const PolynomialInst* a, const PolynomialInst* b);
void bls12_381_polynomial_add_inplace(PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_381_polynomial_subtract(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_381_polynomial_multiply(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_381_polynomial_multiply_by_scalar(const PolynomialInst* a, const scalar_t* scalar);
void bls12_381_polynomial_division(const PolynomialInst* a, const PolynomialInst* b, PolynomialInst** q /*OUT*/, PolynomialInst** r /*OUT*/);
PolynomialInst* bls12_381_polynomial_quotient(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_381_polynomial_remainder(const PolynomialInst* a, const PolynomialInst* b);
PolynomialInst* bls12_381_polynomial_divide_by_vanishing(const PolynomialInst* p, size_t vanishing_poly_degree);
void bls12_381_polynomial_add_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial);
void bls12_381_polynomial_sub_monomial_inplace(PolynomialInst* p, const scalar_t* monomial_coeff, size_t monomial);
void bls12_381_polynomial_evaluate_on_domain(const PolynomialInst* p, scalar_t* domain, size_t domain_size, scalar_t* evals /*OUT*/);
size_t bls12_381_polynomial_degree(PolynomialInst* p);
size_t bls12_381_polynomial_copy_coeffs_range(PolynomialInst* p, scalar_t* memory, size_t start_idx, size_t end_idx);
PolynomialInst* bls12_381_polynomial_even(PolynomialInst* p);
PolynomialInst* bls12_381_polynomial_odd(PolynomialInst* p);
// scalar_t* bls12_381_polynomial_get_coeffs_raw_ptr(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/);
// PolynomialInst* bls12_381_polynomial_slice(PolynomialInst* p, size_t offset, size_t stride, size_t size);
// IntegrityPointer* bls12_381_polynomial_get_coeff_view(PolynomialInst* p, size_t* size /*OUT*/, size_t* device_id /*OUT*/);
// IntegrityPointer* bls12_381_polynomial_get_rou_evaluations_view(PolynomialInst* p, size_t nof_evals, bool is_reversed, size_t* size /*OUT*/, size_t* device_id /*OUT*/);
// const scalar_t* bls12_381_polynomial_intergrity_ptr_get(IntegrityPointer* p);
// bool bls12_381_polynomial_intergrity_ptr_is_valid(IntegrityPointer* p);
// void bls12_381_polynomial_intergrity_ptr_destroy(IntegrityPointer* p);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,176 @@
package polynomial
// #cgo CFLAGS: -I./include/
// #include "polynomial.h"
import "C"
import (
"unsafe"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
)
type PolynomialHandle = C.struct_PolynomialInst
type DensePolynomial struct {
handle *PolynomialHandle
}
func InitPolyBackend() bool {
return (bool)(C.bls12_381_polynomial_init_cuda_backend())
}
func (up *DensePolynomial) Print() {
C.bls12_381_polynomial_print(up.handle)
}
func (up *DensePolynomial) CreateFromCoeffecitients(coeffs core.HostOrDeviceSlice) DensePolynomial {
if coeffs.IsOnDevice() {
coeffs.(core.DeviceSlice).CheckDevice()
}
coeffsPointer := (*C.scalar_t)(coeffs.AsUnsafePointer())
cSize := (C.size_t)(coeffs.Len())
up.handle = C.bls12_381_polynomial_create_from_coefficients(coeffsPointer, cSize)
return *up
}
func (up *DensePolynomial) CreateFromROUEvaluations(evals core.HostOrDeviceSlice) DensePolynomial {
evalsPointer := (*C.scalar_t)(evals.AsUnsafePointer())
cSize := (C.size_t)(evals.Len())
up.handle = C.bls12_381_polynomial_create_from_coefficients(evalsPointer, cSize)
return *up
}
func (up *DensePolynomial) Clone() DensePolynomial {
return DensePolynomial{
handle: C.bls12_381_polynomial_clone(up.handle),
}
}
// TODO @jeremyfelder: Maybe this should be in a SetFinalizer that is set on Create functions?
func (up *DensePolynomial) Delete() {
C.bls12_381_polynomial_delete(up.handle)
}
func (up *DensePolynomial) Add(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_381_polynomial_add(up.handle, b.handle),
}
}
func (up *DensePolynomial) AddInplace(b *DensePolynomial) {
C.bls12_381_polynomial_add_inplace(up.handle, b.handle)
}
func (up *DensePolynomial) Subtract(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_381_polynomial_subtract(up.handle, b.handle),
}
}
func (up *DensePolynomial) Multiply(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_381_polynomial_multiply(up.handle, b.handle),
}
}
func (up *DensePolynomial) MultiplyByScalar(scalar bls12_381.ScalarField) DensePolynomial {
cScalar := (*C.scalar_t)(unsafe.Pointer(scalar.AsPointer()))
return DensePolynomial{
handle: C.bls12_381_polynomial_multiply_by_scalar(up.handle, cScalar),
}
}
func (up *DensePolynomial) Divide(b *DensePolynomial) (DensePolynomial, DensePolynomial) {
var q, r *PolynomialHandle
C.bls12_381_polynomial_division(up.handle, b.handle, &q, &r)
return DensePolynomial{
handle: q,
}, DensePolynomial{
handle: r,
}
}
func (up *DensePolynomial) Quotient(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_381_polynomial_quotient(up.handle, b.handle),
}
}
func (up *DensePolynomial) Remainder(b *DensePolynomial) DensePolynomial {
return DensePolynomial{
handle: C.bls12_381_polynomial_remainder(up.handle, b.handle),
}
}
func (up *DensePolynomial) DivideByVanishing(vanishing_degree uint64) DensePolynomial {
cVanishingDegree := (C.ulong)(vanishing_degree)
return DensePolynomial{
handle: C.bls12_381_polynomial_divide_by_vanishing(up.handle, cVanishingDegree),
}
}
func (up *DensePolynomial) AddMonomial(monomialCoeff bls12_381.ScalarField, monomial uint64) DensePolynomial {
hs := core.HostSliceFromElements([]bls12_381.ScalarField{monomialCoeff})
cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer())
cMonomial := (C.ulong)(monomial)
C.bls12_381_polynomial_add_monomial_inplace(up.handle, cMonomialCoeff, cMonomial)
return *up
}
func (up *DensePolynomial) SubMonomial(monomialCoeff bls12_381.ScalarField, monomial uint64) DensePolynomial {
hs := core.HostSliceFromElements([]bls12_381.ScalarField{monomialCoeff})
cMonomialCoeff := (*C.scalar_t)(hs.AsUnsafePointer())
cMonomial := (C.ulong)(monomial)
C.bls12_381_polynomial_sub_monomial_inplace(up.handle, cMonomialCoeff, cMonomial)
return *up
}
func (up *DensePolynomial) Eval(x bls12_381.ScalarField) bls12_381.ScalarField {
domains := make(core.HostSlice[bls12_381.ScalarField], 1)
domains[0] = x
evals := make(core.HostSlice[bls12_381.ScalarField], 1)
up.EvalOnDomain(domains, evals)
return evals[0]
}
func (up *DensePolynomial) EvalOnDomain(domain, evals core.HostOrDeviceSlice) core.HostOrDeviceSlice {
cDomain := (*C.scalar_t)(domain.AsUnsafePointer())
cDomainSize := (C.size_t)(domain.Len())
cEvals := (*C.scalar_t)(evals.AsUnsafePointer())
C.bls12_381_polynomial_evaluate_on_domain(up.handle, cDomain, cDomainSize, cEvals)
return evals
}
func (up *DensePolynomial) Degree() int {
return int(C.bls12_381_polynomial_degree(up.handle))
}
func (up *DensePolynomial) CopyCoeffsRange(start, end int, out core.HostOrDeviceSlice) (int, core.HostOrDeviceSlice) {
cStart := (C.size_t)(start)
cEnd := (C.size_t)(end)
cScalarOut := (*C.scalar_t)(out.AsUnsafePointer())
__cNumCoeffsRead := C.bls12_381_polynomial_copy_coeffs_range(up.handle, cScalarOut, cStart, cEnd)
return int(__cNumCoeffsRead), out
}
func (up *DensePolynomial) GetCoeff(idx int) bls12_381.ScalarField {
out := make(core.HostSlice[bls12_381.ScalarField], 1)
up.CopyCoeffsRange(idx, idx, out)
return out[0]
}
func (up *DensePolynomial) Even() DensePolynomial {
evenPoly := C.bls12_381_polynomial_even(up.handle)
return DensePolynomial{
handle: evenPoly,
}
}
func (up *DensePolynomial) Odd() DensePolynomial {
oddPoly := C.bls12_381_polynomial_odd(up.handle)
return DensePolynomial{
handle: oddPoly,
}
}

View File

@@ -12,7 +12,7 @@ import (
)
const (
SCALAR_LIMBS int8 = 8
SCALAR_LIMBS int = 8
)
type ScalarField struct {
@@ -35,6 +35,11 @@ func (f ScalarField) AsPointer() *uint32 {
return &f.limbs[0]
}
func (f *ScalarField) FromUint32(v uint32) ScalarField {
f.limbs[0] = v
return *f
}
func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField {
if len(limbs) != f.Len() {
panic("Called FromLimbs with limbs of different length than field")
@@ -89,18 +94,18 @@ func GenerateScalars(size int) core.HostSlice[ScalarField] {
cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0]))
cSize := (C.int)(size)
C.bls12_381GenerateScalars(cScalars, cSize)
C.bls12_381_generate_scalars(cScalars, cSize)
return scalarSlice
}
func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError {
cValues := (*C.scalar_t)(scalars.AsPointer())
cValues := (*C.scalar_t)(scalars.AsUnsafePointer())
cSize := (C.size_t)(scalars.Len())
cIsInto := (C._Bool)(isInto)
defaultCtx, _ := cr.GetDefaultDeviceContext()
cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx))
__ret := C.bls12_381ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx)
__ret := C.bls12_381_scalar_convert_montgomery(cValues, cSize, cIsInto, cCtx)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -0,0 +1,88 @@
package tests
import (
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (
BASE_LIMBS = bls12_381.BASE_LIMBS
)
func TestBaseFieldFromLimbs(t *testing.T) {
emptyField := bls12_381.BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}
func TestBaseFieldGetLimbs(t *testing.T) {
emptyField := bls12_381.BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs")
}
func TestBaseFieldOne(t *testing.T) {
var emptyField bls12_381.BaseField
emptyField.One()
limbOne := test_helpers.GenerateLimbOne(int(BASE_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work")
}
func TestBaseFieldZero(t *testing.T) {
var emptyField bls12_381.BaseField
emptyField.Zero()
limbsZero := make([]uint32, BASE_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed")
}
func TestBaseFieldSize(t *testing.T) {
var emptyField bls12_381.BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestBaseFieldAsPointer(t *testing.T) {
var emptyField bls12_381.BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestBaseFieldFromBytes(t *testing.T) {
var emptyField bls12_381.BaseField
bytes, expected := test_helpers.GenerateBytesArray(int(BASE_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
}
func TestBaseFieldToBytes(t *testing.T) {
var emptyField bls12_381.BaseField
expected, limbs := test_helpers.GenerateBytesArray(int(BASE_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
}

View File

@@ -0,0 +1,103 @@
package tests
import (
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestAffineZero(t *testing.T) {
var fieldZero = bls12_381.BaseField{}
var affineZero bls12_381.Affine
assert.Equal(t, affineZero.X, fieldZero)
assert.Equal(t, affineZero.Y, fieldZero)
x := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
y := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var affine bls12_381.Affine
affine.FromLimbs(x, y)
affine.Zero()
assert.Equal(t, affine.X, fieldZero)
assert.Equal(t, affine.Y, fieldZero)
}
func TestAffineFromLimbs(t *testing.T) {
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var affine bls12_381.Affine
affine.FromLimbs(randLimbs, randLimbs2)
assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs())
assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs())
}
func TestAffineToProjective(t *testing.T) {
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var fieldOne bls12_381.BaseField
fieldOne.One()
var expected bls12_381.Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine bls12_381.Affine
affine.FromLimbs(randLimbs, randLimbs2)
projectivePoint := affine.ToProjective()
assert.Equal(t, expected, projectivePoint)
}
func TestProjectiveZero(t *testing.T) {
var projectiveZero bls12_381.Projective
projectiveZero.Zero()
var fieldZero = bls12_381.BaseField{}
var fieldOne bls12_381.BaseField
fieldOne.One()
assert.Equal(t, projectiveZero.X, fieldZero)
assert.Equal(t, projectiveZero.Y, fieldOne)
assert.Equal(t, projectiveZero.Z, fieldZero)
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var projective bls12_381.Projective
projective.FromLimbs(randLimbs, randLimbs, randLimbs)
projective.Zero()
assert.Equal(t, projective.X, fieldZero)
assert.Equal(t, projective.Y, fieldOne)
assert.Equal(t, projective.Z, fieldZero)
}
func TestProjectiveFromLimbs(t *testing.T) {
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs3 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var projective bls12_381.Projective
projective.FromLimbs(randLimbs, randLimbs2, randLimbs3)
assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs())
assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs())
assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs())
}
func TestProjectiveFromAffine(t *testing.T) {
randLimbs := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(BASE_LIMBS))
var fieldOne bls12_381.BaseField
fieldOne.One()
var expected bls12_381.Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine bls12_381.Affine
affine.FromLimbs(randLimbs, randLimbs2)
var projectivePoint bls12_381.Projective
projectivePoint.FromAffine(affine)
assert.Equal(t, expected, projectivePoint)
}

View File

@@ -0,0 +1,30 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
ecntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/ecntt"
ntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/ntt"
"github.com/stretchr/testify/assert"
)
func TestECNtt(t *testing.T) {
cfg := ntt.GetDefaultNttConfig()
points := bls12_381.GenerateProjectivePoints(1 << largestTestSize)
for _, size := range []int{4, 5, 6, 7, 8} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
pointsCopy := core.HostSliceFromElements[bls12_381.Projective](points[:testSize])
cfg.Ordering = v
cfg.NttAlgorithm = core.Radix2
output := make(core.HostSlice[bls12_381.Projective], testSize)
e := ecntt.ECNtt(pointsCopy, core.KForward, &cfg, output)
assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed")
}
}
}

View File

@@ -1,22 +1,22 @@
//go:build g2
package bls12377
package tests
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/g2"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
func TestG2AffineZero(t *testing.T) {
var fieldZero = G2BaseField{}
var fieldZero = g2.G2BaseField{}
var affineZero G2Affine
var affineZero g2.G2Affine
assert.Equal(t, affineZero.X, fieldZero)
assert.Equal(t, affineZero.Y, fieldZero)
x := generateRandomLimb(int(G2_BASE_LIMBS))
y := generateRandomLimb(int(G2_BASE_LIMBS))
var affine G2Affine
x := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
y := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var affine g2.G2Affine
affine.FromLimbs(x, y)
affine.Zero()
@@ -25,10 +25,10 @@ func TestG2AffineZero(t *testing.T) {
}
func TestG2AffineFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var affine G2Affine
var affine g2.G2Affine
affine.FromLimbs(randLimbs, randLimbs2)
assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs())
@@ -36,15 +36,15 @@ func TestG2AffineFromLimbs(t *testing.T) {
}
func TestG2AffineToProjective(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
var fieldOne G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var fieldOne g2.G2BaseField
fieldOne.One()
var expected G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var expected g2.G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine G2Affine
var affine g2.G2Affine
affine.FromLimbs(randLimbs, randLimbs2)
projectivePoint := affine.ToProjective()
@@ -52,18 +52,18 @@ func TestG2AffineToProjective(t *testing.T) {
}
func TestG2ProjectiveZero(t *testing.T) {
var projectiveZero G2Projective
var projectiveZero g2.G2Projective
projectiveZero.Zero()
var fieldZero = G2BaseField{}
var fieldOne G2BaseField
var fieldZero = g2.G2BaseField{}
var fieldOne g2.G2BaseField
fieldOne.One()
assert.Equal(t, projectiveZero.X, fieldZero)
assert.Equal(t, projectiveZero.Y, fieldOne)
assert.Equal(t, projectiveZero.Z, fieldZero)
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
var projective G2Projective
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var projective g2.G2Projective
projective.FromLimbs(randLimbs, randLimbs, randLimbs)
projective.Zero()
@@ -73,11 +73,11 @@ func TestG2ProjectiveZero(t *testing.T) {
}
func TestG2ProjectiveFromLimbs(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs3 := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs3 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var projective G2Projective
var projective g2.G2Projective
projective.FromLimbs(randLimbs, randLimbs2, randLimbs3)
assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs())
@@ -86,18 +86,18 @@ func TestG2ProjectiveFromLimbs(t *testing.T) {
}
func TestG2ProjectiveFromAffine(t *testing.T) {
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS))
var fieldOne G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
randLimbs2 := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
var fieldOne g2.G2BaseField
fieldOne.One()
var expected G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:])
var expected g2.G2Projective
expected.FromLimbs(randLimbs, randLimbs2, fieldOne.GetLimbs()[:])
var affine G2Affine
var affine g2.G2Affine
affine.FromLimbs(randLimbs, randLimbs2)
var projectivePoint G2Projective
var projectivePoint g2.G2Projective
projectivePoint.FromAffine(affine)
assert.Equal(t, expected, projectivePoint)
}

View File

@@ -1,36 +1,40 @@
//go:build g2
package bw6761
package tests
import (
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/g2"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (
G2BASE_LIMBS = bls12_381.G2BASE_LIMBS
)
func TestG2BaseFieldFromLimbs(t *testing.T) {
emptyField := G2BaseField{}
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
emptyField := bls12_381.G2BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the G2BaseField's limbs")
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.limbs)
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}
func TestG2BaseFieldGetLimbs(t *testing.T) {
emptyField := G2BaseField{}
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
emptyField := bls12_381.G2BaseField{}
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs")
}
func TestG2BaseFieldOne(t *testing.T) {
var emptyField G2BaseField
var emptyField bls12_381.G2BaseField
emptyField.One()
limbOne := generateLimbOne(int(G2_BASE_LIMBS))
limbOne := test_helpers.GenerateLimbOne(int(G2BASE_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
@@ -38,12 +42,12 @@ func TestG2BaseFieldOne(t *testing.T) {
}
func TestG2BaseFieldZero(t *testing.T) {
var emptyField G2BaseField
var emptyField bls12_381.G2BaseField
emptyField.Zero()
limbsZero := make([]uint32, G2_BASE_LIMBS)
limbsZero := make([]uint32, G2BASE_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
@@ -51,24 +55,24 @@ func TestG2BaseFieldZero(t *testing.T) {
}
func TestG2BaseFieldSize(t *testing.T) {
var emptyField G2BaseField
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
var emptyField bls12_381.G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestG2BaseFieldAsPointer(t *testing.T) {
var emptyField G2BaseField
randLimbs := generateRandomLimb(int(G2_BASE_LIMBS))
var emptyField bls12_381.G2BaseField
randLimbs := test_helpers.GenerateRandomLimb(int(G2BASE_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestG2BaseFieldFromBytes(t *testing.T) {
var emptyField G2BaseField
bytes, expected := generateBytesArray(int(G2_BASE_LIMBS))
var emptyField bls12_381.G2BaseField
bytes, expected := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
@@ -76,8 +80,8 @@ func TestG2BaseFieldFromBytes(t *testing.T) {
}
func TestG2BaseFieldToBytes(t *testing.T) {
var emptyField G2BaseField
expected, limbs := generateBytesArray(int(G2_BASE_LIMBS))
var emptyField bls12_381.G2BaseField
expected, limbs := test_helpers.GenerateBytesArray(int(G2BASE_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")

View File

@@ -1,6 +1,4 @@
//go:build g2
package bls12381
package tests
import (
"fmt"
@@ -9,16 +7,18 @@ import (
"github.com/stretchr/testify/assert"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
icicleBls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/g2"
)
func projectiveToGnarkAffineG2(p G2Projective) bls12381.G2Affine {
func projectiveToGnarkAffineG2(p g2.G2Projective) bls12381.G2Affine {
pxBytes := p.X.ToBytesLittleEndian()
pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes]))
pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:]))
@@ -62,7 +62,7 @@ func projectiveToGnarkAffineG2(p G2Projective) bls12381.G2Affine {
return *g2Affine.FromJacobian(&g2Jac)
}
func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points core.HostSlice[G2Affine], out G2Projective) bool {
func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[g2.G2Affine], out g2.G2Projective) bool {
scalarsFr := make([]fr.Element, len(scalars))
for i, v := range scalars {
slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian()))
@@ -73,6 +73,11 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points cor
for i, v := range points {
pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective())
}
return testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr, pointsFp, out)
}
func testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G2Affine], out g2.G2Projective) bool {
var msmRes bls12381.G2Jac
msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{})
@@ -83,54 +88,117 @@ func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points cor
return msmRes.Equal(&icicleResAsJac)
}
func convertIcicleG2AffineToG2Affine(iciclePoints []g2.G2Affine) []bls12381.G2Affine {
points := make([]bls12381.G2Affine, len(iciclePoints))
for index, iciclePoint := range iciclePoints {
xBytes := ([fp.Bytes * 2]byte)(iciclePoint.X.ToBytesLittleEndian())
xA0Bytes := ([fp.Bytes]byte)(xBytes[:fp.Bytes])
xA1Bytes := ([fp.Bytes]byte)(xBytes[fp.Bytes:])
xA0Elem, _ := fp.LittleEndian.Element(&xA0Bytes)
xA1Elem, _ := fp.LittleEndian.Element(&xA1Bytes)
yBytes := ([fp.Bytes * 2]byte)(iciclePoint.Y.ToBytesLittleEndian())
yA0Bytes := ([fp.Bytes]byte)(yBytes[:fp.Bytes])
yA1Bytes := ([fp.Bytes]byte)(yBytes[fp.Bytes:])
yA0Elem, _ := fp.LittleEndian.Element(&yA0Bytes)
yA1Elem, _ := fp.LittleEndian.Element(&yA1Bytes)
points[index] = bls12381.G2Affine{
X: bls12381.E2{
A0: xA0Elem,
A1: xA1Elem,
},
Y: bls12381.E2{
A0: yA0Elem,
A1: yA1Elem,
},
}
}
return points
}
func TestMSMG2(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := G2GenerateAffinePoints(size)
scalars := icicleBls12_381.GenerateScalars(size)
points := g2.G2GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], 1)
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)
cr.SynchronizeStream(&stream)
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0]))
}
}
func TestMSMG2GnarkCryptoTypes(t *testing.T) {
cfg := g2.G2GetDefaultMSMConfig()
for _, power := range []int{3} {
size := 1 << power
scalars := make([]fr.Element, size)
var x fr.Element
for i := 0; i < size; i++ {
x.SetRandom()
scalars[i] = x
}
scalarsHost := (core.HostSlice[fr.Element])(scalars)
points := g2.G2GenerateAffinePoints(size)
pointsGnark := convertIcicleG2AffineToG2Affine(points)
pointsHost := (core.HostSlice[bls12381.G2Affine])(pointsGnark)
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.ArePointsMontgomeryForm = true
cfg.AreScalarsMontgomeryForm = true
e = g2.G2Msm(scalarsHost, pointsHost, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmG2GnarkCryptoTypes(scalarsHost, pointsHost, outHost[0]))
}
}
func TestMSMG2Batch(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := G2GenerateAffinePoints(totalSize)
scalars := icicleBls12_381.GenerateScalars(totalSize)
points := g2.G2GenerateAffinePoints(totalSize)
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], batchSize)
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -143,36 +211,35 @@ func TestMSMG2Batch(t *testing.T) {
}
func TestPrecomputeBaseG2(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
const precomputeFactor = 8
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := G2GenerateAffinePoints(totalSize)
scalars := icicleBls12_381.GenerateScalars(totalSize)
points := g2.G2GenerateAffinePoints(totalSize)
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
e = G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
e = g2.G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
e = G2Msm(scalars, precomputeOut, &cfg, out)
e = g2.G2Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], batchSize)
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
precomputeOut.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -185,30 +252,29 @@ func TestPrecomputeBaseG2(t *testing.T) {
}
func TestMSMG2SkewedDistribution(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
scalars := icicleBls12_381.GenerateScalars(size)
for i := size / 4; i < size; i++ {
scalars[i].One()
}
points := G2GenerateAffinePoints(size)
points := g2.G2GenerateAffinePoints(size)
for i := 0; i < size/4; i++ {
points[i].Zero()
}
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], 1)
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0]))
}
@@ -225,23 +291,23 @@ func TestMSMG2MultiDevice(t *testing.T) {
wg.Add(1)
cr.RunOnDevice(i, func(args ...any) {
defer wg.Done()
cfg := GetDefaultMSMConfig()
cfg := g2.G2GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := G2GenerateAffinePoints(size)
scalars := icicleBls12_381.GenerateScalars(size)
points := g2.G2GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p G2Projective
var p g2.G2Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = G2Msm(scalars, points, &cfg, out)
e = g2.G2Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[G2Projective], 1)
outHost := make(core.HostSlice[g2.G2Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)

View File

@@ -0,0 +1,48 @@
package tests
import (
"os"
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
ntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/ntt"
poly "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/polynomial"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft"
)
const (
largestTestSize = 20
)
func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError {
rouMont, _ := fft.Generator(uint64(1 << largestTestSize))
rou := rouMont.Bits()
rouIcicle := bls12_381.ScalarField{}
limbs := core.ConvertUint64ArrToUint32Arr(rou[:])
rouIcicle.FromLimbs(limbs)
e := ntt.InitDomain(rouIcicle, cfg.Ctx, false)
return e
}
func TestMain(m *testing.M) {
poly.InitPolyBackend()
// setup domain
cfg := ntt.GetDefaultNttConfig()
e := initDomain(largestTestSize, cfg)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("initDomain failed")
}
// execute tests
os.Exit(m.Run())
// release domain
e = ntt.ReleaseDomain(cfg.Ctx)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("ReleaseDomain failed")
}
}

View File

@@ -1,4 +1,4 @@
package bls12381
package tests
import (
"fmt"
@@ -7,16 +7,18 @@ import (
"github.com/stretchr/testify/assert"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
icicleBls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/msm"
)
func projectiveToGnarkAffine(p Projective) bls12381.G1Affine {
func projectiveToGnarkAffine(p icicleBls12_381.Projective) bls12381.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()))
@@ -33,7 +35,7 @@ func projectiveToGnarkAffine(p Projective) bls12381.G1Affine {
return bls12381.G1Affine{X: *x, Y: *y}
}
func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.HostSlice[Affine], out Projective) bool {
func testAgainstGnarkCryptoMsm(scalars core.HostSlice[icicleBls12_381.ScalarField], points core.HostSlice[icicleBls12_381.Affine], out icicleBls12_381.Projective) bool {
scalarsFr := make([]fr.Element, len(scalars))
for i, v := range scalars {
slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian()))
@@ -44,6 +46,11 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.
for i, v := range points {
pointsFp[i] = projectiveToGnarkAffine(v.ToProjective())
}
return testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr, pointsFp, out)
}
func testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsFr core.HostSlice[fr.Element], pointsFp core.HostSlice[bls12381.G1Affine], out icicleBls12_381.Projective) bool {
var msmRes bls12381.G1Jac
msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{})
@@ -54,54 +61,104 @@ func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.
return msmRes.Equal(&icicleResAsJac)
}
func convertIcicleAffineToG1Affine(iciclePoints []icicleBls12_381.Affine) []bls12381.G1Affine {
points := make([]bls12381.G1Affine, len(iciclePoints))
for index, iciclePoint := range iciclePoints {
xBytes := ([fp.Bytes]byte)(iciclePoint.X.ToBytesLittleEndian())
fpXElem, _ := fp.LittleEndian.Element(&xBytes)
yBytes := ([fp.Bytes]byte)(iciclePoint.Y.ToBytesLittleEndian())
fpYElem, _ := fp.LittleEndian.Element(&yBytes)
points[index] = bls12381.G1Affine{
X: fpXElem,
Y: fpYElem,
}
}
return points
}
func TestMSM(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := GenerateAffinePoints(size)
scalars := icicleBls12_381.GenerateScalars(size)
points := icicleBls12_381.GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p Projective
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], 1)
outHost := make(core.HostSlice[icicleBls12_381.Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)
cr.SynchronizeStream(&stream)
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0]))
}
}
func TestMSMGnarkCryptoTypes(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
for _, power := range []int{3} {
size := 1 << power
scalars := make([]fr.Element, size)
var x fr.Element
for i := 0; i < size; i++ {
x.SetRandom()
scalars[i] = x
}
scalarsHost := (core.HostSlice[fr.Element])(scalars)
points := icicleBls12_381.GenerateAffinePoints(size)
pointsGnark := convertIcicleAffineToG1Affine(points)
pointsHost := (core.HostSlice[bls12381.G1Affine])(pointsGnark)
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.ArePointsMontgomeryForm = true
cfg.AreScalarsMontgomeryForm = true
e = msm.Msm(scalarsHost, pointsHost, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[icicleBls12_381.Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsmGnarkCryptoTypes(scalarsHost, pointsHost, outHost[0]))
}
}
func TestMSMBatch(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := GenerateAffinePoints(totalSize)
scalars := icicleBls12_381.GenerateScalars(totalSize)
points := icicleBls12_381.GenerateAffinePoints(totalSize)
var p Projective
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e := out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], batchSize)
outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -114,36 +171,35 @@ func TestMSMBatch(t *testing.T) {
}
func TestPrecomputeBase(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
totalSize := size * batchSize
scalars := GenerateScalars(totalSize)
points := GenerateAffinePoints(totalSize)
scalars := icicleBls12_381.GenerateScalars(totalSize)
points := icicleBls12_381.GenerateAffinePoints(totalSize)
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
e = PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
var p Projective
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
e = Msm(scalars, precomputeOut, &cfg, out)
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], batchSize)
outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()
precomputeOut.Free()
// Check with gnark-crypto
for i := 0; i < batchSize; i++ {
scalarsSlice := scalars[i*size : (i+1)*size]
@@ -156,30 +212,29 @@ func TestPrecomputeBase(t *testing.T) {
}
func TestMSMSkewedDistribution(t *testing.T) {
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
scalars := icicleBls12_381.GenerateScalars(size)
for i := size / 4; i < size; i++ {
scalars[i].One()
}
points := GenerateAffinePoints(size)
points := icicleBls12_381.GenerateAffinePoints(size)
for i := 0; i < size/4; i++ {
points[i].Zero()
}
var p Projective
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e := out.Malloc(p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], 1)
outHost := make(core.HostSlice[icicleBls12_381.Projective], 1)
outHost.CopyFromDevice(&out)
out.Free()
// Check with gnark-crypto
assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0]))
}
@@ -196,23 +251,23 @@ func TestMSMMultiDevice(t *testing.T) {
wg.Add(1)
cr.RunOnDevice(i, func(args ...any) {
defer wg.Done()
cfg := GetDefaultMSMConfig()
cfg := msm.GetDefaultMSMConfig()
cfg.IsAsync = true
for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} {
size := 1 << power
scalars := GenerateScalars(size)
points := GenerateAffinePoints(size)
scalars := icicleBls12_381.GenerateScalars(size)
points := icicleBls12_381.GenerateAffinePoints(size)
stream, _ := cr.CreateStream()
var p Projective
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e := out.MallocAsync(p.Size(), p.Size(), stream)
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.Ctx.Stream = &stream
e = Msm(scalars, points, &cfg, out)
e = msm.Msm(scalars, points, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
outHost := make(core.HostSlice[Projective], 1)
outHost := make(core.HostSlice[icicleBls12_381.Projective], 1)
outHost.CopyFromDeviceAsync(&out, stream)
out.FreeAsync(stream)

View File

@@ -1,40 +1,20 @@
package bls12381
package tests
import (
"os"
"reflect"
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
ntt "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/ntt"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
)
const (
largestTestSize = 17
)
func init() {
cfg := GetDefaultNttConfig()
initDomain(largestTestSize, cfg)
}
func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) core.IcicleError {
rouMont, _ := fft.Generator(uint64(1 << largestTestSize))
rou := rouMont.Bits()
rouIcicle := ScalarField{}
limbs := core.ConvertUint64ArrToUint32Arr(rou[:])
rouIcicle.FromLimbs(limbs)
e := InitDomain(rouIcicle, cfg.Ctx, false)
return e
}
func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool {
domainWithPrecompute := fft.NewDomain(uint64(size))
func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[bls12_381.ScalarField], output core.HostSlice[bls12_381.ScalarField], order core.Ordering, direction core.NTTDir) bool {
scalarsFr := make([]fr.Element, size)
for i, v := range scalars {
slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian()))
@@ -46,6 +26,11 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], ou
outputAsFr[i] = slice64
}
return testAgainstGnarkCryptoNttGnarkTypes(size, scalarsFr, outputAsFr, order, direction)
}
func testAgainstGnarkCryptoNttGnarkTypes(size int, scalarsFr core.HostSlice[fr.Element], outputAsFr core.HostSlice[fr.Element], order core.Ordering, direction core.NTTDir) bool {
domainWithPrecompute := fft.NewDomain(uint64(size))
// DIT + BitReverse == Ordering.kRR
// DIT == Ordering.kRN
// DIF + BitReverse == Ordering.kNN
@@ -68,72 +53,77 @@ func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], ou
}
return reflect.DeepEqual(scalarsFr, outputAsFr)
}
func TestNTTGetDefaultConfig(t *testing.T) {
actual := GetDefaultNttConfig()
expected := generateLimbOne(int(SCALAR_LIMBS))
actual := ntt.GetDefaultNttConfig()
expected := test_helpers.GenerateLimbOne(int(bls12_381.SCALAR_LIMBS))
assert.Equal(t, expected, actual.CosetGen[:])
cosetGenField := ScalarField{}
cosetGenField := bls12_381.ScalarField{}
cosetGenField.One()
assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen)
}
func TestInitDomain(t *testing.T) {
t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function")
cfg := GetDefaultNttConfig()
cfg := ntt.GetDefaultNttConfig()
assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) })
}
func TestNtt(t *testing.T) {
cfg := GetDefaultNttConfig()
scalars := GenerateScalars(1 << largestTestSize)
cfg := ntt.GetDefaultNttConfig()
scalars := bls12_381.GenerateScalars(1 << largestTestSize)
for _, size := range []int{4, largestTestSize} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize])
scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize])
cfg.Ordering = v
// run ntt
output := make(core.HostSlice[ScalarField], testSize)
Ntt(scalarsCopy, core.KForward, &cfg, output)
output := make(core.HostSlice[bls12_381.ScalarField], testSize)
ntt.Ntt(scalarsCopy, core.KForward, &cfg, output)
// Compare with gnark-crypto
assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward))
}
}
}
func TestNttFrElement(t *testing.T) {
cfg := ntt.GetDefaultNttConfig()
scalars := make([]fr.Element, 4)
var x fr.Element
for i := 0; i < 4; i++ {
x.SetRandom()
scalars[i] = x
}
func TestECNtt(t *testing.T) {
cfg := GetDefaultNttConfig()
points := GenerateProjectivePoints(1 << largestTestSize)
for _, size := range []int{4} {
for _, v := range [1]core.Ordering{core.KNN} {
testSize := size
for _, size := range []int{4, 5, 6, 7, 8} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
pointsCopy := core.HostSliceFromElements[Projective](points[:testSize])
scalarsCopy := (core.HostSlice[fr.Element])(scalars[:testSize])
cfg.Ordering = v
cfg.NttAlgorithm = core.Radix2
output := make(core.HostSlice[Projective], testSize)
e := ECNtt(pointsCopy, core.KForward, &cfg, output)
assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ECNtt failed")
// run ntt
output := make(core.HostSlice[fr.Element], testSize)
ntt.Ntt(scalarsCopy, core.KForward, &cfg, output)
// Compare with gnark-crypto
assert.True(t, testAgainstGnarkCryptoNttGnarkTypes(testSize, scalarsCopy, output, v, core.KForward))
}
}
}
func TestNttDeviceAsync(t *testing.T) {
cfg := GetDefaultNttConfig()
scalars := GenerateScalars(1 << largestTestSize)
cfg := ntt.GetDefaultNttConfig()
scalars := bls12_381.GenerateScalars(1 << largestTestSize)
for _, size := range []int{1, 10, largestTestSize} {
for _, direction := range []core.NTTDir{core.KForward, core.KInverse} {
for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
testSize := 1 << size
scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize])
scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:testSize])
stream, _ := cr.CreateStream()
@@ -147,12 +137,11 @@ func TestNttDeviceAsync(t *testing.T) {
deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream)
// run ntt
Ntt(deviceInput, direction, &cfg, deviceOutput)
output := make(core.HostSlice[ScalarField], testSize)
ntt.Ntt(deviceInput, direction, &cfg, deviceOutput)
output := make(core.HostSlice[bls12_381.ScalarField], testSize)
output.CopyFromDeviceAsync(&deviceOutput, stream)
cr.SynchronizeStream(&stream)
// Compare with gnark-crypto
assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction))
}
@@ -161,22 +150,22 @@ func TestNttDeviceAsync(t *testing.T) {
}
func TestNttBatch(t *testing.T) {
cfg := GetDefaultNttConfig()
cfg := ntt.GetDefaultNttConfig()
largestBatchSize := 100
scalars := GenerateScalars(1 << largestTestSize * largestBatchSize)
scalars := bls12_381.GenerateScalars(1 << largestTestSize * largestBatchSize)
for _, size := range []int{4, largestTestSize} {
for _, batchSize := range []int{1, 16, largestBatchSize} {
testSize := 1 << size
totalSize := testSize * batchSize
scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize])
scalarsCopy := core.HostSliceFromElements[bls12_381.ScalarField](scalars[:totalSize])
cfg.Ordering = core.KNN
cfg.BatchSize = int32(batchSize)
// run ntt
output := make(core.HostSlice[ScalarField], totalSize)
Ntt(scalarsCopy, core.KForward, &cfg, output)
output := make(core.HostSlice[bls12_381.ScalarField], totalSize)
ntt.Ntt(scalarsCopy, core.KForward, &cfg, output)
// Compare with gnark-crypto
domainWithPrecompute := fft.NewDomain(uint64(testSize))
@@ -205,36 +194,18 @@ func TestNttBatch(t *testing.T) {
func TestReleaseDomain(t *testing.T) {
t.Skip("Skipped because each test requires the domain to be initialized before running. We ensure this using the TestMain() function")
cfg := GetDefaultNttConfig()
e := ReleaseDomain(cfg.Ctx)
cfg := ntt.GetDefaultNttConfig()
e := ntt.ReleaseDomain(cfg.Ctx)
assert.Equal(t, core.IcicleErrorCode(0), e.IcicleErrorCode, "ReleasDomain failed")
}
func TestMain(m *testing.M) {
// setup domain
cfg := GetDefaultNttConfig()
e := initDomain(largestTestSize, cfg)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("initDomain failed")
}
// execute tests
os.Exit(m.Run())
// release domain
e = ReleaseDomain(cfg.Ctx)
if e.IcicleErrorCode != core.IcicleErrorCode(0) {
panic("ReleaseDomain failed")
}
}
// func TestNttArbitraryCoset(t *testing.T) {
// for _, size := range []int{20} {
// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} {
// testSize := 1 << size
// scalars := GenerateScalars(testSize)
// cfg := GetDefaultNttConfig()
// cfg := ntt.GetDefaultNttConfig()
// var scalarsCopy core.HostSlice[ScalarField]
// for _, v := range scalars {

View File

@@ -0,0 +1,229 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
// "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/ntt"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/polynomial"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/vecOps"
"github.com/stretchr/testify/assert"
)
var one, two, three, four, five bls12_381.ScalarField
func init() {
one.One()
two.FromUint32(2)
three.FromUint32(3)
four.FromUint32(4)
five.FromUint32(5)
}
func rand() bls12_381.ScalarField {
return bls12_381.GenerateScalars(1)[0]
}
func randomPoly(size int) (f polynomial.DensePolynomial) {
f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_381.GenerateScalars(size)))
return f
}
func vecOp(a, b bls12_381.ScalarField, op core.VecOps) bls12_381.ScalarField {
ahost := core.HostSliceWithValue(a, 1)
bhost := core.HostSliceWithValue(b, 1)
out := make(core.HostSlice[bls12_381.ScalarField], 1)
cfg := core.DefaultVecOpsConfig()
vecOps.VecOp(ahost, bhost, out, cfg, op)
return out[0]
}
func TestPolyCreateFromCoefficients(t *testing.T) {
scalars := bls12_381.GenerateScalars(33)
var uniPoly polynomial.DensePolynomial
poly := uniPoly.CreateFromCoeffecitients(scalars)
poly.Print()
}
func TestPolyEval(t *testing.T) {
// testing correct evaluation of f(8) for f(x)=4x^2+2x+5
coeffs := core.HostSliceFromElements([]bls12_381.ScalarField{five, two, four})
var f polynomial.DensePolynomial
f.CreateFromCoeffecitients(coeffs)
var x bls12_381.ScalarField
x.FromUint32(8)
domains := make(core.HostSlice[bls12_381.ScalarField], 1)
domains[0] = x
evals := make(core.HostSlice[bls12_381.ScalarField], 1)
fEvaled := f.EvalOnDomain(domains, evals)
var expected bls12_381.ScalarField
assert.Equal(t, expected.FromUint32(277), fEvaled.(core.HostSlice[bls12_381.ScalarField])[0])
}
func TestPolyClone(t *testing.T) {
f := randomPoly(8)
x := rand()
fx := f.Eval(x)
g := f.Clone()
fg := f.Add(&g)
gx := g.Eval(x)
fgx := fg.Eval(x)
assert.Equal(t, fx, gx)
assert.Equal(t, vecOp(fx, gx, core.Add), fgx)
}
func TestPolyAddSubMul(t *testing.T) {
testSize := 1 << 10
f := randomPoly(testSize)
g := randomPoly(testSize)
x := rand()
fx := f.Eval(x)
gx := g.Eval(x)
polyAdd := f.Add(&g)
fxAddgx := vecOp(fx, gx, core.Add)
assert.Equal(t, polyAdd.Eval(x), fxAddgx)
polySub := f.Subtract(&g)
fxSubgx := vecOp(fx, gx, core.Sub)
assert.Equal(t, polySub.Eval(x), fxSubgx)
polyMul := f.Multiply(&g)
fxMulgx := vecOp(fx, gx, core.Mul)
assert.Equal(t, polyMul.Eval(x), fxMulgx)
s1 := rand()
polMulS1 := f.MultiplyByScalar(s1)
assert.Equal(t, polMulS1.Eval(x), vecOp(fx, s1, core.Mul))
s2 := rand()
polMulS2 := f.MultiplyByScalar(s2)
assert.Equal(t, polMulS2.Eval(x), vecOp(fx, s2, core.Mul))
}
func TestPolyMonomials(t *testing.T) {
var zero bls12_381.ScalarField
var f polynomial.DensePolynomial
f.CreateFromCoeffecitients(core.HostSliceFromElements([]bls12_381.ScalarField{one, zero, two}))
x := rand()
fx := f.Eval(x)
f.AddMonomial(three, 1)
fxAdded := f.Eval(x)
assert.Equal(t, fxAdded, vecOp(fx, vecOp(three, x, core.Mul), core.Add))
f.SubMonomial(one, 0)
fxSub := f.Eval(x)
assert.Equal(t, fxSub, vecOp(fxAdded, one, core.Sub))
}
func TestPolyReadCoeffs(t *testing.T) {
var f polynomial.DensePolynomial
coeffs := core.HostSliceFromElements([]bls12_381.ScalarField{one, two, three, four})
f.CreateFromCoeffecitients(coeffs)
coeffsCopied := make(core.HostSlice[bls12_381.ScalarField], coeffs.Len())
_, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsCopied)
assert.ElementsMatch(t, coeffs, coeffsCopied)
var coeffsDevice core.DeviceSlice
coeffsDevice.Malloc(coeffs.Len()*one.Size(), one.Size())
_, _ = f.CopyCoeffsRange(0, coeffs.Len()-1, coeffsDevice)
coeffsHost := make(core.HostSlice[bls12_381.ScalarField], coeffs.Len())
coeffsHost.CopyFromDevice(&coeffsDevice)
assert.ElementsMatch(t, coeffs, coeffsHost)
}
func TestPolyOddEvenSlicing(t *testing.T) {
size := 1<<10 - 3
f := randomPoly(size)
even := f.Even()
odd := f.Odd()
assert.Equal(t, f.Degree(), even.Degree()+odd.Degree()+1)
x := rand()
var evenExpected, oddExpected bls12_381.ScalarField
for i := size; i >= 0; i-- {
if i%2 == 0 {
mul := vecOp(evenExpected, x, core.Mul)
evenExpected = vecOp(mul, f.GetCoeff(i), core.Add)
} else {
mul := vecOp(oddExpected, x, core.Mul)
oddExpected = vecOp(mul, f.GetCoeff(i), core.Add)
}
}
evenEvaled := even.Eval(x)
assert.Equal(t, evenExpected, evenEvaled)
oddEvaled := odd.Eval(x)
assert.Equal(t, oddExpected, oddEvaled)
}
func TestPolynomialDivision(t *testing.T) {
// divide f(x)/g(x), compute q(x), r(x) and check f(x)=q(x)*g(x)+r(x)
var f, g polynomial.DensePolynomial
f.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_381.GenerateScalars(1 << 4)))
g.CreateFromCoeffecitients(core.HostSliceFromElements(bls12_381.GenerateScalars(1 << 2)))
q, r := f.Divide(&g)
qMulG := q.Multiply(&g)
fRecon := qMulG.Add(&r)
x := bls12_381.GenerateScalars(1)[0]
fEval := f.Eval(x)
fReconEval := fRecon.Eval(x)
assert.Equal(t, fEval, fReconEval)
}
func TestDivideByVanishing(t *testing.T) {
// poly of x^4-1 vanishes ad 4th rou
var zero bls12_381.ScalarField
minus_one := vecOp(zero, one, core.Sub)
coeffs := core.HostSliceFromElements([]bls12_381.ScalarField{minus_one, zero, zero, zero, one}) // x^4-1
var v polynomial.DensePolynomial
v.CreateFromCoeffecitients(coeffs)
f := randomPoly(1 << 3)
fv := f.Multiply(&v)
fDegree := f.Degree()
fvDegree := fv.Degree()
assert.Equal(t, fDegree+4, fvDegree)
fReconstructed := fv.DivideByVanishing(4)
assert.Equal(t, fDegree, fReconstructed.Degree())
x := rand()
assert.Equal(t, f.Eval(x), fReconstructed.Eval(x))
}
// func TestPolySlice(t *testing.T) {
// size := 4
// coeffs := bls12_381.GenerateScalars(size)
// var f DensePolynomial
// f.CreateFromCoeffecitients(coeffs)
// fSlice := f.AsSlice()
// assert.True(t, fSlice.IsOnDevice())
// assert.Equal(t, size, fSlice.Len())
// hostSlice := make(core.HostSlice[bls12_381.ScalarField], size)
// hostSlice.CopyFromDevice(fSlice)
// assert.Equal(t, coeffs, hostSlice)
// cfg := ntt.GetDefaultNttConfig()
// res := make(core.HostSlice[bls12_381.ScalarField], size)
// ntt.Ntt(fSlice, core.KForward, cfg, res)
// assert.Equal(t, f.Eval(one), res[0])
// }

View File

@@ -0,0 +1,120 @@
package tests
import (
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/wrappers/golang/test_helpers"
"github.com/stretchr/testify/assert"
"testing"
)
const (
SCALAR_LIMBS = bls12_381.SCALAR_LIMBS
)
func TestScalarFieldFromLimbs(t *testing.T) {
emptyField := bls12_381.ScalarField{}
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs")
randLimbs[0] = 100
assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}
func TestScalarFieldGetLimbs(t *testing.T) {
emptyField := bls12_381.ScalarField{}
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs")
}
func TestScalarFieldOne(t *testing.T) {
var emptyField bls12_381.ScalarField
emptyField.One()
limbOne := test_helpers.GenerateLimbOne(int(SCALAR_LIMBS))
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.One()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work")
}
func TestScalarFieldZero(t *testing.T) {
var emptyField bls12_381.ScalarField
emptyField.Zero()
limbsZero := make([]uint32, SCALAR_LIMBS)
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
emptyField.Zero()
assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed")
}
func TestScalarFieldSize(t *testing.T) {
var emptyField bls12_381.ScalarField
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}
func TestScalarFieldAsPointer(t *testing.T) {
var emptyField bls12_381.ScalarField
randLimbs := test_helpers.GenerateRandomLimb(int(SCALAR_LIMBS))
emptyField.FromLimbs(randLimbs[:])
assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}
func TestScalarFieldFromBytes(t *testing.T) {
var emptyField bls12_381.ScalarField
bytes, expected := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS))
emptyField.FromBytesLittleEndian(bytes)
assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
}
func TestScalarFieldToBytes(t *testing.T) {
var emptyField bls12_381.ScalarField
expected, limbs := test_helpers.GenerateBytesArray(int(SCALAR_LIMBS))
emptyField.FromLimbs(limbs)
assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
}
func TestBls12_381GenerateScalars(t *testing.T) {
const numScalars = 8
scalars := bls12_381.GenerateScalars(numScalars)
assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars)
assert.Equal(t, numScalars, scalars.Len())
zeroScalar := bls12_381.ScalarField{}
assert.NotContains(t, scalars, zeroScalar)
}
func TestBls12_381MongtomeryConversion(t *testing.T) {
size := 1 << 15
scalars := bls12_381.GenerateScalars(size)
var deviceScalars core.DeviceSlice
scalars.CopyToDevice(&deviceScalars, true)
bls12_381.ToMontgomery(&deviceScalars)
scalarsMontHost := bls12_381.GenerateScalars(size)
scalarsMontHost.CopyFromDevice(&deviceScalars)
assert.NotEqual(t, scalars, scalarsMontHost)
bls12_381.FromMontgomery(&deviceScalars)
scalarsMontHost.CopyFromDevice(&deviceScalars)
assert.Equal(t, scalars, scalarsMontHost)
}

View File

@@ -0,0 +1,69 @@
package tests
import (
"testing"
"github.com/ingonyama-zk/icicle/wrappers/golang/core"
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime"
bls12_381 "github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381"
"github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381/vecOps"
"github.com/stretchr/testify/assert"
)
func TestBls12_381VecOps(t *testing.T) {
testSize := 1 << 14
a := bls12_381.GenerateScalars(testSize)
b := bls12_381.GenerateScalars(testSize)
var scalar bls12_381.ScalarField
scalar.One()
ones := core.HostSliceWithValue(scalar, testSize)
out := make(core.HostSlice[bls12_381.ScalarField], testSize)
out2 := make(core.HostSlice[bls12_381.ScalarField], testSize)
out3 := make(core.HostSlice[bls12_381.ScalarField], testSize)
cfg := core.DefaultVecOpsConfig()
vecOps.VecOp(a, b, out, cfg, core.Add)
vecOps.VecOp(out, b, out2, cfg, core.Sub)
assert.Equal(t, a, out2)
vecOps.VecOp(a, ones, out3, cfg, core.Mul)
assert.Equal(t, a, out3)
}
func TestBls12_381Transpose(t *testing.T) {
rowSize := 1 << 6
columnSize := 1 << 8
onDevice := false
isAsync := false
matrix := bls12_381.GenerateScalars(rowSize * columnSize)
out := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize)
out2 := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize)
ctx, _ := cr.GetDefaultDeviceContext()
vecOps.TransposeMatrix(matrix, out, columnSize, rowSize, ctx, onDevice, isAsync)
vecOps.TransposeMatrix(out, out2, rowSize, columnSize, ctx, onDevice, isAsync)
assert.Equal(t, matrix, out2)
var dMatrix, dOut, dOut2 core.DeviceSlice
onDevice = true
matrix.CopyToDevice(&dMatrix, true)
dOut.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement())
dOut2.Malloc(columnSize*rowSize*matrix.SizeOfElement(), matrix.SizeOfElement())
vecOps.TransposeMatrix(dMatrix, dOut, columnSize, rowSize, ctx, onDevice, isAsync)
vecOps.TransposeMatrix(dOut, dOut2, rowSize, columnSize, ctx, onDevice, isAsync)
output := make(core.HostSlice[bls12_381.ScalarField], rowSize*columnSize)
output.CopyFromDevice(&dOut2)
assert.Equal(t, matrix, output)
}

Some files were not shown because too many files have changed in this diff Show More