Add go bindings (#77)
* Add go bindings * Use Bytes32 type * Update blst package * Add binding for compute_kzg_proof * Use bytes-only input (will fail) * Fix go bindings tests * Use better blobs for benchmarks * Move rand* funcs to helpers & add comment * Add headers check
This commit is contained in:
parent
03b90ef63f
commit
71dd9574d6
|
@ -0,0 +1,29 @@
|
|||
name: Go bindings tests
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ^1.19
|
||||
id: go
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Test
|
||||
run: |
|
||||
cd bindings/go
|
||||
go test .
|
||||
- name: Check headers
|
||||
run: |
|
||||
cmp blst/bindings/blst.h bindings/go/blst_headers/blst.h
|
||||
cmp blst/bindings/blst_aux.h bindings/go/blst_headers/blst_aux.h
|
|
@ -0,0 +1,65 @@
|
|||
# cgo-kzg-4844
|
||||
|
||||
This package implements Go bindings (using [Cgo](https://go.dev/blog/cgo)) for the
|
||||
exported functions in [C-KZG-4844](https://github.com/ethereum/c-kzg-4844).
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
go get github.com/ethereum/c-kzg-4844/bindings/go
|
||||
```
|
||||
|
||||
## Go version
|
||||
|
||||
This package requires `1.19rc1` or later. Version `1.19beta1` and before will
|
||||
not work. These versions have a linking issue and are unable to see `blst`
|
||||
functions.
|
||||
|
||||
## Example
|
||||
|
||||
For example, a module with this source file:
|
||||
```go
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "encoding/hex"
|
||||
import ckzg "github.com/ethereum/c-kzg-4844/bindings/go"
|
||||
|
||||
func main() {
|
||||
ret := ckzg.LoadTrustedSetupFile("trusted_setup.txt")
|
||||
if ret != ckzg.C_KZG_OK {
|
||||
panic("failed to load trusted setup")
|
||||
}
|
||||
defer ckzg.FreeTrustedSetup()
|
||||
|
||||
blob := ckzg.Blob{1, 2, 3}
|
||||
commitment, ret := ckzg.BlobToKZGCommitment(blob)
|
||||
if ret != ckzg.C_KZG_OK {
|
||||
panic("failed to get commitment for blob")
|
||||
}
|
||||
fmt.Println(hex.EncodeToString(commitment[:]))
|
||||
}
|
||||
```
|
||||
|
||||
Will produce this output:
|
||||
```
|
||||
$ go run .
|
||||
88f1aea383b825371cb98acfbae6c81cce601a2e3129461c3c2b816409af8f3e5080db165fd327db687b3ed632153a62
|
||||
```
|
||||
|
||||
The trusted setup file in the example can be downloaded here:
|
||||
* https://github.com/ethereum/c-kzg-4844/raw/main/src/trusted_setup.txt
|
||||
|
||||
## Tests
|
||||
|
||||
Run the tests with this command:
|
||||
```
|
||||
go test
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Run the benchmarks with this command:
|
||||
```
|
||||
go test -bench=Benchmark
|
||||
```
|
|
@ -0,0 +1,483 @@
|
|||
/*
|
||||
* Copyright Supranational LLC
|
||||
* Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLST_H__
|
||||
#define __BLST_H__
|
||||
|
||||
#ifdef __SIZE_TYPE__
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(__UINT8_TYPE__) && defined(__UINT32_TYPE__) \
|
||||
&& defined(__UINT64_TYPE__)
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#elif defined(__BLST_CGO__)
|
||||
typedef _Bool bool; /* it's assumed that cgo calls modern enough compiler */
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901
|
||||
# define bool _Bool
|
||||
#else
|
||||
# define bool int
|
||||
#endif
|
||||
|
||||
#ifdef SWIG
|
||||
# define DEFNULL =NULL
|
||||
#elif defined __cplusplus
|
||||
# define DEFNULL =0
|
||||
#else
|
||||
# define DEFNULL
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BLST_SUCCESS = 0,
|
||||
BLST_BAD_ENCODING,
|
||||
BLST_POINT_NOT_ON_CURVE,
|
||||
BLST_POINT_NOT_IN_GROUP,
|
||||
BLST_AGGR_TYPE_MISMATCH,
|
||||
BLST_VERIFY_FAIL,
|
||||
BLST_PK_IS_INFINITY,
|
||||
BLST_BAD_SCALAR,
|
||||
} BLST_ERROR;
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef uint64_t limb_t;
|
||||
|
||||
typedef struct { byte b[256/8]; } blst_scalar;
|
||||
typedef struct { limb_t l[256/8/sizeof(limb_t)]; } blst_fr;
|
||||
typedef struct { limb_t l[384/8/sizeof(limb_t)]; } blst_fp;
|
||||
/* 0 is "real" part, 1 is "imaginary" */
|
||||
typedef struct { blst_fp fp[2]; } blst_fp2;
|
||||
typedef struct { blst_fp2 fp2[3]; } blst_fp6;
|
||||
typedef struct { blst_fp6 fp6[2]; } blst_fp12;
|
||||
|
||||
void blst_scalar_from_uint32(blst_scalar *out, const uint32_t a[8]);
|
||||
void blst_uint32_from_scalar(uint32_t out[8], const blst_scalar *a);
|
||||
void blst_scalar_from_uint64(blst_scalar *out, const uint64_t a[4]);
|
||||
void blst_uint64_from_scalar(uint64_t out[4], const blst_scalar *a);
|
||||
void blst_scalar_from_bendian(blst_scalar *out, const byte a[32]);
|
||||
void blst_bendian_from_scalar(byte out[32], const blst_scalar *a);
|
||||
void blst_scalar_from_lendian(blst_scalar *out, const byte a[32]);
|
||||
void blst_lendian_from_scalar(byte out[32], const blst_scalar *a);
|
||||
bool blst_scalar_fr_check(const blst_scalar *a);
|
||||
bool blst_sk_check(const blst_scalar *a);
|
||||
bool blst_sk_add_n_check(blst_scalar *out, const blst_scalar *a,
|
||||
const blst_scalar *b);
|
||||
bool blst_sk_sub_n_check(blst_scalar *out, const blst_scalar *a,
|
||||
const blst_scalar *b);
|
||||
bool blst_sk_mul_n_check(blst_scalar *out, const blst_scalar *a,
|
||||
const blst_scalar *b);
|
||||
void blst_sk_inverse(blst_scalar *out, const blst_scalar *a);
|
||||
bool blst_scalar_from_le_bytes(blst_scalar *out, const byte *in, size_t len);
|
||||
bool blst_scalar_from_be_bytes(blst_scalar *out, const byte *in, size_t len);
|
||||
|
||||
#ifndef SWIG
|
||||
/*
|
||||
* BLS12-381-specific Fr operations.
|
||||
*/
|
||||
void blst_fr_add(blst_fr *ret, const blst_fr *a, const blst_fr *b);
|
||||
void blst_fr_sub(blst_fr *ret, const blst_fr *a, const blst_fr *b);
|
||||
void blst_fr_mul_by_3(blst_fr *ret, const blst_fr *a);
|
||||
void blst_fr_lshift(blst_fr *ret, const blst_fr *a, size_t count);
|
||||
void blst_fr_rshift(blst_fr *ret, const blst_fr *a, size_t count);
|
||||
void blst_fr_mul(blst_fr *ret, const blst_fr *a, const blst_fr *b);
|
||||
void blst_fr_sqr(blst_fr *ret, const blst_fr *a);
|
||||
void blst_fr_cneg(blst_fr *ret, const blst_fr *a, bool flag);
|
||||
void blst_fr_eucl_inverse(blst_fr *ret, const blst_fr *a);
|
||||
void blst_fr_inverse(blst_fr *ret, const blst_fr *a);
|
||||
#ifdef BLST_FR_PENTAROOT
|
||||
void blst_fr_pentaroot(blst_fr *ret, const blst_fr *a);
|
||||
void blst_fr_pentapow(blst_fr *ret, const blst_fr *a);
|
||||
#endif
|
||||
|
||||
void blst_fr_from_uint64(blst_fr *ret, const uint64_t a[4]);
|
||||
void blst_uint64_from_fr(uint64_t ret[4], const blst_fr *a);
|
||||
void blst_fr_from_scalar(blst_fr *ret, const blst_scalar *a);
|
||||
void blst_scalar_from_fr(blst_scalar *ret, const blst_fr *a);
|
||||
|
||||
/*
|
||||
* BLS12-381-specific Fp operations.
|
||||
*/
|
||||
void blst_fp_add(blst_fp *ret, const blst_fp *a, const blst_fp *b);
|
||||
void blst_fp_sub(blst_fp *ret, const blst_fp *a, const blst_fp *b);
|
||||
void blst_fp_mul_by_3(blst_fp *ret, const blst_fp *a);
|
||||
void blst_fp_mul_by_8(blst_fp *ret, const blst_fp *a);
|
||||
void blst_fp_lshift(blst_fp *ret, const blst_fp *a, size_t count);
|
||||
void blst_fp_mul(blst_fp *ret, const blst_fp *a, const blst_fp *b);
|
||||
void blst_fp_sqr(blst_fp *ret, const blst_fp *a);
|
||||
void blst_fp_cneg(blst_fp *ret, const blst_fp *a, bool flag);
|
||||
void blst_fp_eucl_inverse(blst_fp *ret, const blst_fp *a);
|
||||
void blst_fp_inverse(blst_fp *ret, const blst_fp *a);
|
||||
bool blst_fp_sqrt(blst_fp *ret, const blst_fp *a);
|
||||
|
||||
void blst_fp_from_uint32(blst_fp *ret, const uint32_t a[12]);
|
||||
void blst_uint32_from_fp(uint32_t ret[12], const blst_fp *a);
|
||||
void blst_fp_from_uint64(blst_fp *ret, const uint64_t a[6]);
|
||||
void blst_uint64_from_fp(uint64_t ret[6], const blst_fp *a);
|
||||
void blst_fp_from_bendian(blst_fp *ret, const byte a[48]);
|
||||
void blst_bendian_from_fp(byte ret[48], const blst_fp *a);
|
||||
void blst_fp_from_lendian(blst_fp *ret, const byte a[48]);
|
||||
void blst_lendian_from_fp(byte ret[48], const blst_fp *a);
|
||||
|
||||
/*
|
||||
* BLS12-381-specific Fp2 operations.
|
||||
*/
|
||||
void blst_fp2_add(blst_fp2 *ret, const blst_fp2 *a, const blst_fp2 *b);
|
||||
void blst_fp2_sub(blst_fp2 *ret, const blst_fp2 *a, const blst_fp2 *b);
|
||||
void blst_fp2_mul_by_3(blst_fp2 *ret, const blst_fp2 *a);
|
||||
void blst_fp2_mul_by_8(blst_fp2 *ret, const blst_fp2 *a);
|
||||
void blst_fp2_lshift(blst_fp2 *ret, const blst_fp2 *a, size_t count);
|
||||
void blst_fp2_mul(blst_fp2 *ret, const blst_fp2 *a, const blst_fp2 *b);
|
||||
void blst_fp2_sqr(blst_fp2 *ret, const blst_fp2 *a);
|
||||
void blst_fp2_cneg(blst_fp2 *ret, const blst_fp2 *a, bool flag);
|
||||
void blst_fp2_eucl_inverse(blst_fp2 *ret, const blst_fp2 *a);
|
||||
void blst_fp2_inverse(blst_fp2 *ret, const blst_fp2 *a);
|
||||
bool blst_fp2_sqrt(blst_fp2 *ret, const blst_fp2 *a);
|
||||
|
||||
/*
|
||||
* BLS12-381-specific Fp12 operations.
|
||||
*/
|
||||
void blst_fp12_sqr(blst_fp12 *ret, const blst_fp12 *a);
|
||||
void blst_fp12_cyclotomic_sqr(blst_fp12 *ret, const blst_fp12 *a);
|
||||
void blst_fp12_mul(blst_fp12 *ret, const blst_fp12 *a, const blst_fp12 *b);
|
||||
void blst_fp12_mul_by_xy00z0(blst_fp12 *ret, const blst_fp12 *a,
|
||||
const blst_fp6 *xy00z0);
|
||||
void blst_fp12_conjugate(blst_fp12 *a);
|
||||
void blst_fp12_inverse(blst_fp12 *ret, const blst_fp12 *a);
|
||||
/* caveat lector! |n| has to be non-zero and not more than 3! */
|
||||
void blst_fp12_frobenius_map(blst_fp12 *ret, const blst_fp12 *a, size_t n);
|
||||
bool blst_fp12_is_equal(const blst_fp12 *a, const blst_fp12 *b);
|
||||
bool blst_fp12_is_one(const blst_fp12 *a);
|
||||
bool blst_fp12_in_group(const blst_fp12 *a);
|
||||
const blst_fp12 *blst_fp12_one();
|
||||
#endif // SWIG
|
||||
|
||||
/*
|
||||
* BLS12-381-specific point operations.
|
||||
*/
|
||||
typedef struct { blst_fp x, y, z; } blst_p1;
|
||||
typedef struct { blst_fp x, y; } blst_p1_affine;
|
||||
|
||||
void blst_p1_add(blst_p1 *out, const blst_p1 *a, const blst_p1 *b);
|
||||
void blst_p1_add_or_double(blst_p1 *out, const blst_p1 *a, const blst_p1 *b);
|
||||
void blst_p1_add_affine(blst_p1 *out, const blst_p1 *a,
|
||||
const blst_p1_affine *b);
|
||||
void blst_p1_add_or_double_affine(blst_p1 *out, const blst_p1 *a,
|
||||
const blst_p1_affine *b);
|
||||
void blst_p1_double(blst_p1 *out, const blst_p1 *a);
|
||||
void blst_p1_mult(blst_p1 *out, const blst_p1 *p, const byte *scalar,
|
||||
size_t nbits);
|
||||
void blst_p1_cneg(blst_p1 *p, bool cbit);
|
||||
void blst_p1_to_affine(blst_p1_affine *out, const blst_p1 *in);
|
||||
void blst_p1_from_affine(blst_p1 *out, const blst_p1_affine *in);
|
||||
bool blst_p1_on_curve(const blst_p1 *p);
|
||||
bool blst_p1_in_g1(const blst_p1 *p);
|
||||
bool blst_p1_is_equal(const blst_p1 *a, const blst_p1 *b);
|
||||
bool blst_p1_is_inf(const blst_p1 *a);
|
||||
const blst_p1 *blst_p1_generator();
|
||||
|
||||
bool blst_p1_affine_on_curve(const blst_p1_affine *p);
|
||||
bool blst_p1_affine_in_g1(const blst_p1_affine *p);
|
||||
bool blst_p1_affine_is_equal(const blst_p1_affine *a, const blst_p1_affine *b);
|
||||
bool blst_p1_affine_is_inf(const blst_p1_affine *a);
|
||||
const blst_p1_affine *blst_p1_affine_generator();
|
||||
|
||||
typedef struct { blst_fp2 x, y, z; } blst_p2;
|
||||
typedef struct { blst_fp2 x, y; } blst_p2_affine;
|
||||
|
||||
void blst_p2_add(blst_p2 *out, const blst_p2 *a, const blst_p2 *b);
|
||||
void blst_p2_add_or_double(blst_p2 *out, const blst_p2 *a, const blst_p2 *b);
|
||||
void blst_p2_add_affine(blst_p2 *out, const blst_p2 *a,
|
||||
const blst_p2_affine *b);
|
||||
void blst_p2_add_or_double_affine(blst_p2 *out, const blst_p2 *a,
|
||||
const blst_p2_affine *b);
|
||||
void blst_p2_double(blst_p2 *out, const blst_p2 *a);
|
||||
void blst_p2_mult(blst_p2 *out, const blst_p2 *p, const byte *scalar,
|
||||
size_t nbits);
|
||||
void blst_p2_cneg(blst_p2 *p, bool cbit);
|
||||
void blst_p2_to_affine(blst_p2_affine *out, const blst_p2 *in);
|
||||
void blst_p2_from_affine(blst_p2 *out, const blst_p2_affine *in);
|
||||
bool blst_p2_on_curve(const blst_p2 *p);
|
||||
bool blst_p2_in_g2(const blst_p2 *p);
|
||||
bool blst_p2_is_equal(const blst_p2 *a, const blst_p2 *b);
|
||||
bool blst_p2_is_inf(const blst_p2 *a);
|
||||
const blst_p2 *blst_p2_generator();
|
||||
|
||||
bool blst_p2_affine_on_curve(const blst_p2_affine *p);
|
||||
bool blst_p2_affine_in_g2(const blst_p2_affine *p);
|
||||
bool blst_p2_affine_is_equal(const blst_p2_affine *a, const blst_p2_affine *b);
|
||||
bool blst_p2_affine_is_inf(const blst_p2_affine *a);
|
||||
const blst_p2_affine *blst_p2_affine_generator();
|
||||
|
||||
/*
|
||||
* Multi-scalar multiplications and other multi-point operations.
|
||||
*/
|
||||
|
||||
void blst_p1s_to_affine(blst_p1_affine dst[], const blst_p1 *const points[],
|
||||
size_t npoints);
|
||||
void blst_p1s_add(blst_p1 *ret, const blst_p1_affine *const points[],
|
||||
size_t npoints);
|
||||
|
||||
size_t blst_p1s_mult_wbits_precompute_sizeof(size_t wbits, size_t npoints);
|
||||
void blst_p1s_mult_wbits_precompute(blst_p1_affine table[], size_t wbits,
|
||||
const blst_p1_affine *const points[],
|
||||
size_t npoints);
|
||||
size_t blst_p1s_mult_wbits_scratch_sizeof(size_t npoints);
|
||||
void blst_p1s_mult_wbits(blst_p1 *ret, const blst_p1_affine table[],
|
||||
size_t wbits, size_t npoints,
|
||||
const byte *const scalars[], size_t nbits,
|
||||
limb_t *scratch);
|
||||
|
||||
size_t blst_p1s_mult_pippenger_scratch_sizeof(size_t npoints);
|
||||
void blst_p1s_mult_pippenger(blst_p1 *ret, const blst_p1_affine *const points[],
|
||||
size_t npoints, const byte *const scalars[],
|
||||
size_t nbits, limb_t *scratch);
|
||||
void blst_p1s_tile_pippenger(blst_p1 *ret, const blst_p1_affine *const points[],
|
||||
size_t npoints, const byte *const scalars[],
|
||||
size_t nbits, limb_t *scratch,
|
||||
size_t bit0, size_t window);
|
||||
|
||||
void blst_p2s_to_affine(blst_p2_affine dst[], const blst_p2 *const points[],
|
||||
size_t npoints);
|
||||
void blst_p2s_add(blst_p2 *ret, const blst_p2_affine *const points[],
|
||||
size_t npoints);
|
||||
|
||||
size_t blst_p2s_mult_wbits_precompute_sizeof(size_t wbits, size_t npoints);
|
||||
void blst_p2s_mult_wbits_precompute(blst_p2_affine table[], size_t wbits,
|
||||
const blst_p2_affine *const points[],
|
||||
size_t npoints);
|
||||
size_t blst_p2s_mult_wbits_scratch_sizeof(size_t npoints);
|
||||
void blst_p2s_mult_wbits(blst_p2 *ret, const blst_p2_affine table[],
|
||||
size_t wbits, size_t npoints,
|
||||
const byte *const scalars[], size_t nbits,
|
||||
limb_t *scratch);
|
||||
|
||||
size_t blst_p2s_mult_pippenger_scratch_sizeof(size_t npoints);
|
||||
void blst_p2s_mult_pippenger(blst_p2 *ret, const blst_p2_affine *const points[],
|
||||
size_t npoints, const byte *const scalars[],
|
||||
size_t nbits, limb_t *scratch);
|
||||
void blst_p2s_tile_pippenger(blst_p2 *ret, const blst_p2_affine *const points[],
|
||||
size_t npoints, const byte *const scalars[],
|
||||
size_t nbits, limb_t *scratch,
|
||||
size_t bit0, size_t window);
|
||||
|
||||
/*
|
||||
* Hash-to-curve operations.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
void blst_map_to_g1(blst_p1 *out, const blst_fp *u, const blst_fp *v DEFNULL);
|
||||
void blst_map_to_g2(blst_p2 *out, const blst_fp2 *u, const blst_fp2 *v DEFNULL);
|
||||
#endif
|
||||
|
||||
void blst_encode_to_g1(blst_p1 *out,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST DEFNULL, size_t DST_len DEFNULL,
|
||||
const byte *aug DEFNULL, size_t aug_len DEFNULL);
|
||||
void blst_hash_to_g1(blst_p1 *out,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST DEFNULL, size_t DST_len DEFNULL,
|
||||
const byte *aug DEFNULL, size_t aug_len DEFNULL);
|
||||
|
||||
void blst_encode_to_g2(blst_p2 *out,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST DEFNULL, size_t DST_len DEFNULL,
|
||||
const byte *aug DEFNULL, size_t aug_len DEFNULL);
|
||||
void blst_hash_to_g2(blst_p2 *out,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST DEFNULL, size_t DST_len DEFNULL,
|
||||
const byte *aug DEFNULL, size_t aug_len DEFNULL);
|
||||
|
||||
/*
|
||||
* Zcash-compatible serialization/deserialization.
|
||||
*/
|
||||
void blst_p1_serialize(byte out[96], const blst_p1 *in);
|
||||
void blst_p1_compress(byte out[48], const blst_p1 *in);
|
||||
void blst_p1_affine_serialize(byte out[96], const blst_p1_affine *in);
|
||||
void blst_p1_affine_compress(byte out[48], const blst_p1_affine *in);
|
||||
BLST_ERROR blst_p1_uncompress(blst_p1_affine *out, const byte in[48]);
|
||||
BLST_ERROR blst_p1_deserialize(blst_p1_affine *out, const byte in[96]);
|
||||
|
||||
void blst_p2_serialize(byte out[192], const blst_p2 *in);
|
||||
void blst_p2_compress(byte out[96], const blst_p2 *in);
|
||||
void blst_p2_affine_serialize(byte out[192], const blst_p2_affine *in);
|
||||
void blst_p2_affine_compress(byte out[96], const blst_p2_affine *in);
|
||||
BLST_ERROR blst_p2_uncompress(blst_p2_affine *out, const byte in[96]);
|
||||
BLST_ERROR blst_p2_deserialize(blst_p2_affine *out, const byte in[192]);
|
||||
|
||||
/*
|
||||
* Specification defines two variants, 'minimal-signature-size' and
|
||||
* 'minimal-pubkey-size'. To unify appearance we choose to distinguish
|
||||
* them by suffix referring to the public key type, more specifically
|
||||
* _pk_in_g1 corresponds to 'minimal-pubkey-size' and _pk_in_g2 - to
|
||||
* 'minimal-signature-size'. It might appear a bit counterintuitive
|
||||
* in sign call, but no matter how you twist it, something is bound to
|
||||
* turn a little odd.
|
||||
*/
|
||||
/*
|
||||
* Secret-key operations.
|
||||
*/
|
||||
void blst_keygen(blst_scalar *out_SK, const byte *IKM, size_t IKM_len,
|
||||
const byte *info DEFNULL, size_t info_len DEFNULL);
|
||||
void blst_sk_to_pk_in_g1(blst_p1 *out_pk, const blst_scalar *SK);
|
||||
void blst_sign_pk_in_g1(blst_p2 *out_sig, const blst_p2 *hash,
|
||||
const blst_scalar *SK);
|
||||
void blst_sk_to_pk_in_g2(blst_p2 *out_pk, const blst_scalar *SK);
|
||||
void blst_sign_pk_in_g2(blst_p1 *out_sig, const blst_p1 *hash,
|
||||
const blst_scalar *SK);
|
||||
|
||||
/*
|
||||
* Pairing interface.
|
||||
*/
|
||||
#ifndef SWIG
|
||||
void blst_miller_loop(blst_fp12 *ret, const blst_p2_affine *Q,
|
||||
const blst_p1_affine *P);
|
||||
void blst_final_exp(blst_fp12 *ret, const blst_fp12 *f);
|
||||
void blst_precompute_lines(blst_fp6 Qlines[68], const blst_p2_affine *Q);
|
||||
void blst_miller_loop_lines(blst_fp12 *ret, const blst_fp6 Qlines[68],
|
||||
const blst_p1_affine *P);
|
||||
bool blst_fp12_finalverify(const blst_fp12 *gt1, const blst_fp12 *gt2);
|
||||
#endif
|
||||
|
||||
#ifdef __BLST_CGO__
|
||||
typedef limb_t blst_pairing;
|
||||
#elif defined(__BLST_RUST_BINDGEN__)
|
||||
typedef struct {} blst_pairing;
|
||||
#else
|
||||
typedef struct blst_opaque blst_pairing;
|
||||
#endif
|
||||
|
||||
size_t blst_pairing_sizeof();
|
||||
void blst_pairing_init(blst_pairing *new_ctx, bool hash_or_encode,
|
||||
const byte *DST DEFNULL, size_t DST_len DEFNULL);
|
||||
const byte *blst_pairing_get_dst(const blst_pairing *ctx);
|
||||
void blst_pairing_commit(blst_pairing *ctx);
|
||||
BLST_ERROR blst_pairing_aggregate_pk_in_g2(blst_pairing *ctx,
|
||||
const blst_p2_affine *PK,
|
||||
const blst_p1_affine *signature,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_chk_n_aggr_pk_in_g2(blst_pairing *ctx,
|
||||
const blst_p2_affine *PK,
|
||||
bool pk_grpchk,
|
||||
const blst_p1_affine *signature,
|
||||
bool sig_grpchk,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_mul_n_aggregate_pk_in_g2(blst_pairing *ctx,
|
||||
const blst_p2_affine *PK,
|
||||
const blst_p1_affine *sig,
|
||||
const byte *scalar,
|
||||
size_t nbits,
|
||||
const byte *msg,
|
||||
size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_chk_n_mul_n_aggr_pk_in_g2(blst_pairing *ctx,
|
||||
const blst_p2_affine *PK,
|
||||
bool pk_grpchk,
|
||||
const blst_p1_affine *sig,
|
||||
bool sig_grpchk,
|
||||
const byte *scalar,
|
||||
size_t nbits,
|
||||
const byte *msg,
|
||||
size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_aggregate_pk_in_g1(blst_pairing *ctx,
|
||||
const blst_p1_affine *PK,
|
||||
const blst_p2_affine *signature,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_chk_n_aggr_pk_in_g1(blst_pairing *ctx,
|
||||
const blst_p1_affine *PK,
|
||||
bool pk_grpchk,
|
||||
const blst_p2_affine *signature,
|
||||
bool sig_grpchk,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_mul_n_aggregate_pk_in_g1(blst_pairing *ctx,
|
||||
const blst_p1_affine *PK,
|
||||
const blst_p2_affine *sig,
|
||||
const byte *scalar,
|
||||
size_t nbits,
|
||||
const byte *msg,
|
||||
size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_chk_n_mul_n_aggr_pk_in_g1(blst_pairing *ctx,
|
||||
const blst_p1_affine *PK,
|
||||
bool pk_grpchk,
|
||||
const blst_p2_affine *sig,
|
||||
bool sig_grpchk,
|
||||
const byte *scalar,
|
||||
size_t nbits,
|
||||
const byte *msg,
|
||||
size_t msg_len,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_pairing_merge(blst_pairing *ctx, const blst_pairing *ctx1);
|
||||
bool blst_pairing_finalverify(const blst_pairing *ctx,
|
||||
const blst_fp12 *gtsig DEFNULL);
|
||||
|
||||
|
||||
/*
|
||||
* Customarily applications aggregate signatures separately.
|
||||
* In which case application would have to pass NULLs for |signature|
|
||||
* to blst_pairing_aggregate calls and pass aggregated signature
|
||||
* collected with these calls to blst_pairing_finalverify. Inputs are
|
||||
* Zcash-compatible "straight-from-wire" byte vectors, compressed or
|
||||
* not.
|
||||
*/
|
||||
BLST_ERROR blst_aggregate_in_g1(blst_p1 *out, const blst_p1 *in,
|
||||
const byte *zwire);
|
||||
BLST_ERROR blst_aggregate_in_g2(blst_p2 *out, const blst_p2 *in,
|
||||
const byte *zwire);
|
||||
|
||||
void blst_aggregated_in_g1(blst_fp12 *out, const blst_p1_affine *signature);
|
||||
void blst_aggregated_in_g2(blst_fp12 *out, const blst_p2_affine *signature);
|
||||
|
||||
/*
|
||||
* "One-shot" CoreVerify entry points.
|
||||
*/
|
||||
BLST_ERROR blst_core_verify_pk_in_g1(const blst_p1_affine *pk,
|
||||
const blst_p2_affine *signature,
|
||||
bool hash_or_encode,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST DEFNULL,
|
||||
size_t DST_len DEFNULL,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
BLST_ERROR blst_core_verify_pk_in_g2(const blst_p2_affine *pk,
|
||||
const blst_p1_affine *signature,
|
||||
bool hash_or_encode,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST DEFNULL,
|
||||
size_t DST_len DEFNULL,
|
||||
const byte *aug DEFNULL,
|
||||
size_t aug_len DEFNULL);
|
||||
|
||||
extern const blst_p1_affine BLS12_381_G1;
|
||||
extern const blst_p1_affine BLS12_381_NEG_G1;
|
||||
extern const blst_p2_affine BLS12_381_G2;
|
||||
extern const blst_p2_affine BLS12_381_NEG_G2;
|
||||
|
||||
#include "blst_aux.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright Supranational LLC
|
||||
* Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BLST_AUX_H__
|
||||
#define __BLST_AUX_H__
|
||||
/*
|
||||
* This file lists interfaces that might be promoted to blst.h or removed,
|
||||
* depending on their proven/unproven worthiness.
|
||||
*/
|
||||
|
||||
void blst_fr_to(blst_fr *ret, const blst_fr *a);
|
||||
void blst_fr_from(blst_fr *ret, const blst_fr *a);
|
||||
|
||||
void blst_fp_to(blst_fp *ret, const blst_fp *a);
|
||||
void blst_fp_from(blst_fp *ret, const blst_fp *a);
|
||||
|
||||
bool blst_fp_is_square(const blst_fp *a);
|
||||
bool blst_fp2_is_square(const blst_fp2 *a);
|
||||
|
||||
void blst_p1_from_jacobian(blst_p1 *out, const blst_p1 *in);
|
||||
void blst_p2_from_jacobian(blst_p2 *out, const blst_p2 *in);
|
||||
|
||||
/*
|
||||
* Below functions produce both point and deserialized outcome of
|
||||
* SkToPk and Sign. However, deserialized outputs are pre-decorated
|
||||
* with sign and infinity bits. This means that you have to bring the
|
||||
* output into compliance prior returning to application. If you want
|
||||
* compressed point value, then do [equivalent of]
|
||||
*
|
||||
* byte temp[96];
|
||||
* blst_sk_to_pk2_in_g1(temp, out_pk, SK);
|
||||
* temp[0] |= 0x80;
|
||||
* memcpy(out, temp, 48);
|
||||
*
|
||||
* Otherwise do
|
||||
*
|
||||
* blst_sk_to_pk2_in_g1(out, out_pk, SK);
|
||||
* out[0] &= ~0x20;
|
||||
*
|
||||
* Either |out| or |out_<point>| can be NULL.
|
||||
*/
|
||||
void blst_sk_to_pk2_in_g1(byte out[96], blst_p1_affine *out_pk,
|
||||
const blst_scalar *SK);
|
||||
void blst_sign_pk2_in_g1(byte out[192], blst_p2_affine *out_sig,
|
||||
const blst_p2 *hash, const blst_scalar *SK);
|
||||
void blst_sk_to_pk2_in_g2(byte out[192], blst_p2_affine *out_pk,
|
||||
const blst_scalar *SK);
|
||||
void blst_sign_pk2_in_g2(byte out[96], blst_p1_affine *out_sig,
|
||||
const blst_p1 *hash, const blst_scalar *SK);
|
||||
|
||||
typedef struct {} blst_uniq;
|
||||
|
||||
size_t blst_uniq_sizeof(size_t n_nodes);
|
||||
void blst_uniq_init(blst_uniq *tree);
|
||||
bool blst_uniq_test(blst_uniq *tree, const byte *msg, size_t len);
|
||||
|
||||
#ifdef expand_message_xmd
|
||||
void expand_message_xmd(unsigned char *bytes, size_t len_in_bytes,
|
||||
const unsigned char *aug, size_t aug_len,
|
||||
const unsigned char *msg, size_t msg_len,
|
||||
const unsigned char *DST, size_t DST_len);
|
||||
#else
|
||||
void blst_expand_message_xmd(byte *out, size_t out_len,
|
||||
const byte *msg, size_t msg_len,
|
||||
const byte *DST, size_t DST_len);
|
||||
#endif
|
||||
|
||||
void blst_p1_unchecked_mult(blst_p1 *out, const blst_p1 *p, const byte *scalar,
|
||||
size_t nbits);
|
||||
void blst_p2_unchecked_mult(blst_p2 *out, const blst_p2 *p, const byte *scalar,
|
||||
size_t nbits);
|
||||
|
||||
void blst_pairing_raw_aggregate(blst_pairing *ctx, const blst_p2_affine *q,
|
||||
const blst_p1_affine *p);
|
||||
blst_fp12 *blst_pairing_as_fp12(blst_pairing *ctx);
|
||||
void blst_bendian_from_fp12(byte out[48*12], const blst_fp12 *a);
|
||||
|
||||
void blst_keygen_v3(blst_scalar *out_SK, const byte *IKM, size_t IKM_len,
|
||||
const byte *info DEFNULL, size_t info_len DEFNULL);
|
||||
void blst_keygen_v4_5(blst_scalar *out_SK, const byte *IKM, size_t IKM_len,
|
||||
const byte *salt, size_t salt_len,
|
||||
const byte *info DEFNULL, size_t info_len DEFNULL);
|
||||
void blst_keygen_v5(blst_scalar *out_SK, const byte *IKM, size_t IKM_len,
|
||||
const byte *salt, size_t salt_len,
|
||||
const byte *info DEFNULL, size_t info_len DEFNULL);
|
||||
void blst_derive_master_eip2333(blst_scalar *out_SK,
|
||||
const byte *IKM, size_t IKM_len);
|
||||
void blst_derive_child_eip2333(blst_scalar *out_SK, const blst_scalar *SK,
|
||||
uint32_t child_index);
|
||||
|
||||
void blst_scalar_from_hexascii(blst_scalar *out, const byte *hex);
|
||||
void blst_fr_from_hexascii(blst_fr *ret, const byte *hex);
|
||||
void blst_fp_from_hexascii(blst_fp *ret, const byte *hex);
|
||||
|
||||
size_t blst_p1_sizeof();
|
||||
size_t blst_p1_affine_sizeof();
|
||||
size_t blst_p2_sizeof();
|
||||
size_t blst_p2_affine_sizeof();
|
||||
size_t blst_fp12_sizeof();
|
||||
|
||||
/*
|
||||
* Single-shot SHA-256 hash function.
|
||||
*/
|
||||
void blst_sha256(byte out[32], const byte *msg, size_t msg_len);
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
module github.com/ethereum/c-kzg-4844/bindings/go
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 h1:wh1wzwAhZBNiZO37uWS/nDaKiIwHz4mDo4pnA+fqTO0=
|
||||
github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,233 @@
|
|||
package cgokzg4844
|
||||
|
||||
// #cgo CFLAGS: -I${SRCDIR}/../../src
|
||||
// #cgo CFLAGS: -I${SRCDIR}/blst_headers
|
||||
// #cgo CFLAGS: -DFIELD_ELEMENTS_PER_BLOB=4096
|
||||
// #include "c_kzg_4844.c"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
// So its functions are available during compilation.
|
||||
_ "github.com/supranational/blst/bindings/go"
|
||||
)
|
||||
|
||||
const (
|
||||
BytesPerBlob = C.BYTES_PER_BLOB
|
||||
BytesPerCommitment = C.BYTES_PER_COMMITMENT
|
||||
BytesPerFieldElement = C.BYTES_PER_FIELD_ELEMENT
|
||||
BytesPerProof = C.BYTES_PER_PROOF
|
||||
FieldElementsPerBlob = C.FIELD_ELEMENTS_PER_BLOB
|
||||
)
|
||||
|
||||
type (
|
||||
CKzgRet int
|
||||
Bytes32 [32]byte
|
||||
Bytes48 [48]byte
|
||||
KZGCommitment Bytes48
|
||||
KZGProof Bytes48
|
||||
Blob [BytesPerBlob]byte
|
||||
)
|
||||
|
||||
const (
|
||||
C_KZG_OK CKzgRet = C.C_KZG_OK
|
||||
C_KZG_BADARGS CKzgRet = C.C_KZG_BADARGS
|
||||
C_KZG_ERROR CKzgRet = C.C_KZG_ERROR
|
||||
C_KZG_MALLOC CKzgRet = C.C_KZG_MALLOC
|
||||
)
|
||||
|
||||
var (
|
||||
loaded = false
|
||||
settings = C.KZGSettings{}
|
||||
)
|
||||
|
||||
/*
|
||||
LoadTrustedSetup is the binding for:
|
||||
|
||||
C_KZG_RET load_trusted_setup(
|
||||
KZGSettings *out,
|
||||
const uint8_t *g1_bytes,
|
||||
size_t n1,
|
||||
const uint8_t *g2_bytes,
|
||||
size_t n2);
|
||||
*/
|
||||
func LoadTrustedSetup(g1Bytes, g2Bytes []byte) CKzgRet {
|
||||
if loaded {
|
||||
panic("trusted setup is already loaded")
|
||||
}
|
||||
if len(g1Bytes)%48 != 0 {
|
||||
panic("len(g1Bytes) is not a multiple of 48")
|
||||
}
|
||||
if len(g2Bytes)%96 != 0 {
|
||||
panic("len(g2Bytes) is not a multiple of 96")
|
||||
}
|
||||
numG1Elements := len(g1Bytes) / 48
|
||||
numG2Elements := len(g2Bytes) / 96
|
||||
ret := C.load_trusted_setup(
|
||||
&settings,
|
||||
*(**C.uint8_t)(unsafe.Pointer(&g1Bytes)),
|
||||
(C.size_t)(numG1Elements),
|
||||
*(**C.uint8_t)(unsafe.Pointer(&g2Bytes)),
|
||||
(C.size_t)(numG2Elements))
|
||||
if CKzgRet(ret) == C_KZG_OK {
|
||||
loaded = true
|
||||
}
|
||||
return CKzgRet(ret)
|
||||
}
|
||||
|
||||
/*
|
||||
LoadTrustedSetupFile is the binding for:
|
||||
|
||||
C_KZG_RET load_trusted_setup_file(
|
||||
KZGSettings *out,
|
||||
FILE *in);
|
||||
*/
|
||||
func LoadTrustedSetupFile(trustedSetupFile string) CKzgRet {
|
||||
if loaded {
|
||||
panic("trusted setup is already loaded")
|
||||
}
|
||||
fp := C.fopen(C.CString(trustedSetupFile), C.CString("rb"))
|
||||
if fp == nil {
|
||||
panic("error reading trusted setup")
|
||||
}
|
||||
ret := C.load_trusted_setup_file(&settings, fp)
|
||||
C.fclose(fp)
|
||||
if CKzgRet(ret) == C_KZG_OK {
|
||||
loaded = true
|
||||
}
|
||||
return CKzgRet(ret)
|
||||
}
|
||||
|
||||
/*
|
||||
FreeTrustedSetup is the binding for:
|
||||
|
||||
void free_trusted_setup(
|
||||
KZGSettings *s);
|
||||
*/
|
||||
func FreeTrustedSetup() {
|
||||
if !loaded {
|
||||
panic("trusted setup isn't loaded")
|
||||
}
|
||||
C.free_trusted_setup(&settings)
|
||||
loaded = false
|
||||
}
|
||||
|
||||
/*
|
||||
BlobToKZGCommitment is the binding for:
|
||||
|
||||
C_KZG_RET blob_to_kzg_commitment(
|
||||
KZGCommitment *out,
|
||||
const Blob *blob,
|
||||
const KZGSettings *s);
|
||||
*/
|
||||
func BlobToKZGCommitment(blob Blob) (KZGCommitment, CKzgRet) {
|
||||
if !loaded {
|
||||
panic("trusted setup isn't loaded")
|
||||
}
|
||||
commitment := KZGCommitment{}
|
||||
ret := C.blob_to_kzg_commitment(
|
||||
(*C.KZGCommitment)(unsafe.Pointer(&commitment)),
|
||||
(*C.Blob)(unsafe.Pointer(&blob)),
|
||||
&settings)
|
||||
return commitment, CKzgRet(ret)
|
||||
}
|
||||
|
||||
/*
|
||||
ComputeKZGProof is the binding for:
|
||||
|
||||
C_KZG_RET compute_kzg_proof(
|
||||
KZGProof *out,
|
||||
const Blob *blob,
|
||||
const Bytes32 *z_bytes,
|
||||
const KZGSettings *s);
|
||||
*/
|
||||
func ComputeKZGProof(blob Blob, zBytes Bytes32) (KZGProof, CKzgRet) {
|
||||
if !loaded {
|
||||
panic("trusted setup isn't loaded")
|
||||
}
|
||||
proof := KZGProof{}
|
||||
ret := C.compute_kzg_proof(
|
||||
(*C.KZGProof)(unsafe.Pointer(&proof)),
|
||||
(*C.Blob)(unsafe.Pointer(&blob)),
|
||||
(*C.Bytes32)(unsafe.Pointer(&zBytes)),
|
||||
&settings)
|
||||
return proof, CKzgRet(ret)
|
||||
}
|
||||
|
||||
/*
|
||||
VerifyKZGProof is the binding for:
|
||||
|
||||
C_KZG_RET verify_kzg_proof(
|
||||
bool *out,
|
||||
const Bytes48 *commitment_bytes,
|
||||
const Bytes32 *z_bytes,
|
||||
const Bytes32 *y_bytes,
|
||||
const Bytes48 *proof_bytes,
|
||||
const KZGSettings *s);
|
||||
*/
|
||||
func VerifyKZGProof(commitmentBytes Bytes48, zBytes, yBytes Bytes32, proofBytes Bytes48) (bool, CKzgRet) {
|
||||
if !loaded {
|
||||
panic("trusted setup isn't loaded")
|
||||
}
|
||||
var result C.bool
|
||||
ret := C.verify_kzg_proof(
|
||||
&result,
|
||||
(*C.Bytes48)(unsafe.Pointer(&commitmentBytes)),
|
||||
(*C.Bytes32)(unsafe.Pointer(&zBytes)),
|
||||
(*C.Bytes32)(unsafe.Pointer(&yBytes)),
|
||||
(*C.Bytes48)(unsafe.Pointer(&proofBytes)),
|
||||
&settings)
|
||||
return bool(result), CKzgRet(ret)
|
||||
}
|
||||
|
||||
/*
|
||||
ComputeAggregateKZGProof is the binding for:
|
||||
|
||||
C_KZG_RET compute_aggregate_kzg_proof(
|
||||
KZGProof *out,
|
||||
const Blob *blobs,
|
||||
size_t n,
|
||||
const KZGSettings *s);
|
||||
*/
|
||||
func ComputeAggregateKZGProof(blobs []Blob) (KZGProof, CKzgRet) {
|
||||
if !loaded {
|
||||
panic("trusted setup isn't loaded")
|
||||
}
|
||||
proof := KZGProof{}
|
||||
ret := C.compute_aggregate_kzg_proof(
|
||||
(*C.KZGProof)(unsafe.Pointer(&proof)),
|
||||
*(**C.Blob)(unsafe.Pointer(&blobs)),
|
||||
(C.size_t)(len(blobs)),
|
||||
&settings)
|
||||
return proof, CKzgRet(ret)
|
||||
}
|
||||
|
||||
/*
|
||||
VerifyAggregateKZGProof is the binding for:
|
||||
|
||||
C_KZG_RET verify_aggregate_kzg_proof(
|
||||
bool *out,
|
||||
const Blob *blobs,
|
||||
const Bytes48 *commitments_bytes,
|
||||
size_t n,
|
||||
const Bytes48 *aggregated_proof_bytes,
|
||||
const KZGSettings *s);
|
||||
*/
|
||||
func VerifyAggregateKZGProof(blobs []Blob, commitmentsBytes []Bytes48, aggregatedProofBytes Bytes48) (bool, CKzgRet) {
|
||||
if !loaded {
|
||||
panic("trusted setup isn't loaded")
|
||||
}
|
||||
if len(blobs) != len(commitmentsBytes) {
|
||||
panic("len(blobs) != len(commitments)")
|
||||
}
|
||||
var result C.bool
|
||||
ret := C.verify_aggregate_kzg_proof(
|
||||
&result,
|
||||
*(**C.Blob)(unsafe.Pointer(&blobs)),
|
||||
*(**C.Bytes48)(unsafe.Pointer(&commitmentsBytes)),
|
||||
(C.size_t)(len(blobs)),
|
||||
(*C.Bytes48)(unsafe.Pointer(&aggregatedProofBytes)),
|
||||
&settings)
|
||||
return bool(result), CKzgRet(ret)
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
package cgokzg4844
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
ret := LoadTrustedSetupFile("../../src/trusted_setup.txt")
|
||||
if ret != 0 {
|
||||
panic("failed to load trusted setup")
|
||||
}
|
||||
defer FreeTrustedSetup()
|
||||
code := m.Run()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helper Functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func (f *Bytes32) UnmarshalText(input []byte) error {
|
||||
bytes, err := hex.DecodeString(string(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(bytes) != len(f) {
|
||||
return errors.New("invalid Bytes32")
|
||||
}
|
||||
copy(f[:], bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Bytes48) UnmarshalText(input []byte) error {
|
||||
bytes, err := hex.DecodeString(string(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(bytes) != len(f) {
|
||||
return errors.New("invalid Bytes48")
|
||||
}
|
||||
copy(f[:], bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Blob) UnmarshalText(input []byte) error {
|
||||
blobBytes, err := hex.DecodeString(string(input))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(blobBytes) != len(b) {
|
||||
return errors.New("invalid Blob")
|
||||
}
|
||||
copy(b[:], blobBytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetRandFieldElement(seed int64) Bytes32 {
|
||||
rand.Seed(seed)
|
||||
bytes := make([]byte, 31)
|
||||
_, err := rand.Read(bytes)
|
||||
if err != nil {
|
||||
panic("failed to get random field element")
|
||||
}
|
||||
|
||||
// This leaves the last byte in fieldElementBytes as
|
||||
// zero, which guarantees it's a canonical field element.
|
||||
var fieldElementBytes Bytes32
|
||||
copy(fieldElementBytes[:], bytes)
|
||||
return fieldElementBytes
|
||||
}
|
||||
|
||||
func GetRandBlob(seed int64) Blob {
|
||||
var blob Blob
|
||||
for i := 0; i < BytesPerBlob; i += BytesPerFieldElement {
|
||||
fieldElementBytes := GetRandFieldElement(seed + int64(i))
|
||||
copy(blob[i:i+BytesPerFieldElement], fieldElementBytes[:])
|
||||
}
|
||||
return blob
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Tests
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func TestComputeAggregateKZGProof(t *testing.T) {
|
||||
type Test struct {
|
||||
TestCases []struct {
|
||||
Polynomials []Blob `json:"Polynomials"`
|
||||
Proof Bytes48 `json:"Proof"`
|
||||
Commitments []Bytes48 `json:"Commitments"`
|
||||
}
|
||||
}
|
||||
|
||||
testFile, err := os.Open("../rust/test_vectors/public_agg_proof.json")
|
||||
require.NoError(t, err)
|
||||
defer testFile.Close()
|
||||
test := Test{}
|
||||
err = json.NewDecoder(testFile).Decode(&test)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, tc := range test.TestCases {
|
||||
proof, ret := ComputeAggregateKZGProof(tc.Polynomials)
|
||||
require.Zero(t, ret)
|
||||
require.Equal(t, tc.Proof[:], proof[:])
|
||||
for i := range tc.Polynomials {
|
||||
commitment, ret := BlobToKZGCommitment(tc.Polynomials[i])
|
||||
require.Equal(t, C_KZG_OK, ret)
|
||||
require.Equal(t, tc.Commitments[i][:], commitment[:])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyKZGProof(t *testing.T) {
|
||||
type Test struct {
|
||||
TestCases []struct {
|
||||
Polynomial Blob `json:"Polynomial"`
|
||||
Proof Bytes48 `json:"Proof"`
|
||||
Commitment Bytes48 `json:"Commitment"`
|
||||
InputPoint Bytes32 `json:"InputPoint"`
|
||||
ClaimedValue Bytes32 `json:"ClaimedValue"`
|
||||
}
|
||||
}
|
||||
|
||||
testFile, err := os.Open("../rust/test_vectors/public_verify_kzg_proof.json")
|
||||
require.NoError(t, err)
|
||||
defer testFile.Close()
|
||||
test := Test{}
|
||||
err = json.NewDecoder(testFile).Decode(&test)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, tc := range test.TestCases {
|
||||
result, ret := VerifyKZGProof(tc.Commitment, tc.InputPoint, tc.ClaimedValue, tc.Proof)
|
||||
require.Equal(t, C_KZG_OK, ret)
|
||||
require.True(t, result)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Benchmarks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
func Benchmark(b *testing.B) {
|
||||
const length = 64
|
||||
blobs := [length]Blob{}
|
||||
commitments := [length]Bytes48{}
|
||||
for i := 0; i < length; i++ {
|
||||
blobs[i] = GetRandBlob(int64(i))
|
||||
commitment, _ := BlobToKZGCommitment(blobs[i])
|
||||
commitments[i] = Bytes48(commitment)
|
||||
}
|
||||
z := Bytes32{1, 2, 3}
|
||||
y := Bytes32{4, 5, 6}
|
||||
trustedProof, _ := ComputeAggregateKZGProof(blobs[:1])
|
||||
proof := Bytes48(trustedProof)
|
||||
|
||||
b.Run("BlobToKZGCommitment", func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, ret := BlobToKZGCommitment(blobs[0])
|
||||
require.Equal(b, C_KZG_OK, ret)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("ComputeKZGProof", func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, ret := ComputeKZGProof(blobs[0], z)
|
||||
require.Equal(b, C_KZG_OK, ret)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("VerifyKZGProof", func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, ret := VerifyKZGProof(commitments[0], z, y, proof)
|
||||
require.Equal(b, C_KZG_OK, ret)
|
||||
}
|
||||
})
|
||||
|
||||
for i := 1; i <= len(blobs); i *= 2 {
|
||||
b.Run(fmt.Sprintf("ComputeAggregateKZGProof(blobs=%v)", i), func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, ret := ComputeAggregateKZGProof(blobs[:i])
|
||||
require.Equal(b, C_KZG_OK, ret)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
for i := 1; i <= len(blobs); i *= 2 {
|
||||
b.Run(fmt.Sprintf("VerifyAggregateKZGProof(blobs=%v)", i), func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, ret := VerifyAggregateKZGProof(blobs[:i], commitments[:i], proof)
|
||||
require.Equal(b, C_KZG_OK, ret)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue