Merge branch '4844'
This commit is contained in:
commit
68897b375c
|
@ -9,3 +9,4 @@ inc/blst_aux.h*
|
||||||
*bindings/csharp/*.exe
|
*bindings/csharp/*.exe
|
||||||
*bindings/csharp/*.dll
|
*bindings/csharp/*.dll
|
||||||
__pycache__
|
__pycache__
|
||||||
|
.DS_Store
|
||||||
|
|
23
README.md
23
README.md
|
@ -1,6 +1,7 @@
|
||||||
# C-KZG-4844: A minimal library for EIP-4844 Polynomial Commitments
|
# C-KZG-4844: A minimal library for EIP-4844 Polynomial Commitments
|
||||||
|
|
||||||
This is a copy of C-KZG stripped down to support the [Polynomial Commitments](https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md) API:
|
This is a copy of C-KZG stripped down to support the [Polynomial Commitments](https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md) API:
|
||||||
|
|
||||||
- `compute_aggregate_kzg_proof`
|
- `compute_aggregate_kzg_proof`
|
||||||
- `verify_aggregate_kzg_proof`
|
- `verify_aggregate_kzg_proof`
|
||||||
- `blob_to_kzg_commitment`
|
- `blob_to_kzg_commitment`
|
||||||
|
@ -9,3 +10,25 @@ This is a copy of C-KZG stripped down to support the [Polynomial Commitments](ht
|
||||||
We also provide `load_trusted_setup` and `free_trusted_setup` to load the
|
We also provide `load_trusted_setup` and `free_trusted_setup` to load the
|
||||||
trusted setup data from a file into an object that can be passed to the API
|
trusted setup data from a file into an object that can be passed to the API
|
||||||
functions, and functions for converting commitments/proofs/points to/from bytes.
|
functions, and functions for converting commitments/proofs/points to/from bytes.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install the blst submodule
|
||||||
|
|
||||||
|
```
|
||||||
|
git submodule update --init
|
||||||
|
```
|
||||||
|
|
||||||
|
Build blst
|
||||||
|
|
||||||
|
```
|
||||||
|
cd src
|
||||||
|
make blst
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the C-KZG code
|
||||||
|
|
||||||
|
```
|
||||||
|
cd src
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
build
|
build
|
||||||
|
dist
|
||||||
*.node
|
*.node
|
||||||
node_modules
|
node_modules
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
.vscode
|
||||||
|
build
|
||||||
|
!dist/deps/blst/build
|
||||||
|
node_modules
|
||||||
|
.gitignore
|
||||||
|
.npmignore
|
||||||
|
.prettierignore
|
||||||
|
.prettierrc.json
|
||||||
|
*.o
|
||||||
|
*.node
|
||||||
|
test.ts
|
||||||
|
kzg.ts
|
||||||
|
jest.config.js
|
||||||
|
rollup.config.js
|
||||||
|
tsconfig.json
|
||||||
|
babel.config.js
|
||||||
|
*.bak
|
||||||
|
Dockerfile
|
||||||
|
binding.dist.gyp
|
||||||
|
Makefile
|
|
@ -2,7 +2,7 @@
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": "binding.gyp",
|
"files": "*.gyp",
|
||||||
"options": { "parser": "json" }
|
"options": { "parser": "json" }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Exists as a test harness for building and running tests in Linux
|
||||||
|
|
||||||
|
FROM node:16
|
||||||
|
|
||||||
|
COPY ./dist/ /app/dist/
|
||||||
|
COPY test.ts /app
|
||||||
|
COPY trusted_setup.txt /app
|
||||||
|
COPY kzg.ts /app
|
||||||
|
COPY kzg.cxx /app
|
||||||
|
COPY package.json /app
|
||||||
|
COPY tsconfig.json /app
|
||||||
|
COPY babel.config.js /app
|
||||||
|
COPY jest.config.js /app
|
||||||
|
COPY binding.dist.gyp /app/binding.gyp
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN yarn install
|
||||||
|
|
||||||
|
CMD ["yarn", "jest"]
|
|
@ -3,8 +3,8 @@ all: clean build format test bundle
|
||||||
clean:
|
clean:
|
||||||
yarn node-gyp clean
|
yarn node-gyp clean
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
rm -rf dist
|
||||||
rm -f *.node
|
rm -f *.node
|
||||||
rm -f dist/kzg.node
|
|
||||||
rm -f *.a
|
rm -f *.a
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
|
|
||||||
|
@ -18,5 +18,21 @@ test: build
|
||||||
format:
|
format:
|
||||||
yarn prettier --write .
|
yarn prettier --write .
|
||||||
|
|
||||||
bundle:
|
bundle: clean
|
||||||
yarn rollup --config rollup.config.js --bundleConfigAsCjs
|
yarn rollup --config rollup.config.js --bundleConfigAsCjs
|
||||||
|
mkdir -p dist/deps/c-kzg
|
||||||
|
cp -r ../../blst dist/deps
|
||||||
|
cp ../../src/c_kzg_4844.c dist/deps/c-kzg
|
||||||
|
cp ../../src/c_kzg_4844.h dist/deps/c-kzg
|
||||||
|
|
||||||
|
publish: bundle
|
||||||
|
mv binding.gyp binding.gyp.bak
|
||||||
|
cp binding.dist.gyp binding.gyp
|
||||||
|
npm publish && mv binding.gyp.bak binding.gyp || mv binding.gyp.bak binding.gyp
|
||||||
|
|
||||||
|
|
||||||
|
linux-test: bundle
|
||||||
|
cp ../../src/trusted_setup.txt .
|
||||||
|
docker build -t "linux-test" .
|
||||||
|
rm trusted_setup.txt
|
||||||
|
docker logs --follow `docker run -d linux-test`
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"target_name": "kzg",
|
||||||
|
"cflags!": ["-fno-exceptions"],
|
||||||
|
"cflags_cc!": ["-fno-exceptions"],
|
||||||
|
"xcode_settings": {
|
||||||
|
"GCC_ENABLE_CPP_EXCEPTIONS": "YES",
|
||||||
|
"CLANG_CXX_LIBRARY": "libc++",
|
||||||
|
"MACOSX_DEPLOYMENT_TARGET": "13.0"
|
||||||
|
},
|
||||||
|
"sources": ["kzg.cxx"],
|
||||||
|
"include_dirs": [
|
||||||
|
"<(module_root_dir)/dist/deps/blst/bindings",
|
||||||
|
"<(module_root_dir)/dist/deps/c-kzg",
|
||||||
|
"<!@(node -p \"require('node-addon-api').include\")"
|
||||||
|
],
|
||||||
|
"libraries": [
|
||||||
|
"<(module_root_dir)/c_kzg_4844.o",
|
||||||
|
"<(module_root_dir)/libblst.a"
|
||||||
|
],
|
||||||
|
"dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"],
|
||||||
|
"defines": ["NAPI_DISABLE_CPP_EXCEPTIONS"],
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"action_name": "build_blst",
|
||||||
|
"inputs": ["<(module_root_dir)/dist/deps/blst/build.sh"],
|
||||||
|
"outputs": ["<(module_root_dir)/libblst.a"],
|
||||||
|
"action": ["<(module_root_dir)/dist/deps/blst/build.sh"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"action_name": "build_ckzg",
|
||||||
|
"inputs": [
|
||||||
|
"<(module_root_dir)/dist/deps/c-kzg/c_kzg_4844.c",
|
||||||
|
"<(module_root_dir)/libblst.a"
|
||||||
|
],
|
||||||
|
"outputs": ["<(module_root_dir)/c_kzg_4844.o"],
|
||||||
|
"action": [
|
||||||
|
"cc",
|
||||||
|
"-I<(module_root_dir)/dist/deps/blst/bindings",
|
||||||
|
"-O2",
|
||||||
|
"-c",
|
||||||
|
"<(module_root_dir)/dist/deps/c-kzg/c_kzg_4844.c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target_name": "action_after_build",
|
||||||
|
"type": "none",
|
||||||
|
"dependencies": ["kzg"],
|
||||||
|
"copies": [
|
||||||
|
{
|
||||||
|
"files": ["./build/Release/kzg.node"],
|
||||||
|
"destination": "./dist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["./build/Release/kzg.node"],
|
||||||
|
"destination": "./"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -30,10 +30,6 @@
|
||||||
{
|
{
|
||||||
"files": ["./build/Release/kzg.node"],
|
"files": ["./build/Release/kzg.node"],
|
||||||
"destination": "."
|
"destination": "."
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": ["./build/Release/kzg.node"],
|
|
||||||
"destination": "./dist"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
export declare type BLSFieldElement = Uint8Array;
|
|
||||||
export declare type KZGProof = Uint8Array;
|
|
||||||
export declare type KZGCommitment = Uint8Array;
|
|
||||||
export declare type Blob = Uint8Array;
|
|
||||||
export declare const FIELD_ELEMENTS_PER_BLOB: number;
|
|
||||||
export declare const BYTES_PER_FIELD_ELEMENT: number;
|
|
||||||
export declare function loadTrustedSetup(filePath: string): void;
|
|
||||||
export declare function freeTrustedSetup(): void;
|
|
||||||
export declare function blobToKzgCommitment(blob: Blob): KZGCommitment;
|
|
||||||
export declare function computeAggregateKzgProof(blobs: Blob[]): KZGProof;
|
|
||||||
export declare function verifyAggregateKzgProof(blobs: Blob[], expectedKzgCommitments: KZGCommitment[], kzgAggregatedProof: KZGProof): boolean;
|
|
|
@ -1 +0,0 @@
|
||||||
export {};
|
|
|
@ -1,44 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The public interface of this module exposes the functions as specified by
|
|
||||||
* https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md#kzg
|
|
||||||
*/
|
|
||||||
const kzg = require("./kzg.node");
|
|
||||||
const FIELD_ELEMENTS_PER_BLOB = kzg.FIELD_ELEMENTS_PER_BLOB;
|
|
||||||
const BYTES_PER_FIELD_ELEMENT = kzg.BYTES_PER_FIELD_ELEMENT;
|
|
||||||
// Stored as internal state
|
|
||||||
let setupHandle;
|
|
||||||
function requireSetupHandle() {
|
|
||||||
if (!setupHandle) {
|
|
||||||
throw new Error("You must call loadTrustedSetup to initialize KZG.");
|
|
||||||
}
|
|
||||||
return setupHandle;
|
|
||||||
}
|
|
||||||
function loadTrustedSetup(filePath) {
|
|
||||||
if (setupHandle) {
|
|
||||||
throw new Error("Call freeTrustedSetup before loading a new trusted setup.");
|
|
||||||
}
|
|
||||||
setupHandle = kzg.loadTrustedSetup(filePath);
|
|
||||||
}
|
|
||||||
function freeTrustedSetup() {
|
|
||||||
kzg.freeTrustedSetup(requireSetupHandle());
|
|
||||||
setupHandle = undefined;
|
|
||||||
}
|
|
||||||
function blobToKzgCommitment(blob) {
|
|
||||||
return kzg.blobToKzgCommitment(blob, requireSetupHandle());
|
|
||||||
}
|
|
||||||
function computeAggregateKzgProof(blobs) {
|
|
||||||
return kzg.computeAggregateKzgProof(blobs, requireSetupHandle());
|
|
||||||
}
|
|
||||||
function verifyAggregateKzgProof(blobs, expectedKzgCommitments, kzgAggregatedProof) {
|
|
||||||
return kzg.verifyAggregateKzgProof(blobs, expectedKzgCommitments, kzgAggregatedProof, requireSetupHandle());
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.BYTES_PER_FIELD_ELEMENT = BYTES_PER_FIELD_ELEMENT;
|
|
||||||
exports.FIELD_ELEMENTS_PER_BLOB = FIELD_ELEMENTS_PER_BLOB;
|
|
||||||
exports.blobToKzgCommitment = blobToKzgCommitment;
|
|
||||||
exports.computeAggregateKzgProof = computeAggregateKzgProof;
|
|
||||||
exports.freeTrustedSetup = freeTrustedSetup;
|
|
||||||
exports.loadTrustedSetup = loadTrustedSetup;
|
|
||||||
exports.verifyAggregateKzgProof = verifyAggregateKzgProof;
|
|
|
@ -155,6 +155,7 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
|
||||||
auto kzg_settings = info[1].As<Napi::External<KZGSettings>>().Data();
|
auto kzg_settings = info[1].As<Napi::External<KZGSettings>>().Data();
|
||||||
|
|
||||||
auto blobs_count = blobs_param.Length();
|
auto blobs_count = blobs_param.Length();
|
||||||
|
|
||||||
auto blobs = (Blob*)calloc(blobs_count, sizeof(Blob));
|
auto blobs = (Blob*)calloc(blobs_count, sizeof(Blob));
|
||||||
|
|
||||||
for (uint32_t blob_index = 0; blob_index < blobs_count; blob_index++) {
|
for (uint32_t blob_index = 0; blob_index < blobs_count; blob_index++) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "c-kzg",
|
"name": "c-kzg",
|
||||||
"version": "0.0.1",
|
"version": "0.0.9",
|
||||||
"description": "NodeJS bindings for C-KZG",
|
"description": "NodeJS bindings for C-KZG",
|
||||||
"author": "Dan Coffman",
|
"author": "Dan Coffman",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -12,12 +12,14 @@
|
||||||
"@rollup/plugin-typescript": "^9.0.2",
|
"@rollup/plugin-typescript": "^9.0.2",
|
||||||
"@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",
|
"prettier": "2.7.1",
|
||||||
"rollup": "^3.2.5",
|
"rollup": "^3.2.5",
|
||||||
"ts-jest": "^29.0.3",
|
"ts-jest": "^29.0.3",
|
||||||
"tslib": "^2.4.1",
|
"tslib": "^2.4.1",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.8.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"node-addon-api": "^5.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,9 @@ export default {
|
||||||
dir: "dist",
|
dir: "dist",
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
},
|
},
|
||||||
plugins: [typescript()],
|
plugins: [
|
||||||
|
typescript({
|
||||||
|
exclude: ["test.ts"],
|
||||||
|
}),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { randomBytes } from "crypto";
|
import { randomBytes } from "crypto";
|
||||||
|
import { existsSync } from "fs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
loadTrustedSetup,
|
loadTrustedSetup,
|
||||||
freeTrustedSetup,
|
freeTrustedSetup,
|
||||||
|
@ -9,7 +11,12 @@ import {
|
||||||
FIELD_ELEMENTS_PER_BLOB,
|
FIELD_ELEMENTS_PER_BLOB,
|
||||||
} from "./kzg";
|
} from "./kzg";
|
||||||
|
|
||||||
const SETUP_FILE_PATH = "../../src/trusted_setup.txt";
|
const setupFileName = "trusted_setup.txt";
|
||||||
|
|
||||||
|
const SETUP_FILE_PATH = existsSync(setupFileName)
|
||||||
|
? setupFileName
|
||||||
|
: `../../src/${setupFileName}`;
|
||||||
|
|
||||||
const BLOB_BYTE_COUNT = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
|
const BLOB_BYTE_COUNT = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
|
||||||
|
|
||||||
const generateRandomBlob = () => new Uint8Array(randomBytes(BLOB_BYTE_COUNT));
|
const generateRandomBlob = () => new Uint8Array(randomBytes(BLOB_BYTE_COUNT));
|
||||||
|
@ -23,10 +30,23 @@ describe("C-KZG", () => {
|
||||||
freeTrustedSetup();
|
freeTrustedSetup();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("computes the correct commitments and aggregate proofs from blobs", () => {
|
it("computes the correct commitments and aggregate proof from blobs", () => {
|
||||||
const blobs = new Array(2).fill(0).map(generateRandomBlob);
|
let blobs = new Array(2).fill(0).map(generateRandomBlob);
|
||||||
const commitments = blobs.map(blobToKzgCommitment);
|
let commitments = blobs.map(blobToKzgCommitment);
|
||||||
const proof = computeAggregateKzgProof(blobs);
|
let proof = computeAggregateKzgProof(blobs);
|
||||||
|
expect(verifyAggregateKzgProof(blobs, commitments, proof)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error when blobs is an empty array", () => {
|
||||||
|
expect(() => computeAggregateKzgProof([])).toThrowError(
|
||||||
|
"Failed to compute proof",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("computes the aggregate proof when for a single blob", () => {
|
||||||
|
let blobs = new Array(1).fill(0).map(generateRandomBlob);
|
||||||
|
let commitments = blobs.map(blobToKzgCommitment);
|
||||||
|
let proof = computeAggregateKzgProof(blobs);
|
||||||
expect(verifyAggregateKzgProof(blobs, commitments, proof)).toBe(true);
|
expect(verifyAggregateKzgProof(blobs, commitments, proof)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1109,14 +1109,25 @@ static C_KZG_RET compute_aggregated_poly_and_commitment(Polynomial poly_out, KZG
|
||||||
const Polynomial polys[],
|
const Polynomial polys[],
|
||||||
const KZGCommitment kzg_commitments[],
|
const KZGCommitment kzg_commitments[],
|
||||||
size_t n) {
|
size_t n) {
|
||||||
BLSFieldElement* r_powers = calloc(n, sizeof(BLSFieldElement));
|
if (n == 0) return C_KZG_BADARGS;
|
||||||
if (r_powers == NULL) return C_KZG_MALLOC;
|
|
||||||
|
|
||||||
C_KZG_RET ret;
|
C_KZG_RET ret;
|
||||||
uint8_t* hash = calloc(32, sizeof(uint8_t));
|
uint8_t* hash = calloc(32, sizeof(uint8_t));
|
||||||
if (hash == NULL) { free(r_powers); return C_KZG_MALLOC; }
|
if (hash == NULL) return C_KZG_MALLOC;
|
||||||
ret = hash_to_bytes(hash, polys, kzg_commitments, n);
|
ret = hash_to_bytes(hash, polys, kzg_commitments, n);
|
||||||
if (ret != C_KZG_OK) { free(r_powers); free(hash); return ret; }
|
if (ret != C_KZG_OK) { free(hash); return ret; }
|
||||||
|
|
||||||
|
if (n == 1) {
|
||||||
|
bytes_to_bls_field(chal_out, hash);
|
||||||
|
poly_lincomb(poly_out, polys, chal_out, n);
|
||||||
|
g1_lincomb(comm_out, kzg_commitments, chal_out, n);
|
||||||
|
free(hash);
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLSFieldElement* r_powers = calloc(n, sizeof(BLSFieldElement));
|
||||||
|
if (r_powers == NULL) { free(hash); return C_KZG_MALLOC; }
|
||||||
|
|
||||||
bytes_to_bls_field(&r_powers[1], hash);
|
bytes_to_bls_field(&r_powers[1], hash);
|
||||||
free(hash);
|
free(hash);
|
||||||
|
|
||||||
|
@ -1135,6 +1146,11 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out,
|
||||||
const Blob blobs[],
|
const Blob blobs[],
|
||||||
size_t n,
|
size_t n,
|
||||||
const KZGSettings *s) {
|
const KZGSettings *s) {
|
||||||
|
if (n == 0) {
|
||||||
|
*out = g1_identity;
|
||||||
|
return C_KZG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
KZGCommitment* commitments = calloc(n, sizeof(KZGCommitment));
|
KZGCommitment* commitments = calloc(n, sizeof(KZGCommitment));
|
||||||
if (commitments == NULL) return C_KZG_MALLOC;
|
if (commitments == NULL) return C_KZG_MALLOC;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue