This commit is contained in:
dancoffman 2022-11-03 15:13:49 -07:00
parent 672346f017
commit b8151db670
No known key found for this signature in database
GPG Key ID: 47B1F53E36A9B3CC
13 changed files with 100 additions and 106 deletions

View File

@ -0,0 +1,2 @@
# Ignore artifacts:
build

View File

@ -0,0 +1,8 @@
{
"overrides": [
{
"files": "binding.gyp",
"options": { "parser": "json" }
}
]
}

View File

@ -1,7 +1,3 @@
install:
brew install llvm
yarn install
clean: clean:
yarn clean yarn clean
rm -rf build rm -rf build
@ -9,15 +5,6 @@ clean:
rm -f *.a rm -f *.a
rm -f *.o rm -f *.o
# objcopy --globalize-symbol=symbolname
# Give symbol symbolname global scoping so that it is visible
# outside of the file in which it is defined. This option may
# be given more than once.
# c_kzg_4844's static void hash() calls sha256_... which are private
# We use objcopy's globalize-symbol to make them public.
# libblst.a: ../../lib/libblst.a
# $$(brew --prefix llvm)/bin/llvm-objcopy --globalize-symbol=sha256_init --globalize-symbol=sha256_update --globalize-symbol=sha256_final $< $@
build: kzg.cxx Makefile build: kzg.cxx Makefile
cd ../../src; make lib cd ../../src; make lib
yarn build yarn build

View File

@ -0,0 +1,19 @@
This directory contains the code necessary to generate NodeJS bindings for C-KZG.
First, install:
```
yarn install
```
Then build
```
make build
```
Run the TypeScript tests
```
yarn test
```

View File

@ -1,6 +1,6 @@
module.exports = { module.exports = {
presets: [ presets: [
['@babel/preset-env', { targets: { node: 'current' } }], ["@babel/preset-env", { targets: { node: "current" } }],
'@babel/preset-typescript', "@babel/preset-typescript",
], ],
}; };

View File

@ -1,27 +1,27 @@
{ {
'targets': [ "targets": [
{ {
'target_name': 'kzg', "target_name": "kzg",
"cflags!": [ "-fno-exceptions" ], "cflags!": ["-fno-exceptions"],
"cflags_cc!": [ "-fno-exceptions" ], "cflags_cc!": ["-fno-exceptions"],
'xcode_settings': { "xcode_settings": {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES', "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
'CLANG_CXX_LIBRARY': 'libc++', "CLANG_CXX_LIBRARY": "libc++",
'MACOSX_DEPLOYMENT_TARGET': '10.7' "MACOSX_DEPLOYMENT_TARGET": "13.0"
}, },
'sources': [ "sources": ["kzg.cxx"],
'kzg.cxx', "include_dirs": [
"../../inc",
"../../src",
"<!@(node -p \"require('node-addon-api').include\")"
], ],
'include_dirs': ['../../inc', '../../src', "<!@(node -p \"require('node-addon-api').include\")"], "libraries": [
'libraries': [ "<(module_root_dir)/c_kzg_4844.o",
'/Users/coffman@coinbase.com/src/c-kzg/bindings/node.js/c_kzg_4844.o', "<(module_root_dir)/sha256.o",
'/Users/coffman@coinbase.com/src/c-kzg/bindings/node.js/sha256.o', "<(module_root_dir)/../../lib/libblst.a"
'/Users/coffman@coinbase.com/src/c-kzg/lib/libblst.a'
], ],
'dependencies': [ "dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
"<!(node -p \"require('node-addon-api').gyp\")" "defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"]
],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ]
} }
] ]
} }

View File

@ -1,5 +1,5 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */ /** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = { module.exports = {
preset: 'ts-jest', preset: "ts-jest",
testEnvironment: 'node', testEnvironment: "node",
}; };

View File

@ -1,16 +1,14 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define NAPI_EXPERIMENTAL #include <sstream> // std::ostringstream
#include <algorithm> // std::copy
#include <iterator> // std::ostream_iterator
#include <napi.h> #include <napi.h>
#include "c_kzg_4844.h" #include "c_kzg_4844.h"
#include "blst.h" #include "blst.h"
#include <sstream> // std::ostringstream Napi::TypedArrayOf<uint8_t> napi_typed_array_from_bytes(uint8_t* array, size_t arrayLength, Napi::Env env) {
#include <algorithm> // std::copy
#include <iterator> // std::ostream_iterator
Napi::TypedArrayOf<uint8_t> napiTypedArrayFromByteArray(uint8_t* array, size_t arrayLength, Napi::Env env) {
// Create std::vector<uint8_t> out of array. // Create std::vector<uint8_t> out of array.
// We allocate it on the heap to allow wrapping it up into ArrayBuffer. // We allocate it on the heap to allow wrapping it up into ArrayBuffer.
std::unique_ptr<std::vector<uint8_t>> nativeArray = std::unique_ptr<std::vector<uint8_t>> nativeArray =
@ -75,13 +73,11 @@ Napi::Value LoadTrustedSetup(const Napi::CallbackInfo& info) {
return env.Null(); return env.Null();
} }
// Consider making this internal state intead
return Napi::External<KZGSettings>::New(info.Env(), kzgSettings); return Napi::External<KZGSettings>::New(info.Env(), kzgSettings);
} }
// freeTrustedSetup: (setupHandle: SetupHandle) => void; // freeTrustedSetup: (setupHandle: SetupHandle) => void;
void FreeTrustedSetup(const Napi::CallbackInfo& info) { void FreeTrustedSetup(const Napi::CallbackInfo& info) {
// Maybe this can be done with a finalizer on the thing returned by LoadTrustedSetup, and then the JS garbage collector can just sort it out.
auto kzgSettings = info[0].As<Napi::External<KZGSettings>>().Data(); auto kzgSettings = info[0].As<Napi::External<KZGSettings>>().Data();
free_trusted_setup(kzgSettings); free_trusted_setup(kzgSettings);
free(kzgSettings); free(kzgSettings);
@ -109,15 +105,14 @@ Napi::Value BlobToKzgCommitment(const Napi::CallbackInfo& info) {
Polynomial polynomial; Polynomial polynomial;
for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) for (size_t i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++)
bytes_to_bls_field(&polynomial[i], &blob[i * 32]); bytes_to_bls_field(&polynomial[i], &blob[i * BYTES_PER_FIELD]);
KZGCommitment commitment; KZGCommitment commitment;
blob_to_kzg_commitment(&commitment, polynomial, kzgSettings); blob_to_kzg_commitment(&commitment, polynomial, kzgSettings);
// Turn it into a byte array
uint8_t commitmentBytes[BYTES_PER_COMMITMENT]; uint8_t commitmentBytes[BYTES_PER_COMMITMENT];
bytes_from_g1(commitmentBytes, &commitment); bytes_from_g1(commitmentBytes, &commitment);
return napiTypedArrayFromByteArray(commitmentBytes, BYTES_PER_COMMITMENT, env); return napi_typed_array_from_bytes(commitmentBytes, BYTES_PER_COMMITMENT, env);
} }
// computeAggregateKzgProof: (blobs: Blob[], setupHandle: SetupHandle) => KZGProof; // computeAggregateKzgProof: (blobs: Blob[], setupHandle: SetupHandle) => KZGProof;
@ -134,17 +129,12 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
auto kzgSettings = info[1].As<Napi::External<KZGSettings>>().Data(); auto kzgSettings = info[1].As<Napi::External<KZGSettings>>().Data();
auto numberOfBlobs = blobs_param.Length(); auto numberOfBlobs = blobs_param.Length();
printf("ComputeAggregateKzgProof called with %i blob(s)\n", numberOfBlobs);
auto polynomial = (Polynomial*)calloc(numberOfBlobs, sizeof(Polynomial)); auto polynomial = (Polynomial*)calloc(numberOfBlobs, sizeof(Polynomial));
for (uint32_t blobIndex = 0; blobIndex < numberOfBlobs; blobIndex++) { for (uint32_t blobIndex = 0; blobIndex < numberOfBlobs; blobIndex++) {
Napi::Value blob = blobs_param[blobIndex]; Napi::Value blob = blobs_param[blobIndex];
auto blobBytes = blob.As<Napi::Uint8Array>().Data(); auto blobBytes = blob.As<Napi::Uint8Array>().Data();
printf("Iterating blob index: %i\n", blobIndex);
for (uint32_t fieldIndex = 0; fieldIndex < FIELD_ELEMENTS_PER_BLOB; fieldIndex++) { for (uint32_t fieldIndex = 0; fieldIndex < FIELD_ELEMENTS_PER_BLOB; fieldIndex++) {
bytes_to_bls_field( bytes_to_bls_field(
&polynomial[blobIndex][fieldIndex], &polynomial[blobIndex][fieldIndex],
@ -168,19 +158,9 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
return env.Undefined(); return env.Undefined();
}; };
printf("proof generated: %llu y: %llu z: %llu\n", proof.x, proof.y, proof.z); uint8_t proofBytes[BYTES_PER_PROOF];
printf("compute_aggregate_kzg_proof ret was %i\n", ret); bytes_from_g1(proofBytes, &proof);
return napi_typed_array_from_bytes(proofBytes, BYTES_PER_PROOF, env);
uint8_t array[48];
bytes_from_g1(array, &proof);
printf("Turned proof into bytes: [");
for (int i = 0; i < sizeof(array); i++) {
printf("%x ", array[i]);
}
printf("]\n");
return napiTypedArrayFromByteArray(array, sizeof(array), env);
} }
// verifyAggregateKzgProof: (blobs: Blob[], expectedKzgCommitments: KZGCommitment[], kzgAggregatedProof: KZGProof) => boolean; // verifyAggregateKzgProof: (blobs: Blob[], expectedKzgCommitments: KZGCommitment[], kzgAggregatedProof: KZGProof) => boolean;
@ -242,15 +222,14 @@ Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) {
} }
bool verificationResult; bool verificationResult;
ret = verify_aggregate_kzg_proof( if (verify_aggregate_kzg_proof(
&verificationResult, &verificationResult,
polynomial, polynomial,
commitments, commitments,
numberOfBlobs, numberOfBlobs,
&proof, &proof,
kzgSettings kzgSettings
); ) != C_KZG_OK) {
if (ret != C_KZG_OK) {
free(commitments); free(commitments);
free(polynomial); free(polynomial);
@ -275,7 +254,6 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
return env.Null(); return env.Null();
} }
// const uint8_t c[48]
auto c_param = info[0].As<Napi::TypedArray>(); auto c_param = info[0].As<Napi::TypedArray>();
if (c_param.TypedArrayType() != napi_uint8_array) { if (c_param.TypedArrayType() != napi_uint8_array) {
Napi::Error::New(env, "Expected an Uint8Array") Napi::Error::New(env, "Expected an Uint8Array")
@ -284,7 +262,6 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
} }
auto c = c_param.As<Napi::Uint8Array>().Data(); auto c = c_param.As<Napi::Uint8Array>().Data();
// const uint8_t x[32]
auto x_param = info[0].As<Napi::TypedArray>(); auto x_param = info[0].As<Napi::TypedArray>();
if (x_param.TypedArrayType() != napi_uint8_array) { if (x_param.TypedArrayType() != napi_uint8_array) {
Napi::Error::New(env, "Expected an Uint8Array") Napi::Error::New(env, "Expected an Uint8Array")
@ -293,7 +270,6 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
} }
auto x = x_param.As<Napi::Uint8Array>().Data(); auto x = x_param.As<Napi::Uint8Array>().Data();
// const uint8_t y[32]
auto y_param = info[0].As<Napi::TypedArray>(); auto y_param = info[0].As<Napi::TypedArray>();
if (y_param.TypedArrayType() != napi_uint8_array) { if (y_param.TypedArrayType() != napi_uint8_array) {
Napi::Error::New(env, "Expected an Uint8Array") Napi::Error::New(env, "Expected an Uint8Array")
@ -302,7 +278,6 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
} }
auto y = y_param.As<Napi::Uint8Array>().Data(); auto y = y_param.As<Napi::Uint8Array>().Data();
// const uint8_t p[48]
auto p_param = info[0].As<Napi::TypedArray>(); auto p_param = info[0].As<Napi::TypedArray>();
if (p_param.TypedArrayType() != napi_uint8_array) { if (p_param.TypedArrayType() != napi_uint8_array) {
Napi::Error::New(info.Env(), "Expected an Uint8Array") Napi::Error::New(info.Env(), "Expected an Uint8Array")
@ -311,7 +286,6 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
} }
auto p = p_param.As<Napi::Uint8Array>().Data(); auto p = p_param.As<Napi::Uint8Array>().Data();
// KZGSettings *s
auto kzgSettings = info[4].As<Napi::External<KZGSettings>>().Data(); auto kzgSettings = info[4].As<Napi::External<KZGSettings>>().Data();
KZGCommitment commitment; KZGCommitment commitment;
@ -343,14 +317,12 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
} }
Napi::Object Init(Napi::Env env, Napi::Object exports) { Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "loadTrustedSetup"), Napi::Function::New(env, LoadTrustedSetup)); exports["loadTrustedSetup"] = Napi::Function::New(env, LoadTrustedSetup);
exports.Set(Napi::String::New(env, "freeTrustedSetup"), Napi::Function::New(env, FreeTrustedSetup)); exports["freeTrustedSetup"] = Napi::Function::New(env, FreeTrustedSetup);
exports.Set(Napi::String::New(env, "verifyKzgProof"), Napi::Function::New(env, VerifyKzgProof)); exports["verifyKzgProof"] = Napi::Function::New(env, VerifyKzgProof);
exports["blobToKzgCommitment"] = Napi::Function::New(env, BlobToKzgCommitment);
exports["computeAggregateKzgProof"] = Napi::Function::New(env, ComputeAggregateKzgProof);
exports.Set(Napi::String::New(env, "blobToKzgCommitment"), Napi::Function::New(env, BlobToKzgCommitment)); exports["verifyAggregateKzgProof"] = Napi::Function::New(env, VerifyAggregateKzgProof);
exports.Set(Napi::String::New(env, "verifyAggregateKzgProof"), Napi::Function::New(env, VerifyAggregateKzgProof));
exports.Set(Napi::String::New(env, "computeAggregateKzgProof"), Napi::Function::New(env, ComputeAggregateKzgProof));
return exports; return exports;
} }

View File

@ -1,5 +1,5 @@
// @ts-expect-error // @ts-expect-error
import bindings from 'bindings'; import bindings from "bindings";
export const BLOB_SIZE = 4096; export const BLOB_SIZE = 4096;
export const NUMBER_OF_FIELDS = 32; export const NUMBER_OF_FIELDS = 32;
@ -20,14 +20,14 @@ type KZG = {
computeAggregateKzgProof: ( computeAggregateKzgProof: (
blobs: Blob[], blobs: Blob[],
setupHandle: SetupHandle, setupHandle: SetupHandle
) => KZGProof; ) => KZGProof;
verifyAggregateKzgProof: ( verifyAggregateKzgProof: (
blobs: Blob[], blobs: Blob[],
expectedKzgCommitments: KZGCommitment[], expectedKzgCommitments: KZGCommitment[],
kzgAggregatedProof: KZGProof, kzgAggregatedProof: KZGProof,
setupHandle: SetupHandle, setupHandle: SetupHandle
) => boolean; ) => boolean;
verifyKzgProof: ( verifyKzgProof: (
@ -35,11 +35,11 @@ type KZG = {
z: BLSFieldElement, z: BLSFieldElement,
y: BLSFieldElement, y: BLSFieldElement,
kzgProof: KZGProof, kzgProof: KZGProof,
setupHandle: SetupHandle, setupHandle: SetupHandle
) => boolean; ) => boolean;
}; };
const kzg: KZG = bindings('kzg.node'); const kzg: KZG = bindings("kzg.node");
// Stored as internal state // Stored as internal state
let setupHandle: SetupHandle | undefined; let setupHandle: SetupHandle | undefined;
@ -47,7 +47,7 @@ let setupHandle: SetupHandle | undefined;
export function loadTrustedSetup(filePath: string) { export function loadTrustedSetup(filePath: string) {
if (setupHandle) { if (setupHandle) {
throw new Error( throw new Error(
'Call freeTrustedSetup before loading a new trusted setup.', "Call freeTrustedSetup before loading a new trusted setup."
); );
} }
setupHandle = kzg.loadTrustedSetup(filePath); setupHandle = kzg.loadTrustedSetup(filePath);
@ -55,7 +55,7 @@ export function loadTrustedSetup(filePath: string) {
export function freeTrustedSetup() { export function freeTrustedSetup() {
if (!setupHandle) { if (!setupHandle) {
throw new Error('You must call loadTrustedSetup before freeTrustedSetup.'); throw new Error("You must call loadTrustedSetup before freeTrustedSetup.");
} }
kzg.freeTrustedSetup(setupHandle); kzg.freeTrustedSetup(setupHandle);
setupHandle = undefined; setupHandle = undefined;
@ -63,14 +63,14 @@ export function freeTrustedSetup() {
export function blobToKzgCommitment(blob: Blob) { export function blobToKzgCommitment(blob: Blob) {
if (!setupHandle) { if (!setupHandle) {
throw new Error('You must call loadTrustedSetup to initialize KZG.'); throw new Error("You must call loadTrustedSetup to initialize KZG.");
} }
return kzg.blobToKzgCommitment(blob, setupHandle); return kzg.blobToKzgCommitment(blob, setupHandle);
} }
export function computeAggregateKzgProof(blobs: Blob[]) { export function computeAggregateKzgProof(blobs: Blob[]) {
if (!setupHandle) { if (!setupHandle) {
throw new Error('You must call loadTrustedSetup to initialize KZG.'); throw new Error("You must call loadTrustedSetup to initialize KZG.");
} }
return kzg.computeAggregateKzgProof(blobs, setupHandle); return kzg.computeAggregateKzgProof(blobs, setupHandle);
} }
@ -82,10 +82,10 @@ export function verifyKzgProof(
polynomialKzg: KZGCommitment, polynomialKzg: KZGCommitment,
z: BLSFieldElement, z: BLSFieldElement,
y: BLSFieldElement, y: BLSFieldElement,
kzgProof: KZGProof, kzgProof: KZGProof
) { ) {
if (!setupHandle) { if (!setupHandle) {
throw new Error('You must call loadTrustedSetup to initialize KZG.'); throw new Error("You must call loadTrustedSetup to initialize KZG.");
} }
return kzg.verifyKzgProof(polynomialKzg, z, y, kzgProof, setupHandle); return kzg.verifyKzgProof(polynomialKzg, z, y, kzgProof, setupHandle);
} }
@ -93,15 +93,15 @@ export function verifyKzgProof(
export function verifyAggregateKzgProof( export function verifyAggregateKzgProof(
blobs: Blob[], blobs: Blob[],
expectedKzgCommitments: KZGCommitment[], expectedKzgCommitments: KZGCommitment[],
kzgAggregatedProof: KZGProof, kzgAggregatedProof: KZGProof
) { ) {
if (!setupHandle) { if (!setupHandle) {
throw new Error('You must call loadTrustedSetup to initialize KZG.'); throw new Error("You must call loadTrustedSetup to initialize KZG.");
} }
return kzg.verifyAggregateKzgProof( return kzg.verifyAggregateKzgProof(
blobs, blobs,
expectedKzgCommitments, expectedKzgCommitments,
kzgAggregatedProof, kzgAggregatedProof,
setupHandle, setupHandle
); );
} }

View File

@ -1,11 +1,10 @@
{ {
"name": "c-kzg", "name": "c-kzg",
"version": "0.0.1", "version": "0.0.1",
"description": "", "description": "NodeJS bindings for C-KZG",
"author": "Dan Coffman", "author": "Dan Coffman",
"license": "MIT", "license": "MIT",
"main": "test.ts", "main": "kzg.ts",
"gypfile": true,
"scripts": { "scripts": {
"clean": "node-gyp clean", "clean": "node-gyp clean",
"build": "node-gyp rebuild", "build": "node-gyp rebuild",
@ -15,12 +14,13 @@
"@babel/preset-typescript": "^7.18.6", "@babel/preset-typescript": "^7.18.6",
"@types/jest": "^29.2.1", "@types/jest": "^29.2.1",
"jest": "^29.2.2", "jest": "^29.2.2",
"node-addon-api": "^5.0.0",
"node-gyp": "^9.3.0", "node-gyp": "^9.3.0",
"prettier": "2.7.1",
"ts-jest": "^29.0.3", "ts-jest": "^29.0.3",
"typescript": "^4.8.4" "typescript": "^4.8.4"
}, },
"dependencies": { "dependencies": {
"bindings": "^1.5.0", "bindings": "^1.5.0"
"node-addon-api": "^5.0.0"
} }
} }

View File

@ -1,4 +1,4 @@
import { randomBytes } from 'crypto'; import { randomBytes } from "crypto";
import { import {
loadTrustedSetup, loadTrustedSetup,
freeTrustedSetup, freeTrustedSetup,
@ -9,15 +9,15 @@ import {
NUMBER_OF_FIELDS, NUMBER_OF_FIELDS,
computeAggregateKzgProof, computeAggregateKzgProof,
verifyAggregateKzgProof, verifyAggregateKzgProof,
} from './kzg'; } from "./kzg";
const SETUP_FILE_PATH = '../../src/trusted_setup.txt'; const SETUP_FILE_PATH = "../../src/trusted_setup.txt";
function generateRandomBlob(): Blob { function generateRandomBlob(): Blob {
return new Uint8Array(randomBytes(BLOB_SIZE * NUMBER_OF_FIELDS)); return new Uint8Array(randomBytes(BLOB_SIZE * NUMBER_OF_FIELDS));
} }
describe('C-KZG', () => { describe("C-KZG", () => {
beforeEach(() => { beforeEach(() => {
loadTrustedSetup(SETUP_FILE_PATH); loadTrustedSetup(SETUP_FILE_PATH);
}); });
@ -26,7 +26,7 @@ describe('C-KZG', () => {
freeTrustedSetup(); freeTrustedSetup();
}); });
it('computes and verifies an aggregate KZG proof', async () => { it("computes and verifies an aggregate KZG proof", async () => {
const blob1 = generateRandomBlob(); const blob1 = generateRandomBlob();
const blob2 = generateRandomBlob(); const blob2 = generateRandomBlob();
const blobs = [blob1, blob2]; const blobs = [blob1, blob2];

View File

@ -2296,6 +2296,11 @@ pkg-dir@^4.2.0:
dependencies: dependencies:
find-up "^4.0.0" find-up "^4.0.0"
prettier@2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64"
integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
pretty-format@^29.0.0, pretty-format@^29.2.1: pretty-format@^29.0.0, pretty-format@^29.2.1:
version "29.2.1" version "29.2.1"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.2.1.tgz#86e7748fe8bbc96a6a4e04fa99172630907a9611" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.2.1.tgz#86e7748fe8bbc96a6a4e04fa99172630907a9611"

View File

@ -35,6 +35,7 @@ extern "C" {
#endif #endif
#define BYTES_PER_COMMITMENT 48 #define BYTES_PER_COMMITMENT 48
#define BYTES_PER_PROOF 48
#define BYTES_PER_FIELD 32 #define BYTES_PER_FIELD 32
#define FIELD_ELEMENTS_PER_BLOB 4096 #define FIELD_ELEMENTS_PER_BLOB 4096