light_system_program/sdk/
address.rs1use std::collections::HashMap;
2
3use anchor_lang::{err, solana_program::pubkey::Pubkey, Result};
4use light_utils::hash_to_bn254_field_size_be;
5
6use crate::{errors::SystemProgramError, NewAddressParams, NewAddressParamsPacked};
7pub fn derive_address(merkle_tree_pubkey: &Pubkey, seed: &[u8; 32]) -> Result<[u8; 32]> {
8 let hash = match hash_to_bn254_field_size_be(
9 [merkle_tree_pubkey.to_bytes(), *seed].concat().as_slice(),
10 ) {
11 Some(hash) => Ok::<[u8; 32], SystemProgramError>(hash.0),
12 None => return err!(SystemProgramError::DeriveAddressError),
13 }?;
14
15 Ok(hash)
16}
17
18pub fn add_and_get_remaining_account_indices(
19 pubkeys: &[Pubkey],
20 remaining_accounts: &mut HashMap<Pubkey, usize>,
21) -> Vec<u8> {
22 let mut vec = Vec::new();
23 let mut next_index: usize = remaining_accounts.len();
24 for pubkey in pubkeys.iter() {
25 match remaining_accounts.get(pubkey) {
26 Some(_) => {}
27 None => {
28 remaining_accounts.insert(*pubkey, next_index);
29 next_index += 1;
30 }
31 };
32 vec.push(*remaining_accounts.get(pubkey).unwrap() as u8);
33 }
34 vec
35}
36pub fn pack_new_address_params(
38 new_address_params: &[NewAddressParams],
39 remaining_accounts: &mut HashMap<Pubkey, usize>,
40) -> Vec<NewAddressParamsPacked> {
41 let mut new_address_params_packed = new_address_params
42 .iter()
43 .map(|x| NewAddressParamsPacked {
44 seed: x.seed,
45 address_merkle_tree_root_index: x.address_merkle_tree_root_index,
46 address_merkle_tree_account_index: 0, address_queue_account_index: 0, })
49 .collect::<Vec<NewAddressParamsPacked>>();
50 let mut next_index: usize = remaining_accounts.len();
51 for (i, params) in new_address_params.iter().enumerate() {
52 match remaining_accounts.get(¶ms.address_merkle_tree_pubkey) {
53 Some(_) => {}
54 None => {
55 remaining_accounts.insert(params.address_merkle_tree_pubkey, next_index);
56 next_index += 1;
57 }
58 };
59 new_address_params_packed[i].address_merkle_tree_account_index = *remaining_accounts
60 .get(¶ms.address_merkle_tree_pubkey)
61 .unwrap()
62 as u8;
63 }
64
65 for (i, params) in new_address_params.iter().enumerate() {
66 match remaining_accounts.get(¶ms.address_queue_pubkey) {
67 Some(_) => {}
68 None => {
69 remaining_accounts.insert(params.address_queue_pubkey, next_index);
70 next_index += 1;
71 }
72 };
73 new_address_params_packed[i].address_queue_account_index = *remaining_accounts
74 .get(¶ms.address_queue_pubkey)
75 .unwrap() as u8;
76 }
77 new_address_params_packed
78}
79
80#[cfg(test)]
81mod tests {
82 use solana_sdk::{signature::Keypair, signer::Signer};
83
84 use super::*;
85
86 #[test]
87 fn test_derive_address_with_valid_input() {
88 let merkle_tree_pubkey = Keypair::new().pubkey();
89 let seeds = [1u8; 32];
90 let result = derive_address(&merkle_tree_pubkey, &seeds);
91 let result_2 = derive_address(&merkle_tree_pubkey, &seeds);
92 assert_eq!(result, result_2);
93 }
94
95 #[test]
96 fn test_derive_address_no_collision_same_seeds_diff_pubkey() {
97 let merkle_tree_pubkey = Keypair::new().pubkey();
98 let merkle_tree_pubkey_2 = Keypair::new().pubkey();
99 let seed = [2u8; 32];
100
101 let result = derive_address(&merkle_tree_pubkey, &seed);
102 let result_2 = derive_address(&merkle_tree_pubkey_2, &seed);
103 assert_ne!(result, result_2);
104 }
105
106 #[test]
107 fn test_add_and_get_remaining_account_indices_empty() {
108 let pubkeys = vec![];
109 let mut remaining_accounts = HashMap::new();
110 let result = add_and_get_remaining_account_indices(&pubkeys, &mut remaining_accounts);
111 assert!(result.is_empty());
112 }
113
114 #[test]
115 fn test_add_and_get_remaining_account_indices_single() {
116 let pubkey = Keypair::new().pubkey();
117 let pubkeys = vec![pubkey];
118 let mut remaining_accounts = HashMap::new();
119 let result = add_and_get_remaining_account_indices(&pubkeys, &mut remaining_accounts);
120 assert_eq!(result, vec![0]);
121 assert_eq!(remaining_accounts.get(&pubkey), Some(&0));
122 }
123
124 #[test]
125 fn test_add_and_get_remaining_account_indices_multiple() {
126 let pubkey1 = Keypair::new().pubkey();
127 let pubkey2 = Keypair::new().pubkey();
128 let pubkeys = vec![pubkey1, pubkey2];
129 let mut remaining_accounts = HashMap::new();
130 let result = add_and_get_remaining_account_indices(&pubkeys, &mut remaining_accounts);
131 assert_eq!(result, vec![0, 1]);
132 assert_eq!(remaining_accounts.get(&pubkey1), Some(&0));
133 assert_eq!(remaining_accounts.get(&pubkey2), Some(&1));
134 }
135
136 #[test]
137 fn test_add_and_get_remaining_account_indices_duplicates() {
138 let pubkey = Keypair::new().pubkey();
139 let pubkeys = vec![pubkey, pubkey];
140 let mut remaining_accounts = HashMap::new();
141 let result = add_and_get_remaining_account_indices(&pubkeys, &mut remaining_accounts);
142 assert_eq!(result, vec![0, 0]);
143 assert_eq!(remaining_accounts.get(&pubkey), Some(&0));
144 assert_eq!(remaining_accounts.len(), 1);
145 }
146
147 #[test]
148 fn test_add_and_get_remaining_account_indices_multiple_duplicates() {
149 let pubkey1 = Keypair::new().pubkey();
150 let pubkey2 = Keypair::new().pubkey();
151 let pubkey3 = Keypair::new().pubkey();
152 let pubkeys = vec![pubkey1, pubkey2, pubkey1, pubkey3, pubkey2, pubkey1];
153 let mut remaining_accounts = HashMap::new();
154 let result = add_and_get_remaining_account_indices(&pubkeys, &mut remaining_accounts);
155 assert_eq!(result, vec![0, 1, 0, 2, 1, 0]);
156 assert_eq!(remaining_accounts.get(&pubkey1), Some(&0));
157 assert_eq!(remaining_accounts.get(&pubkey2), Some(&1));
158 assert_eq!(remaining_accounts.get(&pubkey3), Some(&2));
159 assert_eq!(remaining_accounts.len(), 3);
160 }
161}