@@ -106,7 +106,7 @@ impl Default for StateUpdateConfig {
106
106
leaf_nullifications : CollectionConfig :: new ( 0 , 3 , 0.0 ) ,
107
107
indexed_merkle_tree_updates : CollectionConfig :: new ( 0 , 3 , 1.0 ) ,
108
108
batch_nullify_context : CollectionConfig :: new ( 0 , 2 , 0.0 ) ,
109
- batch_new_addresses : CollectionConfig :: new ( 0 , 3 , 0 .0) ,
109
+ batch_new_addresses : CollectionConfig :: new ( 1 , 3 , 1 .0) ,
110
110
111
111
lamports_min : 1000 ,
112
112
lamports_max : 1_000_000 ,
@@ -249,7 +249,7 @@ fn get_rnd_state_update(
249
249
250
250
let count =
251
251
rng. gen_range ( config. out_accounts_v2 . min_entries ..=config. out_accounts_v2 . max_entries ) ;
252
- metadata. out_accounts_v2_count = count as usize ;
252
+ metadata. out_accounts_v2_count = count;
253
253
for i in 0 ..count {
254
254
let account = AccountWithContext {
255
255
account : Account {
@@ -453,16 +453,23 @@ fn get_rnd_state_update(
453
453
metadata. batch_nullify_context_count += 1 ;
454
454
}
455
455
456
- // Generate batch_new_addresses (Vec<AddressQueueUpdate>)
456
+ // Generate batch_new_addresses (Vec<AddressQueueUpdate>) - V2 addresses for address queue
457
457
if rng. gen_bool ( config. batch_new_addresses . probability ) {
458
+ // Use V2 tree for new addresses (they go into address queue)
459
+ let v2_tree_info = TreeInfo :: get ( V2_TEST_TREE_PUBKEY_STR )
460
+ . expect ( "V2 test tree should exist in QUEUE_TREE_MAPPING" ) ;
461
+ let v2_tree_pubkey = v2_tree_info. tree ;
462
+
458
463
let count = rng. gen_range (
459
464
config. batch_new_addresses . min_entries ..=config. batch_new_addresses . max_entries ,
460
465
) ;
466
+ metadata. batch_new_addresses_count = count;
467
+
461
468
for i in 0 ..count {
462
469
state_update. batch_new_addresses . push ( AddressQueueUpdate {
463
- tree : SerializablePubkey :: from ( test_tree_pubkey ) ,
470
+ tree : SerializablePubkey :: from ( v2_tree_pubkey ) ,
464
471
address : rng. gen :: < [ u8 ; 32 ] > ( ) ,
465
- queue_index : i as u64 ,
472
+ queue_index : nullifier_queue_index + i as u64 , // Continue from where nullifier queue left off
466
473
} ) ;
467
474
}
468
475
}
@@ -549,7 +556,7 @@ fn update_test_state_after_iteration(
549
556
* base_seq_v1 += v1_output_count;
550
557
* base_leaf_index_v1 += v1_output_count;
551
558
* base_leaf_index_v2 += v2_output_count;
552
- * base_nullifier_queue_index += v2_input_count; // Only v2 input accounts get nullifier queue positions
559
+ * base_nullifier_queue_index += v2_input_count + metadata . batch_new_addresses_count as u64 ; // V2 input accounts and new addresses share queue space
553
560
* base_indexed_seq += indexed_updates_count; // Track indexed tree sequence
554
561
555
562
println ! (
@@ -808,6 +815,70 @@ async fn assert_input_accounts_persisted(
808
815
Ok ( ( ) )
809
816
}
810
817
818
+ /// Assert that all batch_new_addresses from the state update were inserted correctly into the address queue
819
+ async fn assert_batch_new_addresses_persisted (
820
+ db_conn : & DatabaseConnection ,
821
+ metadata : & StateUpdateMetadata ,
822
+ state_update : & StateUpdate ,
823
+ ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
824
+ use photon_indexer:: dao:: generated:: address_queues;
825
+ use sea_orm:: ColumnTrait ;
826
+
827
+ // Validate metadata matches actual state update
828
+ assert_eq ! (
829
+ state_update. batch_new_addresses. len( ) ,
830
+ metadata. batch_new_addresses_count,
831
+ "Metadata batch_new_addresses count ({}) doesn't match actual batch_new_addresses ({})" ,
832
+ metadata. batch_new_addresses_count,
833
+ state_update. batch_new_addresses. len( )
834
+ ) ;
835
+
836
+ if state_update. batch_new_addresses . is_empty ( ) {
837
+ println ! ( "✅ No batch_new_addresses - skipping address queue verification" ) ;
838
+ return Ok ( ( ) ) ;
839
+ }
840
+
841
+ // Create expected models from state update
842
+ let expected_models: Vec < address_queues:: Model > = state_update
843
+ . batch_new_addresses
844
+ . iter ( )
845
+ . map ( |address_update| address_queues:: Model {
846
+ address : address_update. address . to_vec ( ) ,
847
+ tree : address_update. tree . 0 . to_bytes ( ) . to_vec ( ) ,
848
+ queue_index : address_update. queue_index as i64 ,
849
+ } )
850
+ . collect ( ) ;
851
+
852
+ // Get all addresses for the query
853
+ let expected_addresses: Vec < Vec < u8 > > = expected_models
854
+ . iter ( )
855
+ . map ( |model| model. address . clone ( ) )
856
+ . collect ( ) ;
857
+
858
+ // Query database for addresses with matching addresses
859
+ let mut db_addresses = address_queues:: Entity :: find ( )
860
+ . filter ( address_queues:: Column :: Address . is_in ( expected_addresses) )
861
+ . all ( db_conn)
862
+ . await ?;
863
+
864
+ // Sort both vectors by address for consistent comparison
865
+ let mut expected_models_sorted = expected_models;
866
+ expected_models_sorted. sort_by ( |a, b| a. address . cmp ( & b. address ) ) ;
867
+ db_addresses. sort_by ( |a, b| a. address . cmp ( & b. address ) ) ;
868
+
869
+ // Single assert comparing the entire vectors
870
+ assert_eq ! (
871
+ db_addresses, expected_models_sorted,
872
+ "Database addresses do not match expected addresses"
873
+ ) ;
874
+
875
+ println ! (
876
+ "✅ Successfully verified {} batch_new_addresses were persisted correctly in address queue" ,
877
+ db_addresses. len( )
878
+ ) ;
879
+ Ok ( ( ) )
880
+ }
881
+
811
882
/// Assert that state tree root matches reference implementation after appending new hashes
812
883
async fn assert_state_tree_root (
813
884
db_conn : & DatabaseConnection ,
@@ -1221,7 +1292,7 @@ async fn test_output_accounts(#[values(DatabaseBackend::Sqlite)] db_backend: Dat
1221
1292
// Set up deterministic randomness following the light-protocol pattern
1222
1293
let mut thread_rng = ThreadRng :: default ( ) ;
1223
1294
let random_seed = thread_rng. next_u64 ( ) ;
1224
- let seed: u64 = 5331180609400104349 ; // random_seed;
1295
+ let seed: u64 = random_seed;
1225
1296
println ! ( "\n \n config structure test seed {}\n \n " , seed) ;
1226
1297
let mut rng = StdRng :: seed_from_u64 ( seed) ;
1227
1298
@@ -1330,6 +1401,11 @@ async fn test_output_accounts(#[values(DatabaseBackend::Sqlite)] db_backend: Dat
1330
1401
. await
1331
1402
. expect ( "Failed to verify input accounts persistence" ) ;
1332
1403
1404
+ // 5.5. Assert that all batch_new_addresses were persisted correctly in address queue
1405
+ assert_batch_new_addresses_persisted ( & setup. db_conn , & metadata, & state_update)
1406
+ . await
1407
+ . expect ( "Failed to verify batch_new_addresses persistence" ) ;
1408
+
1333
1409
// 6. Assert that state tree root matches reference tree root
1334
1410
// - updates reference tree
1335
1411
assert_state_tree_root (
0 commit comments