Remove tsc build step and export raw .js file and .d.ts from node bindings (#260)

This commit is contained in:
Matthew Keil 2023-03-29 20:32:06 -04:00 committed by GitHub
parent 656d0c74a7
commit a7f4890a7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 185 additions and 228 deletions

View File

@ -40,12 +40,13 @@ build: install clean
@# Build the bindings
@$(YARN) node-gyp --loglevel=warn configure
@$(YARN) node-gyp --loglevel=warn build
@$(YARN) tsc -p tsconfig.build.json
# Bundle the distribution, also helpful for cross compatibility checks
.PHONY: bundle
bundle: build
@mkdir dist
@mv deps dist
@cp -r lib dist/lib
@cp -r src dist/src
@cp README.md dist/README.md
@cp package.json dist/package.json

131
bindings/node.js/lib/kzg.d.ts vendored Normal file
View File

@ -0,0 +1,131 @@
/**
* 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
*/
export type Bytes32 = Uint8Array; // 32 bytes
export type Bytes48 = Uint8Array; // 48 bytes
export type KZGProof = Buffer; // 48 bytes
export type KZGCommitment = Buffer; // 48 bytes
export type Blob = Uint8Array; // 4096 * 32 bytes
export type ProofResult = [KZGProof, Bytes32];
export interface TrustedSetupJson {
setup_G1: string[];
setup_G2: string[];
setup_G1_lagrange: string[];
roots_of_unity: string[];
}
export const BYTES_PER_BLOB: number;
export const BYTES_PER_COMMITMENT: number;
export const BYTES_PER_FIELD_ELEMENT: number;
export const BYTES_PER_PROOF: number;
export const FIELD_ELEMENTS_PER_BLOB: number;
/**
* Factory function that passes trusted setup to the bindings
*
* @param {string} filePath
*
* @return {KzgBindings}
*
* @throws {TypeError} - Non-String input
* @throws {Error} - For all other errors. See error message for more info
*/
export function loadTrustedSetup(filePath: string): void;
/**
* Convert a blob to a KZG commitment.
*
* @param {Blob} blob - The blob representing the polynomial to be committed to
*
* @return {KZGCommitment} - The resulting commitment
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function blobToKzgCommitment(blob: Blob): KZGCommitment;
/**
* 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
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function computeKzgProof(blob: Blob, zBytes: Bytes32): ProofResult;
/**
* 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
*
* @return {KZGProof} - The resulting proof
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function computeBlobKzgProof(
blob: Blob,
commitmentBytes: Bytes48,
): KZGProof;
/**
* 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
*
* @return {boolean} - true/false depending on proof validity
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function verifyKzgProof(
commitment: Bytes48,
zBytes: Bytes32,
yBytes: Bytes32,
proof: Bytes48,
): boolean;
/**
* 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
*
* @return {boolean} - true/false depending on proof validity
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function verifyBlobKzgProof(
blob: Blob,
commitment: Bytes48,
proof: Bytes48,
): boolean;
/**
* 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
*
* @return {boolean} - true/false depending on batch validity
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function verifyBlobKzgProofBatch(
blobs: Blob[],
commitments: Bytes48[],
proofs: Bytes48[],
): boolean;

View File

@ -0,0 +1,51 @@
/**
* 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 fs = require("fs");
const path = require("path");
const bindings = require("bindings")("kzg");
/**
* Converts JSON formatted trusted setup into the native format that
* the native library requires. Returns the absolute file path to the
* the formatted file. The path will be the same as the origin
* file but with a ".txt" extension.
*
* @param {string} filePath - The absolute path of JSON formatted trusted setup
*
* @return {string} - The absolute path of the re-formatted trusted setup
*
* @throws {Error} - For invalid file operations
*/
function transformTrustedSetupJson(filePath) {
const trustedSetup = JSON.parse(fs.readFileSync(filePath, "utf8"));
const setupText =
bindings.FIELD_ELEMENTS_PER_BLOB +
"\n65\n" +
trustedSetup.setup_G1.map((p) => p.substring(2)).join("\n") +
"\n" +
trustedSetup.setup_G2.map((p) => p.substring(2)).join("\n");
const outputPath = filePath.replace(".json", ".txt");
fs.writeFileSync(outputPath, setupText);
return outputPath;
}
const originalLoadTrustedSetup = bindings.loadTrustedSetup;
// docstring in ./kzg.d.ts with exported definition
bindings.loadTrustedSetup = function loadTrustedSetup(filePath) {
if (!(filePath && typeof filePath === "string")) {
throw new TypeError(
"must initialize kzg with the filePath to a txt/json trusted setup",
);
}
if (!fs.existsSync(filePath)) {
throw new Error(`no trusted setup found: ${filePath}`);
}
if (path.parse(filePath).ext === ".json") {
filePath = transformTrustedSetupJson(filePath);
}
originalLoadTrustedSetup(filePath);
};
module.exports = exports = bindings;

View File

@ -1,226 +0,0 @@
/**
* 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: KZG = require("bindings")("kzg");
import * as fs from "fs";
import * as path from "path";
export type Bytes32 = Uint8Array; // 32 bytes
export type Bytes48 = Uint8Array; // 48 bytes
export type KZGProof = Buffer; // 48 bytes
export type KZGCommitment = Buffer; // 48 bytes
export type Blob = Uint8Array; // 4096 * 32 bytes
export type ProofResult = [KZGProof, Bytes32];
export interface TrustedSetupJson {
setup_G1: string[];
setup_G2: string[];
setup_G1_lagrange: string[];
roots_of_unity: string[];
}
// The C++ native addon interface
interface KZG {
BYTES_PER_BLOB: number;
BYTES_PER_COMMITMENT: number;
BYTES_PER_FIELD_ELEMENT: number;
BYTES_PER_PROOF: number;
FIELD_ELEMENTS_PER_BLOB: number;
loadTrustedSetup: (filePath: string) => void;
blobToKzgCommitment: (blob: Blob) => KZGCommitment;
computeKzgProof: (blob: Blob, zBytes: Bytes32) => ProofResult;
computeBlobKzgProof: (blob: Blob, commitmentBytes: Bytes48) => KZGProof;
verifyKzgProof: (
commitmentBytes: Bytes48,
zBytes: Bytes32,
yBytes: Bytes32,
proofBytes: Bytes48,
) => boolean;
verifyBlobKzgProof: (
blob: Blob,
commitmentBytes: Bytes48,
proofBytes: Bytes48,
) => boolean;
verifyBlobKzgProofBatch: (
blobs: Blob[],
commitmentsBytes: Bytes48[],
proofsBytes: Bytes48[],
) => boolean;
}
export const BYTES_PER_BLOB = kzg.BYTES_PER_BLOB;
export const BYTES_PER_COMMITMENT = kzg.BYTES_PER_COMMITMENT;
export const BYTES_PER_FIELD_ELEMENT = kzg.BYTES_PER_FIELD_ELEMENT;
export const BYTES_PER_PROOF = kzg.BYTES_PER_PROOF;
export const FIELD_ELEMENTS_PER_BLOB = kzg.FIELD_ELEMENTS_PER_BLOB;
/**
* Converts JSON formatted trusted setup into the native format that
* the native library requires. Returns the absolute file path to the
* the formatted file. The path will be the same as the origin
* file but with a ".txt" extension.
*
* @param {string} filePath - The absolute path of JSON formatted trusted setup
*
* @return {string} - The absolute path of the re-formatted trusted setup
*
* @throws {Error} - For invalid file operations
*/
function transformTrustedSetupJson(filePath: string): string {
const data: TrustedSetupJson = JSON.parse(fs.readFileSync(filePath, "utf8"));
const textFilePath = filePath.replace(".json", ".txt");
const setupText =
kzg.FIELD_ELEMENTS_PER_BLOB +
"\n65\n" +
data.setup_G1.map((p) => p.substring(2)).join("\n") +
"\n" +
data.setup_G2.map((p) => p.substring(2)).join("\n");
fs.writeFileSync(textFilePath, setupText);
return textFilePath;
}
/**
* 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 {@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
* library can be run.
*
* @param {string} filePath - The absolute path of the trusted setup
*
* @return {void}
*
* @throws {Error} - For invalid file operations
*/
export function loadTrustedSetup(filePath: string): void {
if (!(filePath && typeof filePath === "string")) {
throw new TypeError(
"must initialize kzg with the filePath to a txt/json trusted setup",
);
}
if (!fs.existsSync(filePath)) {
throw new Error(`no trusted setup found: ${filePath}`);
}
if (path.parse(filePath).ext === ".json") {
filePath = transformTrustedSetupJson(filePath);
}
return kzg.loadTrustedSetup(filePath);
}
/**
* Convert a blob to a KZG commitment.
*
* @param {Blob} blob - The blob representing the polynomial to be committed to
*
* @return {KZGCommitment} - The resulting commitment
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function blobToKzgCommitment(blob: Blob): KZGCommitment {
return kzg.blobToKzgCommitment(blob);
}
/**
* 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
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function computeKzgProof(blob: Blob, zBytes: Bytes32): ProofResult {
return kzg.computeKzgProof(blob, zBytes);
}
/**
* 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
*
* @return {KZGProof} - The resulting proof
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function computeBlobKzgProof(
blob: Blob,
commitmentBytes: Bytes48,
): KZGProof {
return kzg.computeBlobKzgProof(blob, commitmentBytes);
}
/**
* 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
*
* @return {boolean} - true/false depending on proof validity
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function verifyKzgProof(
commitmentBytes: Bytes48,
zBytes: Bytes32,
yBytes: Bytes32,
proofBytes: Bytes48,
): boolean {
return kzg.verifyKzgProof(commitmentBytes, zBytes, yBytes, proofBytes);
}
/**
* 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
*
* @return {boolean} - true/false depending on proof validity
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function verifyBlobKzgProof(
blob: Blob,
commitmentBytes: Bytes48,
proofBytes: Bytes48,
): boolean {
return kzg.verifyBlobKzgProof(blob, commitmentBytes, proofBytes);
}
/**
* 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
*
* @return {boolean} - true/false depending on batch validity
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function verifyBlobKzgProofBatch(
blobs: Blob[],
commitmentsBytes: Bytes48[],
proofsBytes: Bytes48[],
): boolean {
return kzg.verifyBlobKzgProofBatch(blobs, commitmentsBytes, proofsBytes);
}

View File

@ -1,6 +1,6 @@
import { randomBytes } from "crypto";
import { readFileSync } from "fs";
import { join, resolve } from "path";
import { resolve } from "path";
import { globSync } from "glob";
const yaml = require("js-yaml");