1use std::collections::HashMap;
2
3use anchor_lang::prelude::{AccountMeta, AnchorDeserialize, AnchorSerialize, Pubkey};
4
5#[derive(Default)]
7pub struct RemainingAccounts {
8 next_index: u8,
9 map: HashMap<Pubkey, u8>,
10}
11
12impl RemainingAccounts {
13 pub fn insert_or_get(&mut self, pubkey: Pubkey) -> u8 {
21 *self.map.entry(pubkey).or_insert_with(|| {
22 let index = self.next_index;
23 self.next_index += 1;
24 index
25 })
26 }
27
28 pub fn to_account_metas(&self) -> Vec<AccountMeta> {
32 let mut remaining_accounts = self
33 .map
34 .iter()
35 .map(|(k, i)| {
36 (
37 AccountMeta {
38 pubkey: *k,
39 is_signer: false,
40 is_writable: true,
41 },
42 *i as usize,
43 )
44 })
45 .collect::<Vec<(AccountMeta, usize)>>();
46 remaining_accounts.sort_by(|a, b| a.1.cmp(&b.1));
48 let remaining_accounts = remaining_accounts
49 .iter()
50 .map(|(k, _)| k.clone())
51 .collect::<Vec<AccountMeta>>();
52 remaining_accounts
53 }
54}
55
56#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
57pub struct QueueIndex {
58 pub queue_id: u8,
60 pub index: u16,
62}
63
64#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
65pub struct MerkleContext {
66 pub merkle_tree_pubkey: Pubkey,
67 pub nullifier_queue_pubkey: Pubkey,
68 pub leaf_index: u32,
69 pub queue_index: Option<QueueIndex>,
72}
73
74#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
75pub struct PackedMerkleContext {
76 pub merkle_tree_pubkey_index: u8,
77 pub nullifier_queue_pubkey_index: u8,
78 pub leaf_index: u32,
79 pub queue_index: Option<QueueIndex>,
82}
83
84pub fn pack_merkle_contexts(
85 merkle_contexts: &[MerkleContext],
86 remaining_accounts: &mut RemainingAccounts,
87) -> Vec<PackedMerkleContext> {
88 merkle_contexts
89 .iter()
90 .map(|x| {
91 let merkle_tree_pubkey_index = remaining_accounts.insert_or_get(x.merkle_tree_pubkey);
92 let nullifier_queue_pubkey_index =
93 remaining_accounts.insert_or_get(x.nullifier_queue_pubkey);
94 PackedMerkleContext {
95 merkle_tree_pubkey_index,
96 nullifier_queue_pubkey_index,
97 leaf_index: x.leaf_index,
98 queue_index: x.queue_index,
99 }
100 })
101 .collect::<Vec<_>>()
102}
103
104pub fn pack_merkle_context(
105 merkle_context: MerkleContext,
106 remaining_accounts: &mut RemainingAccounts,
107) -> PackedMerkleContext {
108 pack_merkle_contexts(&[merkle_context], remaining_accounts)[0]
109}
110
111#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
121pub struct MerkleOutputContext {
122 pub merkle_tree_pubkey: Pubkey,
123}
124
125#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
135pub struct PackedMerkleOutputContext {
136 pub merkle_tree_pubkey_index: u8,
137}
138
139pub fn pack_merkle_output_contexts(
142 merkle_contexts: &[MerkleOutputContext],
143 remaining_accounts: &mut RemainingAccounts,
144) -> Vec<PackedMerkleOutputContext> {
145 merkle_contexts
146 .iter()
147 .map(|x| {
148 let merkle_tree_pubkey_index = remaining_accounts.insert_or_get(x.merkle_tree_pubkey);
149 PackedMerkleOutputContext {
150 merkle_tree_pubkey_index,
151 }
152 })
153 .collect::<Vec<_>>()
154}
155
156pub fn pack_merkle_output_context(
159 merkle_output_context: MerkleOutputContext,
160 remaining_accounts: &mut RemainingAccounts,
161) -> PackedMerkleOutputContext {
162 pack_merkle_output_contexts(&[merkle_output_context], remaining_accounts)[0]
163}
164
165#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
166pub struct AddressMerkleContext {
167 pub address_merkle_tree_pubkey: Pubkey,
168 pub address_queue_pubkey: Pubkey,
169}
170
171#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Default)]
172pub struct PackedAddressMerkleContext {
173 pub address_merkle_tree_pubkey_index: u8,
174 pub address_queue_pubkey_index: u8,
175}
176
177pub fn pack_address_merkle_contexts(
180 address_merkle_contexts: &[AddressMerkleContext],
181 remaining_accounts: &mut RemainingAccounts,
182) -> Vec<PackedAddressMerkleContext> {
183 address_merkle_contexts
184 .iter()
185 .map(|x| {
186 let address_merkle_tree_pubkey_index =
187 remaining_accounts.insert_or_get(x.address_merkle_tree_pubkey);
188 let address_queue_pubkey_index =
189 remaining_accounts.insert_or_get(x.address_queue_pubkey);
190 PackedAddressMerkleContext {
191 address_merkle_tree_pubkey_index,
192 address_queue_pubkey_index,
193 }
194 })
195 .collect::<Vec<_>>()
196}
197
198pub fn pack_address_merkle_context(
201 address_merkle_context: AddressMerkleContext,
202 remaining_accounts: &mut RemainingAccounts,
203) -> PackedAddressMerkleContext {
204 pack_address_merkle_contexts(&[address_merkle_context], remaining_accounts)[0]
205}