1use std::collections::{BTreeMap, HashMap, VecDeque};
2
3use ark_ff::Zero;
4use mina_curves::pasta::Fp;
5use mina_signer::CompressedPubKey;
6use poseidon::hash::params::get_merkle_param_for_height;
7
8use crate::{
9 scan_state::{currency::Slot, transaction_logic::AccountState},
10 Account, AccountId, AccountIndex, Address, AddressIterator, BaseLedger, Direction,
11 HashesMatrix, Mask, MerklePath, TreeVersion, V2,
12};
13
14use super::LedgerIntf;
15
16#[derive(Clone, Debug, PartialEq)]
17pub(super) struct SparseLedgerImpl<K: Eq + std::hash::Hash, V> {
18 pub values: BTreeMap<AccountIndex, V>,
19 pub indexes: HashMap<K, Address>,
20 pub indexes_list: VecDeque<K>,
22 pub hashes_matrix: HashesMatrix,
23 pub depth: usize,
24}
25
26impl SparseLedgerImpl<AccountId, Account> {
27 pub fn create(depth: usize, root_hash: Fp) -> Self {
28 let mut hashes_matrix = HashesMatrix::new(depth);
29 hashes_matrix.set(&Address::root(), root_hash);
30
31 Self {
32 values: BTreeMap::new(),
33 indexes: HashMap::new(),
34 indexes_list: VecDeque::new(),
35 depth,
36 hashes_matrix,
37 }
38 }
39
40 pub fn of_ledger_subset_exn(oledger: Mask, keys: &[AccountId]) -> Self {
41 use crate::GetOrCreated::{Added, Existed};
42
43 let mut ledger = oledger.copy();
44 let mut sparse = Self::create(
45 ledger.depth() as usize,
46 BaseLedger::merkle_root(&mut ledger),
47 );
48
49 for key in keys {
50 match BaseLedger::location_of_account(&ledger, key) {
51 Some(addr) => {
52 let account = BaseLedger::get(&ledger, addr.clone()).unwrap();
53 let merkle_path = ledger.merkle_path(addr);
54 sparse.add_path(&merkle_path, key.clone(), *account);
55 }
56 None => {
57 let addr = match ledger
58 .get_or_create_account(key.clone(), Account::empty())
59 .unwrap()
60 {
61 Added(addr) => addr,
62 Existed(_) => panic!("create_empty for a key already present"),
63 };
64
65 let merkle_path = ledger.merkle_path(addr);
66 sparse.add_path(&merkle_path, key.clone(), Account::empty());
67 }
68 }
69 }
70
71 assert_eq!(BaseLedger::merkle_root(&mut ledger), sparse.merkle_root());
72
73 sparse
74 }
75
76 fn get_or_initialize_exn(
77 &self,
78 account_id: &AccountId,
79 addr: &Address,
80 ) -> (AccountState, Account) {
81 let mut account = self.get_exn(addr).clone();
82
83 if account.public_key == CompressedPubKey::empty() {
84 let public_key = account_id.public_key.clone();
85 let token_id = account_id.token_id.clone();
86
87 let delegate = if token_id.is_default() {
89 Some(public_key.clone())
90 } else {
91 None
92 };
93
94 account.delegate = delegate;
95 account.public_key = public_key;
96 account.token_id = token_id;
97
98 (AccountState::Added, account)
99 } else {
100 (AccountState::Existed, account)
101 }
102 }
103
104 pub fn has_locked_tokens_exn(&self, global_slot: Slot, account_id: AccountId) -> bool {
105 let addr = self.find_index_exn(account_id.clone());
106 let (_, account) = self.get_or_initialize_exn(&account_id, &addr);
107 account.has_locked_tokens(global_slot)
108 }
109
110 pub fn iteri<F>(&self, fun: F)
111 where
112 F: Fn(Address, &Account),
113 {
114 let addr = |index: &AccountIndex| Address::from_index(*index, self.depth);
115
116 for (index, value) in &self.values {
117 fun(addr(index), value);
118 }
119 }
120
121 pub fn add_path(
122 &mut self,
123 merkle_path: &[MerklePath],
124 account_id: AccountId,
125 account: Account,
126 ) {
127 assert_eq!(self.depth, merkle_path.len());
128
129 let mut set_hash = |addr: Address, hash: &Fp| {
130 if let Some(prev_hash) = self.hashes_matrix.get(&addr) {
131 assert_eq!(prev_hash, hash);
132 return;
133 };
134
135 self.hashes_matrix.set(&addr, *hash);
136 };
137
138 let mut addr = Address::root();
139
140 for path in merkle_path.iter().rev() {
142 addr = match path {
143 MerklePath::Left(right) => {
144 set_hash(addr.child_right(), right);
145 addr.child_left()
146 }
147 MerklePath::Right(left) => {
148 set_hash(addr.child_left(), left);
149 addr.child_right()
150 }
151 }
152 }
153
154 let account_addr = addr.clone();
155
156 let mut current = account.hash();
157
158 for (height, path) in merkle_path.iter().enumerate() {
160 set_hash(addr.clone(), ¤t);
161
162 let hashes = match path {
163 MerklePath::Left(right) => [current, *right],
164 MerklePath::Right(left) => [*left, current],
165 };
166
167 let param = get_merkle_param_for_height(height);
168 current = poseidon::hash::hash_with_kimchi(param, &hashes);
169
170 addr = addr.parent().unwrap();
171 }
172
173 assert!(addr.is_root());
174 set_hash(addr, ¤t);
175
176 let index = account_addr.to_index();
177 self.indexes
178 .entry(account_id.clone())
179 .or_insert(account_addr);
180 self.indexes_list.push_front(account_id);
181 self.values.insert(index, account);
182 }
183
184 pub(super) fn get_index(&self, account_id: &AccountId) -> Option<&Address> {
185 self.indexes.get(account_id)
186 }
187
188 fn get(&self, addr: &Address) -> Option<&Account> {
189 assert_eq!(addr.length(), self.depth);
190
191 let index = addr.to_index();
192 self.values.get(&index)
193 }
194
195 pub fn get_exn(&self, addr: &Address) -> &Account {
196 self.get(addr).unwrap()
197 }
198
199 pub fn set_exn(&mut self, addr: Address, value: Box<Account>) {
200 assert_eq!(addr.length(), self.depth);
201
202 let index = addr.to_index();
203 self.values.insert(index, *value);
204
205 self.hashes_matrix.invalidate_hashes(addr.to_index());
206 }
207
208 pub fn find_index_exn(&self, key: AccountId) -> Address {
209 self.get_index(&key).cloned().unwrap()
210 }
211
212 pub fn path_exn(&mut self, addr: Address) -> Vec<MerklePath> {
213 let mut merkle_path = Vec::with_capacity(addr.length());
214 let mut path_to_addr = addr.into_iter();
215 let root = Address::root();
216
217 self.emulate_tree_to_get_path(root, &mut path_to_addr, &mut merkle_path);
218
219 merkle_path
220 }
221
222 fn get_value_hash(&mut self, addr: Address) -> Fp {
223 if let Some(hash) = self.hashes_matrix.get(&addr) {
224 return *hash;
225 }
226
227 let hash = match self.get(&addr) {
228 Some(value) => V2::hash_leaf(value),
229 None => V2::empty_hash_at_height(0),
230 };
231
232 self.hashes_matrix.set(&addr, hash);
233
234 hash
235 }
236
237 fn get_node_hash(&mut self, addr: &Address, left: Fp, right: Fp) -> Fp {
238 if let Some(hash) = self.hashes_matrix.get(addr) {
239 return *hash;
240 };
241
242 let depth_in_tree = self.depth - addr.length();
243
244 let hash = V2::hash_node(depth_in_tree - 1, left, right);
245 self.hashes_matrix.set(addr, hash);
246 hash
247 }
248
249 fn emulate_tree_to_get_path(
250 &mut self,
251 addr: Address,
252 path: &mut AddressIterator,
253 merkle_path: &mut Vec<MerklePath>,
254 ) -> Fp {
255 if addr.length() == self.depth {
256 return self.get_value_hash(addr);
257 }
258
259 let next_direction = path.next();
260
261 if let Some(direction) = next_direction.as_ref() {
263 let child = match direction {
264 Direction::Left => addr.child_left(),
265 Direction::Right => addr.child_right(),
266 };
267 self.emulate_tree_to_get_path(child, path, merkle_path);
268 };
269
270 let mut get_child_hash = |addr: Address| match self.hashes_matrix.get(&addr) {
271 Some(hash) => *hash,
272 None => {
273 if let Some(hash) = self.hashes_matrix.get(&addr) {
274 *hash
275 } else {
276 self.emulate_tree_to_get_path(addr, path, merkle_path)
277 }
278 }
279 };
280
281 let left = get_child_hash(addr.child_left());
282 let right = get_child_hash(addr.child_right());
283
284 if let Some(direction) = next_direction {
285 let hash = match direction {
286 Direction::Left => MerklePath::Left(right),
287 Direction::Right => MerklePath::Right(left),
288 };
289 merkle_path.push(hash);
290 };
291
292 self.get_node_hash(&addr, left, right)
293 }
294
295 pub fn merkle_root(&mut self) -> Fp {
296 let root = Address::root();
297
298 if let Some(hash) = self.hashes_matrix.get(&root) {
299 return *hash;
300 };
301
302 self.emulate_tree_merkle_root(root)
303 }
304
305 pub fn emulate_tree_merkle_root(&mut self, addr: Address) -> Fp {
306 let current_depth = self.depth - addr.length();
307
308 if current_depth == 0 {
309 return self.get_value_hash(addr);
310 }
311
312 let mut get_child_hash = |addr: Address| {
313 if let Some(hash) = self.hashes_matrix.get(&addr) {
314 *hash
315 } else {
316 self.emulate_tree_merkle_root(addr)
317 }
318 };
319
320 let left_hash = get_child_hash(addr.child_left());
321 let right_hash = get_child_hash(addr.child_right());
322
323 self.get_node_hash(&addr, left_hash, right_hash)
324 }
325
326 fn location_of_account_impl(&self, account_id: &AccountId) -> Option<Address> {
327 self.get_index(account_id).cloned()
328 }
329
330 }
336
337impl LedgerIntf for SparseLedgerImpl<AccountId, Account> {
338 type Location = Address;
339
340 fn get(&self, addr: &Self::Location) -> Option<Box<Account>> {
342 let account = self.get(addr)?;
343
344 if account.public_key == CompressedPubKey::empty() {
345 None
346 } else {
347 Some(Box::new(account.clone()))
348 }
349 }
350
351 fn location_of_account(&self, account_id: &AccountId) -> Option<Self::Location> {
353 let addr = self.get_index(account_id)?;
354 let account = self.get(addr)?;
355
356 if account.public_key == CompressedPubKey::empty() {
357 None
358 } else {
359 Some(addr.clone())
360 }
361 }
362
363 fn set(&mut self, addr: &Self::Location, account: Box<Account>) {
365 self.set_exn(addr.clone(), account);
366 }
367
368 fn get_or_create(
370 &mut self,
371 account_id: &AccountId,
372 ) -> Result<(AccountState, Box<Account>, Self::Location), String> {
373 let addr = self
374 .get_index(account_id)
375 .ok_or_else(|| "failed".to_string())?;
376 let account = self.get(addr).ok_or_else(|| "failed".to_string())?;
377 let mut account = Box::new(account.clone());
378
379 let addr = addr.clone();
380 if account.public_key == CompressedPubKey::empty() {
381 let public_key = account_id.public_key.clone();
382
383 account.delegate = Some(public_key.clone());
384 account.public_key = public_key;
385 account.token_id = account_id.token_id.clone();
386
387 self.set(&addr, account.clone());
388 Ok((AccountState::Added, account, addr))
389 } else {
390 Ok((AccountState::Existed, account, addr))
391 }
392 }
393
394 fn create_new_account(&mut self, account_id: AccountId, to_set: Account) -> Result<(), ()> {
396 let addr = self.get_index(&account_id).ok_or(())?;
397 let account = self.get(addr).ok_or(())?;
398
399 if account.public_key == CompressedPubKey::empty() {
400 let addr = addr.clone();
401 self.set(&addr, Box::new(to_set));
402 }
403
404 Ok(())
405 }
406
407 fn remove_accounts_exn(&mut self, _account_ids: &[AccountId]) {
409 unimplemented!("remove_accounts_exn: not implemented")
410 }
411
412 fn merkle_root(&mut self) -> Fp {
414 self.merkle_root()
415 }
416
417 fn empty(depth: usize) -> Self {
419 Self::create(depth, Fp::zero())
420 }
421
422 fn create_masked(&self) -> Self {
423 unimplemented!() }
425
426 fn apply_mask(&mut self, _mask: Self) {
427 unimplemented!() }
429
430 fn account_locations(&self) -> Vec<Self::Location> {
431 let mut addrs: Vec<Address> = self.indexes.values().cloned().collect();
432
433 addrs.sort_by_key(Address::to_index);
434
435 addrs
436 }
437}