@@ -43,9 +43,9 @@ pub struct BatchPublicTransactionEvent {
43
43
pub new_addresses : Vec < NewAddress > ,
44
44
pub input_sequence_numbers : Vec < MerkleTreeSequenceNumber > ,
45
45
pub address_sequence_numbers : Vec < MerkleTreeSequenceNumber > ,
46
+ pub nullifier_queue_indices : Vec < u64 > ,
46
47
}
47
48
48
- // TODO: remove unwraps
49
49
/// We piece the event together from 2 instructions:
50
50
/// 1. light_system_program::{Invoke, InvokeCpi, InvokeCpiReadOnly} (one of the 3)
51
51
/// 2. account_compression::InsertIntoQueues
@@ -65,39 +65,66 @@ pub fn event_from_light_transaction(
65
65
) -> Result < Option < BatchPublicTransactionEvent > , ZeroCopyError > {
66
66
let mut event = PublicTransactionEvent :: default ( ) ;
67
67
let mut ix_set_cpi_context = false ;
68
- let found_event = instructions. iter ( ) . any ( |x| {
69
- match_system_program_instruction ( x, false , & mut event, & mut ix_set_cpi_context) . unwrap ( )
70
- } ) ;
68
+ let mut input_merkle_tree_indices = Vec :: new ( ) ;
69
+ let found_event = instructions
70
+ . iter ( )
71
+ . zip ( remaining_accounts. iter ( ) )
72
+ . any ( |( x, accounts) | {
73
+ match_system_program_instruction (
74
+ x,
75
+ false ,
76
+ & mut event,
77
+ & mut ix_set_cpi_context,
78
+ & mut input_merkle_tree_indices,
79
+ accounts,
80
+ )
81
+ . unwrap_or_default ( )
82
+ } ) ;
71
83
println ! ( "found event {}" , found_event) ;
72
84
if !found_event {
73
85
return Ok ( None ) ;
74
86
}
75
87
println ! ( "ix_set_cpi_context {}" , ix_set_cpi_context) ;
76
88
// If an instruction set the cpi context add the instructions that set the cpi context.
77
89
if ix_set_cpi_context {
78
- instructions. iter ( ) . for_each ( |x| {
79
- match_system_program_instruction ( x, true , & mut event, & mut true ) . unwrap ( ) ;
80
- } ) ;
90
+ instructions
91
+ . iter ( )
92
+ . zip ( remaining_accounts. iter ( ) )
93
+ . try_for_each ( |( x, accounts) | -> Result < ( ) , ZeroCopyError > {
94
+ match_system_program_instruction (
95
+ x,
96
+ true ,
97
+ & mut event,
98
+ & mut true ,
99
+ & mut input_merkle_tree_indices,
100
+ accounts,
101
+ ) ?;
102
+ Ok ( ( ) )
103
+ } ) ?;
81
104
println ! ( "added cpi context to event {}" , found_event) ;
82
105
}
83
106
// New addresses in batched trees.
84
107
let mut new_addresses = Vec :: new ( ) ;
85
108
let mut input_sequence_numbers = Vec :: new ( ) ;
86
109
let mut address_sequence_numbers = Vec :: new ( ) ;
87
- let pos = instructions. iter ( ) . enumerate ( ) . position ( |( i, x) | {
110
+ let mut pos = None ;
111
+ for ( i, instruction) in instructions. iter ( ) . enumerate ( ) {
88
112
if remaining_accounts[ i] . len ( ) < 3 {
89
- return false ;
113
+ continue ;
90
114
}
91
- match_account_compression_program_instruction (
92
- x ,
115
+ let res = match_account_compression_program_instruction (
116
+ instruction ,
93
117
& mut event,
94
118
& mut new_addresses,
95
119
& mut input_sequence_numbers,
96
120
& mut address_sequence_numbers,
97
121
& remaining_accounts[ i] [ 2 ..] ,
98
- )
99
- . unwrap ( )
100
- } ) ;
122
+ ) ?;
123
+ if res {
124
+ pos = Some ( i) ;
125
+ break ;
126
+ }
127
+ }
101
128
102
129
println ! ( "pos {:?}" , pos) ;
103
130
if let Some ( pos) = pos {
@@ -106,11 +133,35 @@ pub fn event_from_light_transaction(
106
133
println ! ( "event pubkey array {:?}" , event. pubkey_array) ;
107
134
println ! ( "input_sequence_numbers {:?}" , input_sequence_numbers) ;
108
135
println ! ( "address_sequence_numbers {:?}" , address_sequence_numbers) ;
136
+
137
+ // Nullifier queue indices are continous similar to sequence numbers.
138
+ // The emitted sequence number marks the first insertion into the queue in this tx.
139
+ // Iterate over all sequence numbers, match with input accounts Merkle tree and increment the sequence number.
140
+ // u64::MAX means it is a v1 account and it doesn't have a queue index.
141
+ let mut nullifier_queue_indices =
142
+ vec ! [ u64 :: MAX ; event. input_compressed_account_hashes. len( ) ] ;
143
+ let mut internal_input_sequence_numbers = input_sequence_numbers. clone ( ) ;
144
+ internal_input_sequence_numbers. iter_mut ( ) . for_each ( |seq| {
145
+ for ( i, merkle_tree_pubkey) in input_merkle_tree_indices. iter ( ) . enumerate ( ) {
146
+ println ! (
147
+ " seq pubkey {:?} == merkle tree pubkey {:?}" ,
148
+ seq. pubkey, * merkle_tree_pubkey
149
+ ) ;
150
+ if * merkle_tree_pubkey == seq. pubkey {
151
+ nullifier_queue_indices[ i] = seq. seq ;
152
+ seq. seq += 1 ;
153
+ }
154
+ }
155
+ } ) ;
156
+ println ! ( "input_merkle_tree_indices {:?}" , input_merkle_tree_indices) ;
157
+ println ! ( "nullifier_queue_indices {:?}" , nullifier_queue_indices) ;
158
+ println ! ( "input_sequence_numbers {:?}" , input_sequence_numbers) ;
109
159
Ok ( Some ( BatchPublicTransactionEvent {
110
160
event,
111
161
new_addresses,
112
162
input_sequence_numbers,
113
163
address_sequence_numbers,
164
+ nullifier_queue_indices,
114
165
} ) )
115
166
} else {
116
167
Ok ( None )
@@ -194,6 +245,8 @@ pub fn match_system_program_instruction(
194
245
set_cpi_context : bool ,
195
246
event : & mut PublicTransactionEvent ,
196
247
ix_set_cpi_context : & mut bool ,
248
+ input_merkle_tree_indices : & mut Vec < Pubkey > ,
249
+ accounts : & [ Pubkey ] ,
197
250
) -> Result < bool , ZeroCopyError > {
198
251
if instruction. len ( ) < 12 {
199
252
return Ok ( false ) ;
@@ -212,10 +265,21 @@ pub fn match_system_program_instruction(
212
265
event. relay_fee = data. relay_fee . map ( |x| ( * x) . into ( ) ) ;
213
266
event. compress_or_decompress_lamports =
214
267
data. compress_or_decompress_lamports . map ( |x| ( * x) . into ( ) ) ;
268
+ // We are only interested in remaining account which start after 9 static accounts.
269
+ let remaining_accounts = accounts. split_at ( 8 ) . 1 ;
270
+ data. input_compressed_accounts_with_merkle_context
271
+ . iter ( )
272
+ . for_each ( |x| {
273
+ input_merkle_tree_indices. push (
274
+ remaining_accounts[ x. merkle_context . merkle_tree_pubkey_index as usize ] ,
275
+ ) ;
276
+ } ) ;
215
277
Ok ( true )
216
278
}
217
279
DISCRIMINATOR_INVOKE_CPI => {
218
280
let ( data, _) = ZInstructionDataInvokeCpi :: zero_copy_at ( instruction) ?;
281
+ // We are only interested in remaining account which start after 10 static accounts.
282
+ let remaining_accounts = accounts. split_at ( 9 ) . 1 ;
219
283
// We need to find the instruction that executed the verification first.
220
284
// If cpi context was set we need to find those instructions afterwards and add them to the event.
221
285
if let Some ( cpi_context) = data. cpi_context {
@@ -230,6 +294,15 @@ pub fn match_system_program_instruction(
230
294
. output_compressed_accounts
231
295
. push ( OutputCompressedAccountWithPackedContext :: from ( x) ) ;
232
296
} ) ;
297
+ // We are only interested in remaining account which start after 9 static accounts.
298
+ data. input_compressed_accounts_with_merkle_context
299
+ . iter ( )
300
+ . for_each ( |x| {
301
+ input_merkle_tree_indices. push (
302
+ remaining_accounts
303
+ [ x. merkle_context . merkle_tree_pubkey_index as usize ] ,
304
+ ) ;
305
+ } ) ;
233
306
return Ok ( true ) ;
234
307
}
235
308
}
@@ -242,11 +315,20 @@ pub fn match_system_program_instruction(
242
315
event. relay_fee = data. relay_fee . map ( |x| ( * x) . into ( ) ) ;
243
316
event. compress_or_decompress_lamports =
244
317
data. compress_or_decompress_lamports . map ( |x| ( * x) . into ( ) ) ;
318
+ data. input_compressed_accounts_with_merkle_context
319
+ . iter ( )
320
+ . for_each ( |x| {
321
+ input_merkle_tree_indices. push (
322
+ remaining_accounts[ x. merkle_context . merkle_tree_pubkey_index as usize ] ,
323
+ ) ;
324
+ } ) ;
245
325
Ok ( true )
246
326
}
247
327
DISCRIMINATOR_INVOKE_CPI_WITH_READ_ONLY => {
248
328
let ( data, _) = ZInstructionDataInvokeCpiWithReadOnly :: zero_copy_at ( instruction) ?;
249
329
let data = data. invoke_cpi ;
330
+ // We are only interested in remaining account which start after 10 static accounts.
331
+ let remaining_accounts = accounts. split_at ( 9 ) . 1 ;
250
332
// We need to find the instruction that executed the verification first.
251
333
// If cpi context was set we need to find those instructions afterwards and add them to the event.
252
334
if let Some ( cpi_context) = data. cpi_context {
@@ -261,6 +343,14 @@ pub fn match_system_program_instruction(
261
343
. output_compressed_accounts
262
344
. push ( OutputCompressedAccountWithPackedContext :: from ( x) ) ;
263
345
} ) ;
346
+ data. input_compressed_accounts_with_merkle_context
347
+ . iter ( )
348
+ . for_each ( |x| {
349
+ input_merkle_tree_indices. push (
350
+ remaining_accounts
351
+ [ x. merkle_context . merkle_tree_pubkey_index as usize ] ,
352
+ ) ;
353
+ } ) ;
264
354
return Ok ( true ) ;
265
355
}
266
356
}
@@ -273,6 +363,13 @@ pub fn match_system_program_instruction(
273
363
event. relay_fee = data. relay_fee . map ( |x| ( * x) . into ( ) ) ;
274
364
event. compress_or_decompress_lamports =
275
365
data. compress_or_decompress_lamports . map ( |x| ( * x) . into ( ) ) ;
366
+ data. input_compressed_accounts_with_merkle_context
367
+ . iter ( )
368
+ . for_each ( |x| {
369
+ input_merkle_tree_indices. push (
370
+ remaining_accounts[ x. merkle_context . merkle_tree_pubkey_index as usize ] ,
371
+ ) ;
372
+ } ) ;
276
373
Ok ( true )
277
374
}
278
375
_ => Ok ( false ) ,
0 commit comments