Skip to content

Commit 051fe83

Browse files
authored
feat: parse nullifier queue indices from event (#1598)
1 parent b9eebe4 commit 051fe83

File tree

1 file changed

+111
-14
lines changed
  • program-libs/compressed-account/src

1 file changed

+111
-14
lines changed

program-libs/compressed-account/src/event.rs

Lines changed: 111 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ pub struct BatchPublicTransactionEvent {
4343
pub new_addresses: Vec<NewAddress>,
4444
pub input_sequence_numbers: Vec<MerkleTreeSequenceNumber>,
4545
pub address_sequence_numbers: Vec<MerkleTreeSequenceNumber>,
46+
pub nullifier_queue_indices: Vec<u64>,
4647
}
4748

48-
// TODO: remove unwraps
4949
/// We piece the event together from 2 instructions:
5050
/// 1. light_system_program::{Invoke, InvokeCpi, InvokeCpiReadOnly} (one of the 3)
5151
/// 2. account_compression::InsertIntoQueues
@@ -65,39 +65,66 @@ pub fn event_from_light_transaction(
6565
) -> Result<Option<BatchPublicTransactionEvent>, ZeroCopyError> {
6666
let mut event = PublicTransactionEvent::default();
6767
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+
});
7183
println!("found event {}", found_event);
7284
if !found_event {
7385
return Ok(None);
7486
}
7587
println!("ix_set_cpi_context {}", ix_set_cpi_context);
7688
// If an instruction set the cpi context add the instructions that set the cpi context.
7789
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+
})?;
81104
println!("added cpi context to event {}", found_event);
82105
}
83106
// New addresses in batched trees.
84107
let mut new_addresses = Vec::new();
85108
let mut input_sequence_numbers = Vec::new();
86109
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() {
88112
if remaining_accounts[i].len() < 3 {
89-
return false;
113+
continue;
90114
}
91-
match_account_compression_program_instruction(
92-
x,
115+
let res = match_account_compression_program_instruction(
116+
instruction,
93117
&mut event,
94118
&mut new_addresses,
95119
&mut input_sequence_numbers,
96120
&mut address_sequence_numbers,
97121
&remaining_accounts[i][2..],
98-
)
99-
.unwrap()
100-
});
122+
)?;
123+
if res {
124+
pos = Some(i);
125+
break;
126+
}
127+
}
101128

102129
println!("pos {:?}", pos);
103130
if let Some(pos) = pos {
@@ -106,11 +133,35 @@ pub fn event_from_light_transaction(
106133
println!("event pubkey array {:?}", event.pubkey_array);
107134
println!("input_sequence_numbers {:?}", input_sequence_numbers);
108135
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);
109159
Ok(Some(BatchPublicTransactionEvent {
110160
event,
111161
new_addresses,
112162
input_sequence_numbers,
113163
address_sequence_numbers,
164+
nullifier_queue_indices,
114165
}))
115166
} else {
116167
Ok(None)
@@ -194,6 +245,8 @@ pub fn match_system_program_instruction(
194245
set_cpi_context: bool,
195246
event: &mut PublicTransactionEvent,
196247
ix_set_cpi_context: &mut bool,
248+
input_merkle_tree_indices: &mut Vec<Pubkey>,
249+
accounts: &[Pubkey],
197250
) -> Result<bool, ZeroCopyError> {
198251
if instruction.len() < 12 {
199252
return Ok(false);
@@ -212,10 +265,21 @@ pub fn match_system_program_instruction(
212265
event.relay_fee = data.relay_fee.map(|x| (*x).into());
213266
event.compress_or_decompress_lamports =
214267
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+
});
215277
Ok(true)
216278
}
217279
DISCRIMINATOR_INVOKE_CPI => {
218280
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;
219283
// We need to find the instruction that executed the verification first.
220284
// If cpi context was set we need to find those instructions afterwards and add them to the event.
221285
if let Some(cpi_context) = data.cpi_context {
@@ -230,6 +294,15 @@ pub fn match_system_program_instruction(
230294
.output_compressed_accounts
231295
.push(OutputCompressedAccountWithPackedContext::from(x));
232296
});
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+
});
233306
return Ok(true);
234307
}
235308
}
@@ -242,11 +315,20 @@ pub fn match_system_program_instruction(
242315
event.relay_fee = data.relay_fee.map(|x| (*x).into());
243316
event.compress_or_decompress_lamports =
244317
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+
});
245325
Ok(true)
246326
}
247327
DISCRIMINATOR_INVOKE_CPI_WITH_READ_ONLY => {
248328
let (data, _) = ZInstructionDataInvokeCpiWithReadOnly::zero_copy_at(instruction)?;
249329
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;
250332
// We need to find the instruction that executed the verification first.
251333
// If cpi context was set we need to find those instructions afterwards and add them to the event.
252334
if let Some(cpi_context) = data.cpi_context {
@@ -261,6 +343,14 @@ pub fn match_system_program_instruction(
261343
.output_compressed_accounts
262344
.push(OutputCompressedAccountWithPackedContext::from(x));
263345
});
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+
});
264354
return Ok(true);
265355
}
266356
}
@@ -273,6 +363,13 @@ pub fn match_system_program_instruction(
273363
event.relay_fee = data.relay_fee.map(|x| (*x).into());
274364
event.compress_or_decompress_lamports =
275365
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+
});
276373
Ok(true)
277374
}
278375
_ => Ok(false),

0 commit comments

Comments
 (0)