-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Describe the changes This PR... ## Linked Issues Resolves # --------- Co-authored-by: Jeremy Felder <[email protected]> Co-authored-by: DmytroTym <[email protected]>
- Loading branch information
1 parent
9fc0839
commit af6bfc9
Showing
10 changed files
with
960 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ on: | |
branches: | ||
- main | ||
paths: | ||
- 'docs/*' | ||
- 'docs/**' | ||
|
||
permissions: | ||
contents: write | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,105 @@ | ||
# Golang bindings | ||
|
||
Golang is WIP in v1, coming soon. Please checkout a previous [release v0.1.0](https://github.com/ingonyama-zk/icicle/releases/tag/v0.1.0) for golang bindings. | ||
Golang bindings allow you to use ICICLE as a golang library. | ||
The source code for all Golang libraries can be found [here](https://github.com/ingonyama-zk/icicle/tree/main/wrappers/golang). | ||
|
||
The Golang bindings are comprised of multiple packages. | ||
|
||
[`core`](https://github.com/ingonyama-zk/icicle/tree/main/wrappers/golang/core) which defines all shared methods and structures, such as configuration structures, or memory slices. | ||
|
||
[`cuda-runtime`](https://github.com/ingonyama-zk/icicle/tree/main/wrappers/golang/cuda_runtime) which defines abstractions for CUDA methods for allocating memory, initializing and managing streams, and `DeviceContext` which enables users to define and keep track of devices. | ||
|
||
Each curve has its own package which you can find [here](https://github.com/ingonyama-zk/icicle/tree/main/wrappers/golang/curves). If your project uses BN254 you only need to install that single package named [`bn254`](https://github.com/ingonyama-zk/icicle/tree/main/wrappers/golang/curves/bn254). | ||
|
||
## Using ICICLE Golang bindings in your project | ||
|
||
To add ICICLE to your `go.mod` file. | ||
|
||
```bash | ||
go get github.com/ingonyama-zk/icicle | ||
``` | ||
|
||
If you want to specify a specific branch | ||
|
||
```bash | ||
go get github.com/ingonyama-zk/icicle@<branch_name> | ||
``` | ||
|
||
For a specific commit | ||
|
||
```bash | ||
go get github.com/ingonyama-zk/icicle@<commit_id> | ||
``` | ||
|
||
To build the shared libraries you can run this script: | ||
|
||
``` | ||
./build <curve> [G2_enabled] | ||
curve - The name of the curve to build or "all" to build all curves | ||
G2_enabled - Optional - To build with G2 enabled | ||
``` | ||
|
||
For example if you want to build all curves with G2 enabled you would run: | ||
|
||
```bash | ||
./build.sh all ON | ||
``` | ||
|
||
If you are interested in building a specific curve you would run: | ||
|
||
```bash | ||
./build.sh bls12_381 ON | ||
``` | ||
|
||
Now you can import ICICLE into your project | ||
|
||
```golang | ||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
|
||
"github.com/ingonyama-zk/icicle/wrappers/golang/core" | ||
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" | ||
) | ||
... | ||
``` | ||
|
||
## Running tests | ||
|
||
To run all tests, for all curves: | ||
|
||
```bash | ||
go test --tags=g2 ./... -count=1 | ||
``` | ||
|
||
If you dont want to include g2 tests then drop `--tags=g2`. | ||
|
||
If you wish to run test for a specific curve: | ||
|
||
```bash | ||
go test <path_to_curve> -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. | ||
|
||
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 | ||
#include "icicle.h" // make sure you use the correct header file(s) | ||
*/ | ||
import "C" | ||
|
||
func main() { | ||
// Now you can call the C functions from the ICICLE libraries. | ||
// Note that C function calls are prefixed with 'C.' in Go code. | ||
} | ||
``` | ||
|
||
Replace `/path/to/shared/libs` with the actual path where the shared libraries are located on your system. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
# MSM | ||
|
||
|
||
### Supported curves | ||
|
||
`bls12-377`, `bls12-381`, `bn254`, `bw6-761` | ||
|
||
## MSM Example | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"github.com/ingonyama-zk/icicle/wrappers/golang/core" | ||
cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" | ||
) | ||
|
||
func Main() { | ||
// Obtain the default MSM configuration. | ||
cfg := GetDefaultMSMConfig() | ||
|
||
// Define the size of the problem, here 2^18. | ||
size := 1 << 18 | ||
|
||
// Generate scalars and points for the MSM operation. | ||
scalars := GenerateScalars(size) | ||
points := GenerateAffinePoints(size) | ||
|
||
// Create a CUDA stream for asynchronous operations. | ||
stream, _ := cr.CreateStream() | ||
var p Projective | ||
|
||
// Allocate memory on the device for the result of the MSM operation. | ||
var out core.DeviceSlice | ||
_, e := out.MallocAsync(p.Size(), p.Size(), stream) | ||
|
||
if e != cr.CudaSuccess { | ||
panic(e) | ||
} | ||
|
||
// Set the CUDA stream in the MSM configuration. | ||
cfg.Ctx.Stream = &stream | ||
cfg.IsAsync = true | ||
|
||
// Perform the MSM operation. | ||
e = Msm(scalars, points, &cfg, out) | ||
|
||
if e != cr.CudaSuccess { | ||
panic(e) | ||
} | ||
|
||
// Allocate host memory for the results and copy the results from the device. | ||
outHost := make(core.HostSlice[Projective], 1) | ||
cr.SynchronizeStream(&stream) | ||
outHost.CopyFromDevice(&out) | ||
|
||
// Free the device memory allocated for the results. | ||
out.Free() | ||
} | ||
``` | ||
|
||
## MSM Method | ||
|
||
```go | ||
func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError | ||
``` | ||
|
||
### Parameters | ||
|
||
- **scalars**: A slice containing the scalars for multiplication. It can reside either in host memory or device memory. | ||
- **points**: A slice containing the points to be multiplied with scalars. Like scalars, these can also be in host or device memory. | ||
- **cfg**: A pointer to an `MSMConfig` object, which contains various configuration options for the MSM operation. | ||
- **results**: A slice where the results of the MSM operation will be stored. This slice can be in host or device memory. | ||
|
||
### Return Value | ||
|
||
- **CudaError**: Returns a CUDA error code indicating the success or failure of the MSM operation. | ||
|
||
## MSMConfig | ||
|
||
The `MSMConfig` structure holds configuration parameters for the MSM operation, allowing customization of its behavior to optimize performance based on the specifics of the operation or the underlying hardware. | ||
|
||
```go | ||
type MSMConfig struct { | ||
Ctx cr.DeviceContext | ||
PrecomputeFactor int32 | ||
C int32 | ||
Bitsize int32 | ||
LargeBucketFactor int32 | ||
batchSize int32 | ||
areScalarsOnDevice bool | ||
AreScalarsMontgomeryForm bool | ||
arePointsOnDevice bool | ||
ArePointsMontgomeryForm bool | ||
areResultsOnDevice bool | ||
IsBigTriangle bool | ||
IsAsync bool | ||
} | ||
``` | ||
|
||
### Fields | ||
|
||
- **Ctx**: Device context containing details like device id and stream. | ||
- **PrecomputeFactor**: Controls the number of extra points to pre-compute. | ||
- **C**: Window bitsize, a key parameter in the "bucket method" for MSM. | ||
- **Bitsize**: Number of bits of the largest scalar. | ||
- **LargeBucketFactor**: Sensitivity to frequently occurring buckets. | ||
- **batchSize**: Number of results to compute in one batch. | ||
- **areScalarsOnDevice**: Indicates if scalars are located on the device. | ||
- **AreScalarsMontgomeryForm**: True if scalars are in Montgomery form. | ||
- **arePointsOnDevice**: Indicates if points are located on the device. | ||
- **ArePointsMontgomeryForm**: True if point coordinates are in Montgomery form. | ||
- **areResultsOnDevice**: Indicates if results are stored on the device. | ||
- **IsBigTriangle**: If `true` MSM will run in Large triangle accumulation if `false` Bucket accumulation will be chosen. Default value: false. | ||
- **IsAsync**: If true, runs MSM asynchronously. | ||
|
||
### Default Configuration | ||
|
||
Use `GetDefaultMSMConfig` to obtain a default configuration, which can then be customized as needed. | ||
|
||
```go | ||
func GetDefaultMSMConfig() MSMConfig | ||
``` | ||
|
||
|
||
## How do I toggle between the supported algorithms? | ||
|
||
When creating your MSM Config you may state which algorithm you wish to use. `cfg.Ctx.IsBigTriangle = true` will activate Large triangle accumulation and `cfg.Ctx.IsBigTriangle = false` will activate Bucket accumulation. | ||
|
||
```go | ||
... | ||
|
||
// Obtain the default MSM configuration. | ||
cfg := GetDefaultMSMConfig() | ||
|
||
cfg.Ctx.IsBigTriangle = true | ||
|
||
... | ||
``` | ||
|
||
## How do I toggle between MSM modes? | ||
|
||
Toggling between MSM modes occurs automatically based on the number of results you are expecting from the `MSM` function. | ||
|
||
The number of results is interpreted from the size of `var out core.DeviceSlice`. Thus its important when allocating memory for `var out core.DeviceSlice` to make sure that you are allocating `<number of results> X <size of a single point>`. | ||
|
||
```go | ||
... | ||
|
||
batchSize := 3 | ||
var p G2Projective | ||
var out core.DeviceSlice | ||
out.Malloc(batchSize*p.Size(), p.Size()) | ||
|
||
... | ||
``` | ||
|
||
## Support for G2 group | ||
|
||
To activate G2 support first you must make sure you are building the static libraries with G2 feature enabled. | ||
|
||
```bash | ||
./build.sh bls12_381 ON | ||
``` | ||
|
||
Now when importing `icicle`, you should have access to G2 features. | ||
|
||
```go | ||
import ( | ||
"github.com/ingonyama-zk/icicle/wrappers/golang/core" | ||
) | ||
``` | ||
|
||
These features include `G2Projective` and `G2Affine` points as well as a `G2Msm` method. | ||
|
||
```go | ||
... | ||
|
||
cfg := GetDefaultMSMConfig() | ||
size := 1 << 12 | ||
batchSize := 3 | ||
totalSize := size * batchSize | ||
scalars := GenerateScalars(totalSize) | ||
points := G2GenerateAffinePoints(totalSize) | ||
|
||
var p G2Projective | ||
var out core.DeviceSlice | ||
out.Malloc(batchSize*p.Size(), p.Size()) | ||
G2Msm(scalars, points, &cfg, out) | ||
|
||
... | ||
``` | ||
|
||
`G2Msm` works the same way as normal MSM, the difference is that it uses G2 Points. | ||
|
||
Additionally when you are building your application make sure to use the g2 feature flag | ||
|
||
```bash | ||
go build -tags=g2 | ||
``` |
Oops, something went wrong.