-
Notifications
You must be signed in to change notification settings - Fork 131
/
Copy pathc_kzg_4844_jni.c
377 lines (304 loc) · 12.3 KB
/
c_kzg_4844_jni.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
#include <stdio.h>
#include <stdlib.h>
#include "c_kzg_4844_jni.h"
#include "c_kzg_4844.h"
static const char *TRUSTED_SETUP_NOT_LOADED = "Trusted Setup is not loaded.";
KZGSettings *settings;
void reset_trusted_setup()
{
if (settings)
{
if (settings->fs)
{
free_trusted_setup(settings);
}
free(settings);
settings = NULL;
}
}
void throw_exception(JNIEnv *env, const char *message)
{
jclass exception_class = (*env)->FindClass(env, "java/lang/RuntimeException");
(*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);
}
void throw_invalid_size_exception(JNIEnv *env, const char *prefix, size_t size, size_t expected_size)
{
char message[100];
sprintf(message, "%s Expected %zu bytes but got %zu.", prefix, expected_size, size);
throw_c_kzg_exception(env, C_KZG_BADARGS, message);
}
KZGSettings *allocate_settings(JNIEnv *env)
{
KZGSettings *s = malloc(sizeof(KZGSettings));
if (s == NULL)
{
throw_exception(env, "Failed to allocate memory for the Trusted Setup.");
}
else
{
s->fs = NULL;
s->g1_values = NULL;
s->g2_values = NULL;
}
return s;
}
JNIEXPORT jint JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_getFieldElementsPerBlob(JNIEnv *env, jclass thisCls)
{
return (jint)FIELD_ELEMENTS_PER_BLOB;
}
JNIEXPORT void JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_loadTrustedSetup__Ljava_lang_String_2(JNIEnv *env, jclass thisCls, jstring file)
{
if (settings)
{
throw_exception(env, "Trusted Setup is already loaded. Free it before loading a new one.");
return;
}
settings = allocate_settings(env);
const char *file_native = (*env)->GetStringUTFChars(env, file, 0);
FILE *f = fopen(file_native, "r");
if (f == NULL)
{
reset_trusted_setup();
(*env)->ReleaseStringUTFChars(env, file, file_native);
throw_exception(env, "Couldn't load Trusted Setup. File might not exist or there is a permission issue.");
return;
}
C_KZG_RET ret = load_trusted_setup_file(settings, f);
(*env)->ReleaseStringUTFChars(env, file, file_native);
fclose(f);
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_loadTrustedSetup___3BJ_3BJ(JNIEnv *env, jclass thisCls, jbyteArray g1, jlong g1Count, jbyteArray g2, jlong g2Count)
{
if (settings)
{
throw_exception(env, "Trusted Setup is already loaded. Free it before loading a new one.");
return;
}
size_t g1_bytes = (size_t)(*env)->GetArrayLength(env, g1);
size_t g1_expected_bytes = (size_t)g1Count * 48;
if (g1_bytes != g1_expected_bytes)
{
throw_invalid_size_exception(env, "Invalid g1 size.", g1_bytes, g1_expected_bytes);
return;
}
size_t g2_bytes = (size_t)(*env)->GetArrayLength(env, g2);
size_t g2_expected_bytes = (size_t)g2Count * 96;
if (g2_bytes != g2_expected_bytes)
{
throw_invalid_size_exception(env, "Invalid g2 size.", g2_bytes, g2_expected_bytes);
return;
}
settings = allocate_settings(env);
jbyte *g1_native = (*env)->GetByteArrayElements(env, g1, NULL);
jbyte *g2_native = (*env)->GetByteArrayElements(env, g2, NULL);
C_KZG_RET ret = load_trusted_setup(settings, (uint8_t *)g1_native, (size_t)g1Count, (uint8_t *)g2_native, (size_t)g2Count);
(*env)->ReleaseByteArrayElements(env, g1, g1_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, g2, g2_native, JNI_ABORT);
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)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return;
}
reset_trusted_setup();
}
JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_blobToKzgCommitment(JNIEnv *env, jclass thisCls, jbyteArray blob)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return NULL;
}
size_t blob_size = (size_t)(*env)->GetArrayLength(env, blob);
if (blob_size != BYTES_PER_BLOB)
{
throw_invalid_size_exception(env, "Invalid blob size.", blob_size, BYTES_PER_BLOB);
return NULL;
}
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);
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)
{
throw_c_kzg_exception(env, ret, "There was an error in blobToKzgCommitment.");
return NULL;
}
return commitment;
}
JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blob, jbyteArray z_bytes)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return NULL;
}
Blob *blob_native = (Blob *)(*env)->GetByteArrayElements(env, blob, NULL);
Bytes32 *z_native = (Bytes32 *)(*env)->GetByteArrayElements(env, z_bytes, NULL);
jbyteArray proof = (*env)->NewByteArray(env, BYTES_PER_PROOF);
KZGProof *proof_native = (KZGProof *)(uint8_t *)(*env)->GetByteArrayElements(env, proof, NULL);
C_KZG_RET ret = compute_kzg_proof(proof_native, blob_native, z_native, settings);
(*env)->ReleaseByteArrayElements(env, blob, (jbyte *)blob_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, 0);
if (ret != C_KZG_OK)
{
throw_c_kzg_exception(env, ret, "There was an error in computeKzgProof.");
return NULL;
}
return proof;
}
JNIEXPORT jbyteArray JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_computeBlobKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blob)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return NULL;
}
size_t blob_size = (size_t)(*env)->GetArrayLength(env, blob);
if (blob_size != BYTES_PER_BLOB)
{
throw_invalid_size_exception(env, "Invalid blob size.", blob_size, BYTES_PER_BLOB);
return NULL;
}
Blob *blob_native = (Blob *)(*env)->GetByteArrayElements(env, blob, NULL);
jbyteArray proof = (*env)->NewByteArray(env, BYTES_PER_PROOF);
KZGProof *proof_native = (KZGProof *)(uint8_t *)(*env)->GetByteArrayElements(env, proof, NULL);
C_KZG_RET ret = compute_blob_kzg_proof(proof_native, blob_native, settings);
(*env)->ReleaseByteArrayElements(env, blob, (jbyte *)blob_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, proof, (jbyte *)proof_native, 0);
if (ret != C_KZG_OK)
{
throw_c_kzg_exception(env, ret, "There was an error in computeBlobKzgProof.");
return NULL;
}
return proof;
}
JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyKzgProof(JNIEnv *env, jclass thisCls, jbyteArray commitment_bytes, jbyteArray z_bytes, jbyteArray y_bytes, jbyteArray proof_bytes)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return 0;
}
Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitment_bytes, NULL);
Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof_bytes, NULL);
Bytes32 *z_native = (Bytes32 *)(*env)->GetByteArrayElements(env, z_bytes, NULL);
Bytes32 *y_native = (Bytes32 *)(*env)->GetByteArrayElements(env, y_bytes, NULL);
bool out;
C_KZG_RET ret = verify_kzg_proof(&out, commitment_native, z_native, y_native, proof_native, settings);
(*env)->ReleaseByteArrayElements(env, commitment_bytes, (jbyte *)commitment_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, z_bytes, (jbyte *)z_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, y_bytes, (jbyte *)y_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, proof_bytes, (jbyte *)proof_native, JNI_ABORT);
if (ret != C_KZG_OK)
{
throw_c_kzg_exception(env, ret, "There was an error in verifyKzgProof.");
return 0;
}
return (jboolean)out;
}
JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyBlobKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blob, jbyteArray commitment_bytes, jbyteArray proof_bytes)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return 0;
}
size_t blob_size = (size_t)(*env)->GetArrayLength(env, blob);
if (blob_size != BYTES_PER_BLOB)
{
throw_invalid_size_exception(env, "Invalid blob size.", blob_size, BYTES_PER_BLOB);
return 0;
}
size_t commitment_bytes_size = (size_t)(*env)->GetArrayLength(env, commitment_bytes);
if (commitment_bytes_size != BYTES_PER_COMMITMENT)
{
throw_invalid_size_exception(env, "Invalid commitment size.", commitment_bytes_size, BYTES_PER_COMMITMENT);
return 0;
}
size_t proof_bytes_size = (size_t)(*env)->GetArrayLength(env, proof_bytes);
if (proof_bytes_size != BYTES_PER_COMMITMENT)
{
throw_invalid_size_exception(env, "Invalid proof size.", proof_bytes_size, BYTES_PER_PROOF);
return 0;
}
Blob *blob_native = (Blob *)(*env)->GetByteArrayElements(env, blob, NULL);
Bytes48 *commitment_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitment_bytes, NULL);
Bytes48 *proof_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proof_bytes, NULL);
bool out;
C_KZG_RET ret = verify_blob_kzg_proof(&out, blob_native, commitment_native, proof_native, settings);
(*env)->ReleaseByteArrayElements(env, blob, (jbyte *)blob_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, commitment_bytes, (jbyte *)commitment_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, proof_bytes, (jbyte *)proof_native, JNI_ABORT);
if (ret != C_KZG_OK)
{
throw_c_kzg_exception(env, ret, "There was an error in verifyBlobKzgProof.");
return 0;
}
return (jboolean)out;
}
JNIEXPORT jboolean JNICALL Java_ethereum_ckzg4844_CKZG4844JNI_verifyBlobKzgProofBatch(JNIEnv *env, jclass thisCls, jbyteArray blobs, jbyteArray commitments_bytes, jbyteArray proofs_bytes, jlong count)
{
if (settings == NULL)
{
throw_exception(env, TRUSTED_SETUP_NOT_LOADED);
return 0;
}
size_t count_native = (size_t)count;
size_t blobs_size = (size_t)(*env)->GetArrayLength(env, blobs);
if (blobs_size != count_native * BYTES_PER_BLOB)
{
throw_invalid_size_exception(env, "Invalid blobs size.", blobs_size, count_native * BYTES_PER_BLOB);
return 0;
}
size_t commitments_bytes_size = (size_t)(*env)->GetArrayLength(env, commitments_bytes);
if (commitments_bytes_size != count_native * BYTES_PER_COMMITMENT)
{
throw_invalid_size_exception(env, "Invalid commitments size.", commitments_bytes_size, count_native * BYTES_PER_COMMITMENT);
return 0;
}
size_t proofs_bytes_size = (size_t)(*env)->GetArrayLength(env, proofs_bytes);
if (proofs_bytes_size != count_native * BYTES_PER_PROOF)
{
throw_invalid_size_exception(env, "Invalid proofs size.", proofs_bytes_size, count_native * BYTES_PER_PROOF);
return 0;
}
Blob *blobs_native = (Blob *)(*env)->GetByteArrayElements(env, blobs, NULL);
Bytes48 *commitments_native = (Bytes48 *)(*env)->GetByteArrayElements(env, commitments_bytes, NULL);
Bytes48 *proofs_native = (Bytes48 *)(*env)->GetByteArrayElements(env, proofs_bytes, NULL);
bool out;
C_KZG_RET ret = verify_blob_kzg_proof_batch(&out, blobs_native, commitments_native, proofs_native, count_native, settings);
(*env)->ReleaseByteArrayElements(env, blobs, (jbyte *)blobs_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, commitments_bytes, (jbyte *)commitments_native, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, proofs_bytes, (jbyte *)proofs_native, JNI_ABORT);
if (ret != C_KZG_OK)
{
throw_c_kzg_exception(env, ret, "There was an error in verifyBlobKzgProofBatch.");
return 0;
}
return (jboolean)out;
}