@@ -2,7 +2,7 @@ use crate::_comparison_tools::lt::{assert_gt_240_bit, assert_lt_240_bit, lt_fiel
2
2
use crate::_string_tools::string_chopper::slice_string ;
3
3
use crate::enums::Layer::ARRAY_LAYER ;
4
4
use crate::json::JSON ;
5
- use crate::json_entry::JSONEntry ;
5
+ use crate::json_entry:: { JSONEntry , JSONEntryPacked } ;
6
6
use crate::keyhash::ByteHasher ;
7
7
use crate::keymap::KeyIndexData ;
8
8
use crate::utils::cast_num_to_u32 ;
@@ -57,7 +57,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
57
57
let keyhash = keyhash + self .root_id * two_pow_216 ;
58
58
59
59
// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
60
- let key_index = unsafe { self . find_key_in_map ( keyhash ) };
60
+ let key_index = unsafe { find_key_in_map ::< MaxNumValues >( self . key_hashes , keyhash ) };
61
61
62
62
assert_eq (self .key_hashes [key_index ], keyhash , "get_json_entry_unchecked: key not found" );
63
63
let entry : JSONEntry = self .json_entries_packed [key_index ].into ();
@@ -97,7 +97,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
97
97
let keyhash = keyhash + self .root_id * two_pow_216 ;
98
98
99
99
// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
100
- let key_index = unsafe { self . find_key_in_map ( keyhash ) };
100
+ let key_index = unsafe { find_key_in_map ::< MaxNumValues >( self . key_hashes , keyhash ) };
101
101
102
102
assert_eq (self .key_hashes [key_index ], keyhash , "get_json_entry_unchecked: key not found" );
103
103
let entry : JSONEntry = self .json_entries_packed [key_index ].into ();
@@ -121,7 +121,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
121
121
let keyhash = keyhash + self .root_id * two_pow_216 ;
122
122
123
123
// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
124
- let key_index = unsafe { self . find_key_in_map ( keyhash ) };
124
+ let key_index = unsafe { find_key_in_map ::< MaxNumValues >( self . key_hashes , keyhash ) };
125
125
126
126
assert_eq (self .key_hashes [key_index ], keyhash , "get_json_entry_unchecked: key not found" );
127
127
let entry : JSONEntry = self .json_entries_packed [key_index ].into ();
@@ -144,7 +144,7 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
144
144
let keyhash = keyhash + self .root_id * two_pow_216 ;
145
145
146
146
// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
147
- let key_index = unsafe { self . find_key_in_map ( keyhash ) };
147
+ let key_index = unsafe { find_key_in_map ::< MaxNumValues >( self . key_hashes , keyhash ) };
148
148
149
149
assert_eq (self .key_hashes [key_index ], keyhash , "get_json_entry_unchecked: key not found" );
150
150
let entry : JSONEntry = self .json_entries_packed [key_index ].into ();
@@ -173,82 +173,6 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
173
173
result
174
174
}
175
175
176
- pub (crate ) unconstrained fn find_key_in_map (self , target : Field ) -> u32 {
177
- let mut found_index : u32 = 0 ;
178
- let mut found : bool = false ;
179
- for i in 0 ..MaxNumValues {
180
- let key_hash = self .key_hashes [i ];
181
- if (key_hash == target ) {
182
- found_index = i ;
183
- found = true ;
184
- break ;
185
- }
186
- }
187
- assert (found , "find_key_in_map, key not found" );
188
- found_index
189
- }
190
-
191
- /**
192
- * @brief figures out if `target` exists as a key in `self.key_hashes`
193
- * @details if `target` does not exist, we return the two indicies of adjacent
194
- * entries in `self.key_hashes`, lhs_index, rhs_index, where
195
- * lhs_index < key_hash < rhs_index
196
- **/
197
- pub (crate ) unconstrained fn search_for_key_in_map (self , target : Field ) -> KeySearchResult {
198
- let mut found_index : Field = 0 ;
199
- let mut found : bool = false ;
200
-
201
- let mut lhs_maximum : Field = 0 ;
202
- let mut rhs_minimum : Field = -1 ;
203
- let mut lhs_maximum_index : Field = 0 ;
204
- let mut rhs_minimum_index : Field = 0 ;
205
- for i in 0 ..MaxNumValues {
206
- let key_hash = self .key_hashes [i ];
207
- if (key_hash == target ) {
208
- found_index = i as Field ;
209
- found = true ;
210
- break ;
211
- } else {
212
- if key_hash .lt (target ) & (lhs_maximum .lt (key_hash )) {
213
- lhs_maximum = key_hash ;
214
- lhs_maximum_index = i as Field ;
215
- }
216
- if (target .lt (key_hash )) & (key_hash .lt (rhs_minimum )) {
217
- rhs_minimum = key_hash ;
218
- rhs_minimum_index = i as Field ;
219
- }
220
- }
221
- }
222
- let target_lt_smallest_entry = target .lt (self .key_hashes [0 ]);
223
- let target_gt_largest_entry = self .key_hashes [MaxNumValues - 1 ].lt (target );
224
-
225
- let result_not_first_or_last =
226
- !target_lt_smallest_entry & !target_gt_largest_entry & !found ;
227
-
228
- let mut lhs_index = result_not_first_or_last as Field * lhs_maximum_index ;
229
- let mut rhs_index = result_not_first_or_last as Field * rhs_minimum_index ;
230
-
231
- // if target_lt_smallest_entry, rhs_index = 0
232
- // if target_gt_largest_entry, lhs_index = TranscriptEntries - 1
233
- rhs_index = rhs_index * (1 - target_lt_smallest_entry as Field );
234
-
235
- // we rely here on the fact that target_gt_largest_entry and result_not_first_or_last are mutually exclusive
236
- lhs_index = lhs_index + target_gt_largest_entry as Field * (MaxNumValues as Field - 1 );
237
-
238
- // If target is FOUND, we want the following:
239
- // keyhash[target_index] - 1 < hash < keyhash[target_index] + 1
240
- lhs_index = lhs_index + found as Field * found_index ;
241
- rhs_index = rhs_index + found as Field * found_index ;
242
-
243
- KeySearchResult {
244
- found ,
245
- target_lt_smallest_entry ,
246
- target_gt_largest_entry ,
247
- lhs_index : lhs_index as u32 ,
248
- rhs_index : rhs_index as u32 ,
249
- }
250
- }
251
-
252
176
/**
253
177
* @brief returns a bool that describes whether a given key exists at the root of the JSON
254
178
**/
@@ -280,7 +204,8 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
280
204
let keyhash = keyhash + self .root_id * two_pow_216 ;
281
205
282
206
// Safety: The assertion below checks that the keyhash is stored in the the index returned by the unconstrained function
283
- let search_result = unsafe { self .search_for_key_in_map (keyhash ) };
207
+ let search_result =
208
+ unsafe { search_for_key_in_map ::<MaxNumValues >(self .key_hashes , keyhash ) };
284
209
if search_result .found {
285
210
assert_eq (search_result .lhs_index , search_result .rhs_index );
286
211
}
@@ -342,7 +267,8 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
342
267
let keyhash = keyhash + self .root_id * two_pow_216 ;
343
268
344
269
// Safety: the assertion (search_result.lhs_index - search_result.rhs_index) * found == 0 constraints this function
345
- let search_result = unsafe { self .search_for_key_in_map (keyhash ) };
270
+ let search_result =
271
+ unsafe { search_for_key_in_map ::<MaxNumValues >(self .key_hashes , keyhash ) };
346
272
if search_result .found {
347
273
assert_eq (search_result .lhs_index , search_result .rhs_index );
348
274
}
@@ -376,33 +302,20 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
376
302
(search_result .found , search_result .lhs_index )
377
303
}
378
304
379
- pub (crate ) unconstrained fn __get_keys_at_root <let MaxNumKeys : u32 >(
380
- self ,
381
- ) -> BoundedVec <Field , MaxNumKeys > {
382
- let root_object : JSONEntry =
383
- JSONEntry ::from (self .json_entries_packed [self .root_index_in_transcript ]);
384
-
385
- let mut result_ptr = 0 ;
386
- let mut result : [Field ; MaxNumKeys ] = [0 ; MaxNumKeys ];
387
- for i in 0 ..MaxNumValues {
388
- let target_entry : JSONEntry = JSONEntry ::from (self .unsorted_json_entries_packed [i ]);
389
- if (target_entry .parent_index == self .root_id ) {
390
- result [result_ptr ] = i as Field ;
391
- result_ptr += 1 ;
392
- }
393
- }
394
- assert_eq (result_ptr as Field , root_object .num_children );
395
-
396
- BoundedVec ::from_parts_unchecked (result , result_ptr as u32 )
397
- }
398
-
399
305
pub (crate ) fn get_keys_at_root <let MaxNumKeys : u32 , let MaxKeyBytes : u32 >(
400
306
self ,
401
307
) -> BoundedVec <BoundedVec <u8 , MaxKeyBytes >, MaxNumKeys > {
402
308
let root_object : JSONEntry =
403
309
JSONEntry ::from (self .json_entries_packed [self .root_index_in_transcript ]);
404
310
// Safety: the length of the index is constrained later.
405
- let key_indices : BoundedVec <Field , MaxNumKeys > = unsafe { self .__get_keys_at_root () };
311
+ let key_indices : BoundedVec <Field , MaxNumKeys > = unsafe {
312
+ __get_keys_at_root ::<MaxNumKeys , MaxNumValues >(
313
+ self .root_id ,
314
+ self .root_index_in_transcript ,
315
+ self .json_entries_packed ,
316
+ self .unsorted_json_entries_packed ,
317
+ )
318
+ };
406
319
407
320
assert (key_indices .len () as Field == root_object .num_children );
408
321
@@ -424,6 +337,109 @@ impl<let NumBytes: u32, let NumPackedFields: u32, let MaxNumTokens: u32, let Max
424
337
}
425
338
}
426
339
340
+ unconstrained fn find_key_in_map <let MaxNumValues : u32 >(
341
+ key_hashes : [Field ; MaxNumValues ],
342
+ target : Field ,
343
+ ) -> u32 {
344
+ let mut found_index : u32 = 0 ;
345
+ let mut found : bool = false ;
346
+ for i in 0 ..MaxNumValues {
347
+ let key_hash = key_hashes [i ];
348
+ if (key_hash == target ) {
349
+ found_index = i ;
350
+ found = true ;
351
+ break ;
352
+ }
353
+ }
354
+ assert (found , "find_key_in_map, key not found" );
355
+ found_index
356
+ }
357
+
358
+ /**
359
+ * @brief figures out if `target` exists as a key in `self.key_hashes`
360
+ * @details if `target` does not exist, we return the two indicies of adjacent
361
+ * entries in `self.key_hashes`, lhs_index, rhs_index, where
362
+ * lhs_index < key_hash < rhs_index
363
+ **/
364
+ unconstrained fn search_for_key_in_map <let MaxNumValues : u32 >(
365
+ key_hashes : [Field ; MaxNumValues ],
366
+ target : Field ,
367
+ ) -> KeySearchResult {
368
+ let mut found_index : Field = 0 ;
369
+ let mut found : bool = false ;
370
+
371
+ let mut lhs_maximum : Field = 0 ;
372
+ let mut rhs_minimum : Field = -1 ;
373
+ let mut lhs_maximum_index : Field = 0 ;
374
+ let mut rhs_minimum_index : Field = 0 ;
375
+ for i in 0 ..MaxNumValues {
376
+ let key_hash = key_hashes [i ];
377
+ if (key_hash == target ) {
378
+ found_index = i as Field ;
379
+ found = true ;
380
+ break ;
381
+ } else {
382
+ if key_hash .lt (target ) & (lhs_maximum .lt (key_hash )) {
383
+ lhs_maximum = key_hash ;
384
+ lhs_maximum_index = i as Field ;
385
+ }
386
+ if (target .lt (key_hash )) & (key_hash .lt (rhs_minimum )) {
387
+ rhs_minimum = key_hash ;
388
+ rhs_minimum_index = i as Field ;
389
+ }
390
+ }
391
+ }
392
+ let target_lt_smallest_entry = target .lt (key_hashes [0 ]);
393
+ let target_gt_largest_entry = key_hashes [MaxNumValues - 1 ].lt (target );
394
+
395
+ let result_not_first_or_last = !target_lt_smallest_entry & !target_gt_largest_entry & !found ;
396
+
397
+ let mut lhs_index = result_not_first_or_last as Field * lhs_maximum_index ;
398
+ let mut rhs_index = result_not_first_or_last as Field * rhs_minimum_index ;
399
+
400
+ // if target_lt_smallest_entry, rhs_index = 0
401
+ // if target_gt_largest_entry, lhs_index = TranscriptEntries - 1
402
+ rhs_index = rhs_index * (1 - target_lt_smallest_entry as Field );
403
+
404
+ // we rely here on the fact that target_gt_largest_entry and result_not_first_or_last are mutually exclusive
405
+ lhs_index = lhs_index + target_gt_largest_entry as Field * (MaxNumValues as Field - 1 );
406
+
407
+ // If target is FOUND, we want the following:
408
+ // keyhash[target_index] - 1 < hash < keyhash[target_index] + 1
409
+ lhs_index = lhs_index + found as Field * found_index ;
410
+ rhs_index = rhs_index + found as Field * found_index ;
411
+
412
+ KeySearchResult {
413
+ found ,
414
+ target_lt_smallest_entry ,
415
+ target_gt_largest_entry ,
416
+ lhs_index : lhs_index as u32 ,
417
+ rhs_index : rhs_index as u32 ,
418
+ }
419
+ }
420
+
421
+ unconstrained fn __get_keys_at_root <let MaxNumKeys : u32 , let MaxNumValues : u32 >(
422
+ root_id : Field ,
423
+ root_index_in_transcript : u32 ,
424
+ json_entries_packed : [JSONEntryPacked ; MaxNumValues ],
425
+ unsorted_json_entries_packed : [JSONEntryPacked ; MaxNumValues ],
426
+ ) -> BoundedVec <Field , MaxNumKeys > {
427
+ let root_object : JSONEntry = JSONEntry ::from (json_entries_packed [root_index_in_transcript ]);
428
+
429
+ let mut result_ptr = 0 ;
430
+ let mut result : [Field ; MaxNumKeys ] = [0 ; MaxNumKeys ];
431
+ for i in 0 ..MaxNumValues {
432
+ let target_entry : JSONEntry = JSONEntry ::from (unsorted_json_entries_packed [i ]);
433
+ if (target_entry .parent_index == root_id ) {
434
+ result [result_ptr ] = i as Field ;
435
+ result_ptr += 1 ;
436
+ }
437
+ }
438
+ assert_eq (result_ptr as Field , root_object .num_children );
439
+
440
+ BoundedVec ::from_parts_unchecked (result , result_ptr as u32 )
441
+ }
442
+
427
443
#[test]
428
444
fn test_get_keys_at_root () {
429
445
let s = "{ \" A\" : 1, \" foo\" : false, \" bar\" : { \" one\" : \" A\" , \" two\" : \" B\" }, \" baz\" : \" 12345\" }" ;
0 commit comments