@@ -5,9 +5,8 @@ use jni::objects::{JByteArray, JClass, JLongArray, JObject, JValue};
5
5
use jni:: sys:: { jboolean, jlong} ;
6
6
use jni:: JNIEnv ;
7
7
8
- // TODO: Convert the unwraps into Exceptions
9
- // TODO: The java code solely uses `java/lang/IllegalArgumentException`
10
- // TODO: swap for custom exception or use a more specific exception
8
+ mod errors;
9
+ use errors:: Error ;
11
10
12
11
#[ no_mangle]
13
12
pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_peerDASContextNew (
@@ -36,18 +35,22 @@ pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_computeCe
36
35
blob : JByteArray < ' local > ,
37
36
) -> JObject < ' local > {
38
37
let ctx = & * ( ctx_ptr as * const PeerDASContext ) ;
39
- let blob = env. convert_byte_array ( blob) . unwrap ( ) ;
40
-
41
- let ( cells, proofs) = match ctx. prover_ctx ( ) . compute_cells_and_kzg_proofs ( & blob) {
38
+ match compute_cells_and_kzg_proofs ( & mut env, ctx, blob) {
42
39
Ok ( cells_and_proofs) => cells_and_proofs,
43
40
Err ( err) => {
44
- env. throw_new ( "java/lang/IllegalArgumentException" , format ! ( "{:?}" , err) )
45
- . expect ( "Failed to throw exception for `compute_cells_and_kzg_proofs`" ) ;
41
+ throw_on_error ( & mut env, err, "computeCellsAndKZGProofs" ) ;
46
42
return JObject :: default ( ) ;
47
43
}
48
- } ;
49
-
50
- return cells_and_proofs_to_jobject ( & mut env, & cells, & proofs) . unwrap ( ) ;
44
+ }
45
+ }
46
+ fn compute_cells_and_kzg_proofs < ' local > (
47
+ env : & mut JNIEnv < ' local > ,
48
+ ctx : & PeerDASContext ,
49
+ blob : JByteArray < ' local > ,
50
+ ) -> Result < JObject < ' local > , Error > {
51
+ let blob = env. convert_byte_array ( blob) ?;
52
+ let ( cells, proofs) = ctx. prover_ctx ( ) . compute_cells_and_kzg_proofs ( & blob) ?;
53
+ cells_and_proofs_to_jobject ( env, & cells, & proofs) . map_err ( Error :: from)
51
54
}
52
55
53
56
#[ no_mangle]
@@ -60,18 +63,22 @@ pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_blobToKZG
60
63
blob : JByteArray < ' local > ,
61
64
) -> JByteArray < ' local > {
62
65
let ctx = & * ( ctx_ptr as * const PeerDASContext ) ;
63
- let blob = env. convert_byte_array ( blob) . unwrap ( ) ;
64
-
65
- let commitment = match ctx. prover_ctx ( ) . blob_to_kzg_commitment ( & blob) {
66
+ match blob_to_kzg_commitment ( & mut env, ctx, blob) {
66
67
Ok ( commitment) => commitment,
67
68
Err ( err) => {
68
- env. throw_new ( "java/lang/IllegalArgumentException" , format ! ( "{:?}" , err) )
69
- . expect ( "Failed to throw exception for `blob_to_kzg_commitment`" ) ;
69
+ throw_on_error ( & mut env, err, "blobToKZGCommitment" ) ;
70
70
return JByteArray :: default ( ) ;
71
71
}
72
- } ;
73
-
74
- return env. byte_array_from_slice ( & commitment) . unwrap ( ) ;
72
+ }
73
+ }
74
+ fn blob_to_kzg_commitment < ' local > (
75
+ env : & mut JNIEnv < ' local > ,
76
+ ctx : & PeerDASContext ,
77
+ blob : JByteArray < ' local > ,
78
+ ) -> Result < JByteArray < ' local > , Error > {
79
+ let blob = env. convert_byte_array ( blob) ?;
80
+ let commitment = ctx. prover_ctx ( ) . blob_to_kzg_commitment ( & blob) ?;
81
+ env. byte_array_from_slice ( & commitment) . map_err ( Error :: from)
75
82
}
76
83
77
84
#[ no_mangle]
@@ -88,24 +95,34 @@ pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_verifyCel
88
95
) -> jboolean {
89
96
let ctx = & * ( ctx_ptr as * const PeerDASContext ) ;
90
97
91
- let commitment_bytes = env. convert_byte_array ( & commitment_bytes) . unwrap ( ) ;
98
+ match verify_cell_kzg_proof ( & mut env, ctx, commitment_bytes, cell_id, cell, proof_bytes) {
99
+ Ok ( result) => result,
100
+ Err ( err) => {
101
+ throw_on_error ( & mut env, err, "verifyCellKZGProof" ) ;
102
+ return jboolean:: default ( ) ;
103
+ }
104
+ }
105
+ }
106
+ fn verify_cell_kzg_proof (
107
+ env : & mut JNIEnv ,
108
+ ctx : & PeerDASContext ,
109
+ commitment_bytes : JByteArray ,
110
+ cell_id : jlong ,
111
+ cell : JByteArray ,
112
+ proof_bytes : JByteArray ,
113
+ ) -> Result < jboolean , Error > {
114
+ let commitment_bytes = env. convert_byte_array ( commitment_bytes) ?;
92
115
let cell_id = cell_id as u64 ;
93
- let cell = env. convert_byte_array ( & cell) . unwrap ( ) ;
94
- let proof_bytes = env. convert_byte_array ( & proof_bytes) . unwrap ( ) ;
116
+ let cell = env. convert_byte_array ( cell) ? ;
117
+ let proof_bytes = env. convert_byte_array ( proof_bytes) ? ;
95
118
96
119
match ctx
97
120
. verifier_ctx ( )
98
121
. verify_cell_kzg_proof ( & commitment_bytes, cell_id, & cell, & proof_bytes)
99
122
{
100
- Ok ( _) => return jboolean:: from ( true ) ,
101
- Err ( VerifierError :: InvalidProof ) => {
102
- return jboolean:: from ( false ) ;
103
- }
104
- Err ( err) => {
105
- env. throw_new ( "java/lang/IllegalArgumentException" , format ! ( "{:?}" , err) )
106
- . expect ( "Failed to throw exception for `verify_cell_kzg_proof`" ) ;
107
- return jboolean:: default ( ) ;
108
- }
123
+ Ok ( _) => Ok ( jboolean:: from ( true ) ) ,
124
+ Err ( VerifierError :: InvalidProof ) => Ok ( jboolean:: from ( false ) ) ,
125
+ Err ( err) => Err ( Error :: VerifierError ( err) ) ,
109
126
}
110
127
}
111
128
@@ -124,30 +141,49 @@ pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_verifyCel
124
141
) -> jboolean {
125
142
let ctx = & * ( ctx_ptr as * const PeerDASContext ) ;
126
143
127
- let commitment_bytes = jobject_array_to_2d_byte_array ( & mut env, commitment_bytes) . unwrap ( ) ;
128
- let row_indices = jlongarray_to_vec_u64 ( & env, row_indices) ;
129
- let column_indices = jlongarray_to_vec_u64 ( & env, column_indices) ;
130
- let cells = jobject_array_to_2d_byte_array ( & mut env, cells) . unwrap ( ) ;
131
- let proofs = jobject_array_to_2d_byte_array ( & mut env, proofs) . unwrap ( ) ;
132
-
133
- match ctx. verifier_ctx ( ) . verify_cell_kzg_proof_batch (
144
+ match verify_cell_kzg_proof_batch (
145
+ & mut env,
146
+ ctx,
134
147
commitment_bytes,
135
148
row_indices,
136
149
column_indices,
137
- cells. iter ( ) . map ( |cell| cell . as_slice ( ) ) . collect ( ) ,
150
+ cells,
138
151
proofs,
139
152
) {
140
- Ok ( _) => return jboolean:: from ( true ) ,
141
- Err ( VerifierError :: InvalidProof ) => {
142
- return jboolean:: from ( false ) ;
143
- }
153
+ Ok ( result) => result,
144
154
Err ( err) => {
145
- env. throw_new ( "java/lang/IllegalArgumentException" , format ! ( "{:?}" , err) )
146
- . expect ( "Failed to throw exception for `verify_cell_kzg_proof_batch`" ) ;
155
+ throw_on_error ( & mut env, err, "verifyCellKZGProofBatch" ) ;
147
156
return jboolean:: default ( ) ;
148
157
}
149
158
}
150
159
}
160
+ fn verify_cell_kzg_proof_batch < ' local > (
161
+ env : & mut JNIEnv ,
162
+ ctx : & PeerDASContext ,
163
+ commitment_bytes : JObjectArray < ' local > ,
164
+ row_indices : JLongArray ,
165
+ column_indices : JLongArray ,
166
+ cells : JObjectArray < ' local > ,
167
+ proofs : JObjectArray < ' local > ,
168
+ ) -> Result < jboolean , Error > {
169
+ let commitment_bytes = jobject_array_to_2d_byte_array ( env, commitment_bytes) ?;
170
+ let row_indices = jlongarray_to_vec_u64 ( env, row_indices) ?;
171
+ let column_indices = jlongarray_to_vec_u64 ( env, column_indices) ?;
172
+ let cells = jobject_array_to_2d_byte_array ( env, cells) ?;
173
+ let proofs = jobject_array_to_2d_byte_array ( env, proofs) ?;
174
+
175
+ match ctx. verifier_ctx ( ) . verify_cell_kzg_proof_batch (
176
+ commitment_bytes,
177
+ row_indices,
178
+ column_indices,
179
+ cells. iter ( ) . map ( |cell| cell. as_slice ( ) ) . collect ( ) ,
180
+ proofs,
181
+ ) {
182
+ Ok ( _) => Ok ( jboolean:: from ( true ) ) ,
183
+ Err ( VerifierError :: InvalidProof ) => Ok ( jboolean:: from ( false ) ) ,
184
+ Err ( err) => Err ( Error :: VerifierError ( err) ) ,
185
+ }
186
+ }
151
187
152
188
#[ no_mangle]
153
189
pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_recoverCellsAndProof <
@@ -161,54 +197,52 @@ pub unsafe extern "system" fn Java_ethereum_cryptography_LibPeerDASKZG_recoverCe
161
197
) -> JObject < ' local > {
162
198
let ctx = & * ( ctx_ptr as * const PeerDASContext ) ;
163
199
164
- let cell_ids = jlongarray_to_vec_u64 ( & env, cell_ids) ;
165
-
166
- let cells = match jobject_array_to_2d_byte_array ( & mut env, cells) {
167
- Ok ( cells) => cells,
200
+ match recover_cells_and_kzg_proofs ( & mut env, ctx, cell_ids, cells) {
201
+ Ok ( cells_and_proofs) => cells_and_proofs,
168
202
Err ( err) => {
169
- env. throw_new ( "java/lang/IllegalArgumentException" , & err. to_string ( ) )
170
- . expect ( "Failed to throw exception for `recover_all_cells`" ) ;
203
+ throw_on_error ( & mut env, err, "recoverCellsAndProof" ) ;
171
204
return JObject :: default ( ) ;
172
205
}
173
- } ;
206
+ }
207
+ }
208
+ fn recover_cells_and_kzg_proofs < ' local > (
209
+ env : & mut JNIEnv < ' local > ,
210
+ ctx : & PeerDASContext ,
211
+ cell_ids : JLongArray ,
212
+ cells : JObjectArray < ' local > ,
213
+ ) -> Result < JObject < ' local > , Error > {
214
+ let cell_ids = jlongarray_to_vec_u64 ( env, cell_ids) ?;
215
+ let cells = jobject_array_to_2d_byte_array ( env, cells) ?;
174
216
175
- let ( recovered_cells, recovered_proofs) = match ctx. prover_ctx ( ) . recover_cells_and_proofs (
217
+ let ( recovered_cells, recovered_proofs) = ctx. prover_ctx ( ) . recover_cells_and_proofs (
176
218
cell_ids,
177
219
cells. iter ( ) . map ( |x| x. as_slice ( ) ) . collect ( ) ,
178
220
vec ! [ ] ,
179
- ) {
180
- Ok ( recovered_cells_and_proofs) => recovered_cells_and_proofs,
181
- Err ( err) => {
182
- env. throw_new ( "java/lang/IllegalArgumentException" , format ! ( "{:?}" , err) )
183
- . expect ( "Failed to throw exception for `recover_all_cells`" ) ;
184
- return JObject :: default ( ) ;
185
- }
186
- } ;
221
+ ) ?;
187
222
188
- return cells_and_proofs_to_jobject ( & mut env, & recovered_cells, & recovered_proofs) . unwrap ( ) ;
223
+ cells_and_proofs_to_jobject ( env, & recovered_cells, & recovered_proofs) . map_err ( Error :: from )
189
224
}
190
225
191
- fn jlongarray_to_vec_u64 ( env : & JNIEnv , array : JLongArray ) -> Vec < u64 > {
226
+ /// Converts a JLongArray to a Vec<u64>
227
+ fn jlongarray_to_vec_u64 ( env : & JNIEnv , array : JLongArray ) -> Result < Vec < u64 > , Error > {
192
228
// Step 1: Get the length of the JLongArray
193
- let array_length = env
194
- . get_array_length ( & array)
195
- . expect ( "Unable to get array length" ) ;
229
+ let array_length = env. get_array_length ( & array) ?;
196
230
197
231
// Step 2: Create a buffer to hold the jlong elements (these are i64s)
198
232
let mut buffer: Vec < i64 > = vec ! [ 0 ; array_length as usize ] ;
199
233
200
234
// Step 3: Get the elements from the JLongArray
201
- env. get_long_array_region ( array, 0 , & mut buffer)
202
- . expect ( "Unable to get array region" ) ;
235
+ env. get_long_array_region ( array, 0 , & mut buffer) ?;
203
236
204
237
// Step 4: Convert the Vec<i64> to Vec<u64>
205
- buffer. into_iter ( ) . map ( |x| x as u64 ) . collect ( )
238
+ Ok ( buffer. into_iter ( ) . map ( |x| x as u64 ) . collect ( ) )
206
239
}
207
240
241
+ /// Converts a JObjectArray to a Vec<Vec<u8>>
208
242
fn jobject_array_to_2d_byte_array (
209
243
env : & mut JNIEnv ,
210
244
array : JObjectArray ,
211
- ) -> Result < Vec < Vec < u8 > > , jni :: errors :: Error > {
245
+ ) -> Result < Vec < Vec < u8 > > , Error > {
212
246
// Get the length of the outer array
213
247
let outer_len = env. get_array_length ( & array) ?;
214
248
@@ -235,57 +269,63 @@ fn jobject_array_to_2d_byte_array(
235
269
Ok ( result)
236
270
}
237
271
272
+ /// Converts a Vec<Vec<u8>> to a JObject that represents a CellsAndProofs object in Java
238
273
fn cells_and_proofs_to_jobject < ' local > (
239
274
env : & mut JNIEnv < ' local > ,
240
275
cells : & [ impl AsRef < [ u8 ] > ] ,
241
276
proofs : & [ impl AsRef < [ u8 ] > ] ,
242
- ) -> Result < JObject < ' local > , jni :: errors :: Error > {
277
+ ) -> Result < JObject < ' local > , Error > {
243
278
// Create a new instance of the CellsAndProofs class in Java
244
- let cells_and_proofs_class = env
245
- . find_class ( "ethereum/cryptography/CellsAndProofs" )
246
- . unwrap ( ) ;
279
+ let cells_and_proofs_class = env. find_class ( "ethereum/cryptography/CellsAndProofs" ) ?;
247
280
248
- let cell_byte_array_class = env. find_class ( "[B" ) . unwrap ( ) ;
249
- let proof_byte_array_class = env. find_class ( "[B" ) . unwrap ( ) ;
281
+ let cell_byte_array_class = env. find_class ( "[B" ) ? ;
282
+ let proof_byte_array_class = env. find_class ( "[B" ) ? ;
250
283
251
284
// Create 2D array for cells
252
- let cells_array = env
253
- . new_object_array (
254
- cells. len ( ) as i32 ,
255
- cell_byte_array_class,
256
- env. new_byte_array ( 0 ) . unwrap ( ) ,
257
- )
258
- . unwrap ( ) ;
285
+ let cells_array = env. new_object_array (
286
+ cells. len ( ) as i32 ,
287
+ cell_byte_array_class,
288
+ env. new_byte_array ( 0 ) ?,
289
+ ) ?;
259
290
260
291
for ( i, cell) in cells. into_iter ( ) . enumerate ( ) {
261
- let cell_array = env. byte_array_from_slice ( cell. as_ref ( ) ) . unwrap ( ) ;
262
- env. set_object_array_element ( & cells_array, i as i32 , cell_array)
263
- . unwrap ( ) ;
292
+ let cell_array = env. byte_array_from_slice ( cell. as_ref ( ) ) ?;
293
+ env. set_object_array_element ( & cells_array, i as i32 , cell_array) ?;
264
294
}
265
295
266
296
// Create 2D array for proofs
267
- let proofs_array = env
268
- . new_object_array (
269
- proofs. len ( ) as i32 ,
270
- proof_byte_array_class,
271
- env. new_byte_array ( 0 ) . unwrap ( ) ,
272
- )
273
- . unwrap ( ) ;
297
+ let proofs_array = env. new_object_array (
298
+ proofs. len ( ) as i32 ,
299
+ proof_byte_array_class,
300
+ env. new_byte_array ( 0 ) ?,
301
+ ) ?;
274
302
275
303
for ( i, proof) in proofs. into_iter ( ) . enumerate ( ) {
276
- let proof_array = env. byte_array_from_slice ( proof. as_ref ( ) ) . unwrap ( ) ;
277
- env. set_object_array_element ( & proofs_array, i as i32 , proof_array)
278
- . unwrap ( ) ;
304
+ let proof_array = env. byte_array_from_slice ( proof. as_ref ( ) ) ?;
305
+ env. set_object_array_element ( & proofs_array, i as i32 , proof_array) ?;
279
306
}
280
307
281
308
// Create the CellsAndProofs object
282
- let cells_and_proofs_obj = env
283
- . new_object (
284
- cells_and_proofs_class,
285
- "([[B[[B)V" ,
286
- & [ JValue :: Object ( & cells_array) , JValue :: Object ( & proofs_array) ] ,
287
- )
288
- . unwrap ( ) ;
309
+ let cells_and_proofs_obj = env. new_object (
310
+ cells_and_proofs_class,
311
+ "([[B[[B)V" ,
312
+ & [ JValue :: Object ( & cells_array) , JValue :: Object ( & proofs_array) ] ,
313
+ ) ?;
289
314
290
315
Ok ( cells_and_proofs_obj)
291
316
}
317
+
318
+ /// Throws an exception in Java
319
+ fn throw_on_error ( env : & mut JNIEnv , err : Error , func_name : & ' static str ) {
320
+ let reason = match err {
321
+ Error :: Jni ( err) => format ! ( "{:?}" , err) ,
322
+ Error :: ProverError ( err) => format ! ( "{:?}" , err) ,
323
+ Error :: VerifierError ( err) => format ! ( "{:?}" , err) ,
324
+ } ;
325
+ let msg = format ! (
326
+ "function {} has thrown an exception, with reason: {}" ,
327
+ func_name, reason
328
+ ) ;
329
+ env. throw_new ( "java/lang/IllegalArgumentException" , msg)
330
+ . expect ( "Failed to throw exception" ) ;
331
+ }
0 commit comments