Bytes-only interface (#62)
* Convert argument types to bytes * Update java bindings * Update python bindings * Update node.js bindings * Update c# bindings * Fix java binding compile issues * Fix incorrect memcpy in nodejs bindings * Fix bug (called the wrong func) * Fix issues with java bindings * Fix issues with node.js bindings * Remove unnecessary wrapped funcs for c# * Rename struct member to bytes * Use goto out for callocs * Fix nit * Make un-exported funcs static * Fix python bindings * Check commitment length in python bindings * Update python error message * Steal good ideas from #37 * Fix tests.py which didn't get copied over * Convert remaining a[] to *a * Add missing Py_DECREF * Bytes only rust (#1) * Make interface bytes only * Fix benches * Avoid newtypes for kzg types * Fix benches again * Make fields private * tidy * Address review comments * Fix one small thing in rust bindings * Use ckzg types where possible * Remove null terminator from domain bytes in rust * Update rust binding docs * Use BYTES_PER_* where applicable * Add extra check for calloc Co-authored-by: Pawan Dhananjay <pawandhananjay@gmail.com>
This commit is contained in:
parent
7e3189d48a
commit
69f6155d75
|
@ -27,7 +27,7 @@ public class Ckzg
|
|||
/// <param name="blob">Flatten array of blob elements</param>
|
||||
/// <param name="ts">Trusted setup settings</param>
|
||||
/// <returns>Returns error code or <c>0</c> if successful</returns>
|
||||
[DllImport("ckzg", EntryPoint = "blob_to_kzg_commitment_wrap", CallingConvention = CallingConvention.Cdecl)]
|
||||
[DllImport("ckzg", EntryPoint = "blob_to_kzg_commitment", CallingConvention = CallingConvention.Cdecl)]
|
||||
public unsafe static extern int BlobToKzgCommitment(byte* commitment, byte* blob, IntPtr ts);
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ public class Ckzg
|
|||
/// <param name="count">Blobs count</param>
|
||||
/// <param name="ts">Trusted setup settings</param>
|
||||
/// <returns>Returns error code or <c>0</c> if successful</returns>
|
||||
[DllImport("ckzg", EntryPoint = "compute_aggregate_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)] // returns 0 on success
|
||||
[DllImport("ckzg", EntryPoint = "compute_aggregate_kzg_proof", CallingConvention = CallingConvention.Cdecl)]
|
||||
public unsafe static extern int ComputeAggregatedKzgProof(byte* proof, byte* blobs, int count, IntPtr ts);
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class Ckzg
|
|||
/// <param name="proof"></param>
|
||||
/// <param name="ts">Trusted setup settings</param>
|
||||
/// <returns>Returns error code or <c>0</c> if the proof is correct</returns>
|
||||
[DllImport("ckzg", EntryPoint = "verify_aggregate_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)] // returns 0 on success
|
||||
[DllImport("ckzg", EntryPoint = "verify_aggregate_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)]
|
||||
public unsafe static extern int VerifyAggregatedKzgProof(byte* blobs, byte* commitments, int count, byte* proof, IntPtr ts);
|
||||
|
||||
/// <summary>
|
||||
|
@ -64,7 +64,7 @@ public class Ckzg
|
|||
/// <param name="proof">Proof</param>
|
||||
/// <param name="ts">Trusted setup settings</param>
|
||||
/// <returns>Returns error code or <c>0</c> if the proof is correct</returns>
|
||||
[DllImport("ckzg", EntryPoint = "verify_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)] // returns 0 on success
|
||||
[DllImport("ckzg", EntryPoint = "verify_kzg_proof_wrap", CallingConvention = CallingConvention.Cdecl)]
|
||||
public unsafe static extern int VerifyKzgProof(byte* commitment, byte* z, byte* y, byte* proof, IntPtr ts);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -24,55 +24,17 @@ void free_trusted_setup_wrap(KZGSettings *s) {
|
|||
free(s);
|
||||
}
|
||||
|
||||
C_KZG_RET blob_to_kzg_commitment_wrap(uint8_t out[48], const Blob *blob, const KZGSettings *s) {
|
||||
KZGCommitment c;
|
||||
C_KZG_RET ret;
|
||||
ret = blob_to_kzg_commitment(&c, blob, s);
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
bytes_from_g1(out, &c);
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
int verify_aggregate_kzg_proof_wrap(const Blob blobs[], const uint8_t commitments[], size_t n, const uint8_t proof[48], const KZGSettings *s) {
|
||||
KZGProof f;
|
||||
C_KZG_RET ret;
|
||||
ret = bytes_to_g1(&f, proof);
|
||||
if (ret != C_KZG_OK) return -1;
|
||||
|
||||
KZGCommitment* c = calloc(n, sizeof(KZGCommitment));
|
||||
if (c == NULL) return -2;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
ret = bytes_to_g1(&c[i], &commitments[i * 48]);
|
||||
if (ret != C_KZG_OK) { free(c); return -1; }
|
||||
}
|
||||
|
||||
int verify_aggregate_kzg_proof_wrap(const Blob *blobs, const KZGCommitment *commitments, size_t n, const KZGProof *proof, const KZGSettings *s) {
|
||||
bool b;
|
||||
ret = verify_aggregate_kzg_proof(&b, blobs, c, n, &f, s);
|
||||
free(c);
|
||||
C_KZG_RET ret = verify_aggregate_kzg_proof(&b, blobs, commitments, n, proof, s);
|
||||
if (ret != C_KZG_OK) return -1;
|
||||
|
||||
return b ? 0 : 1;
|
||||
}
|
||||
|
||||
C_KZG_RET compute_aggregate_kzg_proof_wrap(uint8_t out[48], const Blob blobs[], size_t n, const KZGSettings *s) {
|
||||
KZGProof f;
|
||||
C_KZG_RET ret;
|
||||
ret = compute_aggregate_kzg_proof(&f, blobs, n, s);
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
bytes_from_g1(out, &f);
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
int verify_kzg_proof_wrap(const uint8_t c[48], const uint8_t z[32], const uint8_t y[32], const uint8_t p[48], KZGSettings *s) {
|
||||
KZGCommitment commitment;
|
||||
KZGProof proof;
|
||||
int verify_kzg_proof_wrap(const KZGCommitment *c, const BLSFieldElement *z, const BLSFieldElement *y, const KZGProof *p, KZGSettings *s) {
|
||||
bool out;
|
||||
|
||||
if (bytes_to_g1(&commitment, c) != C_KZG_OK) return -1;
|
||||
if (bytes_to_g1(&proof, p) != C_KZG_OK) return -1;
|
||||
|
||||
if (verify_kzg_proof(&out, &commitment, z, y, &proof, s) != C_KZG_OK)
|
||||
if (verify_kzg_proof(&out, c, z, y, p, s) != C_KZG_OK)
|
||||
return -2;
|
||||
|
||||
return out ? 0 : 1;
|
||||
|
|
|
@ -13,10 +13,10 @@ DLLEXPORT KZGSettings* load_trusted_setup_wrap(const char* file);
|
|||
|
||||
DLLEXPORT void free_trusted_setup_wrap(KZGSettings *s);
|
||||
|
||||
DLLEXPORT C_KZG_RET blob_to_kzg_commitment_wrap(uint8_t out[48], const Blob *blob, const KZGSettings *s);
|
||||
DLLEXPORT C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZGSettings *s);
|
||||
|
||||
DLLEXPORT int verify_aggregate_kzg_proof_wrap(const Blob blobs[], const uint8_t commitments[], size_t n, const uint8_t proof[48], const KZGSettings *s);
|
||||
DLLEXPORT int verify_aggregate_kzg_proof_wrap(const Blob blobs[], const KZGCommitment *commitments, size_t n, const KZGProof *proof, const KZGSettings *s);
|
||||
|
||||
DLLEXPORT C_KZG_RET compute_aggregate_kzg_proof_wrap(uint8_t out[48], const Blob blobs[], size_t n, const KZGSettings *s);
|
||||
DLLEXPORT C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out, const Blob blobs[], size_t n, const KZGSettings *s);
|
||||
|
||||
DLLEXPORT int verify_kzg_proof_wrap(const uint8_t c[48], const uint8_t z[32], const uint8_t y[32], const uint8_t p[48], KZGSettings *s);
|
||||
DLLEXPORT int verify_kzg_proof_wrap(const KZGCommitment *c, const BLSFieldElement *z, const BLSFieldElement *y, const KZGProof *p, KZGSettings *s);
|
||||
|
|
|
@ -15,18 +15,18 @@ void calculate_proof_and_commitment(char * trusted_setup_path){
|
|||
blob[n] = i % 250;
|
||||
n++;
|
||||
}
|
||||
int res0 = compute_aggregate_kzg_proof_wrap(proof, blob, 1, s);
|
||||
int res1 = blob_to_kzg_commitment_wrap(commitment, blob, s);
|
||||
int res0 = compute_aggregate_kzg_proof(proof, blob, 1, s);
|
||||
int res1 = blob_to_kzg_commitment(commitment, blob, s);
|
||||
|
||||
FILE *f = fopen("output.txt", "wt");
|
||||
// commitment
|
||||
for(int i = 0; i< 48; i++){
|
||||
for(int i = 0; i < 48; i++){
|
||||
fprintf(f, "%02x", commitment[i]);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
||||
// proof
|
||||
for(int i = 0; i< 48; i++){
|
||||
for(int i = 0; i < 48; i++){
|
||||
fprintf(f, "%02x", proof[i]);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
|
|
|
@ -58,13 +58,16 @@ endif
|
|||
|
||||
all: build test benchmark
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
mkdir -p ${LIBRARY_FOLDER}
|
||||
${CLANG_EXECUTABLE} ${CC_FLAGS} ${CLANG_FLAGS} ${OPTIMIZATION_LEVEL} -Wall -Wno-missing-braces ${addprefix -I,${INCLUDE_DIRS}} -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/${JNI_INCLUDE_FOLDER}" -DFIELD_ELEMENTS_PER_BLOB=${FIELD_ELEMENTS_PER_BLOB} -o ${LIBRARY_FOLDER}/${LIBRARY_RESOURCE} ${TARGETS}
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
${GRADLE_COMMAND} clean test
|
||||
|
||||
.PHONY: benchmark
|
||||
benchmark:
|
||||
${GRADLE_COMMAND} clean jmh
|
||||
|
||||
|
|
|
@ -141,13 +141,15 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeAggregate
|
|||
return NULL;
|
||||
}
|
||||
|
||||
size_t count_native = (size_t)count;
|
||||
jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL);
|
||||
jbyteArray proof = (*env)->NewByteArray(env, BYTES_PER_PROOF);
|
||||
KZGProof *proof_native = (KZGProof *)(uint8_t *)(*env)->GetByteArrayElements(env, proof, NULL);
|
||||
|
||||
KZGProof p;
|
||||
|
||||
C_KZG_RET ret = compute_aggregate_kzg_proof(&p, (const Blob *)blobs_native, (size_t)count, settings);
|
||||
C_KZG_RET ret = compute_aggregate_kzg_proof(proof_native, (const Blob *)blobs_native, count_native, settings);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, blobs, blobs_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, 0);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
|
@ -155,13 +157,6 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeAggregate
|
|||
return NULL;
|
||||
}
|
||||
|
||||
jbyteArray proof = (*env)->NewByteArray(env, BYTES_PER_PROOF);
|
||||
uint8_t *out = (uint8_t *)(*env)->GetByteArrayElements(env, proof, 0);
|
||||
|
||||
bytes_from_g1(out, &p);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, proof, (jbyte *)out, 0);
|
||||
|
||||
return proof;
|
||||
}
|
||||
|
||||
|
@ -182,50 +177,16 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg
|
|||
}
|
||||
|
||||
size_t count_native = (size_t)count;
|
||||
|
||||
jbyte *proof_native = (*env)->GetByteArrayElements(env, proof, NULL);
|
||||
|
||||
KZGProof f;
|
||||
|
||||
C_KZG_RET ret;
|
||||
|
||||
ret = bytes_to_g1(&f, (uint8_t *)proof_native);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, proof, proof_native, JNI_ABORT);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
throw_c_kzg_exception(env, ret, "There was an error while converting proof to g1.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
KZGCommitment *c = calloc(count_native, sizeof(KZGCommitment));
|
||||
|
||||
uint8_t *commitments_native = (uint8_t *)(*env)->GetByteArrayElements(env, commitments, NULL);
|
||||
|
||||
for (size_t i = 0; i < count_native; i++)
|
||||
{
|
||||
ret = bytes_to_g1(&c[i], &commitments_native[i * BYTES_PER_COMMITMENT]);
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
(*env)->ReleaseByteArrayElements(env, commitments, (jbyte *)commitments_native, JNI_ABORT);
|
||||
free(c);
|
||||
char arr[100];
|
||||
sprintf(arr, "There was an error while converting commitment (%zu/%zu) to g1.", i + 1, count_native);
|
||||
throw_c_kzg_exception(env, ret, arr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, commitments, (jbyte *)commitments_native, JNI_ABORT);
|
||||
|
||||
KZGProof *proof_native = (KZGProof *)(*env)->GetByteArrayElements(env, proof, NULL);
|
||||
KZGCommitment *commitments_native = (KZGCommitment *)(*env)->GetByteArrayElements(env, commitments, NULL);
|
||||
jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL);
|
||||
|
||||
bool out;
|
||||
ret = verify_aggregate_kzg_proof(&out, (const Blob *)blobs_native, c, count_native, &f, settings);
|
||||
C_KZG_RET ret = verify_aggregate_kzg_proof(&out, (const Blob *)blobs_native, commitments_native, count_native, proof_native, settings);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, commitments, (jbyte *)commitments_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, blobs, blobs_native, JNI_ABORT);
|
||||
free(c);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
|
@ -252,13 +213,13 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_blobToKzgCommitm
|
|||
}
|
||||
|
||||
jbyte *blob_native = (*env)->GetByteArrayElements(env, blob, NULL);
|
||||
jbyteArray commitment = (*env)->NewByteArray(env, BYTES_PER_COMMITMENT);
|
||||
KZGCommitment *commitment_native = (KZGCommitment *)(*env)->GetByteArrayElements(env, commitment, NULL);
|
||||
|
||||
KZGCommitment c;
|
||||
C_KZG_RET ret;
|
||||
|
||||
ret = blob_to_kzg_commitment(&c, (const Blob *)blob_native, settings);
|
||||
C_KZG_RET ret = blob_to_kzg_commitment(commitment_native, (const Blob *)blob_native, settings);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, blob, blob_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, commitment, (jbyte *)commitment_native, 0);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
|
@ -266,13 +227,6 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_blobToKzgCommitm
|
|||
return NULL;
|
||||
}
|
||||
|
||||
jbyteArray commitment = (*env)->NewByteArray(env, BYTES_PER_COMMITMENT);
|
||||
uint8_t *out = (uint8_t *)(*env)->GetByteArrayElements(env, commitment, 0);
|
||||
|
||||
bytes_from_g1(out, &c);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, commitment, (jbyte *)out, 0);
|
||||
|
||||
return commitment;
|
||||
}
|
||||
|
||||
|
@ -284,45 +238,18 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI
|
|||
return 0;
|
||||
}
|
||||
|
||||
C_KZG_RET ret;
|
||||
|
||||
KZGCommitment c;
|
||||
|
||||
jbyte *commitment_native = (*env)->GetByteArrayElements(env, commitment, NULL);
|
||||
|
||||
ret = bytes_to_g1(&c, (uint8_t *)commitment_native);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, commitment, commitment_native, JNI_ABORT);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
throw_c_kzg_exception(env, ret, "There was an error while converting commitment to g1.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
KZGProof p;
|
||||
|
||||
jbyte *proof_native = (*env)->GetByteArrayElements(env, proof, NULL);
|
||||
|
||||
ret = bytes_to_g1(&p, (uint8_t *)proof_native);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, proof, proof_native, JNI_ABORT);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
throw_c_kzg_exception(env, ret, "There was an error while converting proof to g1.");
|
||||
return 0;
|
||||
}
|
||||
KZGCommitment *commitment_native = (KZGCommitment *)(*env)->GetByteArrayElements(env, commitment, NULL);
|
||||
KZGProof *proof_native = (KZGProof *)(*env)->GetByteArrayElements(env, proof, NULL);
|
||||
BLSFieldElement *z_native = (BLSFieldElement *)(*env)->GetByteArrayElements(env, z, NULL);
|
||||
BLSFieldElement *y_native = (BLSFieldElement *)(*env)->GetByteArrayElements(env, y, NULL);
|
||||
|
||||
bool out;
|
||||
C_KZG_RET ret = verify_kzg_proof(&out, commitment_native, z_native, y_native, proof_native, settings);
|
||||
|
||||
jbyte *z_native = (*env)->GetByteArrayElements(env, z, NULL);
|
||||
jbyte *y_native = (*env)->GetByteArrayElements(env, y, NULL);
|
||||
|
||||
ret = verify_kzg_proof(&out, &c, (uint8_t *)z_native, (uint8_t *)y_native, &p, settings);
|
||||
|
||||
(*env)->ReleaseByteArrayElements(env, z, z_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, y, y_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, commitment, (jbyte *)commitment_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, z, (jbyte *)z_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, y, (jbyte *)y_native, JNI_ABORT);
|
||||
(*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, JNI_ABORT);
|
||||
|
||||
if (ret != C_KZG_OK)
|
||||
{
|
||||
|
|
|
@ -149,9 +149,7 @@ Napi::Value BlobToKzgCommitment(const Napi::CallbackInfo& info) {
|
|||
return env.Undefined();
|
||||
};
|
||||
|
||||
uint8_t commitment_bytes[BYTES_PER_COMMITMENT];
|
||||
bytes_from_g1(commitment_bytes, &commitment);
|
||||
return napi_typed_array_from_bytes(commitment_bytes, BYTES_PER_COMMITMENT, env);
|
||||
return napi_typed_array_from_bytes((uint8_t *)(&commitment), BYTES_PER_COMMITMENT, env);
|
||||
}
|
||||
|
||||
// computeAggregateKzgProof: (blobs: Blob[], setupHandle: SetupHandle) => KZGProof;
|
||||
|
@ -196,9 +194,7 @@ Napi::Value ComputeAggregateKzgProof(const Napi::CallbackInfo& info) {
|
|||
return env.Undefined();
|
||||
};
|
||||
|
||||
uint8_t proof_bytes[BYTES_PER_PROOF];
|
||||
bytes_from_g1(proof_bytes, &proof);
|
||||
return napi_typed_array_from_bytes(proof_bytes, BYTES_PER_PROOF, env);
|
||||
return napi_typed_array_from_bytes((uint8_t *)(&proof), BYTES_PER_PROOF, env);
|
||||
}
|
||||
|
||||
// verifyAggregateKzgProof: (blobs: Blob[], expectedKzgCommitments: KZGCommitment[], kzgAggregatedProof: KZGProof, setupHandle: SetupHandle) => boolean;
|
||||
|
@ -238,39 +234,12 @@ Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) {
|
|||
// Extract blob bytes from parameter
|
||||
Napi::Value blob = blobs_param[blob_index];
|
||||
auto blob_bytes = blob.As<Napi::Uint8Array>().Data();
|
||||
|
||||
memcpy(blobs[blob_index].bytes, blob_bytes, BYTES_PER_BLOB);
|
||||
|
||||
// Extract a G1 point for each commitment
|
||||
// Extract commitment from parameter
|
||||
Napi::Value commitment = commitments_param[blob_index];
|
||||
auto commitment_bytes = commitment.As<Napi::Uint8Array>().Data();
|
||||
|
||||
ret = bytes_to_g1(&commitments[blob_index], commitment_bytes);
|
||||
if (ret != C_KZG_OK) {
|
||||
std::ostringstream ss;
|
||||
std::copy(commitment_bytes, commitment_bytes + BYTES_PER_COMMITMENT, std::ostream_iterator<int>(ss, ","));
|
||||
|
||||
Napi::TypeError::New(
|
||||
env,
|
||||
"Invalid commitment data"
|
||||
).ThrowAsJavaScriptException();
|
||||
|
||||
free(commitments);
|
||||
free(blobs);
|
||||
|
||||
return env.Null();
|
||||
}
|
||||
}
|
||||
|
||||
KZGProof proof;
|
||||
ret = bytes_to_g1(&proof, proof_bytes);
|
||||
if (ret != C_KZG_OK) {
|
||||
free(commitments);
|
||||
free(blobs);
|
||||
|
||||
Napi::Error::New(env, "Invalid proof data")
|
||||
.ThrowAsJavaScriptException();
|
||||
return env.Null();
|
||||
memcpy(&commitments[blob_index], commitment_bytes, BYTES_PER_COMMITMENT);
|
||||
}
|
||||
|
||||
bool verification_result;
|
||||
|
@ -279,7 +248,7 @@ Napi::Value VerifyAggregateKzgProof(const Napi::CallbackInfo& info) {
|
|||
blobs,
|
||||
commitments,
|
||||
blobs_count,
|
||||
&proof,
|
||||
(KZGProof *)proof_bytes,
|
||||
kzg_settings
|
||||
);
|
||||
|
||||
|
@ -317,24 +286,17 @@ Napi::Value VerifyKzgProof(const Napi::CallbackInfo& info) {
|
|||
return env.Null();
|
||||
}
|
||||
|
||||
KZGCommitment commitment;
|
||||
auto ret = bytes_to_g1(&commitment, polynomial_kzg);
|
||||
if (ret != C_KZG_OK) {
|
||||
std::ostringstream ss;
|
||||
std::copy(polynomial_kzg, polynomial_kzg + BYTES_PER_COMMITMENT, std::ostream_iterator<int>(ss, ","));
|
||||
|
||||
Napi::TypeError::New(env, "Failed to parse argument commitment: " + ss.str() + " Return code was: " + std::to_string(ret)).ThrowAsJavaScriptException();
|
||||
return env.Null();
|
||||
};
|
||||
|
||||
KZGProof proof;
|
||||
if (bytes_to_g1(&proof, kzg_proof) != C_KZG_OK) {
|
||||
Napi::TypeError::New(env, "Invalid kzgProof").ThrowAsJavaScriptException();
|
||||
return env.Null();
|
||||
}
|
||||
|
||||
bool out;
|
||||
if (verify_kzg_proof(&out, &commitment, z, y, &proof, kzg_settings) != C_KZG_OK) {
|
||||
C_KZG_RET ret = verify_kzg_proof(
|
||||
&out,
|
||||
(KZGCommitment *)polynomial_kzg,
|
||||
(BLSFieldElement *)z,
|
||||
(BLSFieldElement *)y,
|
||||
(KZGProof *)kzg_proof,
|
||||
kzg_settings
|
||||
);
|
||||
|
||||
if (ret != C_KZG_OK) {
|
||||
Napi::TypeError::New(env, "Failed to verify KZG proof").ThrowAsJavaScriptException();
|
||||
return env.Null();
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ describe("C-KZG", () => {
|
|||
const proof = computeAggregateKzgProof(blobs);
|
||||
expect(() =>
|
||||
verifyAggregateKzgProof(blobs, commitments, proof),
|
||||
).toThrowError("Invalid commitment data");
|
||||
).toThrowError("verify_aggregate_kzg_proof failed with error code: 1");
|
||||
});
|
||||
|
||||
describe("computing commitment from blobs", () => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
INCLUDE_DIRS = .. ../../src ../../inc
|
||||
INCLUDE_PY = $(shell python -c 'import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))')
|
||||
INCLUDE_PY = $(shell python3 -c 'import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))')
|
||||
|
||||
FIELD_ELEMENTS_PER_BLOB?=4096
|
||||
|
||||
|
@ -8,10 +8,10 @@ FIELD_ELEMENTS_PER_BLOB?=4096
|
|||
all: test ecc_test
|
||||
|
||||
test: tests.py ckzg.so
|
||||
python $<
|
||||
python3 $<
|
||||
|
||||
ecc_test: py_ecc_tests.py ckzg.so
|
||||
python $<
|
||||
python3 $<
|
||||
|
||||
ckzg.so: ckzg.c ../../src/c_kzg_4844.o ../../lib/libblst.a
|
||||
clang -O -Wall -shared -fPIC -Wl,-Bsymbolic -I${INCLUDE_PY} ${addprefix -I,${INCLUDE_DIRS}} -DFIELD_ELEMENTS_PER_BLOB=${FIELD_ELEMENTS_PER_BLOB} -o $@ $^
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
#include <Python.h>
|
||||
#include "c_kzg_4844.h"
|
||||
|
||||
static void free_G1(PyObject *c) {
|
||||
free(PyCapsule_GetPointer(c, "G1"));
|
||||
}
|
||||
|
||||
static void free_KZGSettings(PyObject *c) {
|
||||
KZGSettings *s = PyCapsule_GetPointer(c, "KZGSettings");
|
||||
free_trusted_setup(s);
|
||||
|
@ -39,21 +35,20 @@ static PyObject* blob_to_kzg_commitment_wrap(PyObject *self, PyObject *args) {
|
|||
!PyCapsule_IsValid(s, "KZGSettings"))
|
||||
return PyErr_Format(PyExc_ValueError, "expected bytes and trusted setup");
|
||||
|
||||
if (PyBytes_Size(b) != 32 * FIELD_ELEMENTS_PER_BLOB)
|
||||
return PyErr_Format(PyExc_ValueError, "expected 32 * FIELD_ELEMENTS_PER_BLOB bytes");
|
||||
if (PyBytes_Size(b) != BYTES_PER_BLOB)
|
||||
return PyErr_Format(PyExc_ValueError, "expected blobs to be BYTES_PER_BLOB bytes");
|
||||
|
||||
Blob *blob = (Blob*)PyBytes_AsString(b);
|
||||
|
||||
KZGCommitment *k = (KZGCommitment*)malloc(sizeof(KZGCommitment));
|
||||
|
||||
if (k == NULL) return PyErr_NoMemory();
|
||||
PyObject *out = PyBytes_FromStringAndSize(NULL, BYTES_PER_COMMITMENT);
|
||||
if (out == NULL) return PyErr_NoMemory();
|
||||
|
||||
Blob *blob = (Blob *)PyBytes_AsString(b);
|
||||
KZGCommitment *k = (KZGCommitment *)PyBytes_AsString(out);
|
||||
if (blob_to_kzg_commitment(k, blob, PyCapsule_GetPointer(s, "KZGSettings")) != C_KZG_OK) {
|
||||
free(k);
|
||||
Py_DECREF(out);
|
||||
return PyErr_Format(PyExc_RuntimeError, "blob_to_kzg_commitment failed");
|
||||
}
|
||||
|
||||
return PyCapsule_New(k, "G1", free_G1);
|
||||
return out;
|
||||
}
|
||||
|
||||
static PyObject* compute_aggregate_kzg_proof_wrap(PyObject *self, PyObject *args) {
|
||||
|
@ -65,97 +60,70 @@ static PyObject* compute_aggregate_kzg_proof_wrap(PyObject *self, PyObject *args
|
|||
return PyErr_Format(PyExc_ValueError, "expected bytes, trusted setup");
|
||||
|
||||
Py_ssize_t n = PyBytes_Size(b);
|
||||
if (n % (32 * FIELD_ELEMENTS_PER_BLOB) != 0)
|
||||
return PyErr_Format(PyExc_ValueError, "expected a multiple of 32 * FIELD_ELEMENTS_PER_BLOB bytes");
|
||||
n = n / 32 / FIELD_ELEMENTS_PER_BLOB;
|
||||
if (n % BYTES_PER_BLOB != 0)
|
||||
return PyErr_Format(PyExc_ValueError, "expected blobs to be a multiple of BYTES_PER_BLOB bytes");
|
||||
n = n / BYTES_PER_BLOB;
|
||||
|
||||
Blob* blobs = (Blob*)PyBytes_AsString(b);
|
||||
|
||||
KZGProof *k = (KZGProof*)malloc(sizeof(KZGProof));
|
||||
|
||||
if (k == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
PyObject *out = PyBytes_FromStringAndSize(NULL, BYTES_PER_PROOF);
|
||||
if (out == NULL) return PyErr_NoMemory();
|
||||
|
||||
Blob *blobs = (Blob *)PyBytes_AsString(b);
|
||||
KZGProof *k = (KZGProof *)PyBytes_AsString(out);
|
||||
if (compute_aggregate_kzg_proof(k, blobs, n,
|
||||
PyCapsule_GetPointer(s, "KZGSettings")) != C_KZG_OK) {
|
||||
free(k);
|
||||
Py_DECREF(out);
|
||||
return PyErr_Format(PyExc_RuntimeError, "compute_aggregate_kzg_proof failed");
|
||||
}
|
||||
|
||||
return PyCapsule_New(k, "G1", free_G1);
|
||||
return out;
|
||||
}
|
||||
|
||||
static PyObject* verify_aggregate_kzg_proof_wrap(PyObject *self, PyObject *args) {
|
||||
PyObject *b, *c, *p, *s, *e;
|
||||
PyObject *b, *c, *p, *s;
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "verify_aggregate_kzg_proof", 4, 4, &b, &c, &p, &s) ||
|
||||
!PyBytes_Check(b) ||
|
||||
!PySequence_Check(c) ||
|
||||
!PyCapsule_IsValid(p, "G1") ||
|
||||
!PyBytes_Check(c) ||
|
||||
!PyBytes_Check(p) ||
|
||||
!PyCapsule_IsValid(s, "KZGSettings"))
|
||||
return PyErr_Format(PyExc_ValueError,
|
||||
"expected bytes, sequence, proof, trusted setup");
|
||||
"expected bytes, bytes, bytes, trusted setup");
|
||||
|
||||
if (PyBytes_Size(p) != BYTES_PER_PROOF)
|
||||
return PyErr_Format(PyExc_ValueError, "expected proof to be BYTES_PER_PROOF bytes");
|
||||
|
||||
Py_ssize_t n = PyBytes_Size(b);
|
||||
if (n % (32 * FIELD_ELEMENTS_PER_BLOB) != 0)
|
||||
return PyErr_Format(PyExc_ValueError, "expected a multiple of 32 * FIELD_ELEMENTS_PER_BLOB bytes");
|
||||
n = n / 32 / FIELD_ELEMENTS_PER_BLOB;
|
||||
if (n % BYTES_PER_BLOB != 0)
|
||||
return PyErr_Format(PyExc_ValueError, "expected blobs to be a multiple of BYTES_PER_BLOB bytes");
|
||||
n = n / BYTES_PER_BLOB;
|
||||
|
||||
if (PySequence_Length(c) != n)
|
||||
Py_ssize_t m = PyBytes_Size(c);
|
||||
if (m % BYTES_PER_COMMITMENT != 0)
|
||||
return PyErr_Format(PyExc_ValueError, "expected commitments to be a multiple of BYTES_PER_COMMITMENT bytes");
|
||||
m = m / BYTES_PER_COMMITMENT;
|
||||
|
||||
if (m != n)
|
||||
return PyErr_Format(PyExc_ValueError, "expected same number of commitments as polynomials");
|
||||
|
||||
KZGCommitment* commitments = calloc(n, sizeof(KZGCommitment));
|
||||
|
||||
if (commitments == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
Blob* blobs = (Blob*)PyBytes_AsString(b);
|
||||
|
||||
for (Py_ssize_t i = 0; i < n; i++) {
|
||||
e = PySequence_GetItem(c, i);
|
||||
if (!PyCapsule_IsValid(e, "G1")) {
|
||||
free(commitments);
|
||||
return PyErr_Format(PyExc_ValueError, "expected G1 capsules");
|
||||
}
|
||||
memcpy(&commitments[i], PyCapsule_GetPointer(e, "G1"), sizeof(KZGCommitment));
|
||||
}
|
||||
const Blob* blobs = (Blob *)PyBytes_AsString(b);
|
||||
const KZGProof *proof = (KZGProof *)PyBytes_AsString(p);
|
||||
const KZGCommitment *commitments = (KZGCommitment *)PyBytes_AsString(c);
|
||||
|
||||
bool out;
|
||||
|
||||
if (verify_aggregate_kzg_proof(&out,
|
||||
blobs, commitments, n,
|
||||
PyCapsule_GetPointer(p, "G1"),
|
||||
blobs, commitments, n, proof,
|
||||
PyCapsule_GetPointer(s, "KZGSettings")) != C_KZG_OK) {
|
||||
free(commitments);
|
||||
return PyErr_Format(PyExc_RuntimeError, "verify_aggregate_kzg_proof failed");
|
||||
}
|
||||
|
||||
free(commitments);
|
||||
if (out) Py_RETURN_TRUE; else Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyObject* bytes_from_g1_wrap(PyObject *self, PyObject *args) {
|
||||
PyObject *c;
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "bytes_from_g1", 1, 1, &c) ||
|
||||
!PyCapsule_IsValid(c, "G1"))
|
||||
return PyErr_Format(PyExc_ValueError, "expected G1 capsule");
|
||||
|
||||
uint8_t bytes[48];
|
||||
bytes_from_g1(bytes, PyCapsule_GetPointer(c, "G1"));
|
||||
|
||||
return PyBytes_FromStringAndSize((char*)bytes, 48);
|
||||
}
|
||||
|
||||
static PyMethodDef ckzgmethods[] = {
|
||||
{"load_trusted_setup", load_trusted_setup_wrap, METH_VARARGS, "Load trusted setup from file path"},
|
||||
{"blob_to_kzg_commitment", blob_to_kzg_commitment_wrap, METH_VARARGS, "Create a commitment from a blob"},
|
||||
{"compute_aggregate_kzg_proof", compute_aggregate_kzg_proof_wrap, METH_VARARGS, "Compute aggregate KZG proof"},
|
||||
{"verify_aggregate_kzg_proof", verify_aggregate_kzg_proof_wrap, METH_VARARGS, "Verify aggregate KZG proof"},
|
||||
// for tests/debugging
|
||||
{"bytes_from_g1", bytes_from_g1_wrap, METH_VARARGS, "Convert a group element to 48 bytes"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ ts_pyecc = load_trusted_setup("../../src/trusted_setup.txt")
|
|||
commitment_pyecc = kzg_proofs.commit_to_poly(polynomial, ts_pyecc)
|
||||
commitment_ckzg = ckzg.blob_to_kzg_commitment(b''.join([r.to_bytes(32, "little") for r in polynomial_l_rbo]), ts)
|
||||
|
||||
assert compress_G1(commitment_pyecc).to_bytes(48, "big") == ckzg.bytes_from_g1(commitment_ckzg)
|
||||
assert compress_G1(commitment_pyecc).to_bytes(48, "big") == commitment_ckzg
|
||||
|
||||
# TODO: update this test for the new ckzg interface
|
||||
# proof_pyecc = kzg_proofs.compute_proof_single(polynomial, x, ts_pyecc)
|
||||
|
|
|
@ -14,7 +14,7 @@ blobs = [
|
|||
|
||||
ts = ckzg.load_trusted_setup("../../src/trusted_setup.txt")
|
||||
|
||||
kzg_commitments = [ckzg.blob_to_kzg_commitment(blob, ts) for blob in blobs]
|
||||
kzg_commitments = b''.join([ckzg.blob_to_kzg_commitment(blob, ts) for blob in blobs])
|
||||
|
||||
# Compute proof for these blobs
|
||||
|
||||
|
|
|
@ -6,25 +6,25 @@ use rand::{rngs::ThreadRng, Rng};
|
|||
use std::sync::Arc;
|
||||
|
||||
fn generate_random_blob_for_bench(rng: &mut ThreadRng) -> Blob {
|
||||
let mut arr: Blob = [0; BYTES_PER_BLOB];
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
rng.fill(&mut arr[..]);
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..FIELD_ELEMENTS_PER_BLOB {
|
||||
arr[i * BYTES_PER_FIELD_ELEMENT + BYTES_PER_FIELD_ELEMENT - 1] = 0;
|
||||
}
|
||||
arr
|
||||
arr.into()
|
||||
}
|
||||
|
||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
let mut rng = rand::thread_rng();
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = Arc::new(KzgSettings::load_trusted_setup_file(trusted_setup_file).unwrap());
|
||||
let kzg_settings = Arc::new(KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap());
|
||||
|
||||
let blob = generate_random_blob_for_bench(&mut rng);
|
||||
c.bench_function("blob_to_kzg_commitment", |b| {
|
||||
b.iter(|| KzgCommitment::blob_to_kzg_commitment(blob, &kzg_settings))
|
||||
b.iter(|| KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings))
|
||||
});
|
||||
|
||||
for num_blobs in [4, 8, 16].iter() {
|
||||
|
@ -37,15 +37,15 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
group.bench_with_input(
|
||||
BenchmarkId::new("compute_aggregate_kzg_proof", *num_blobs),
|
||||
&blobs,
|
||||
|b, blobs| b.iter(|| KzgProof::compute_aggregate_kzg_proof(blobs, &kzg_settings)),
|
||||
|b, blobs| b.iter(|| KZGProof::compute_aggregate_kzg_proof(blobs, &kzg_settings)),
|
||||
);
|
||||
|
||||
let kzg_commitments: Vec<KzgCommitment> = blobs
|
||||
let kzg_commitments: Vec<KZGCommitment> = blobs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|blob| KzgCommitment::blob_to_kzg_commitment(blob, &kzg_settings))
|
||||
.map(|blob| KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings))
|
||||
.collect();
|
||||
let proof = KzgProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap();
|
||||
let proof = KZGProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap();
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("verify_aggregate_kzg_proof", *num_blobs),
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
include!("./consts.rs");
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use libc::FILE;
|
||||
|
||||
pub const BYTES_PER_COMMITMENT: usize = 48;
|
||||
|
@ -9,97 +11,145 @@ pub const BYTES_PER_PROOF: usize = 48;
|
|||
pub const BYTES_PER_FIELD_ELEMENT: usize = 32;
|
||||
pub const BYTES_PER_BLOB: usize = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
|
||||
|
||||
pub type byte = u8;
|
||||
pub type limb_t = u64;
|
||||
type byte = u8;
|
||||
type limb_t = u64;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_scalar {
|
||||
pub b: [byte; 32usize],
|
||||
struct blst_scalar {
|
||||
b: [byte; 32usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fr {
|
||||
pub l: [limb_t; 4usize],
|
||||
struct blst_fr {
|
||||
l: [limb_t; 4usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fp {
|
||||
pub l: [limb_t; 6usize],
|
||||
struct blst_fp {
|
||||
l: [limb_t; 6usize],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fp2 {
|
||||
pub fp: [blst_fp; 2usize],
|
||||
struct blst_fp2 {
|
||||
fp: [blst_fp; 2usize],
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fp6 {
|
||||
pub fp2: [blst_fp2; 3usize],
|
||||
struct blst_fp6 {
|
||||
fp2: [blst_fp2; 3usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_fp12 {
|
||||
pub fp6: [blst_fp6; 2usize],
|
||||
struct blst_fp12 {
|
||||
fp6: [blst_fp6; 2usize],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_p1 {
|
||||
pub x: blst_fp,
|
||||
pub y: blst_fp,
|
||||
pub z: blst_fp,
|
||||
struct blst_p1 {
|
||||
x: blst_fp,
|
||||
y: blst_fp,
|
||||
z: blst_fp,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_p1_affine {
|
||||
pub x: blst_fp,
|
||||
pub y: blst_fp,
|
||||
struct blst_p1_affine {
|
||||
x: blst_fp,
|
||||
y: blst_fp,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_p2 {
|
||||
pub x: blst_fp2,
|
||||
pub y: blst_fp2,
|
||||
pub z: blst_fp2,
|
||||
struct blst_p2 {
|
||||
x: blst_fp2,
|
||||
y: blst_fp2,
|
||||
z: blst_fp2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct blst_p2_affine {
|
||||
pub x: blst_fp2,
|
||||
pub y: blst_fp2,
|
||||
struct blst_p2_affine {
|
||||
x: blst_fp2,
|
||||
y: blst_fp2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct BLSFieldElement {
|
||||
bytes: [u8; BYTES_PER_FIELD_ELEMENT],
|
||||
}
|
||||
|
||||
impl Deref for BLSFieldElement {
|
||||
type Target = [u8; BYTES_PER_FIELD_ELEMENT];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Blob {
|
||||
bytes: [u8; BYTES_PER_BLOB],
|
||||
}
|
||||
|
||||
impl Deref for Blob {
|
||||
type Target = [u8; BYTES_PER_BLOB];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Blob {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct KZGProof {
|
||||
bytes: [u8; BYTES_PER_PROOF],
|
||||
}
|
||||
|
||||
impl Deref for KZGProof {
|
||||
type Target = [u8; BYTES_PER_PROOF];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub const FIAT_SHAMIR_PROTOCOL_DOMAIN: &[u8; 16usize] = b"FSBLOBVERIFY_V1_";
|
||||
type g1_t = blst_p1;
|
||||
type g2_t = blst_p2;
|
||||
type fr_t = blst_fr;
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct KZGCommitment {
|
||||
bytes: [u8; BYTES_PER_COMMITMENT],
|
||||
}
|
||||
|
||||
impl Deref for KZGCommitment {
|
||||
type Target = [u8; BYTES_PER_COMMITMENT];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub const FIAT_SHAMIR_PROTOCOL_DOMAIN: [u8; 16usize] = [
|
||||
70, 83, 66, 76, 79, 66, 86, 69, 82, 73, 70, 89, 95, 86, 49, 95,
|
||||
];
|
||||
pub type g1_t = blst_p1;
|
||||
pub type g2_t = blst_p2;
|
||||
pub type fr_t = blst_fr;
|
||||
pub type KZGCommitment = g1_t;
|
||||
pub type KZGProof = g1_t;
|
||||
pub type BLSFieldElement = fr_t;
|
||||
pub type Blob = [u8; BYTES_PER_BLOB];
|
||||
#[repr(u32)]
|
||||
#[doc = " The common return type for all routines in which something can go wrong."]
|
||||
#[doc = ""]
|
||||
#[doc = " @warning In the case of @p C_KZG_OK or @p C_KZG_BADARGS, the caller can assume that all memory allocated by the"]
|
||||
#[doc = " called routines has been deallocated. However, in the case of @p C_KZG_ERROR or @p C_KZG_MALLOC being returned, these"]
|
||||
#[doc = " are unrecoverable and memory may have been leaked."]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum C_KZG_RET {
|
||||
#[doc = "< Success!"]
|
||||
C_KZG_OK = 0,
|
||||
#[doc = "< The supplied data is invalid in some way"]
|
||||
#[doc = "< The supplied data is invalid in some way."]
|
||||
C_KZG_BADARGS = 1,
|
||||
#[doc = "< Internal error - this should never occur and may indicate a bug in the library"]
|
||||
#[doc = "< Internal error - this should never occur and may indicate a bug in the library."]
|
||||
C_KZG_ERROR = 2,
|
||||
#[doc = "< Could not allocate memory"]
|
||||
#[doc = "< Could not allocate memory."]
|
||||
C_KZG_MALLOC = 3,
|
||||
}
|
||||
#[doc = " Stores the setup and parameters needed for performing FFTs."]
|
||||
|
@ -107,80 +157,25 @@ pub enum C_KZG_RET {
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct FFTSettings {
|
||||
#[doc = "< The maximum size of FFT these settings support, a power of 2."]
|
||||
pub max_width: u64,
|
||||
max_width: u64,
|
||||
#[doc = "< Ascending powers of the root of unity, size `width + 1`."]
|
||||
pub expanded_roots_of_unity: *const fr_t,
|
||||
expanded_roots_of_unity: *const fr_t,
|
||||
#[doc = "< Descending powers of the root of unity, size `width + 1`."]
|
||||
pub reverse_roots_of_unity: *const fr_t,
|
||||
reverse_roots_of_unity: *const fr_t,
|
||||
#[doc = "< Powers of the root of unity in bit-reversal permutation, size `width`."]
|
||||
pub roots_of_unity: *const fr_t,
|
||||
roots_of_unity: *const fr_t,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bindgen_test_layout_FFTSettings() {
|
||||
const UNINIT: ::std::mem::MaybeUninit<FFTSettings> = ::std::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<FFTSettings>(),
|
||||
32usize,
|
||||
concat!("Size of: ", stringify!(FFTSettings))
|
||||
);
|
||||
assert_eq!(
|
||||
::std::mem::align_of::<FFTSettings>(),
|
||||
8usize,
|
||||
concat!("Alignment of ", stringify!(FFTSettings))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).max_width) as usize - ptr as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(FFTSettings),
|
||||
"::",
|
||||
stringify!(max_width)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).expanded_roots_of_unity) as usize - ptr as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(FFTSettings),
|
||||
"::",
|
||||
stringify!(expanded_roots_of_unity)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).reverse_roots_of_unity) as usize - ptr as usize },
|
||||
16usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(FFTSettings),
|
||||
"::",
|
||||
stringify!(reverse_roots_of_unity)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).roots_of_unity) as usize - ptr as usize },
|
||||
24usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(FFTSettings),
|
||||
"::",
|
||||
stringify!(roots_of_unity)
|
||||
)
|
||||
);
|
||||
}
|
||||
#[doc = " Stores the setup and parameters needed for computing KZG proofs."]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct KZGSettings {
|
||||
#[doc = "< The corresponding settings for performing FFTs"]
|
||||
pub fs: *const FFTSettings,
|
||||
#[doc = "< G1 group elements from the trusted setup, in Lagrange form bit-reversal permutation"]
|
||||
pub g1_values: *const g1_t,
|
||||
#[doc = "< G2 group elements from the trusted setup; both arrays have FIELD_ELEMENTS_PER_BLOB elements"]
|
||||
pub g2_values: *const g2_t,
|
||||
#[doc = "< The corresponding settings for performing FFTs."]
|
||||
fs: *const FFTSettings,
|
||||
#[doc = "< G1 group elements from the trusted setup, in Lagrange form bit-reversal permutation."]
|
||||
g1_values: *const g1_t,
|
||||
#[doc = "< G2 group elements from the trusted setup; both arrays have FIELD_ELEMENTS_PER_BLOB elements."]
|
||||
g2_values: *const g2_t,
|
||||
}
|
||||
|
||||
/// Safety: FFTSettings is initialized once on calling `load_trusted_setup`. After
|
||||
|
@ -190,65 +185,8 @@ pub struct KZGSettings {
|
|||
unsafe impl Sync for KZGSettings {}
|
||||
unsafe impl Send for KZGSettings {}
|
||||
|
||||
#[test]
|
||||
fn bindgen_test_layout_KZGSettings() {
|
||||
const UNINIT: ::std::mem::MaybeUninit<KZGSettings> = ::std::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::std::mem::size_of::<KZGSettings>(),
|
||||
24usize,
|
||||
concat!("Size of: ", stringify!(KZGSettings))
|
||||
);
|
||||
assert_eq!(
|
||||
::std::mem::align_of::<KZGSettings>(),
|
||||
8usize,
|
||||
concat!("Alignment of ", stringify!(KZGSettings))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).fs) as usize - ptr as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(KZGSettings),
|
||||
"::",
|
||||
stringify!(fs)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).g1_values) as usize - ptr as usize },
|
||||
8usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(KZGSettings),
|
||||
"::",
|
||||
stringify!(g1_values)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::std::ptr::addr_of!((*ptr).g2_values) as usize - ptr as usize },
|
||||
16usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(KZGSettings),
|
||||
"::",
|
||||
stringify!(g2_values)
|
||||
)
|
||||
);
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Interface functions"]
|
||||
pub fn bytes_to_g1(out: *mut g1_t, in_: *const u8) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn bytes_from_g1(out: *mut u8, in_: *const g1_t);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn bytes_to_bls_field(out: *mut BLSFieldElement, in_: *const u8) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn load_trusted_setup_file(out: *mut KZGSettings, in_: *mut FILE) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn load_trusted_setup(
|
||||
out: *mut KZGSettings,
|
||||
g1_bytes: *const u8, /* n1 * 48 bytes */
|
||||
|
@ -257,13 +195,16 @@ extern "C" {
|
|||
n2: usize,
|
||||
) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn load_trusted_setup_file(out: *mut KZGSettings, in_: *mut FILE) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn free_trusted_setup(s: *mut KZGSettings);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn compute_aggregate_kzg_proof(
|
||||
out: *mut KZGProof,
|
||||
blobs: *const u8, // pointer to the first byte in a 2D array ([[u8; BYTES_PER_BLOB]])
|
||||
blobs: *const Blob,
|
||||
n: usize,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
@ -271,7 +212,7 @@ extern "C" {
|
|||
extern "C" {
|
||||
pub fn verify_aggregate_kzg_proof(
|
||||
out: *mut bool,
|
||||
blobs: *const u8, // pointer to the first byte in a 2D array ([[u8; BYTES_PER_BLOB]])
|
||||
blobs: *const Blob,
|
||||
expected_kzg_commitments: *const KZGCommitment,
|
||||
n: usize,
|
||||
kzg_aggregated_proof: *const KZGProof,
|
||||
|
@ -279,14 +220,18 @@ extern "C" {
|
|||
) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn blob_to_kzg_commitment(out: *mut KZGCommitment, blob: *mut u8, s: *const KZGSettings);
|
||||
pub fn blob_to_kzg_commitment(
|
||||
out: *mut KZGCommitment,
|
||||
blob: *const Blob,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn verify_kzg_proof(
|
||||
out: *mut bool,
|
||||
polynomial_kzg: *const KZGCommitment,
|
||||
z: *const u8,
|
||||
y: *const u8,
|
||||
z: *const BLSFieldElement,
|
||||
y: *const BLSFieldElement,
|
||||
kzg_proof: *const KZGProof,
|
||||
s: *const KZGSettings,
|
||||
) -> C_KZG_RET;
|
||||
|
|
|
@ -2,19 +2,14 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
mod bindings;
|
||||
use bindings::{g1_t, C_KZG_RET};
|
||||
include!("bindings.rs");
|
||||
|
||||
use libc::fopen;
|
||||
use std::ffi::CString;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::os::unix::prelude::OsStrExt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub use bindings::{
|
||||
Blob, BYTES_PER_BLOB, BYTES_PER_COMMITMENT, BYTES_PER_FIELD_ELEMENT, BYTES_PER_PROOF,
|
||||
FIAT_SHAMIR_PROTOCOL_DOMAIN, FIELD_ELEMENTS_PER_BLOB,
|
||||
};
|
||||
|
||||
pub const BYTES_PER_G1_POINT: usize = 48;
|
||||
pub const BYTES_PER_G2_POINT: usize = 96;
|
||||
|
||||
|
@ -34,44 +29,8 @@ pub enum Error {
|
|||
CError(C_KZG_RET),
|
||||
}
|
||||
|
||||
pub fn bytes_to_g1(bytes: &[u8]) -> Result<g1_t, Error> {
|
||||
let mut g1_point = MaybeUninit::<g1_t>::uninit();
|
||||
unsafe {
|
||||
let res = bindings::bytes_to_g1(g1_point.as_mut_ptr(), bytes.as_ptr());
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(g1_point.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_from_g1(g1_point: g1_t) -> [u8; BYTES_PER_G1_POINT] {
|
||||
let mut bytes = [0; 48];
|
||||
unsafe { bindings::bytes_from_g1(bytes.as_mut_ptr(), &g1_point) }
|
||||
bytes
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct BlsFieldElement(bindings::BLSFieldElement);
|
||||
|
||||
impl BlsFieldElement {
|
||||
pub fn bytes_to_bls_field(bytes: [u8; BYTES_PER_FIELD_ELEMENT]) -> Result<Self, Error> {
|
||||
let mut bls_field_element = MaybeUninit::<bindings::BLSFieldElement>::uninit();
|
||||
unsafe {
|
||||
let res = bindings::bytes_to_bls_field(bls_field_element.as_mut_ptr(), bytes.as_ptr());
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(Self(bls_field_element.assume_init()))
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds the parameters of a kzg trusted setup ceremony.
|
||||
pub struct KzgSettings(bindings::KZGSettings);
|
||||
impl KzgSettings {
|
||||
impl KZGSettings {
|
||||
/// Initializes a trusted setup from `FIELD_ELEMENTS_PER_BLOB` g1 points
|
||||
/// and 65 g2 points in byte format.
|
||||
pub fn load_trusted_setup(
|
||||
|
@ -92,12 +51,12 @@ impl KzgSettings {
|
|||
g2_bytes.len()
|
||||
)));
|
||||
}
|
||||
let mut kzg_settings = MaybeUninit::<bindings::KZGSettings>::uninit();
|
||||
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
|
||||
unsafe {
|
||||
let n1 = g1_bytes.len();
|
||||
let n2 = g2_bytes.len();
|
||||
|
||||
let res = bindings::load_trusted_setup(
|
||||
let res = load_trusted_setup(
|
||||
kzg_settings.as_mut_ptr(),
|
||||
g1_bytes.as_ptr() as *const u8,
|
||||
n1,
|
||||
|
@ -105,7 +64,7 @@ impl KzgSettings {
|
|||
n2,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(Self(kzg_settings.assume_init()))
|
||||
Ok(kzg_settings.assume_init())
|
||||
} else {
|
||||
Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid trusted setup: {:?}",
|
||||
|
@ -125,12 +84,12 @@ impl KzgSettings {
|
|||
let file_path = CString::new(file_path.as_os_str().as_bytes()).map_err(|e| {
|
||||
Error::InvalidTrustedSetup(format!("Invalid trusted setup file: {:?}", e))
|
||||
})?;
|
||||
let mut kzg_settings = MaybeUninit::<bindings::KZGSettings>::uninit();
|
||||
let mut kzg_settings = MaybeUninit::<KZGSettings>::uninit();
|
||||
unsafe {
|
||||
let file_ptr = fopen(file_path.as_ptr(), &('r' as libc::c_char));
|
||||
let res = bindings::load_trusted_setup_file(kzg_settings.as_mut_ptr(), file_ptr);
|
||||
let res = load_trusted_setup_file(kzg_settings.as_mut_ptr(), file_ptr);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(Self(kzg_settings.assume_init()))
|
||||
Ok(kzg_settings.assume_init())
|
||||
} else {
|
||||
Err(Error::InvalidTrustedSetup(format!(
|
||||
"Invalid trusted setup: {:?}",
|
||||
|
@ -141,15 +100,13 @@ impl KzgSettings {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for KzgSettings {
|
||||
impl Drop for KZGSettings {
|
||||
fn drop(&mut self) {
|
||||
unsafe { bindings::free_trusted_setup(&mut self.0) }
|
||||
unsafe { free_trusted_setup(self) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KzgProof(bindings::KZGProof);
|
||||
|
||||
impl KzgProof {
|
||||
impl KZGProof {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_PROOF {
|
||||
return Err(Error::InvalidKzgProof(format!(
|
||||
|
@ -160,11 +117,11 @@ impl KzgProof {
|
|||
}
|
||||
let mut proof_bytes = [0; BYTES_PER_PROOF];
|
||||
proof_bytes.copy_from_slice(bytes);
|
||||
Ok(Self(bytes_to_g1(bytes)?))
|
||||
Ok(Self { bytes: proof_bytes })
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; BYTES_PER_G1_POINT] {
|
||||
bytes_from_g1(self.0)
|
||||
self.bytes
|
||||
}
|
||||
|
||||
pub fn as_hex_string(&self) -> String {
|
||||
|
@ -173,18 +130,18 @@ impl KzgProof {
|
|||
|
||||
pub fn compute_aggregate_kzg_proof(
|
||||
blobs: &[Blob],
|
||||
kzg_settings: &KzgSettings,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<Self, Error> {
|
||||
let mut kzg_proof = MaybeUninit::<bindings::KZGProof>::uninit();
|
||||
let mut kzg_proof = MaybeUninit::<KZGProof>::uninit();
|
||||
unsafe {
|
||||
let res = bindings::compute_aggregate_kzg_proof(
|
||||
let res = compute_aggregate_kzg_proof(
|
||||
kzg_proof.as_mut_ptr(),
|
||||
blobs.as_ptr() as *const u8,
|
||||
blobs.as_ptr(),
|
||||
blobs.len(),
|
||||
&kzg_settings.0,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(Self(kzg_proof.assume_init()))
|
||||
Ok(kzg_proof.assume_init())
|
||||
} else {
|
||||
Err(Error::CError(res))
|
||||
}
|
||||
|
@ -194,23 +151,18 @@ impl KzgProof {
|
|||
pub fn verify_aggregate_kzg_proof(
|
||||
&self,
|
||||
blobs: &[Blob],
|
||||
expected_kzg_commitments: &[KzgCommitment],
|
||||
kzg_settings: &KzgSettings,
|
||||
expected_kzg_commitments: &[KZGCommitment],
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
// TODO: pass without allocating a vec
|
||||
let res = bindings::verify_aggregate_kzg_proof(
|
||||
let res = verify_aggregate_kzg_proof(
|
||||
verified.as_mut_ptr(),
|
||||
blobs.as_ptr() as *const u8,
|
||||
expected_kzg_commitments
|
||||
.iter()
|
||||
.map(|c| c.0)
|
||||
.collect::<Vec<_>>()
|
||||
.as_ptr(),
|
||||
blobs.as_ptr(),
|
||||
expected_kzg_commitments.as_ptr(),
|
||||
blobs.len(),
|
||||
&self.0,
|
||||
&kzg_settings.0,
|
||||
self,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
|
@ -222,20 +174,20 @@ impl KzgProof {
|
|||
|
||||
pub fn verify_kzg_proof(
|
||||
&self,
|
||||
kzg_commitment: KzgCommitment,
|
||||
z: [u8; BYTES_PER_FIELD_ELEMENT],
|
||||
y: [u8; BYTES_PER_FIELD_ELEMENT],
|
||||
kzg_settings: &KzgSettings,
|
||||
kzg_commitment: KZGCommitment,
|
||||
z: BLSFieldElement,
|
||||
y: BLSFieldElement,
|
||||
kzg_settings: &KZGSettings,
|
||||
) -> Result<bool, Error> {
|
||||
let mut verified: MaybeUninit<bool> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
let res = bindings::verify_kzg_proof(
|
||||
let res = verify_kzg_proof(
|
||||
verified.as_mut_ptr(),
|
||||
&kzg_commitment.0,
|
||||
z.as_ptr(),
|
||||
y.as_ptr(),
|
||||
&self.0,
|
||||
&kzg_settings.0,
|
||||
&kzg_commitment,
|
||||
&z,
|
||||
&y,
|
||||
self,
|
||||
kzg_settings,
|
||||
);
|
||||
if let C_KZG_RET::C_KZG_OK = res {
|
||||
Ok(verified.assume_init())
|
||||
|
@ -246,9 +198,7 @@ impl KzgProof {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct KzgCommitment(bindings::KZGCommitment);
|
||||
|
||||
impl KzgCommitment {
|
||||
impl KZGCommitment {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
|
||||
if bytes.len() != BYTES_PER_COMMITMENT {
|
||||
return Err(Error::InvalidKzgCommitment(format!(
|
||||
|
@ -257,65 +207,89 @@ impl KzgCommitment {
|
|||
bytes.len(),
|
||||
)));
|
||||
}
|
||||
let mut proof_bytes = [0; BYTES_PER_COMMITMENT];
|
||||
proof_bytes.copy_from_slice(bytes);
|
||||
Ok(Self(bytes_to_g1(bytes)?))
|
||||
let mut commitment = [0; BYTES_PER_COMMITMENT];
|
||||
commitment.copy_from_slice(bytes);
|
||||
Ok(Self { bytes: commitment })
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; BYTES_PER_G1_POINT] {
|
||||
bytes_from_g1(self.0)
|
||||
self.bytes
|
||||
}
|
||||
|
||||
pub fn as_hex_string(&self) -> String {
|
||||
hex::encode(self.to_bytes())
|
||||
}
|
||||
|
||||
pub fn blob_to_kzg_commitment(mut blob: Blob, kzg_settings: &KzgSettings) -> Self {
|
||||
let mut kzg_commitment: MaybeUninit<bindings::KZGCommitment> = MaybeUninit::uninit();
|
||||
pub fn blob_to_kzg_commitment(blob: Blob, kzg_settings: &KZGSettings) -> Self {
|
||||
let mut kzg_commitment: MaybeUninit<KZGCommitment> = MaybeUninit::uninit();
|
||||
unsafe {
|
||||
bindings::blob_to_kzg_commitment(
|
||||
blob_to_kzg_commitment(
|
||||
kzg_commitment.as_mut_ptr(),
|
||||
blob.as_mut_ptr(),
|
||||
&kzg_settings.0,
|
||||
blob.as_ptr() as *const Blob,
|
||||
kzg_settings,
|
||||
);
|
||||
Self(kzg_commitment.assume_init())
|
||||
kzg_commitment.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_COMMITMENT]> for KZGCommitment {
|
||||
fn from(value: [u8; BYTES_PER_COMMITMENT]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_PROOF]> for KZGProof {
|
||||
fn from(value: [u8; BYTES_PER_PROOF]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_BLOB]> for Blob {
|
||||
fn from(value: [u8; BYTES_PER_BLOB]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; BYTES_PER_FIELD_ELEMENT]> for BLSFieldElement {
|
||||
fn from(value: [u8; BYTES_PER_FIELD_ELEMENT]) -> Self {
|
||||
Self { bytes: value }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rand::{rngs::ThreadRng, Rng};
|
||||
|
||||
fn generate_random_blob(rng: &mut ThreadRng) -> Blob {
|
||||
let mut arr: Blob = [0; BYTES_PER_BLOB];
|
||||
let mut arr = [0u8; BYTES_PER_BLOB];
|
||||
rng.fill(&mut arr[..]);
|
||||
// Ensure that the blob is canonical by ensuring that
|
||||
// each field element contained in the blob is < BLS_MODULUS
|
||||
for i in 0..FIELD_ELEMENTS_PER_BLOB {
|
||||
arr[i * BYTES_PER_FIELD_ELEMENT + BYTES_PER_FIELD_ELEMENT - 1] = 0;
|
||||
}
|
||||
arr
|
||||
arr.into()
|
||||
}
|
||||
|
||||
fn test_simple(trusted_setup_file: PathBuf) {
|
||||
let mut rng = rand::thread_rng();
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KzgSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
|
||||
let num_blobs: usize = rng.gen_range(0..16);
|
||||
let mut blobs: Vec<Blob> = (0..num_blobs)
|
||||
.map(|_| generate_random_blob(&mut rng))
|
||||
.collect();
|
||||
|
||||
let kzg_commitments: Vec<KzgCommitment> = blobs
|
||||
let kzg_commitments: Vec<KZGCommitment> = blobs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|blob| KzgCommitment::blob_to_kzg_commitment(blob, &kzg_settings))
|
||||
.map(|blob| KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings))
|
||||
.collect();
|
||||
|
||||
let kzg_proof = KzgProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap();
|
||||
let kzg_proof = KZGProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap();
|
||||
|
||||
assert!(kzg_proof
|
||||
.verify_aggregate_kzg_proof(&blobs, &kzg_commitments, &kzg_settings)
|
||||
|
@ -345,7 +319,7 @@ mod tests {
|
|||
fn test_compute_agg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KzgSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
|
||||
let test_file = PathBuf::from("test_vectors/public_agg_proof.json");
|
||||
let json_data: serde_json::Value =
|
||||
|
@ -375,15 +349,15 @@ mod tests {
|
|||
let blob = hex::decode(data).unwrap();
|
||||
let mut blob_data = [0; BYTES_PER_BLOB];
|
||||
blob_data.copy_from_slice(&blob);
|
||||
blob_data
|
||||
Blob { bytes: blob_data }
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let proof = KzgProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap();
|
||||
let proof = KZGProof::compute_aggregate_kzg_proof(&blobs, &kzg_settings).unwrap();
|
||||
assert_eq!(proof.as_hex_string(), expected_proof);
|
||||
|
||||
for (i, blob) in blobs.into_iter().enumerate() {
|
||||
let commitment = KzgCommitment::blob_to_kzg_commitment(blob, &kzg_settings);
|
||||
let commitment = KZGCommitment::blob_to_kzg_commitment(blob, &kzg_settings);
|
||||
assert_eq!(
|
||||
commitment.as_hex_string().as_str(),
|
||||
expected_kzg_commitments[i]
|
||||
|
@ -397,7 +371,7 @@ mod tests {
|
|||
fn test_verify_kzg_proof() {
|
||||
let trusted_setup_file = PathBuf::from("../../src/trusted_setup.txt");
|
||||
assert!(trusted_setup_file.exists());
|
||||
let kzg_settings = KzgSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
let kzg_settings = KZGSettings::load_trusted_setup_file(trusted_setup_file).unwrap();
|
||||
|
||||
let test_file = PathBuf::from("test_vectors/public_verify_kzg_proof.json");
|
||||
let json_data: serde_json::Value =
|
||||
|
@ -406,11 +380,11 @@ mod tests {
|
|||
let tests = json_data.get("TestCases").unwrap().as_array().unwrap();
|
||||
for test in tests.iter() {
|
||||
let proof = test.get("Proof").unwrap().as_str().unwrap();
|
||||
let kzg_proof = KzgProof::from_bytes(&hex::decode(proof).unwrap()).unwrap();
|
||||
let kzg_proof = KZGProof::from_bytes(&hex::decode(proof).unwrap()).unwrap();
|
||||
|
||||
let commitment = test.get("Commitment").unwrap().as_str().unwrap();
|
||||
let kzg_commitment =
|
||||
KzgCommitment::from_bytes(&hex::decode(commitment).unwrap()).unwrap();
|
||||
KZGCommitment::from_bytes(&hex::decode(commitment).unwrap()).unwrap();
|
||||
|
||||
let z = test.get("InputPoint").unwrap().as_str().unwrap();
|
||||
let mut z_bytes = [0; BYTES_PER_FIELD_ELEMENT];
|
||||
|
@ -421,7 +395,12 @@ mod tests {
|
|||
y_bytes.copy_from_slice(&hex::decode(y).unwrap());
|
||||
|
||||
assert!(kzg_proof
|
||||
.verify_kzg_proof(kzg_commitment, z_bytes, y_bytes, &kzg_settings)
|
||||
.verify_kzg_proof(
|
||||
kzg_commitment,
|
||||
z_bytes.into(),
|
||||
y_bytes.into(),
|
||||
&kzg_settings
|
||||
)
|
||||
.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
118
src/c_kzg_4844.c
118
src/c_kzg_4844.c
|
@ -790,13 +790,13 @@ static bool pairings_verify(const g1_t *a1, const g2_t *a2, const g1_t *b1, cons
|
|||
return blst_fp12_is_one(>_point);
|
||||
}
|
||||
|
||||
typedef struct { BLSFieldElement evals[FIELD_ELEMENTS_PER_BLOB]; } Polynomial;
|
||||
typedef struct { fr_t evals[FIELD_ELEMENTS_PER_BLOB]; } Polynomial;
|
||||
|
||||
void bytes_from_g1(uint8_t out[48], const g1_t *in) {
|
||||
static void bytes_from_g1(uint8_t out[48], const g1_t *in) {
|
||||
blst_p1_compress(out, in);
|
||||
}
|
||||
|
||||
C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) {
|
||||
static C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) {
|
||||
blst_p1_affine tmp;
|
||||
if (blst_p1_uncompress(&tmp, bytes) != BLST_SUCCESS)
|
||||
return C_KZG_BADARGS;
|
||||
|
@ -804,11 +804,11 @@ C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t bytes[48]) {
|
|||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
static void bytes_from_bls_field(uint8_t out[32], const BLSFieldElement *in) {
|
||||
static void bytes_from_bls_field(uint8_t out[32], const fr_t *in) {
|
||||
blst_scalar_from_fr((blst_scalar*)out, in);
|
||||
}
|
||||
|
||||
C_KZG_RET load_trusted_setup(KZGSettings *out, const uint8_t g1_bytes[], size_t n1, const uint8_t g2_bytes[], size_t n2) {
|
||||
C_KZG_RET load_trusted_setup(KZGSettings *out, const uint8_t *g1_bytes, size_t n1, const uint8_t *g2_bytes, size_t n2) {
|
||||
uint64_t i;
|
||||
blst_p2_affine g2_affine;
|
||||
g1_t *g1_projective = NULL;
|
||||
|
@ -890,21 +890,21 @@ void free_trusted_setup(KZGSettings *s) {
|
|||
free_kzg_settings(s);
|
||||
}
|
||||
|
||||
static void compute_powers(BLSFieldElement out[], BLSFieldElement *x, uint64_t n) {
|
||||
BLSFieldElement current_power = fr_one;
|
||||
static void compute_powers(fr_t *out, fr_t *x, uint64_t n) {
|
||||
fr_t current_power = fr_one;
|
||||
for (uint64_t i = 0; i < n; i++) {
|
||||
out[i] = current_power;
|
||||
fr_mul(¤t_power, ¤t_power, x);
|
||||
}
|
||||
}
|
||||
|
||||
static void hash_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) {
|
||||
static void hash_to_bls_field(fr_t *out, const uint8_t bytes[32]) {
|
||||
blst_scalar tmp;
|
||||
blst_scalar_from_lendian(&tmp, bytes);
|
||||
blst_fr_from_scalar(out, &tmp);
|
||||
}
|
||||
|
||||
C_KZG_RET bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) {
|
||||
static C_KZG_RET bytes_to_bls_field(fr_t *out, const uint8_t bytes[32]) {
|
||||
blst_scalar tmp;
|
||||
blst_scalar_from_lendian(&tmp, bytes);
|
||||
if (!blst_scalar_fr_check(&tmp)) return C_KZG_BADARGS;
|
||||
|
@ -912,7 +912,7 @@ C_KZG_RET bytes_to_bls_field(BLSFieldElement *out, const uint8_t bytes[32]) {
|
|||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
static void poly_lincomb(Polynomial *out, const Polynomial *vectors, const fr_t scalars[], uint64_t n) {
|
||||
static void poly_lincomb(Polynomial *out, const Polynomial *vectors, const fr_t *scalars, uint64_t n) {
|
||||
fr_t tmp;
|
||||
uint64_t i, j;
|
||||
for (j = 0; j < FIELD_ELEMENTS_PER_BLOB; j++)
|
||||
|
@ -992,7 +992,7 @@ static C_KZG_RET g1_lincomb(g1_t *out, const g1_t *p, const fr_t *coeffs, const
|
|||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
static C_KZG_RET poly_to_kzg_commitment(KZGCommitment *out, const Polynomial *p, const KZGSettings *s) {
|
||||
static C_KZG_RET poly_to_kzg_commitment(g1_t *out, const Polynomial *p, const KZGSettings *s) {
|
||||
return g1_lincomb(out, s->g1_values, (const fr_t *)(&p->evals), FIELD_ELEMENTS_PER_BLOB);
|
||||
}
|
||||
|
||||
|
@ -1006,10 +1006,16 @@ static C_KZG_RET poly_from_blob(Polynomial *p, const Blob *blob) {
|
|||
}
|
||||
|
||||
C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out, const Blob *blob, const KZGSettings *s) {
|
||||
C_KZG_RET ret;
|
||||
Polynomial p;
|
||||
C_KZG_RET ret = poly_from_blob(&p, blob);
|
||||
g1_t commitment;
|
||||
|
||||
ret = poly_from_blob(&p, blob);
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
return poly_to_kzg_commitment(out, &p, s);
|
||||
ret = poly_to_kzg_commitment(&commitment, &p, s);
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
bytes_from_g1((uint8_t *)(out), &commitment);
|
||||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1041,20 +1047,27 @@ static C_KZG_RET verify_kzg_proof_impl(bool *out, const g1_t *commitment, const
|
|||
|
||||
C_KZG_RET verify_kzg_proof(bool *out,
|
||||
const KZGCommitment *commitment,
|
||||
const uint8_t z[BYTES_PER_FIELD_ELEMENT],
|
||||
const uint8_t y[BYTES_PER_FIELD_ELEMENT],
|
||||
const BLSFieldElement *z,
|
||||
const BLSFieldElement *y,
|
||||
const KZGProof *kzg_proof,
|
||||
const KZGSettings *s) {
|
||||
BLSFieldElement frz, fry;
|
||||
C_KZG_RET ret;
|
||||
ret = bytes_to_bls_field(&frz, z);
|
||||
fr_t frz, fry;
|
||||
g1_t g1commitment, g1proof;
|
||||
|
||||
ret = bytes_to_g1(&g1commitment, (const uint8_t *)(commitment));
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
ret = bytes_to_bls_field(&fry, y);
|
||||
ret = bytes_to_bls_field(&frz, (const uint8_t *)(z));
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
return verify_kzg_proof_impl(out, commitment, &frz, &fry, kzg_proof, s);
|
||||
ret = bytes_to_bls_field(&fry, (const uint8_t *)(y));
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
ret = bytes_to_g1(&g1proof, (const uint8_t *)(kzg_proof));
|
||||
if (ret != C_KZG_OK) return ret;
|
||||
|
||||
return verify_kzg_proof_impl(out, &g1commitment, &frz, &fry, &g1proof, s);
|
||||
}
|
||||
|
||||
static C_KZG_RET evaluate_polynomial_in_evaluation_form(BLSFieldElement *out, const Polynomial *p, const BLSFieldElement *x, const KZGSettings *s) {
|
||||
static C_KZG_RET evaluate_polynomial_in_evaluation_form(fr_t *out, const Polynomial *p, const fr_t *x, const KZGSettings *s) {
|
||||
C_KZG_RET ret;
|
||||
fr_t tmp;
|
||||
fr_t *inverses_in = NULL;
|
||||
|
@ -1107,9 +1120,9 @@ out:
|
|||
* @retval C_KZG_OK All is well
|
||||
* @retval C_KZG_MALLOC Memory allocation failed
|
||||
*/
|
||||
static C_KZG_RET compute_kzg_proof(KZGProof *out, const Polynomial *p, const BLSFieldElement *x, const KZGSettings *s) {
|
||||
static C_KZG_RET compute_kzg_proof(g1_t *out, const Polynomial *p, const fr_t *x, const KZGSettings *s) {
|
||||
C_KZG_RET ret;
|
||||
BLSFieldElement y;
|
||||
fr_t y;
|
||||
fr_t *inverses_in = NULL;
|
||||
fr_t *inverses = NULL;
|
||||
|
||||
|
@ -1180,7 +1193,7 @@ void sha256_init(SHA256_CTX *ctx);
|
|||
void sha256_update(SHA256_CTX *ctx, const void *_inp, size_t len);
|
||||
void sha256_final(unsigned char md[32], SHA256_CTX *ctx);
|
||||
|
||||
static void hash(uint8_t md[32], const uint8_t input[], size_t n) {
|
||||
static void hash(uint8_t md[32], const uint8_t *input, size_t n) {
|
||||
SHA256_CTX ctx;
|
||||
sha256_init(&ctx);
|
||||
sha256_update(&ctx, input, n);
|
||||
|
@ -1194,8 +1207,8 @@ static void bytes_of_uint64(uint8_t out[8], uint64_t n) {
|
|||
}
|
||||
}
|
||||
|
||||
static C_KZG_RET compute_challenges(BLSFieldElement *out, BLSFieldElement r_powers[],
|
||||
const Polynomial *polys, const KZGCommitment comms[], uint64_t n) {
|
||||
static C_KZG_RET compute_challenges(fr_t *out, fr_t *r_powers,
|
||||
const Polynomial *polys, const g1_t *comms, uint64_t n) {
|
||||
size_t i;
|
||||
uint64_t j;
|
||||
const size_t ni = 32; // len(FIAT_SHAMIR_PROTOCOL_DOMAIN) + 8 + 8
|
||||
|
@ -1233,7 +1246,7 @@ static C_KZG_RET compute_challenges(BLSFieldElement *out, BLSFieldElement r_powe
|
|||
hash(r_bytes, hash_input, 33);
|
||||
|
||||
/* Compute r_powers */
|
||||
BLSFieldElement r;
|
||||
fr_t r;
|
||||
hash_to_bls_field(&r, r_bytes);
|
||||
compute_powers(r_powers, &r, n);
|
||||
|
||||
|
@ -1247,11 +1260,11 @@ static C_KZG_RET compute_challenges(BLSFieldElement *out, BLSFieldElement r_powe
|
|||
return C_KZG_OK;
|
||||
}
|
||||
|
||||
static C_KZG_RET compute_aggregated_poly_and_commitment(Polynomial *poly_out, KZGCommitment *comm_out, BLSFieldElement *chal_out,
|
||||
static C_KZG_RET compute_aggregated_poly_and_commitment(Polynomial *poly_out, g1_t *comm_out, fr_t *chal_out,
|
||||
const Polynomial *polys,
|
||||
const KZGCommitment *kzg_commitments,
|
||||
const g1_t *kzg_commitments,
|
||||
size_t n) {
|
||||
BLSFieldElement* r_powers = calloc(n, sizeof(BLSFieldElement));
|
||||
fr_t* r_powers = calloc(n, sizeof(fr_t));
|
||||
if (0 < n && r_powers == NULL) return C_KZG_MALLOC;
|
||||
|
||||
C_KZG_RET ret;
|
||||
|
@ -1273,9 +1286,9 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out,
|
|||
const KZGSettings *s) {
|
||||
C_KZG_RET ret;
|
||||
Polynomial* polys = NULL;
|
||||
KZGCommitment* commitments = NULL;
|
||||
g1_t* commitments = NULL;
|
||||
|
||||
commitments = calloc(n, sizeof(KZGCommitment));
|
||||
commitments = calloc(n, sizeof(g1_t));
|
||||
if (0 < n && commitments == NULL) {
|
||||
ret = C_KZG_MALLOC;
|
||||
goto out;
|
||||
|
@ -1295,12 +1308,15 @@ C_KZG_RET compute_aggregate_kzg_proof(KZGProof *out,
|
|||
}
|
||||
|
||||
Polynomial aggregated_poly;
|
||||
KZGCommitment aggregated_poly_commitment;
|
||||
BLSFieldElement evaluation_challenge;
|
||||
g1_t aggregated_poly_commitment;
|
||||
fr_t evaluation_challenge;
|
||||
ret = compute_aggregated_poly_and_commitment(&aggregated_poly, &aggregated_poly_commitment, &evaluation_challenge, polys, commitments, n);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
ret = compute_kzg_proof(out, &aggregated_poly, &evaluation_challenge, s);
|
||||
g1_t proof;
|
||||
ret = compute_kzg_proof(&proof, &aggregated_poly, &evaluation_challenge, s);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
bytes_from_g1((uint8_t *)(out), &proof);
|
||||
|
||||
out:
|
||||
if (commitments != NULL) free(commitments);
|
||||
|
@ -1315,26 +1331,46 @@ C_KZG_RET verify_aggregate_kzg_proof(bool *out,
|
|||
const KZGProof *kzg_aggregated_proof,
|
||||
const KZGSettings *s) {
|
||||
C_KZG_RET ret;
|
||||
Polynomial* polys = calloc(n, sizeof(Polynomial));
|
||||
if (polys == NULL) return C_KZG_MALLOC;
|
||||
g1_t* commitments = NULL;
|
||||
Polynomial* polys = NULL;
|
||||
|
||||
g1_t proof;
|
||||
ret = bytes_to_g1(&proof, (uint8_t *)(kzg_aggregated_proof));
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
commitments = calloc(n, sizeof(g1_t));
|
||||
if (0 < n && commitments == NULL) {
|
||||
ret = C_KZG_MALLOC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
polys = calloc(n, sizeof(Polynomial));
|
||||
if (0 < n && polys == NULL) {
|
||||
ret = C_KZG_MALLOC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
ret = bytes_to_g1(&commitments[i], (uint8_t *)(&expected_kzg_commitments[i]));
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
ret = poly_from_blob(&polys[i], &blobs[i]);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
}
|
||||
|
||||
Polynomial aggregated_poly;
|
||||
KZGCommitment aggregated_poly_commitment;
|
||||
BLSFieldElement evaluation_challenge;
|
||||
ret = compute_aggregated_poly_and_commitment(&aggregated_poly, &aggregated_poly_commitment, &evaluation_challenge, polys, expected_kzg_commitments, n);
|
||||
g1_t aggregated_poly_commitment;
|
||||
fr_t evaluation_challenge;
|
||||
ret = compute_aggregated_poly_and_commitment(&aggregated_poly, &aggregated_poly_commitment, &evaluation_challenge, polys, commitments, n);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
BLSFieldElement y;
|
||||
fr_t y;
|
||||
ret = evaluate_polynomial_in_evaluation_form(&y, &aggregated_poly, &evaluation_challenge, s);
|
||||
if (ret != C_KZG_OK) goto out;
|
||||
|
||||
ret = verify_kzg_proof_impl(out, &aggregated_poly_commitment, &evaluation_challenge, &y, kzg_aggregated_proof, s);
|
||||
ret = verify_kzg_proof_impl(out, &aggregated_poly_commitment, &evaluation_challenge, &y, &proof, s);
|
||||
|
||||
out:
|
||||
if (commitments != NULL) free(commitments);
|
||||
if (polys != NULL) free(polys);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -37,16 +37,16 @@ extern "C" {
|
|||
#define BYTES_PER_COMMITMENT 48
|
||||
#define BYTES_PER_PROOF 48
|
||||
#define BYTES_PER_FIELD_ELEMENT 32
|
||||
#define BYTES_PER_BLOB FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT
|
||||
#define BYTES_PER_BLOB (FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT)
|
||||
static const char *FIAT_SHAMIR_PROTOCOL_DOMAIN = "FSBLOBVERIFY_V1_";
|
||||
|
||||
typedef blst_p1 g1_t; /**< Internal G1 group element type */
|
||||
typedef blst_p2 g2_t; /**< Internal G2 group element type */
|
||||
typedef blst_fr fr_t; /**< Internal Fr field element type */
|
||||
|
||||
typedef g1_t KZGCommitment;
|
||||
typedef g1_t KZGProof;
|
||||
typedef fr_t BLSFieldElement;
|
||||
typedef struct { uint8_t bytes[BYTES_PER_COMMITMENT]; } KZGCommitment;
|
||||
typedef struct { uint8_t bytes[BYTES_PER_PROOF]; } KZGProof;
|
||||
typedef struct { uint8_t bytes[BYTES_PER_FIELD_ELEMENT]; } BLSFieldElement;
|
||||
typedef struct { uint8_t bytes[BYTES_PER_BLOB]; } Blob;
|
||||
|
||||
/**
|
||||
|
@ -82,15 +82,10 @@ typedef struct {
|
|||
* Interface functions
|
||||
*/
|
||||
|
||||
C_KZG_RET bytes_to_g1(g1_t* out, const uint8_t in[48]);
|
||||
void bytes_from_g1(uint8_t out[48], const g1_t *in);
|
||||
|
||||
C_KZG_RET bytes_to_bls_field(BLSFieldElement *out, const uint8_t in[BYTES_PER_FIELD_ELEMENT]);
|
||||
|
||||
C_KZG_RET load_trusted_setup(KZGSettings *out,
|
||||
const uint8_t g1_bytes[], /* n1 * 48 bytes */
|
||||
const uint8_t *g1_bytes, /* n1 * 48 bytes */
|
||||
size_t n1,
|
||||
const uint8_t g2_bytes[], /* n2 * 96 bytes */
|
||||
const uint8_t *g2_bytes, /* n2 * 96 bytes */
|
||||
size_t n2);
|
||||
|
||||
C_KZG_RET load_trusted_setup_file(KZGSettings *out,
|
||||
|
@ -117,8 +112,8 @@ C_KZG_RET blob_to_kzg_commitment(KZGCommitment *out,
|
|||
|
||||
C_KZG_RET verify_kzg_proof(bool *out,
|
||||
const KZGCommitment *polynomial_kzg,
|
||||
const uint8_t z[BYTES_PER_FIELD_ELEMENT],
|
||||
const uint8_t y[BYTES_PER_FIELD_ELEMENT],
|
||||
const BLSFieldElement *z,
|
||||
const BLSFieldElement *y,
|
||||
const KZGProof *kzg_proof,
|
||||
const KZGSettings *s);
|
||||
|
||||
|
|
Loading…
Reference in New Issue