diff --git a/bindings/node.js/CONTRIBUTING.md b/bindings/node.js/CONTRIBUTING.md new file mode 100644 index 0000000..dacf857 --- /dev/null +++ b/bindings/node.js/CONTRIBUTING.md @@ -0,0 +1,45 @@ +# Contribution Guidelines + +Thanks for your interest in contributing to the Node.js bindings for +c-kzg-4844. + +## Prerequisites + +- [NodeJS](https://nodejs.org/) (LTS) +- [Yarn](https://yarnpkg.com/) + +## Setup + +Open a terminal and navigate to the root of the `c-kzg-4844` repo and run the +following commands if you have not already done so: + +```sh +git submodule update --init # Install the blst submodule +cd src +make blst # Build blst +cd ../bindings/node.js +yarn install --ignore-scripts # Install dependencies +make # Build bindings and verify build worked +``` + +## Project Commands + +* `make clean` - cleans artifacts +* `make build` - prepares assets and builds bindings +* `make test` - runs unit tests +* `make format` - lints code +* `make bundle` - builds `dist` for publishing +* `make publish` - runs `npm publish` + +## `n-api` and `node-addon-api` + +There are two different flavors of abi-stable node addons. +[n-api](https://nodejs.org/api/n-api.html) is the `C` api that is natively +exported by `node.js`. There is also a header-only `C++` implementation of the +`n-api` called [node-addon-api](https://github.com/nodejs/node-addon-api). +There is mixed usage of the two in this library. + +The addon was built to be +[context-aware](https://nodejs.github.io/node-addon-examples/special-topics/context-awareness/) +so it will be safe to run on a worker thread. Be sure not to use any +static/global variables as those are not thread safe. diff --git a/bindings/node.js/README.md b/bindings/node.js/README.md index ae873c1..24dee6c 100644 --- a/bindings/node.js/README.md +++ b/bindings/node.js/README.md @@ -1,93 +1,171 @@ -This package wraps the c-kzg C code in C++ NAPI bindings which allow it to be imported into a NodeJS program. +# C-KZG-4844 + +This is a TypeScript library for EIP-4844 that implements the [Polynomial +Commitments](https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/polynomial-commitments.md) +API. The core functionality was originally a stripped-down copy of +[C-KZG](https://github.com/benjaminion/c-kzg), but has been heavily modified +since then. This package wraps that native `c-kzg` C code in C/C++ NAPI +bindings for use in node.js applications. Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md -# Usage +## Prerequisites -Install this library with +Installation requires compilation of C code. Target environment must have: + +- A compiler like g++ or clang +- [`make`](https://www.gnu.org/software/make/manual/make.html) +- [`python3`](https://docs.python.org/3/) + +## Installation ```sh yarn add c-kzg +# or +npm i -S c-kzg ``` -Import from it like any other library +## Usage -```js +```ts import { - KZGCommitment, + BYTES_PER_BLOB, + Blob, + Bytes48, blobToKzgCommitment, - verifyAggregateKzgProof, - loadTrustedSetup, - transformTrustedSetupJSON, + computeBlobKzgProof, + verifyBlobKzgProofBatch, } from "c-kzg"; + +const blobs = [] as Blob[]; +const commitments = [] as Bytes48[]; +const proofs = [] as Bytes48[]; + +for (let i = 0; i < BATCH_SIZE; i++) { + blobs.push(Buffer.alloc(BYTES_PER_BLOB, "*")); + commitments.push(blobToKzgCommitment(blobs[i])); + proofs.push(computeBlobKzgProof(blobs[i], commitments[i])); +} + +const isValid = verifyBlobKzgProofBatch(blobs, commitments, proofs); ``` -# Requirements +## API -The C and C++ code is compiled by node-gyp on installation. Your environment will need +### `loadTrustedSetup` -- A compiler like g++ or clang -- `make` -- `python3` - -# Contributing - -This directory contains the code necessary to generate NodeJS bindings for C-KZG. - -The bindings file has the following interface: - -```js - - loadTrustedSetup: (filePath: string) => SetupHandle; - - freeTrustedSetup: (setupHandle: SetupHandle) => void; - - blobToKzgCommitment: (blob: Blob, setupHandle: SetupHandle) => KZGCommitment; - - computeAggregateKzgProof: ( - blobs: Blob[], - setupHandle: SetupHandle - ) => KZGProof; - - verifyAggregateKzgProof: ( - blobs: Blob[], - expectedKzgCommitments: KZGCommitment[], - kzgAggregatedProof: KZGProof, - setupHandle: SetupHandle - ) => boolean; +```ts +/** + * Sets up the c-kzg library. Pass in a properly formatted trusted setup file + * to configure the library. File must be in json format, see TrustedSetupJson + * interface for more details, or as a properly formatted utf-8 encoded file. + * + * @remark This function must be run before any other functions in this + * library can be run. + * + * @param {string} filePath - The absolute path of the trusted setup + */ +loadTrustedSetup(filePath: string): void; ``` -But this library wraps it in module with manages the setupHandle internally. +### `blobToKzgCommitment` -First, -`npm install -g yarn` if you don't have it. - -Install the blst submodule - -```sh -git submodule update --init +```ts +/** + * Convert a blob to a KZG commitment. + * + * @param {Blob} blob - The blob representing the polynomial to be committed to + */ +blobToKzgCommitment(blob: Blob): KZGCommitment; ``` -Build blst and c_kzg_4844.c +### `computeKzgProof` -``` -cd src && make blst lib +```ts +/** + * Compute KZG proof for polynomial in Lagrange form at position z. + * + * @param {Blob} blob - The blob (polynomial) to generate a proof for + * @param {Bytes32} zBytes - The generator z-value for the evaluation points + * + * @return {ProofResult} - Tuple containing the resulting proof and evaluation + * of the polynomial at the evaluation point z + */ +computeKzgProof(blob: Blob, zBytes: Bytes32): ProofResult; ``` -Generate NodeJS bindings and run the TypeScript tests against them +### `computeBlobKzgProof` -```sh -cd ../bindings/node.js && yarn install && make test +```ts +/** + * Given a blob, return the KZG proof that is used to verify it against the + * commitment. + * + * @param {Blob} blob - The blob (polynomial) to generate a proof for + * @param {Bytes48} commitmentBytes - Commitment to verify + */ +computeBlobKzgProof( + blob: Blob, + commitmentBytes: Bytes48, +): KZGProof; ``` -After doing this once, you can re-build (if necessary) and re-run the tests with +### `verifyKzgProof` -```sh -make build test +```ts +/** + * Verify a KZG poof claiming that `p(z) == y`. + * + * @param {Bytes48} commitmentBytes - The serialized commitment corresponding to + * polynomial p(x) + * @param {Bytes32} zBytes - The serialized evaluation point + * @param {Bytes32} yBytes - The serialized claimed evaluation result + * @param {Bytes48} proofBytes - The serialized KZG proof + */ +verifyKzgProof( + commitmentBytes: Bytes48, + zBytes: Bytes32, + yBytes: Bytes32, + proofBytes: Bytes48, +): boolean; ``` -After making changes, regenerate the distributable JS and type defs +### `verifyBlobKzgProof` -```sh -make bundle +```ts +/** + * Given a blob and its proof, verify that it corresponds to the provided + * commitment. + * + * @param {Blob} blob - The serialized blob to verify + * @param {Bytes48} commitmentBytes - The serialized commitment to verify + * @param {Bytes48} proofBytes - The serialized KZG proof for verification + */ +verifyBlobKzgProof( + blob: Blob, + commitmentBytes: Bytes48, + proofBytes: Bytes48, +): boolean; +``` + +### `verifyBlobKzgProofBatch` + +```ts +/** + * Given an array of blobs and their proofs, verify that they corresponds to + * their provided commitment. + * + * Note: blobs[0] relates to commitmentBytes[0] and proofBytes[0] + * + * @param {Blob} blobs - An array of serialized blobs to verify + * @param {Bytes48} commitmentBytes - An array of serialized commitments to + * verify + * @param {Bytes48} proofBytes - An array of serialized KZG proofs for + * verification + */ +verifyBlobKzgProofBatch( + blobs: Blob[], + commitmentsBytes: Bytes48[], + proofsBytes: Bytes48[], +): boolean; ``` diff --git a/bindings/node.js/lib/kzg.ts b/bindings/node.js/lib/kzg.ts index 4d24785..c331ffc 100644 --- a/bindings/node.js/lib/kzg.ts +++ b/bindings/node.js/lib/kzg.ts @@ -89,7 +89,7 @@ function transformTrustedSetupJson(filePath: string): string { /** * Sets up the c-kzg library. Pass in a properly formatted trusted setup file - * to configure the library. File must be in json format, see or {@link TrustedSetupJson} + * to configure the library. File must be in json format, see {@link TrustedSetupJson} * interface for more details, or as a properly formatted utf-8 encoded file. * * @remark This function must be run before any other functions in this