c-kzg-4844/bindings/node.js/kzg.ts

244 lines
6.7 KiB
TypeScript
Raw Normal View History

/**
* 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
*/
2022-11-04 05:57:03 +00:00
const kzg: KZG = require("./kzg.node");
const fs = require("fs");
2022-11-03 19:57:46 +00:00
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
type SetupHandle = Object;
// The C++ native addon interface
type KZG = {
2023-02-14 21:11:10 +00:00
BYTES_PER_BLOB: number;
BYTES_PER_COMMITMENT: number;
2022-11-04 18:44:57 +00:00
BYTES_PER_FIELD_ELEMENT: number;
2023-02-14 21:11:10 +00:00
BYTES_PER_PROOF: number;
FIELD_ELEMENTS_PER_BLOB: number;
2022-11-03 21:39:02 +00:00
loadTrustedSetup: (filePath: string) => SetupHandle;
2022-11-03 19:57:46 +00:00
freeTrustedSetup: (setupHandle: SetupHandle) => void;
2022-11-03 19:57:46 +00:00
2022-11-03 00:17:17 +00:00
blobToKzgCommitment: (blob: Blob, setupHandle: SetupHandle) => KZGCommitment;
2022-11-03 19:57:46 +00:00
computeKzgProof: (
blob: Blob,
zBytes: Bytes32,
setupHandle: SetupHandle,
) => KZGProof;
2023-02-18 21:49:52 +00:00
computeBlobKzgProof: (blob: Blob, setupHandle: SetupHandle) => KZGProof;
2022-11-03 21:39:02 +00:00
verifyKzgProof: (
commitmentBytes: Bytes48,
zBytes: Bytes32,
yBytes: Bytes32,
proofBytes: Bytes48,
setupHandle: SetupHandle,
2022-11-03 21:39:02 +00:00
) => boolean;
2023-02-18 21:49:52 +00:00
verifyBlobKzgProof: (
blob: Blob,
commitmentBytes: Bytes48,
proofBytes: Bytes48,
setupHandle: SetupHandle,
) => boolean;
verifyBlobKzgProofBatch: (
blobs: Blob[],
commitmentsBytes: Bytes48[],
proofsBytes: Bytes48[],
setupHandle: SetupHandle,
) => boolean;
};
type TrustedSetupJSON = {
setup_G1: string[];
setup_G2: string[];
setup_G1_lagrange: string[];
roots_of_unity: string[];
};
2023-02-14 21:11:10 +00:00
export const BYTES_PER_BLOB = kzg.BYTES_PER_BLOB;
export const BYTES_PER_COMMITMENT = kzg.BYTES_PER_COMMITMENT;
2022-11-04 18:44:57 +00:00
export const BYTES_PER_FIELD_ELEMENT = kzg.BYTES_PER_FIELD_ELEMENT;
2023-02-14 21:11:10 +00:00
export const BYTES_PER_PROOF = kzg.BYTES_PER_PROOF;
export const FIELD_ELEMENTS_PER_BLOB = kzg.FIELD_ELEMENTS_PER_BLOB;
2022-11-03 21:39:02 +00:00
// Stored as internal state
let setupHandle: SetupHandle | undefined;
2022-11-04 20:29:52 +00:00
function requireSetupHandle(): SetupHandle {
if (!setupHandle) {
throw new Error("You must call loadTrustedSetup to initialize KZG.");
}
return setupHandle;
}
export async function transformTrustedSetupJSON(
filePath: string,
): Promise<string> {
const data: TrustedSetupJSON = JSON.parse(fs.readFileSync(filePath));
const textFilePath = filePath.replace(".json", "") + ".txt";
try {
fs.unlinkSync(textFilePath);
} catch {}
const file = fs.createWriteStream(textFilePath);
file.write(`${FIELD_ELEMENTS_PER_BLOB}\n65\n`);
file.write(data.setup_G1.map((p) => p.replace("0x", "")).join("\n"));
file.write("\n");
file.write(data.setup_G2.map((p) => p.replace("0x", "")).join("\n"));
file.end();
const p = new Promise((resolve) => {
file.close(resolve);
});
await p;
return textFilePath;
}
2022-11-04 04:54:59 +00:00
export function loadTrustedSetup(filePath: string): void {
2022-11-03 21:39:02 +00:00
if (setupHandle) {
throw new Error(
"Call freeTrustedSetup before loading a new trusted setup.",
2022-11-03 21:39:02 +00:00
);
}
2022-11-03 21:39:02 +00:00
setupHandle = kzg.loadTrustedSetup(filePath);
}
2022-11-04 04:54:59 +00:00
export function freeTrustedSetup(): void {
2022-11-04 20:29:52 +00:00
kzg.freeTrustedSetup(requireSetupHandle());
2022-11-03 21:39:02 +00:00
setupHandle = undefined;
}
/**
* 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
*/
2022-11-04 04:54:59 +00:00
export function blobToKzgCommitment(blob: Blob): KZGCommitment {
2022-11-04 20:29:52 +00:00
return kzg.blobToKzgCommitment(blob, requireSetupHandle());
2022-11-03 21:39:02 +00:00
}
/**
* 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 {KZGProof} - The resulting proof
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
export function computeKzgProof(blob: Blob, zBytes: Bytes32): KZGProof {
return kzg.computeKzgProof(blob, zBytes, requireSetupHandle());
}
/**
* 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
*
* @return {KZGProof} - The resulting proof
*
* @throws {TypeError} - For invalid arguments or failure of the native library
*/
2023-02-18 21:49:52 +00:00
export function computeBlobKzgProof(blob: Blob): KZGProof {
return kzg.computeBlobKzgProof(blob, requireSetupHandle());
2022-11-03 21:39:02 +00:00
}
/**
* 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
*/
2022-12-13 19:21:43 +00:00
export function verifyKzgProof(
commitmentBytes: Bytes48,
zBytes: Bytes32,
yBytes: Bytes32,
proofBytes: Bytes48,
2022-12-13 19:21:43 +00:00
): boolean {
return kzg.verifyKzgProof(
commitmentBytes,
zBytes,
yBytes,
proofBytes,
2022-12-13 19:21:43 +00:00
requireSetupHandle(),
);
}
/**
* 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
*/
2023-02-18 21:49:52 +00:00
export function verifyBlobKzgProof(
blob: Blob,
commitmentBytes: Bytes48,
proofBytes: Bytes48,
): boolean {
return kzg.verifyBlobKzgProof(
blob,
commitmentBytes,
proofBytes,
requireSetupHandle(),
);
}
/**
* 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
*/
2023-02-18 21:49:52 +00:00
export function verifyBlobKzgProofBatch(
2022-11-03 21:39:02 +00:00
blobs: Blob[],
commitmentsBytes: Bytes48[],
2023-02-18 21:49:52 +00:00
proofsBytes: Bytes48[],
2022-11-04 04:54:59 +00:00
): boolean {
2023-02-18 21:49:52 +00:00
return kzg.verifyBlobKzgProofBatch(
2022-11-03 21:39:02 +00:00
blobs,
commitmentsBytes,
2023-02-18 21:49:52 +00:00
proofsBytes,
2022-11-04 20:29:52 +00:00
requireSetupHandle(),
2022-11-03 21:39:02 +00:00
);
}