[Java binding] Load trusted setup from params + custom exception
This commit is contained in:
parent
17626f0fd7
commit
46d64e231a
|
@ -3,9 +3,6 @@
|
||||||
#include "c_kzg_4844_jni.h"
|
#include "c_kzg_4844_jni.h"
|
||||||
#include "c_kzg_4844.h"
|
#include "c_kzg_4844.h"
|
||||||
|
|
||||||
static const char *C_KZG_RETURN_TYPES[] = {
|
|
||||||
"C_KZG_OK", "C_KZG_BADARGS", "C_KZG_ERROR", "C_KZG_MALLOC"};
|
|
||||||
|
|
||||||
static const char *TRUSTED_SETUP_NOT_LOADED = "Trusted Setup is not loaded.";
|
static const char *TRUSTED_SETUP_NOT_LOADED = "Trusted Setup is not loaded.";
|
||||||
|
|
||||||
KZGSettings *settings;
|
KZGSettings *settings;
|
||||||
|
@ -18,8 +15,17 @@ void reset_trusted_setup()
|
||||||
|
|
||||||
void throw_exception(JNIEnv *env, const char *message)
|
void throw_exception(JNIEnv *env, const char *message)
|
||||||
{
|
{
|
||||||
jclass Exception = (*env)->FindClass(env, "java/lang/RuntimeException");
|
jclass exception_class = (*env)->FindClass(env, "java/lang/RuntimeException");
|
||||||
(*env)->ThrowNew(env, Exception, message);
|
(*env)->ThrowNew(env, exception_class, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void throw_c_kzg_exception(JNIEnv *env, C_KZG_RET error_code, const char *message)
|
||||||
|
{
|
||||||
|
jclass exception_class = (*env)->FindClass(env, "ethereum/ckzg4844/CKZGException");
|
||||||
|
jstring error_message = (*env)->NewStringUTF(env, message);
|
||||||
|
jmethodID exception_init = (*env)->GetMethodID(env, exception_class, "<init>", "(ILjava/lang/String;)V");
|
||||||
|
jobject exception = (*env)->NewObject(env, exception_class, exception_init, error_code, error_message);
|
||||||
|
(*env)->Throw(env, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_getFieldElementsPerBlob(JNIEnv *env, jclass thisCls)
|
JNIEXPORT jint JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_getFieldElementsPerBlob(JNIEnv *env, jclass thisCls)
|
||||||
|
@ -27,7 +33,7 @@ JNIEXPORT jint JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_getFieldElementsPerBlo
|
||||||
return (jint)FIELD_ELEMENTS_PER_BLOB;
|
return (jint)FIELD_ELEMENTS_PER_BLOB;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup(JNIEnv *env, jclass thisCls, jstring file)
|
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup__Ljava_lang_String_2(JNIEnv *env, jclass thisCls, jstring file)
|
||||||
{
|
{
|
||||||
if (settings != NULL)
|
if (settings != NULL)
|
||||||
{
|
{
|
||||||
|
@ -55,9 +61,7 @@ JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup(JNIEn
|
||||||
reset_trusted_setup();
|
reset_trusted_setup();
|
||||||
(*env)->ReleaseStringUTFChars(env, file, file_native);
|
(*env)->ReleaseStringUTFChars(env, file, file_native);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while loading the Trusted Setup.");
|
||||||
sprintf(arr, "There was an error while loading the Trusted Setup: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +70,28 @@ JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup(JNIEn
|
||||||
(*env)->ReleaseStringUTFChars(env, file, file_native);
|
(*env)->ReleaseStringUTFChars(env, file, file_native);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup___3BJ_3BJ(JNIEnv *env, jclass thisCls, jbyteArray g1, jlong g1Count, jbyteArray g2, jlong g2Count)
|
||||||
|
{
|
||||||
|
if (settings != NULL)
|
||||||
|
{
|
||||||
|
throw_exception(env, "Trusted Setup is already loaded. Free it before loading a new one.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
settings = malloc(sizeof(KZGSettings));
|
||||||
|
|
||||||
|
uint8_t *g1_native = (uint8_t *)(*env)->GetByteArrayElements(env, g1, NULL);
|
||||||
|
uint8_t *g2_native = (uint8_t *)(*env)->GetByteArrayElements(env, g2, NULL);
|
||||||
|
|
||||||
|
C_KZG_RET ret = load_trusted_setup(settings, g1_native, (size_t)g1Count, g2_native, (size_t)g2Count);
|
||||||
|
|
||||||
|
if (ret != C_KZG_OK)
|
||||||
|
{
|
||||||
|
reset_trusted_setup();
|
||||||
|
throw_c_kzg_exception(env, ret, "There was an error while loading the Trusted Setup.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_freeTrustedSetup(JNIEnv *env, jclass thisCls)
|
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_freeTrustedSetup(JNIEnv *env, jclass thisCls)
|
||||||
{
|
{
|
||||||
if (settings == NULL)
|
if (settings == NULL)
|
||||||
|
@ -85,6 +111,13 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeAggregate
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t blobs_size = (size_t)(*env)->GetArrayLength(env, blobs);
|
||||||
|
if (blobs_size == 0)
|
||||||
|
{
|
||||||
|
throw_exception(env, "Passing byte array with 0 elements for blobs is not supported.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL);
|
jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL);
|
||||||
|
|
||||||
KZGProof p;
|
KZGProof p;
|
||||||
|
@ -93,9 +126,7 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeAggregate
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while computing aggregate kzg proof.");
|
||||||
sprintf(arr, "There was an error while computing aggregate kzg proof: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +158,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg
|
||||||
jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL);
|
jbyte *blobs_native = (*env)->GetByteArrayElements(env, blobs, NULL);
|
||||||
uint8_t *commitments_native = (uint8_t *)(*env)->GetByteArrayElements(env, commitments, NULL);
|
uint8_t *commitments_native = (uint8_t *)(*env)->GetByteArrayElements(env, commitments, NULL);
|
||||||
uint8_t *proof_native = (uint8_t *)(*env)->GetByteArrayElements(env, proof, NULL);
|
uint8_t *proof_native = (uint8_t *)(*env)->GetByteArrayElements(env, proof, NULL);
|
||||||
size_t native_count = (size_t)count;
|
size_t count_native = (size_t)count;
|
||||||
|
|
||||||
KZGProof f;
|
KZGProof f;
|
||||||
|
|
||||||
|
@ -137,36 +168,32 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyAggregateKzg
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while converting proof to g1.");
|
||||||
sprintf(arr, "There was an error while converting proof bytes to g1: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
KZGCommitment *c = calloc(native_count, sizeof(KZGCommitment));
|
KZGCommitment *c = calloc(count_native, sizeof(KZGCommitment));
|
||||||
|
|
||||||
for (size_t i = 0; i < native_count; i++)
|
for (size_t i = 0; i < count_native; i++)
|
||||||
{
|
{
|
||||||
ret = bytes_to_g1(&c[i], &commitments_native[i * BYTES_PER_COMMITMENT]);
|
ret = bytes_to_g1(&c[i], &commitments_native[i * BYTES_PER_COMMITMENT]);
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
free(c);
|
free(c);
|
||||||
char arr[100];
|
char arr[100];
|
||||||
sprintf(arr, "There was an error while converting commitment (%zu/%zu) bytes to g1: %s", i + 1, native_count, C_KZG_RETURN_TYPES[ret]);
|
sprintf(arr, "There was an error while converting commitment (%zu/%zu) to g1.", i + 1, count_native);
|
||||||
throw_exception(env, arr);
|
throw_c_kzg_exception(env, ret, arr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool out;
|
bool out;
|
||||||
ret = verify_aggregate_kzg_proof(&out, (uint8_t const(*)[BYTES_PER_BLOB])blobs_native, c, native_count, &f, settings);
|
ret = verify_aggregate_kzg_proof(&out, (uint8_t const(*)[BYTES_PER_BLOB])blobs_native, c, count_native, &f, settings);
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
free(c);
|
free(c);
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while verifying aggregate kzg proof.");
|
||||||
sprintf(arr, "There was an error while verifying aggregate kzg proof: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,10 +226,8 @@ JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_blobToKzgCommitm
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while converting blob to commitment.");
|
||||||
sprintf(arr, "There was an error while converting blob bytes to a commitment: %s", C_KZG_RETURN_TYPES[ret]);
|
return NULL;
|
||||||
throw_exception(env, arr);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jbyteArray commitment = (*env)->NewByteArray(env, BYTES_PER_COMMITMENT);
|
jbyteArray commitment = (*env)->NewByteArray(env, BYTES_PER_COMMITMENT);
|
||||||
|
@ -238,9 +263,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while converting commitment to g1.");
|
||||||
sprintf(arr, "There was an error while converting commitment bytes to g1: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,9 +271,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while converting proof to g1.");
|
||||||
sprintf(arr, "There was an error while converting proof bytes to g1: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,9 +279,7 @@ JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNI
|
||||||
|
|
||||||
if (ret != C_KZG_OK)
|
if (ret != C_KZG_OK)
|
||||||
{
|
{
|
||||||
char arr[100];
|
throw_c_kzg_exception(env, ret, "There was an error while verifying kzg proof.");
|
||||||
sprintf(arr, "There was an error while verifying kzg proof: %s", C_KZG_RETURN_TYPES[ret]);
|
|
||||||
throw_exception(env, arr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,14 @@ extern "C"
|
||||||
* Method: loadTrustedSetup
|
* Method: loadTrustedSetup
|
||||||
* Signature: (Ljava/lang/String;)V
|
* Signature: (Ljava/lang/String;)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup(JNIEnv *, jclass, jstring);
|
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup__Ljava_lang_String_2(JNIEnv *, jclass, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: ethereum_ckzg4844_CKZG4844JNI
|
||||||
|
* Method: loadTrustedSetup
|
||||||
|
* Signature: ([BJ[BJ)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup___3BJ_3BJ(JNIEnv *, jclass, jbyteArray, jlong, jbyteArray, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: ethereum_ckzg4844_CKZG4844JNI
|
* Class: ethereum_ckzg4844_CKZG4844JNI
|
||||||
|
|
|
@ -87,12 +87,26 @@ public class CKZG4844JNI {
|
||||||
* Loads the trusted setup from a file. Once loaded, the same setup will be used for all the
|
* Loads the trusted setup from a file. Once loaded, the same setup will be used for all the
|
||||||
* crypto native calls. To load a new setup, free the current one by calling
|
* crypto native calls. To load a new setup, free the current one by calling
|
||||||
* {@link #freeTrustedSetup()} and then load the new one. If no trusted setup has been loaded, all
|
* {@link #freeTrustedSetup()} and then load the new one. If no trusted setup has been loaded, all
|
||||||
* the crypto native calls will throw an exception.
|
* the crypto native calls will throw a {@link RuntimeException}.
|
||||||
*
|
*
|
||||||
* @param file a path to a trusted setup file
|
* @param file a path to a trusted setup file
|
||||||
|
* @throws CKZGException if there is a crypto error
|
||||||
*/
|
*/
|
||||||
public static native void loadTrustedSetup(String file);
|
public static native void loadTrustedSetup(String file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative to {@link #loadTrustedSetup(String)}. Loads the trusted setup from method
|
||||||
|
* parameters instead of a file.
|
||||||
|
*
|
||||||
|
* @param g1 g1 values as bytes
|
||||||
|
* @param g1Count the count of the g1 values
|
||||||
|
* @param g2 g2 values as bytes
|
||||||
|
* @param g2Count the count of the g2 values
|
||||||
|
* @throws CKZGException if there is a crypto error
|
||||||
|
*/
|
||||||
|
public static native void loadTrustedSetup(byte[] g1, long g1Count, byte[] g2,
|
||||||
|
long g2Count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free the current trusted setup. This method will throw an exception if no trusted setup has
|
* Free the current trusted setup. This method will throw an exception if no trusted setup has
|
||||||
* been loaded.
|
* been loaded.
|
||||||
|
@ -105,6 +119,7 @@ public class CKZG4844JNI {
|
||||||
* @param blobs blobs as flattened bytes
|
* @param blobs blobs as flattened bytes
|
||||||
* @param count the count of the blobs
|
* @param count the count of the blobs
|
||||||
* @return the aggregated proof
|
* @return the aggregated proof
|
||||||
|
* @throws CKZGException if there is a crypto error
|
||||||
*/
|
*/
|
||||||
public static native byte[] computeAggregateKzgProof(byte[] blobs, long count);
|
public static native byte[] computeAggregateKzgProof(byte[] blobs, long count);
|
||||||
|
|
||||||
|
@ -116,6 +131,7 @@ public class CKZG4844JNI {
|
||||||
* @param count the count of the blobs (should be same as the count of the commitments)
|
* @param count the count of the blobs (should be same as the count of the commitments)
|
||||||
* @param proof the proof that needs verifying
|
* @param proof the proof that needs verifying
|
||||||
* @return true if the proof is valid and false otherwise
|
* @return true if the proof is valid and false otherwise
|
||||||
|
* @throws CKZGException if there is a crypto error
|
||||||
*/
|
*/
|
||||||
public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commitments, long count,
|
public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commitments, long count,
|
||||||
byte[] proof);
|
byte[] proof);
|
||||||
|
@ -125,6 +141,7 @@ public class CKZG4844JNI {
|
||||||
*
|
*
|
||||||
* @param blob blob bytes
|
* @param blob blob bytes
|
||||||
* @return the commitment
|
* @return the commitment
|
||||||
|
* @throws CKZGException if there is a crypto error
|
||||||
*/
|
*/
|
||||||
public static native byte[] blobToKzgCommitment(byte[] blob);
|
public static native byte[] blobToKzgCommitment(byte[] blob);
|
||||||
|
|
||||||
|
@ -136,6 +153,7 @@ public class CKZG4844JNI {
|
||||||
* @param y Y
|
* @param y Y
|
||||||
* @param proof the proof that needs verifying
|
* @param proof the proof that needs verifying
|
||||||
* @return true if the proof is valid and false otherwise
|
* @return true if the proof is valid and false otherwise
|
||||||
|
* @throws CKZGException if there is a crypto error
|
||||||
*/
|
*/
|
||||||
public static native boolean verifyKzgProof(byte[] commitment, byte[] z, byte[] y, byte[] proof);
|
public static native boolean verifyKzgProof(byte[] commitment, byte[] z, byte[] y, byte[] proof);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package ethereum.ckzg4844;
|
||||||
|
|
||||||
|
import static ethereum.ckzg4844.CKZGException.CKZGError.fromErrorCode;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when there is an error in the underlying c-kzg library.
|
||||||
|
*/
|
||||||
|
public class CKZGException extends RuntimeException {
|
||||||
|
|
||||||
|
private final CKZGError error;
|
||||||
|
private final String errorMessage;
|
||||||
|
|
||||||
|
public CKZGException(int errorCode, String errorMessage) {
|
||||||
|
super(String.format("%s (%s)", errorMessage, fromErrorCode(errorCode)));
|
||||||
|
this.error = fromErrorCode(errorCode);
|
||||||
|
this.errorMessage = errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CKZGError getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CKZGError {
|
||||||
|
|
||||||
|
UNKNOWN(0), C_KZG_BADARGS(1), C_KZG_ERROR(2), C_KZG_MALLOC(3);
|
||||||
|
|
||||||
|
public final int errorCode;
|
||||||
|
|
||||||
|
CKZGError(int errorCode) {
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CKZGError fromErrorCode(int errorCode) {
|
||||||
|
return Arrays.stream(CKZGError.values()).filter(error -> error.errorCode == errorCode)
|
||||||
|
.findFirst().orElse(UNKNOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,17 +6,23 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import ethereum.ckzg4844.CKZG4844JNI.Preset;
|
import ethereum.ckzg4844.CKZG4844JNI.Preset;
|
||||||
|
import ethereum.ckzg4844.CKZGException.CKZGError;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
public class CKZG4844JNITest {
|
public class CKZG4844JNITest {
|
||||||
|
|
||||||
private static final Preset PRESET;
|
private static final Preset PRESET;
|
||||||
|
|
||||||
|
private static final Map<Preset, String> TRUSTED_SETUP_FILE_BY_PRESET = Map.of(Preset.MAINNET,
|
||||||
|
"../../src/trusted_setup.txt", Preset.MINIMAL, "../../src/trusted_setup_4.txt");
|
||||||
|
|
||||||
static {
|
static {
|
||||||
PRESET = Optional.ofNullable(System.getenv("PRESET")).map(String::toUpperCase)
|
PRESET = Optional.ofNullable(System.getenv("PRESET")).map(String::toUpperCase)
|
||||||
.map(Preset::valueOf).orElse(Preset.MAINNET);
|
.map(Preset::valueOf).orElse(Preset.MAINNET);
|
||||||
|
@ -30,10 +36,11 @@ public class CKZG4844JNITest {
|
||||||
CKZG4844JNI.getBytesPerBlob());
|
CKZG4844JNI.getBytesPerBlob());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void computesAndVerifiesProofs() {
|
@ValueSource(booleans = {true, false})
|
||||||
|
public void computesAndVerifiesProofs(final boolean useTrustedSetupFile) {
|
||||||
|
|
||||||
loadTrustedSetup();
|
loadTrustedSetup(useTrustedSetupFile);
|
||||||
|
|
||||||
final int count = 3;
|
final int count = 3;
|
||||||
|
|
||||||
|
@ -75,6 +82,23 @@ public class CKZG4844JNITest {
|
||||||
parameters.getProof()));
|
parameters.getProof()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkCustomExceptionIsThrownAsExpected() {
|
||||||
|
|
||||||
|
loadTrustedSetup();
|
||||||
|
|
||||||
|
final byte[] blob = TestUtils.createNonCanonicalBlob();
|
||||||
|
|
||||||
|
final CKZGException exception = assertThrows(CKZGException.class,
|
||||||
|
() -> CKZG4844JNI.blobToKzgCommitment(blob));
|
||||||
|
|
||||||
|
assertEquals(CKZGError.C_KZG_BADARGS, exception.getError());
|
||||||
|
assertEquals("There was an error while converting blob to commitment.",
|
||||||
|
exception.getErrorMessage());
|
||||||
|
|
||||||
|
CKZG4844JNI.freeTrustedSetup();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void passingZeroElementArraysForBlobsDoesNotCauseSegmentationFaultErrors() {
|
public void passingZeroElementArraysForBlobsDoesNotCauseSegmentationFaultErrors() {
|
||||||
|
|
||||||
|
@ -86,10 +110,15 @@ public class CKZG4844JNITest {
|
||||||
assertEquals("Passing byte array with 0 elements for a blob is not supported.",
|
assertEquals("Passing byte array with 0 elements for a blob is not supported.",
|
||||||
exception.getMessage());
|
exception.getMessage());
|
||||||
|
|
||||||
|
exception = assertThrows(RuntimeException.class,
|
||||||
|
() -> CKZG4844JNI.computeAggregateKzgProof(new byte[0], 1));
|
||||||
|
|
||||||
|
assertEquals("Passing byte array with 0 elements for blobs is not supported.",
|
||||||
|
exception.getMessage());
|
||||||
|
|
||||||
exception = assertThrows(RuntimeException.class,
|
exception = assertThrows(RuntimeException.class,
|
||||||
() -> CKZG4844JNI.verifyAggregateKzgProof(new byte[0], TestUtils.createRandomCommitment(),
|
() -> CKZG4844JNI.verifyAggregateKzgProof(new byte[0], TestUtils.createRandomCommitment(),
|
||||||
1,
|
1, TestUtils.createRandomProof(1)));
|
||||||
TestUtils.createRandomProof(1)));
|
|
||||||
|
|
||||||
assertEquals("Passing byte array with 0 elements for blobs is not supported.",
|
assertEquals("Passing byte array with 0 elements for blobs is not supported.",
|
||||||
exception.getMessage());
|
exception.getMessage());
|
||||||
|
@ -136,17 +165,23 @@ public class CKZG4844JNITest {
|
||||||
assertEquals("Trusted Setup is not loaded.", exception.getMessage());
|
assertEquals("Trusted Setup is not loaded.", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadTrustedSetup() {
|
private static void loadTrustedSetup(final boolean useFile) {
|
||||||
if (PRESET.equals(Preset.MINIMAL)) {
|
if (useFile) {
|
||||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup_4.txt");
|
loadTrustedSetup();
|
||||||
} else {
|
} else {
|
||||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup.txt");
|
final LoadTrustedSetupParameters parameters = TestUtils.createLoadTrustedSetupParameters(
|
||||||
|
TRUSTED_SETUP_FILE_BY_PRESET.get(PRESET));
|
||||||
|
CKZG4844JNI.loadTrustedSetup(parameters.getG1(), parameters.getG1Count(), parameters.getG2(),
|
||||||
|
parameters.getG2Count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void loadTrustedSetup() {
|
||||||
|
CKZG4844JNI.loadTrustedSetup(TRUSTED_SETUP_FILE_BY_PRESET.get(PRESET));
|
||||||
|
}
|
||||||
|
|
||||||
private static Stream<VerifyKzgProofParameters> getVerifyKzgProofTestVectors() {
|
private static Stream<VerifyKzgProofParameters> getVerifyKzgProofTestVectors() {
|
||||||
loadTrustedSetup();
|
loadTrustedSetup();
|
||||||
return TestUtils.getVerifyKzgProofTestVectors().stream()
|
return TestUtils.getVerifyKzgProofTestVectors().stream().onClose(CKZG4844JNI::freeTrustedSetup);
|
||||||
.onClose(CKZG4844JNI::freeTrustedSetup);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ethereum.ckzg4844;
|
||||||
|
|
||||||
|
public class LoadTrustedSetupParameters {
|
||||||
|
|
||||||
|
private final byte[] g1;
|
||||||
|
private final long g1Count;
|
||||||
|
private final byte[] g2;
|
||||||
|
private final long g2Count;
|
||||||
|
|
||||||
|
public LoadTrustedSetupParameters(final byte[] g1, final long g1Count, final byte[] g2,
|
||||||
|
final long g2Count) {
|
||||||
|
this.g1 = g1;
|
||||||
|
this.g1Count = g1Count;
|
||||||
|
this.g2 = g2;
|
||||||
|
this.g2Count = g2Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getG1() {
|
||||||
|
return g1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getG1Count() {
|
||||||
|
return g1Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getG2() {
|
||||||
|
return g2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getG2Count() {
|
||||||
|
return g2Count;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,8 @@ package ethereum.ckzg4844;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
|
@ -35,8 +37,7 @@ public class TestUtils {
|
||||||
public static byte[] createRandomBlob() {
|
public static byte[] createRandomBlob() {
|
||||||
final byte[][] blob = IntStream.range(0, CKZG4844JNI.getFieldElementsPerBlob())
|
final byte[][] blob = IntStream.range(0, CKZG4844JNI.getFieldElementsPerBlob())
|
||||||
.mapToObj(__ -> randomBLSFieldElement())
|
.mapToObj(__ -> randomBLSFieldElement())
|
||||||
.map(fieldElement -> fieldElement.toArray(ByteOrder.LITTLE_ENDIAN))
|
.map(fieldElement -> fieldElement.toArray(ByteOrder.LITTLE_ENDIAN)).toArray(byte[][]::new);
|
||||||
.toArray(byte[][]::new);
|
|
||||||
return flatten(blob);
|
return flatten(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +61,14 @@ public class TestUtils {
|
||||||
return flatten(commitments);
|
return flatten(commitments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] createNonCanonicalBlob() {
|
||||||
|
final byte[][] blob = IntStream.range(0, CKZG4844JNI.getFieldElementsPerBlob())
|
||||||
|
.mapToObj(__ -> UInt256.valueOf(CKZG4844JNI.BLS_MODULUS.add(BigInteger.valueOf(42))))
|
||||||
|
.map(greaterThanModulus -> greaterThanModulus.toArray(ByteOrder.LITTLE_ENDIAN))
|
||||||
|
.toArray(byte[][]::new);
|
||||||
|
return flatten(blob);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated using <a
|
* Generated using <a
|
||||||
* href="https://github.com/crate-crypto/proto-danksharding-fuzzy-test/">proto-danksharding-fuzzy-test</a>
|
* href="https://github.com/crate-crypto/proto-danksharding-fuzzy-test/">proto-danksharding-fuzzy-test</a>
|
||||||
|
@ -74,23 +83,42 @@ public class TestUtils {
|
||||||
final ArrayNode testCases = (ArrayNode) jsonNode.get("TestCases");
|
final ArrayNode testCases = (ArrayNode) jsonNode.get("TestCases");
|
||||||
final Stream.Builder<VerifyKzgProofParameters> testVectors = Stream.builder();
|
final Stream.Builder<VerifyKzgProofParameters> testVectors = Stream.builder();
|
||||||
testVectors.add(VerifyKzgProofParameters.ZERO);
|
testVectors.add(VerifyKzgProofParameters.ZERO);
|
||||||
IntStream.range(0,
|
IntStream.range(0, jsonNode.get("NumTestCases").asInt()).mapToObj(i -> {
|
||||||
jsonNode.get("NumTestCases").asInt())
|
final JsonNode testCase = testCases.get(i);
|
||||||
.mapToObj(i -> {
|
final Bytes32 z = Bytes32.fromHexString(testCase.get("InputPoint").asText());
|
||||||
final JsonNode testCase = testCases.get(i);
|
final Bytes32 y = Bytes32.fromHexString(testCase.get("ClaimedValue").asText());
|
||||||
final Bytes32 z = Bytes32.fromHexString(testCase.get("InputPoint").asText());
|
final Bytes commitment = Bytes.fromHexString(testCase.get("Commitment").asText(),
|
||||||
final Bytes32 y = Bytes32.fromHexString(testCase.get("ClaimedValue").asText());
|
CKZG4844JNI.BYTES_PER_COMMITMENT);
|
||||||
final Bytes commitment = Bytes.fromHexString(testCase.get("Commitment").asText(),
|
final Bytes proof = Bytes.fromHexString(testCase.get("Proof").asText(),
|
||||||
CKZG4844JNI.BYTES_PER_COMMITMENT);
|
CKZG4844JNI.BYTES_PER_PROOF);
|
||||||
final Bytes proof = Bytes.fromHexString(testCase.get("Proof").asText(),
|
return new VerifyKzgProofParameters(commitment.toArray(), z.toArray(), y.toArray(),
|
||||||
CKZG4844JNI.BYTES_PER_PROOF);
|
proof.toArray());
|
||||||
return new VerifyKzgProofParameters(commitment.toArray(), z.toArray(), y.toArray(),
|
}).forEach(testVectors::add);
|
||||||
proof.toArray());
|
|
||||||
})
|
|
||||||
.forEach(testVectors::add);
|
|
||||||
return testVectors.build().collect(Collectors.toList());
|
return testVectors.build().collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LoadTrustedSetupParameters createLoadTrustedSetupParameters(
|
||||||
|
final String trustedSetup) {
|
||||||
|
try (final BufferedReader reader = new BufferedReader(new FileReader(trustedSetup))) {
|
||||||
|
final int g1Count = Integer.parseInt(reader.readLine());
|
||||||
|
final int g2Count = Integer.parseInt(reader.readLine());
|
||||||
|
|
||||||
|
final ByteBuffer g1 = ByteBuffer.allocate(g1Count * 48);
|
||||||
|
final ByteBuffer g2 = ByteBuffer.allocate(g2Count * 96);
|
||||||
|
|
||||||
|
for (int i = 0; i < g1Count; i++) {
|
||||||
|
g1.put(Bytes.fromHexString(reader.readLine()).toArray());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < g2Count; i++) {
|
||||||
|
g2.put(Bytes.fromHexString(reader.readLine()).toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LoadTrustedSetupParameters(g1.array(), g1Count, g2.array(), g2Count);
|
||||||
|
} catch (final IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static UInt256 randomBLSFieldElement() {
|
private static UInt256 randomBLSFieldElement() {
|
||||||
final BigInteger attempt = new BigInteger(CKZG4844JNI.BLS_MODULUS.bitLength(), RANDOM);
|
final BigInteger attempt = new BigInteger(CKZG4844JNI.BLS_MODULUS.bitLength(), RANDOM);
|
||||||
if (attempt.compareTo(CKZG4844JNI.BLS_MODULUS) < 0) {
|
if (attempt.compareTo(CKZG4844JNI.BLS_MODULUS) < 0) {
|
||||||
|
|
Loading…
Reference in New Issue