Closer to working
This commit is contained in:
parent
a5ca06450f
commit
672346f017
|
@ -37,34 +37,7 @@ Napi::TypedArrayOf<uint8_t> napiTypedArrayFromByteArray(uint8_t* array, size_t a
|
||||||
return Napi::Uint8Array::New(env, arrayLength, arrayBuffer, 0);
|
return Napi::Uint8Array::New(env, arrayLength, arrayBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int verifyAggregateKzgProof(const uint8_t blobs[], const uint8_t commitments[], size_t n, const uint8_t proof[48], const KZGSettings *s) {
|
// loadTrustedSetup: (filePath: string) => SetupHandle;
|
||||||
Polynomial* p = (Polynomial*)calloc(n, sizeof(Polynomial));
|
|
||||||
if (p == NULL) return -1;
|
|
||||||
|
|
||||||
KZGCommitment* c = (KZGCommitment*)calloc(n, sizeof(KZGCommitment));
|
|
||||||
if (c == NULL) { free(p); return -1; }
|
|
||||||
|
|
||||||
C_KZG_RET ret;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
for (size_t j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++)
|
|
||||||
bytes_to_bls_field(&p[i][j], &blobs[i * FIELD_ELEMENTS_PER_BLOB * 32 + j * 32]);
|
|
||||||
ret = bytes_to_g1(&c[i], &commitments[i * 48]);
|
|
||||||
if (ret != C_KZG_OK) { free(c); free(p); return -1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
KZGProof f;
|
|
||||||
ret = bytes_to_g1(&f, proof);
|
|
||||||
if (ret != C_KZG_OK) { free(c); free(p); return -1; }
|
|
||||||
|
|
||||||
bool b;
|
|
||||||
ret = verify_aggregate_kzg_proof(&b, p, c, n, &f, s);
|
|
||||||
if (ret != C_KZG_OK) { free(c); free(p); return -1; }
|
|
||||||
|
|
||||||
free(c); free(p);
|
|
||||||
return b ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Napi::Value LoadTrustedSetup(const Napi::CallbackInfo& info) {
|
Napi::Value LoadTrustedSetup(const Napi::CallbackInfo& info) {
|
||||||
Napi::Env env = info.Env();
|
Napi::Env env = info.Env();
|
||||||
|
|
||||||
|
@ -106,17 +79,17 @@ Napi::Value LoadTrustedSetup(const Napi::CallbackInfo& info) {
|
||||||
return Napi::External<KZGSettings>::New(info.Env(), kzgSettings);
|
return Napi::External<KZGSettings>::New(info.Env(), kzgSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// freeTrustedSetup: (setupHandle: SetupHandle) => void;
|
||||||
void FreeTrustedSetup(const Napi::CallbackInfo& info) {
|
void FreeTrustedSetup(const Napi::CallbackInfo& info) {
|
||||||
Napi::Env env = info.Env();
|
// 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.
|
||||||
KZGSettings* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// blobToKzgCommitment: (blob: Blob) => KZGCommitment;
|
// blobToKzgCommitment: (blob: Blob, setupHandle: SetupHandle) => KZGCommitment;
|
||||||
Napi::Value BlobToKzgCommitment(const Napi::CallbackInfo& info) {
|
Napi::Value BlobToKzgCommitment(const Napi::CallbackInfo& info) {
|
||||||
Napi::Env env = info.Env();
|
auto env = info.Env();
|
||||||
|
|
||||||
if (info.Length() != 2) {
|
if (info.Length() != 2) {
|
||||||
Napi::TypeError::New(env, "Wrong number of arguments")
|
Napi::TypeError::New(env, "Wrong number of arguments")
|
||||||
|
@ -130,9 +103,9 @@ Napi::Value BlobToKzgCommitment(const Napi::CallbackInfo& info) {
|
||||||
.ThrowAsJavaScriptException();
|
.ThrowAsJavaScriptException();
|
||||||
return env.Undefined();
|
return env.Undefined();
|
||||||
}
|
}
|
||||||
uint8_t* blob = typedArray.As<Napi::Uint8Array>().Data();
|
auto blob = typedArray.As<Napi::Uint8Array>().Data();
|
||||||
|
|
||||||
KZGSettings* kzgSettings = info[1].As<Napi::External<KZGSettings>>().Data();
|
auto kzgSettings = info[1].As<Napi::External<KZGSettings>>().Data();
|
||||||
|
|
||||||
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++)
|
||||||
|
@ -142,15 +115,12 @@ Napi::Value BlobToKzgCommitment(const Napi::CallbackInfo& info) {
|
||||||
blob_to_kzg_commitment(&commitment, polynomial, kzgSettings);
|
blob_to_kzg_commitment(&commitment, polynomial, kzgSettings);
|
||||||
|
|
||||||
// Turn it into a byte array
|
// Turn it into a byte array
|
||||||
uint8_t array[48];
|
uint8_t commitmentBytes[BYTES_PER_COMMITMENT];
|
||||||
bytes_from_g1(array, &commitment);
|
bytes_from_g1(commitmentBytes, &commitment);
|
||||||
return napiTypedArrayFromByteArray(array, sizeof(array), env);
|
return napiTypedArrayFromByteArray(commitmentBytes, BYTES_PER_COMMITMENT, env);
|
||||||
}
|
|
||||||
|
|
||||||
Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) {
|
|
||||||
Napi::Env env = info.Env();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// computeAggregateKzgProof: (blobs: Blob[], setupHandle: SetupHandle) => KZGProof;
|
||||||
Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
|
Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
|
||||||
auto env = info.Env();
|
auto env = info.Env();
|
||||||
|
|
||||||
|
@ -164,34 +134,16 @@ 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();
|
||||||
// auto blobs = blobs_param.As<Napi::Array<Napi::Uint8Array>>();
|
|
||||||
|
|
||||||
int BYTES_PER_FIELD = 32;
|
printf("ComputeAggregateKzgProof called with %i blob(s)\n", numberOfBlobs);
|
||||||
int BYTES_PER_BLOB = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD;
|
|
||||||
|
|
||||||
printf("ComputeAggregateKzgProof called with %i blobs", numberOfBlobs);
|
|
||||||
|
|
||||||
// uint8_t blobBytes[numberOfBlobs * FIELD_ELEMENTS_PER_BLOB];
|
|
||||||
// for(int i = 0; i < numberOfBlobs; i++)
|
|
||||||
// {
|
|
||||||
// Napi::Value blob = blobs_param[i];
|
|
||||||
// if (blob.IsTypedArray())
|
|
||||||
// {
|
|
||||||
// auto blobBytes = blob.As<Napi::Uint8Array>().Data();
|
|
||||||
// memcpy(blobBytes + i * BYTES_PER_BLOB, blobBytes, BYTES_PER_BLOB);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// printf("ComputeAggregateKzgProof copied %i bytes", sizeof(blobBytes));
|
|
||||||
|
|
||||||
auto polynomial = (Polynomial*)calloc(numberOfBlobs, sizeof(Polynomial));
|
auto polynomial = (Polynomial*)calloc(numberOfBlobs, sizeof(Polynomial));
|
||||||
// if (p == NULL) return C_KZG_ERROR;
|
|
||||||
|
|
||||||
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", blobIndex);
|
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(
|
||||||
|
@ -201,13 +153,6 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ComputeAggregateKzgProof 1");
|
|
||||||
printf("ComputeAggregateKzgProof 1");
|
|
||||||
printf("ComputeAggregateKzgProof 1");
|
|
||||||
printf("ComputeAggregateKzgProof 1");
|
|
||||||
|
|
||||||
// return env.Null();
|
|
||||||
|
|
||||||
KZGProof proof;
|
KZGProof proof;
|
||||||
C_KZG_RET ret = compute_aggregate_kzg_proof(
|
C_KZG_RET ret = compute_aggregate_kzg_proof(
|
||||||
&proof,
|
&proof,
|
||||||
|
@ -215,33 +160,112 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
|
||||||
numberOfBlobs,
|
numberOfBlobs,
|
||||||
kzgSettings
|
kzgSettings
|
||||||
);
|
);
|
||||||
|
|
||||||
Napi::TypeError::New(env, "STOPPING HERE")
|
|
||||||
.ThrowAsJavaScriptException();
|
|
||||||
return env.Null();
|
|
||||||
|
|
||||||
printf("ComputeAggregateKzgProof 2");
|
|
||||||
|
|
||||||
free(polynomial);
|
free(polynomial);
|
||||||
|
|
||||||
printf("ComputeAggregateKzgProof 3");
|
|
||||||
|
|
||||||
if (ret != C_KZG_OK) {
|
if (ret != C_KZG_OK) {
|
||||||
Napi::TypeError::New(env, "Failed to compute proof")
|
Napi::TypeError::New(env, "Failed to compute proof")
|
||||||
.ThrowAsJavaScriptException();
|
.ThrowAsJavaScriptException();
|
||||||
return env.Null();
|
return env.Undefined();
|
||||||
};
|
};
|
||||||
|
|
||||||
printf("ComputeAggregateKzgProof 4");
|
printf("proof generated: %llu y: %llu z: %llu\n", proof.x, proof.y, proof.z);
|
||||||
|
printf("compute_aggregate_kzg_proof ret was %i\n", ret);
|
||||||
|
|
||||||
uint8_t* bytes;
|
uint8_t array[48];
|
||||||
bytes_from_g1(bytes, &proof);
|
bytes_from_g1(array, &proof);
|
||||||
|
|
||||||
printf("ComputeAggregateKzgProof 5");
|
printf("Turned proof into bytes: [");
|
||||||
|
for (int i = 0; i < sizeof(array); i++) {
|
||||||
|
printf("%x ", array[i]);
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
return napiTypedArrayFromByteArray(bytes, sizeof(bytes), env);
|
return napiTypedArrayFromByteArray(array, sizeof(array), env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verifyAggregateKzgProof: (blobs: Blob[], expectedKzgCommitments: KZGCommitment[], kzgAggregatedProof: KZGProof) => boolean;
|
||||||
|
Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) {
|
||||||
|
auto env = info.Env();
|
||||||
|
|
||||||
|
if (info.Length() != 4) {
|
||||||
|
Napi::TypeError::New(env, "Wrong number of arguments")
|
||||||
|
.ThrowAsJavaScriptException();
|
||||||
|
return env.Null();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto blobs_param = info[0].As<Napi::Array>();
|
||||||
|
|
||||||
|
auto comittments_param = info[1].As<Napi::Array>();
|
||||||
|
|
||||||
|
auto proof_param = info[2].As<Napi::TypedArray>();
|
||||||
|
auto proofBytes = proof_param.As<Napi::Uint8Array>().Data();
|
||||||
|
|
||||||
|
auto kzgSettings = info[3].As<Napi::External<KZGSettings>>().Data();
|
||||||
|
|
||||||
|
auto numberOfBlobs = blobs_param.Length();
|
||||||
|
auto polynomial = (Polynomial*)calloc(numberOfBlobs, sizeof(Polynomial));
|
||||||
|
auto commitments = (KZGCommitment*)calloc(numberOfBlobs, sizeof(KZGCommitment));
|
||||||
|
|
||||||
|
C_KZG_RET ret;
|
||||||
|
|
||||||
|
for (uint32_t blobIndex = 0; blobIndex < numberOfBlobs; blobIndex++) {
|
||||||
|
Napi::Value blob = blobs_param[blobIndex];
|
||||||
|
auto blobBytes = blob.As<Napi::Uint8Array>().Data();
|
||||||
|
|
||||||
|
Napi::Value commitment = comittments_param[blobIndex];
|
||||||
|
auto commitmentBytes = commitment.As<Napi::Uint8Array>().Data();
|
||||||
|
|
||||||
|
for (uint32_t fieldIndex = 0; fieldIndex < FIELD_ELEMENTS_PER_BLOB; fieldIndex++) {
|
||||||
|
bytes_to_bls_field(&polynomial[blobIndex][fieldIndex], &blobBytes[fieldIndex * BYTES_PER_FIELD]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bytes_to_g1(&commitments[blobIndex], &commitmentBytes[blobIndex * BYTES_PER_COMMITMENT]);
|
||||||
|
if (ret != C_KZG_OK) {
|
||||||
|
free(commitments);
|
||||||
|
free(polynomial);
|
||||||
|
|
||||||
|
Napi::TypeError::New(env, "Error parsing blobs and commitments")
|
||||||
|
.ThrowAsJavaScriptException();
|
||||||
|
return env.Null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KZGProof proof;
|
||||||
|
ret = bytes_to_g1(&proof, proofBytes);
|
||||||
|
if (ret != C_KZG_OK) {
|
||||||
|
free(commitments);
|
||||||
|
free(polynomial);
|
||||||
|
|
||||||
|
Napi::TypeError::New(env, "Error converting proof parameter to KZGProof")
|
||||||
|
.ThrowAsJavaScriptException();
|
||||||
|
return env.Null();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verificationResult;
|
||||||
|
ret = verify_aggregate_kzg_proof(
|
||||||
|
&verificationResult,
|
||||||
|
polynomial,
|
||||||
|
commitments,
|
||||||
|
numberOfBlobs,
|
||||||
|
&proof,
|
||||||
|
kzgSettings
|
||||||
|
);
|
||||||
|
if (ret != C_KZG_OK) {
|
||||||
|
free(commitments);
|
||||||
|
free(polynomial);
|
||||||
|
|
||||||
|
Napi::TypeError::New(env, "Error calling verify_aggregate_kzg_proof")
|
||||||
|
.ThrowAsJavaScriptException();
|
||||||
|
return env.Null();
|
||||||
|
}
|
||||||
|
|
||||||
|
free(commitments);
|
||||||
|
free(polynomial);
|
||||||
|
|
||||||
|
return Napi::Boolean::New(env, verificationResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyKzgProof: (polynomialKzg: KZGCommitment, z: BLSFieldElement, y: BLSFieldElement, kzgProof: KZGProof, setupHandle: SetupHandle) => boolean;
|
||||||
Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
|
Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
|
||||||
auto env = info.Env();
|
auto env = info.Env();
|
||||||
|
|
||||||
|
@ -304,19 +328,18 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
|
||||||
std::copy(c, c+sizeof(c), std::ostream_iterator<int>(ss, ","));
|
std::copy(c, c+sizeof(c), std::ostream_iterator<int>(ss, ","));
|
||||||
Napi::TypeError::New(env, "Failed to parse argument commitment: " + ss.str() + " Return code was: " + std::to_string(ret)).ThrowAsJavaScriptException();
|
Napi::TypeError::New(env, "Failed to parse argument commitment: " + ss.str() + " Return code was: " + std::to_string(ret)).ThrowAsJavaScriptException();
|
||||||
return env.Null();
|
return env.Null();
|
||||||
// return -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (bytes_to_g1(&proof, p) != C_KZG_OK) {
|
if (bytes_to_g1(&proof, p) != C_KZG_OK) {
|
||||||
Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
|
Napi::TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
|
||||||
return env.Null();
|
return env.Null();
|
||||||
// return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verify_kzg_proof(&out, &commitment, &fx, &fy, &proof, kzgSettings) != C_KZG_OK) {
|
if (verify_kzg_proof(&out, &commitment, &fx, &fy, &proof, kzgSettings) != C_KZG_OK) {
|
||||||
return env.Null();
|
return Napi::Boolean::New(env, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return env.Null();
|
return Napi::Boolean::New(env, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||||
|
@ -332,19 +355,3 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_API_MODULE(addon, Init)
|
NODE_API_MODULE(addon, Init)
|
||||||
|
|
||||||
|
|
||||||
// SCRATCH
|
|
||||||
// Napi::Object obj = Napi::Object::New(env);
|
|
||||||
|
|
||||||
// // Assign values to properties
|
|
||||||
// obj.Set("hello", "world");
|
|
||||||
// // obj.Set(uint32_t(42), "The Answer to Life, the Universe, and Everything");
|
|
||||||
// // obj.Set("Douglas Adams", true);
|
|
||||||
// // obj.Set("fftSettings", kzgSettings->fs);
|
|
||||||
// // Napi::Array::Array(napi_env env, napi_value value);
|
|
||||||
|
|
||||||
// const Napi::Array g1Values = Napi::Array::New(env, )
|
|
||||||
|
|
||||||
// obj.Set('g1Values', kzgSettings->g1_values);
|
|
||||||
// obj.Set('g2Values', kzgSettings->g2_values);
|
|
||||||
|
|
|
@ -4,56 +4,104 @@ 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;
|
||||||
|
|
||||||
// Consider making this internal state of the native code
|
|
||||||
// so we don't have to pass it around in the application layer
|
|
||||||
export type SetupHandle = Object;
|
export type SetupHandle = Object;
|
||||||
|
|
||||||
export enum ReturnValue {
|
export type BLSFieldElement = Uint8Array;
|
||||||
/** Success! */
|
|
||||||
OK = 0,
|
|
||||||
/** The supplied data is invalid in some way */
|
|
||||||
BADARGS,
|
|
||||||
/** Internal error - this should never occur and may indicate a bug in the library */
|
|
||||||
ERROR,
|
|
||||||
/** Could not allocate memory */
|
|
||||||
MALLOC,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Point = Uint8Array;
|
|
||||||
export type KZGProof = Uint8Array;
|
export type KZGProof = Uint8Array;
|
||||||
export type KZGCommitment = Uint8Array;
|
export type KZGCommitment = Uint8Array;
|
||||||
export type Blob = Uint8Array;
|
export type Blob = Uint8Array;
|
||||||
export type Blobs = Blob[];
|
|
||||||
|
|
||||||
type KZG = {
|
type KZG = {
|
||||||
loadTrustedSetup: (path: string) => SetupHandle;
|
loadTrustedSetup: (filePath: string) => SetupHandle;
|
||||||
|
|
||||||
freeTrustedSetup: (setupHandle: SetupHandle) => void;
|
freeTrustedSetup: (setupHandle: SetupHandle) => void;
|
||||||
|
|
||||||
blobToKzgCommitment: (blob: Blob, setupHandle: SetupHandle) => KZGCommitment;
|
blobToKzgCommitment: (blob: Blob, setupHandle: SetupHandle) => KZGCommitment;
|
||||||
|
|
||||||
verifyAggregateKzgProof: (blobs: Blobs) => ReturnValue;
|
|
||||||
|
|
||||||
computeAggregateKzgProof: (
|
computeAggregateKzgProof: (
|
||||||
blobs: Blobs,
|
blobs: Blob[],
|
||||||
setupHandle: SetupHandle,
|
setupHandle: SetupHandle,
|
||||||
) => KZGProof;
|
) => KZGProof;
|
||||||
|
|
||||||
verifyKzgProof: (
|
verifyAggregateKzgProof: (
|
||||||
commitment: KZGCommitment,
|
blobs: Blob[],
|
||||||
x: Point,
|
expectedKzgCommitments: KZGCommitment[],
|
||||||
y: Point,
|
kzgAggregatedProof: KZGProof,
|
||||||
proof: KZGProof,
|
|
||||||
setupHandle: SetupHandle,
|
setupHandle: SetupHandle,
|
||||||
) => ReturnValue;
|
) => boolean;
|
||||||
|
|
||||||
|
verifyKzgProof: (
|
||||||
|
polynomialKzg: KZGCommitment,
|
||||||
|
z: BLSFieldElement,
|
||||||
|
y: BLSFieldElement,
|
||||||
|
kzgProof: KZGProof,
|
||||||
|
setupHandle: SetupHandle,
|
||||||
|
) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const kzg: KZG = bindings('kzg.node');
|
const kzg: KZG = bindings('kzg.node');
|
||||||
|
|
||||||
export const loadTrustedSetup = kzg.loadTrustedSetup;
|
// Stored as internal state
|
||||||
export const freeTrustedSetup = kzg.freeTrustedSetup;
|
let setupHandle: SetupHandle | undefined;
|
||||||
export const blobToKzgCommitment = kzg.blobToKzgCommitment;
|
|
||||||
export const verifyAggregateKzgProof = kzg.verifyAggregateKzgProof;
|
export function loadTrustedSetup(filePath: string) {
|
||||||
export const computeAggregateKzgProof = kzg.computeAggregateKzgProof;
|
if (setupHandle) {
|
||||||
export const verifyKzgProof = kzg.verifyKzgProof;
|
throw new Error(
|
||||||
export default kzg;
|
'Call freeTrustedSetup before loading a new trusted setup.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setupHandle = kzg.loadTrustedSetup(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function freeTrustedSetup() {
|
||||||
|
if (!setupHandle) {
|
||||||
|
throw new Error('You must call loadTrustedSetup before freeTrustedSetup.');
|
||||||
|
}
|
||||||
|
kzg.freeTrustedSetup(setupHandle);
|
||||||
|
setupHandle = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function blobToKzgCommitment(blob: Blob) {
|
||||||
|
if (!setupHandle) {
|
||||||
|
throw new Error('You must call loadTrustedSetup to initialize KZG.');
|
||||||
|
}
|
||||||
|
return kzg.blobToKzgCommitment(blob, setupHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function computeAggregateKzgProof(blobs: Blob[]) {
|
||||||
|
if (!setupHandle) {
|
||||||
|
throw new Error('You must call loadTrustedSetup to initialize KZG.');
|
||||||
|
}
|
||||||
|
return kzg.computeAggregateKzgProof(blobs, setupHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify KZG proof that ``p(z) == y`` where ``p(z)`` is the polynomial represented by ``polynomialKzg``.
|
||||||
|
*/
|
||||||
|
export function verifyKzgProof(
|
||||||
|
polynomialKzg: KZGCommitment,
|
||||||
|
z: BLSFieldElement,
|
||||||
|
y: BLSFieldElement,
|
||||||
|
kzgProof: KZGProof,
|
||||||
|
) {
|
||||||
|
if (!setupHandle) {
|
||||||
|
throw new Error('You must call loadTrustedSetup to initialize KZG.');
|
||||||
|
}
|
||||||
|
return kzg.verifyKzgProof(polynomialKzg, z, y, kzgProof, setupHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function verifyAggregateKzgProof(
|
||||||
|
blobs: Blob[],
|
||||||
|
expectedKzgCommitments: KZGCommitment[],
|
||||||
|
kzgAggregatedProof: KZGProof,
|
||||||
|
) {
|
||||||
|
if (!setupHandle) {
|
||||||
|
throw new Error('You must call loadTrustedSetup to initialize KZG.');
|
||||||
|
}
|
||||||
|
return kzg.verifyAggregateKzgProof(
|
||||||
|
blobs,
|
||||||
|
expectedKzgCommitments,
|
||||||
|
kzgAggregatedProof,
|
||||||
|
setupHandle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -4,77 +4,44 @@ import {
|
||||||
freeTrustedSetup,
|
freeTrustedSetup,
|
||||||
verifyKzgProof,
|
verifyKzgProof,
|
||||||
blobToKzgCommitment,
|
blobToKzgCommitment,
|
||||||
ReturnValue,
|
|
||||||
SetupHandle,
|
|
||||||
Blob,
|
Blob,
|
||||||
BLOB_SIZE,
|
BLOB_SIZE,
|
||||||
NUMBER_OF_FIELDS,
|
NUMBER_OF_FIELDS,
|
||||||
computeAggregateKzgProof,
|
computeAggregateKzgProof,
|
||||||
|
verifyAggregateKzgProof,
|
||||||
} from './kzg';
|
} from './kzg';
|
||||||
|
|
||||||
const SETUP_FILE_PATH = '../../src/trusted_setup.txt';
|
const SETUP_FILE_PATH = '../../src/trusted_setup.txt';
|
||||||
|
|
||||||
const COMMITMENT_BYTE_LENGTH = 48;
|
|
||||||
|
|
||||||
function generateRandomBlob(): Blob {
|
function generateRandomBlob(): Blob {
|
||||||
return new Uint8Array(randomBytes(NUMBER_OF_FIELDS * BLOB_SIZE));
|
return new Uint8Array(randomBytes(BLOB_SIZE * NUMBER_OF_FIELDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('C-KZG', () => {
|
describe('C-KZG', () => {
|
||||||
let sharedSetupHandle: SetupHandle;
|
beforeEach(() => {
|
||||||
|
loadTrustedSetup(SETUP_FILE_PATH);
|
||||||
beforeAll(() => {
|
|
||||||
sharedSetupHandle = loadTrustedSetup(SETUP_FILE_PATH);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setup', () => {
|
afterEach(() => {
|
||||||
it('can both load and free', () => {
|
freeTrustedSetup();
|
||||||
expect(
|
|
||||||
freeTrustedSetup(loadTrustedSetup(SETUP_FILE_PATH)),
|
|
||||||
).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('computing a KZG commitment from a blob', () => {
|
it('computes and verifies an aggregate KZG proof', async () => {
|
||||||
it('returns data with the correct length', () => {
|
const blob1 = generateRandomBlob();
|
||||||
const blob = generateRandomBlob();
|
const blob2 = generateRandomBlob();
|
||||||
const commitment = blobToKzgCommitment(blob, sharedSetupHandle);
|
const blobs = [blob1, blob2];
|
||||||
expect(commitment.length).toBe(COMMITMENT_BYTE_LENGTH);
|
|
||||||
});
|
const commitments = blobs.map(blobToKzgCommitment);
|
||||||
|
|
||||||
|
const proof = computeAggregateKzgProof(blobs);
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
commitments,
|
||||||
|
proof,
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('verifying a KZG proof', () => {
|
const result = verifyAggregateKzgProof(blobs, commitments, proof);
|
||||||
it.only('returns the expected value', () => {
|
|
||||||
const byteEncoder = new TextEncoder();
|
|
||||||
|
|
||||||
const blob = generateRandomBlob();
|
expect(result).toBe(true);
|
||||||
const commitment = blobToKzgCommitment(blob, sharedSetupHandle);
|
|
||||||
const proof = computeAggregateKzgProof([blob], sharedSetupHandle);
|
|
||||||
|
|
||||||
const x = byteEncoder.encode(
|
|
||||||
'0345f802a75a6c0d9cc5b8a1e71642b8fa80b0a78938edc6da1e591149578d1a',
|
|
||||||
);
|
|
||||||
const y = byteEncoder.encode(
|
|
||||||
'3b17cab634c3795d311380f3bc93ce8e768efc0e2b9e79496cfc8f351594b472',
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = verifyKzgProof(commitment, y, x, proof, sharedSetupHandle);
|
|
||||||
console.log({ result });
|
|
||||||
expect(result).toBe(ReturnValue.OK);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('computing an aggregate KZG proof', () => {
|
|
||||||
it('returns the expected value', () => {
|
|
||||||
const blob = generateRandomBlob();
|
|
||||||
const commitment = blobToKzgCommitment(blob, sharedSetupHandle);
|
|
||||||
const proof = computeAggregateKzgProof([blob], sharedSetupHandle);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('verifying an aggregate KZG proof', () => {
|
|
||||||
it('returns the expected value', () => {
|
|
||||||
expect(true).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BYTES_PER_COMMITMENT 48
|
||||||
#define BYTES_PER_FIELD 32
|
#define BYTES_PER_FIELD 32
|
||||||
#define FIELD_ELEMENTS_PER_BLOB 4096
|
#define FIELD_ELEMENTS_PER_BLOB 4096
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue