1use std::{
2 collections::{HashMap, HashSet},
3 path::PathBuf,
4};
5
6use mina_curves::pasta::Fp;
7use mina_signer::CompressedPubKey;
8
9use crate::{
10 account::{Account, AccountId, TokenId},
11 address::{Address, AddressIterator, Direction},
12 base::{AccountIndex, BaseLedger, GetOrCreated, MerklePath, Uuid},
13 database::{Database, DatabaseError},
14 mask::UnregisterBehavior,
15 next_uuid,
16 tree_version::{TreeVersion, V2},
17 HashesMatrix,
18};
19
20use super::Mask;
21
22pub enum MaskImpl {
23 Root {
24 database: Database<V2>,
25 childs: HashMap<Uuid, Mask>,
26 },
27 Attached {
28 parent: Mask,
29 owning_account: HashMap<AccountIndex, Account>,
30 token_owners: Option<HashMap<TokenId, AccountId>>,
31 id_to_addr: HashMap<AccountId, Address>,
32 last_location: Option<Address>,
33 depth: u8,
34 childs: HashMap<Uuid, Mask>,
35 hashes: HashesMatrix,
36 uuid: Uuid,
37 },
38 Unattached {
39 depth: u8,
40 childs: HashMap<Uuid, Mask>,
41 owning_account: HashMap<AccountIndex, Account>,
42 token_owners: Option<HashMap<TokenId, AccountId>>,
43 id_to_addr: HashMap<AccountId, Address>,
44 last_location: Option<Address>,
45 hashes: HashesMatrix,
46 uuid: Uuid,
47 },
48}
49
50impl Drop for MaskImpl {
51 fn drop(&mut self) {
52 if self.uuid().starts_with("temporary") {
53 return;
54 }
55 super::alive_remove(&self.get_uuid());
56 }
57}
58
59impl Clone for MaskImpl {
60 fn clone(&self) -> Self {
61 let copy = match self {
62 Self::Root { database, childs } => Self::Root {
63 database: database.clone_db(database.get_directory().unwrap()),
64 childs: childs.clone(),
65 },
66 Self::Attached {
67 parent,
68 owning_account,
69 token_owners,
70 id_to_addr,
71 last_location,
72 depth,
73 childs,
74 hashes,
75 uuid: _,
76 } => Self::Attached {
77 parent: parent.clone(),
78 owning_account: owning_account.clone(),
79 token_owners: token_owners.clone(),
80 id_to_addr: id_to_addr.clone(),
81 last_location: last_location.clone(),
82 depth: *depth,
83 childs: childs.clone(),
84 hashes: hashes.clone(),
85 uuid: next_uuid(),
86 },
87 Self::Unattached {
88 depth,
89 childs,
90 owning_account,
91 token_owners,
92 id_to_addr,
93 last_location,
94 hashes,
95 uuid: _,
96 } => Self::Unattached {
97 depth: *depth,
98 childs: childs.clone(),
99 owning_account: owning_account.clone(),
100 token_owners: token_owners.clone(),
101 id_to_addr: id_to_addr.clone(),
102 last_location: last_location.clone(),
103 hashes: hashes.clone(),
104 uuid: next_uuid(),
105 },
106 };
107 super::alive_add(©.uuid());
108 copy
109 }
110}
111
112impl std::fmt::Debug for MaskImpl {
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 match self {
115 Self::Root { database, childs } => f
116 .debug_struct("Root")
117 .field("database_uuid", &database.get_uuid())
118 .field("database", &database)
119 .field("childs", &childs.len())
120 .finish(),
121 Self::Attached {
122 parent,
123 owning_account,
124 token_owners,
125 id_to_addr,
126 last_location,
127 depth,
128 childs,
129 hashes,
130 uuid,
131 } => f
132 .debug_struct("Attached")
133 .field("uuid", uuid)
134 .field("parent", &parent.get_uuid())
135 .field("owning_account", &owning_account.len())
136 .field(
137 "token_owners",
138 &token_owners.as_ref().map(|to| to.len()).unwrap_or(0),
139 )
140 .field("id_to_addr", &id_to_addr.len())
141 .field("last_location", last_location)
142 .field("depth", depth)
143 .field("num_accounts", &self.num_accounts())
144 .field("childs", &childs.len())
145 .field("hashes_matrix", &hashes)
146 .finish(),
147 Self::Unattached {
148 depth,
149 childs,
150 owning_account,
151 token_owners,
152 id_to_addr,
153 last_location,
154 hashes,
155 uuid,
156 } => f
157 .debug_struct("Unattached")
158 .field("depth", depth)
159 .field("childs", &childs.len())
160 .field("owning_account", &owning_account.len())
161 .field(
162 "token_owners",
163 &token_owners.as_ref().map(|to| to.len()).unwrap_or(0),
164 )
165 .field("id_to_addr", &id_to_addr.len())
166 .field("last_location", last_location)
167 .field("uuid", uuid)
168 .field("hashes_matrix", &hashes)
169 .finish(),
170 }
171 }
172}
173
174use MaskImpl::*;
175
176#[derive(Debug)]
178pub enum MaskImplShort {
179 Root______(Uuid),
180 Attached__(Uuid),
181 Unattached(Uuid),
182}
183
184impl MaskImpl {
185 pub fn short(&self) -> MaskImplShort {
187 match self {
188 Root { database, .. } => MaskImplShort::Root______(database.get_uuid()),
189 Attached { uuid, .. } => MaskImplShort::Attached__(uuid.clone()),
190 Unattached { uuid, .. } => MaskImplShort::Unattached(uuid.clone()),
191 }
192 }
193
194 pub fn is_root(&self) -> bool {
195 match self {
196 Root { .. } => true,
197 Attached { .. } | Unattached { .. } => false,
198 }
199 }
200
201 pub fn is_attached(&self) -> bool {
202 match self {
203 Attached { .. } => true,
204 Root { .. } | Unattached { .. } => false,
205 }
206 }
207
208 pub(super) fn any_child_alive(&self) -> bool {
209 let childs = match self {
210 Root { childs, .. } => childs,
211 Attached { childs, .. } => childs,
212 Unattached { childs, .. } => childs,
213 };
214
215 !childs.is_empty()
216 }
217
218 pub fn set_token_owners(&mut self) {
219 match self {
220 Root { database, .. } => database.set_token_owners(),
221 Attached { token_owners, .. } | Unattached { token_owners, .. } => {
222 if token_owners.is_none() {
223 *token_owners = Some(Default::default());
224 }
225 }
226 }
227 }
228
229 pub fn unset_token_owners(&mut self) {
230 match self {
231 Root { database, .. } => {
232 database.unset_token_owners();
233 }
234 Attached { token_owners, .. } | Unattached { token_owners, .. } => {
235 *token_owners = None;
236 }
237 }
238 }
239
240 pub fn has_token_owners(&self) -> bool {
241 match self {
242 Root { database, .. } => database.has_token_owners(),
243 Attached { token_owners, .. } => token_owners.is_some(),
244 Unattached { token_owners, .. } => token_owners.is_some(),
245 }
246 }
247
248 pub fn register_mask(&mut self, self_mask: Mask, mask: Mask) -> Mask {
250 let childs = self.childs();
251
252 let old = childs.insert(mask.get_uuid(), mask.clone());
253 assert!(old.is_none(), "mask is already registered");
254
255 let parent_last_filled = self.last_filled();
256
257 mask.set_parent(self_mask, Some(parent_last_filled));
258 mask
259 }
260
261 pub fn unregister_mask(&mut self, behavior: UnregisterBehavior, remove_from_parent: bool) {
263 use UnregisterBehavior::*;
264
265 let parent = match self.get_parent() {
266 Some(parent) => parent,
267 None => return,
268 };
269
270 let trigger_detach_signal = matches!(behavior, Check | Recursive);
271
272 match behavior {
273 Check => {
274 assert!(
275 self.childs().is_empty(),
276 "mask has {} children that must be unregistered first",
277 self.childs().len()
278 );
279 }
280 IPromiseIAmReparentingThisMask => (),
281 Recursive => {
282 for child in self.childs().values_mut() {
283 child.unregister_mask_impl(Recursive, false);
284 }
285 }
286 }
287
288 if remove_from_parent {
290 let removed = parent.remove_child_uuid(self.uuid());
291 assert!(removed.is_some(), "Mask not a child of the parent");
292 }
293
294 self.unset_parent(trigger_detach_signal);
295 }
296
297 pub fn remove_and_reparent(&mut self) -> Option<Mask> {
298 let (parent, childs, uuid) = match self {
301 Root { .. } => panic!("Cannot reparent a root mask"),
302 Unattached { .. } => panic!("Cannot reparent a unattached mask"),
303 Attached {
304 parent,
305 childs,
306 uuid,
307 ..
308 } => (parent, childs, uuid.clone()),
309 };
310
311 let childs = std::mem::take(childs);
312
313 parent
317 .remove_child_uuid(uuid)
318 .expect("Parent doesn't have this mask as child");
319
320 for child in childs.values() {
321 child.remove_parent();
322 parent.register_mask(child.clone());
323 }
324
325 self.remove_parent()
326 }
327
328 pub fn set_parent(&mut self, parent: Mask, parent_last_filled: Option<Option<Address>>) {
329 match self {
330 Root { .. } => panic!("set_parent() on a root"),
331 Attached { .. } => panic!("mask is already attached"),
332 Unattached {
333 depth,
334 childs,
335 uuid,
336 owning_account,
337 token_owners,
338 id_to_addr,
339 last_location,
340 hashes,
341 } => {
342 use std::mem::{replace, take};
343
344 *self = Attached {
345 parent,
346 owning_account: take(owning_account),
347 token_owners: take(token_owners),
348 id_to_addr: take(id_to_addr),
349 last_location: take(last_location),
350 depth: *depth,
351 childs: take(childs),
352 hashes: replace(hashes, HashesMatrix::new(*depth as usize)),
353 uuid: replace(uuid, "temporary_set_parent".to_string()),
354 };
355
356 let last_filled = match parent_last_filled {
357 Some(last_filled) => last_filled,
358 None => self.last_filled(), };
360
361 if let Attached { last_location, .. } = self {
362 *last_location = last_filled;
363 };
364 }
365 }
366 }
367
368 fn uuid(&self) -> Uuid {
369 self.get_uuid()
370 }
371
372 pub fn get_parent(&self) -> Option<Mask> {
373 match self {
374 Root { .. } | Unattached { .. } => None,
375 Attached { parent, .. } => Some(parent.clone()),
376 }
377 }
378
379 pub fn unset_parent(&mut self, trigger_detach_signal: bool) {
380 let parent = self.remove_parent();
381
382 assert!(
383 parent.is_some(),
384 "unset_parent called on a non-attached mask"
385 );
386
387 if trigger_detach_signal {
388 }
390 }
391
392 pub fn nmasks_to_root(&self) -> usize {
393 match self {
394 Root { .. } => 0,
395 Attached { parent, .. } => 1 + parent.with(|parent| parent.nmasks_to_root()),
396 Unattached { .. } => panic!(),
397 }
398 }
399
400 pub fn get_hash(&mut self, addr: Address) -> Option<Fp> {
402 self.get_inner_hash_at_addr(addr).ok()
403 }
404
405 pub fn commit(&mut self) {
407 let depth = self.depth() as usize;
408 let self_uuid = self.uuid();
409 match self {
412 Root { .. } => panic!("commit on a root"),
413 Unattached { .. } => panic!("commit on a unattached mask"),
414 Attached {
415 parent,
416 owning_account,
417 token_owners,
418 id_to_addr,
419 hashes,
420 ..
421 } => {
422 assert_ne!(parent.get_uuid(), self_uuid);
423
424 let (accounts, hashes) = {
425 if let Some(to) = token_owners.as_mut() {
426 to.clear();
427 }
428 id_to_addr.clear();
429 (std::mem::take(owning_account), hashes.take())
430 };
431
432 for (index, account) in accounts {
433 let addr = Address::from_index(index, depth);
434 parent.set_impl(addr, Box::new(account), Some(self_uuid.clone()));
435 }
436
437 parent.transfert_hashes(hashes);
438
439 }
443 }
444 }
445
446 pub fn commit_and_reparent(&mut self) -> Option<Mask> {
447 self.commit();
448 self.remove_and_reparent()
449 }
450
451 pub fn commit_and_reparent_to_root(&mut self) -> Option<Mask> {
454 if !self.is_attached() {
455 return None;
456 }
457
458 let mut parent = self.commit_and_reparent()?;
459 loop {
460 let binding = parent.with(|parent| {
461 if !parent.is_attached() {
462 return None;
463 }
464 parent.commit_and_reparent()
465 });
466 parent = match binding {
467 Some(new_parent) => new_parent,
468 None => return Some(parent),
469 };
470 }
471 }
472
473 pub fn parent_set_notify(&mut self, account_index: AccountIndex, account: &Account) {
478 assert!(self.is_attached());
479
480 for child in self.childs().values() {
481 child.parent_set_notify(account_index, account)
482 }
483
484 match self {
485 Root { .. } => panic!("parent_set_notify on a root"),
486 Unattached { .. } => panic!("parent_set_notify on an unattached"),
487 Attached {
488 owning_account,
489 id_to_addr,
490 hashes,
491 ..
492 } => {
493 let account_id = account.id();
494
495 hashes.invalidate_hashes(account_index);
496
497 let own_account = match id_to_addr
498 .get(&account_id)
499 .and_then(|addr| owning_account.get(&addr.to_index()))
500 .cloned()
501 {
502 Some(own) => own,
503 None => return,
504 };
505
506 if own_account != *account {
507 return;
509 }
510
511 self.remove_own_account(&[account_id]);
512 }
513 }
514 }
515
516 pub fn remove_parent(&mut self) -> Option<Mask> {
517 match self {
518 Root { .. } => panic!("remove_parent on a root"),
519 Unattached { .. } => panic!("remove_parent on an unattached"),
520 Attached { .. } => (),
521 }
522
523 let Self::Attached {
524 parent,
525 owning_account,
526 token_owners,
527 id_to_addr,
528 last_location,
529 depth,
530 childs,
531 hashes,
532 uuid,
533 } = self
534 else {
535 unreachable!()
537 };
538
539 let parent = parent.clone();
540 let owning_account = std::mem::take(owning_account);
541 let depth = std::mem::take(depth);
542 let childs = std::mem::take(childs);
543 let token_owners = std::mem::take(token_owners);
544 let id_to_addr = std::mem::take(id_to_addr);
545 let last_location = std::mem::take(last_location);
546 let hashes = std::mem::replace(hashes, HashesMatrix::new(depth as usize));
547 let uuid = std::mem::replace(uuid, "temporary".to_string());
548
549 *self = Self::Unattached {
550 owning_account,
551 token_owners,
552 id_to_addr,
553 last_location,
554 depth,
555 childs,
556 hashes,
557 uuid,
558 };
559
560 Some(parent)
561 }
562
563 pub fn remove_child_uuid(&mut self, uuid: Uuid) -> Option<Mask> {
564 self.childs().remove(&uuid)
565 }
566
567 fn childs(&mut self) -> &mut HashMap<Uuid, Mask> {
568 match self {
569 Root { childs, .. } => childs,
570 Attached { childs, .. } => childs,
571 Unattached { childs, .. } => childs,
572 }
573 }
574
575 pub fn get_cached_hash(&self, addr: &Address) -> Option<Fp> {
576 let matrix = match self {
577 Root { database, .. } => return database.get_cached_hash(addr),
578 Attached { hashes, .. } => hashes,
579 Unattached { hashes, .. } => hashes,
580 };
581
582 matrix.get(addr).copied()
583 }
584
585 pub fn set_cached_hash_unchecked(&mut self, addr: &Address, hash: Fp) {
586 self.set_cached_hash(addr, hash)
587 }
588
589 fn set_cached_hash(&mut self, addr: &Address, hash: Fp) {
590 let matrix = match self {
591 Root { database, .. } => return database.set_cached_hash(addr, hash),
592 Attached { hashes, .. } => hashes,
593 Unattached { hashes, .. } => hashes,
594 };
595
596 matrix.set(addr, hash);
597 }
598
599 pub fn empty_hash_at_height(&mut self, height: usize) -> Fp {
600 let matrix = match self {
601 Root { database, .. } => return database.empty_hash_at_height(height),
602 Attached { hashes, .. } => hashes,
603 Unattached { hashes, .. } => hashes,
604 };
605
606 matrix.empty_hash_at_height(height)
607 }
608
609 fn invalidate_hashes(&mut self, account_index: AccountIndex) {
610 let matrix = match self {
611 Root { database, .. } => return database.invalidate_hashes(account_index),
612 Attached { hashes, .. } => hashes,
613 Unattached { hashes, .. } => hashes,
614 };
615
616 matrix.invalidate_hashes(account_index)
617 }
618
619 pub fn compute_hash_or_parent(&mut self, addr: Address, last_account: &Address) -> Fp {
620 let (matrix, own, parent) = match self {
621 Root { database, .. } => {
622 return database.with(|db| db.emulate_tree_recursive(addr, last_account));
623 }
624 Attached {
625 hashes,
626 id_to_addr,
627 parent,
628 ..
629 } => (hashes, id_to_addr, Some(parent)),
630 Unattached {
631 hashes, id_to_addr, ..
632 } => (hashes, id_to_addr, None),
633 };
634
635 if let Some(hash) = matrix.get(&addr).cloned() {
636 return hash;
637 }
638
639 let hash = if own.values().any(|a| addr.is_parent_of(a)) {
643 self.emulate_tree_recursive(addr, last_account)
644 } else {
645 let parent = parent.as_ref().unwrap();
647 parent.with(|parent| parent.compute_hash_or_parent(addr.clone(), last_account))
648 };
649
650 hash
651 }
652
653 pub fn compute_hash_or_parent_for_merkle_path(
654 &mut self,
655 addr: Address,
656 last_account: &Address,
657 path: &mut AddressIterator,
658 merkle_path: &mut Vec<MerklePath>,
659 first: bool,
660 ) -> Fp {
661 let (matrix, own, parent) = match self {
662 Root { database, .. } => {
663 return database
664 .with(|db| db.emulate_tree_to_get_path(addr, last_account, path, merkle_path));
665 }
666 Attached {
667 hashes,
668 id_to_addr,
669 parent,
670 ..
671 } => (hashes, id_to_addr, Some(parent)),
672 Unattached {
673 hashes, id_to_addr, ..
674 } => (hashes, id_to_addr, None),
675 };
676
677 if !first {
678 if let Some(hash) = matrix.get(&addr).cloned() {
679 return hash;
680 }
681 }
682
683 let hash = if own.values().any(|a| addr.is_parent_of(a)) {
687 self.emulate_merkle_path_recursive(addr, last_account, path, merkle_path)
688 } else {
689 let parent = parent.as_ref().unwrap();
691 parent.with(|parent| {
692 parent.compute_hash_or_parent_for_merkle_path(
693 addr,
694 last_account,
695 path,
696 merkle_path,
697 first,
698 )
699 })
700 };
701
702 hash
703 }
704
705 pub fn depth(&self) -> u8 {
706 match self {
707 Root { database, .. } => database.depth(),
708 Attached { depth, .. } => *depth,
709 Unattached { depth, .. } => *depth,
710 }
711 }
712
713 fn emulate_tree_to_get_hash_at(&mut self, addr: Address) -> Fp {
714 if let Some(hash) = self.get_cached_hash(&addr) {
715 return hash;
716 };
717
718 let last_account = self
719 .last_filled()
720 .unwrap_or_else(|| Address::first(self.depth() as usize));
721
722 self.compute_hash_or_parent(addr, &last_account)
723 }
725
726 fn emulate_tree_recursive(&mut self, addr: Address, last_account: &Address) -> Fp {
728 let tree_depth = self.depth() as usize;
729 let current_depth = tree_depth - addr.length();
730
731 if current_depth == 0 {
732 return self
733 .get_account_hash(addr.to_index())
734 .unwrap_or_else(|| self.empty_hash_at_height(0));
735 }
736
737 let mut get_child_hash = |addr: Address| {
738 if let Some(hash) = self.get_cached_hash(&addr) {
739 hash
740 } else if addr.is_before(last_account) {
741 self.compute_hash_or_parent(addr, last_account)
742 } else {
743 self.empty_hash_at_height(current_depth - 1)
744 }
745 };
746
747 let left_hash = get_child_hash(addr.child_left());
748 let right_hash = get_child_hash(addr.child_right());
749
750 match self.get_cached_hash(&addr) {
751 Some(hash) => hash,
752 None => {
753 let hash = V2::hash_node(current_depth - 1, left_hash, right_hash);
754 self.set_cached_hash(&addr, hash);
755 hash
756 }
757 }
758 }
759
760 fn emulate_merkle_path_recursive(
761 &mut self,
762 addr: Address,
763 last_account: &Address,
764 path: &mut AddressIterator,
765 merkle_path: &mut Vec<MerklePath>,
766 ) -> Fp {
767 let tree_depth = self.depth() as usize;
768
769 if addr.length() == tree_depth {
770 return self
771 .get_account_hash(addr.to_index())
772 .unwrap_or_else(|| self.empty_hash_at_height(0));
773 }
774
775 let next_direction = path.next();
776
777 if let Some(direction) = next_direction.as_ref() {
779 let child = match direction {
780 Direction::Left => addr.child_left(),
781 Direction::Right => addr.child_right(),
782 };
783 self.emulate_merkle_path_recursive(child, last_account, path, merkle_path);
784 };
785
786 let depth_in_tree = tree_depth - addr.length();
787
788 let mut get_child_hash = |addr: Address| match self.get_cached_hash(&addr) {
789 Some(hash) => hash,
790 None => {
791 if addr.is_before(last_account) {
792 self.compute_hash_or_parent_for_merkle_path(
793 addr,
794 last_account,
795 path,
796 merkle_path,
797 false,
798 )
799 } else {
800 self.empty_hash_at_height(depth_in_tree - 1)
801 }
802 }
803 };
804
805 let left = get_child_hash(addr.child_left());
806 let right = get_child_hash(addr.child_right());
807
808 if let Some(direction) = next_direction {
809 let hash = match direction {
810 Direction::Left => MerklePath::Left(right),
811 Direction::Right => MerklePath::Right(left),
812 };
813 merkle_path.push(hash);
814 };
815
816 match self.get_cached_hash(&addr) {
817 Some(hash) => hash,
818 None => {
819 let hash = V2::hash_node(depth_in_tree - 1, left, right);
820 self.set_cached_hash(&addr, hash);
821 hash
822 }
823 }
824 }
825
826 fn remove_own_account(&mut self, ids: &[AccountId]) {
827 match self {
828 Root { .. } => todo!(),
829 Unattached {
830 owning_account,
831 token_owners,
832 id_to_addr,
833 last_location,
834 hashes,
835 ..
836 }
837 | Attached {
838 owning_account,
839 token_owners,
840 id_to_addr,
841 last_location,
842 hashes,
843 ..
844 } => {
845 let mut addrs = ids
846 .iter()
847 .map(|account_id| id_to_addr.remove(account_id).unwrap())
848 .collect::<Vec<_>>();
849 addrs.sort_by_key(Address::to_index);
850
851 for addr in addrs.iter().rev() {
852 let account_index = addr.to_index();
853 hashes.invalidate_hashes(account_index);
854
855 let account = owning_account.remove(&account_index).unwrap();
856 token_owners
857 .as_mut()
858 .map(|to| to.remove(&account.id().derive_token_id()))
859 .unwrap_or_default();
860
861 if last_location
862 .as_ref()
863 .map(|last| last == addr)
864 .unwrap_or(false)
865 {
866 *last_location = addr.prev();
867 }
868 }
869
870 if owning_account.is_empty() {
871 *last_location = None;
872 }
873 }
874 }
875 }
876
877 pub(super) fn set_impl(
878 &mut self,
879 addr: Address,
880 account: Box<Account>,
881 child_to_ignore: Option<Uuid>,
882 ) {
883 let account_index = addr.to_index();
884
885 for (uuid, child) in self.childs() {
886 if Some(uuid) == child_to_ignore.as_ref() {
887 continue;
888 }
889 child.parent_set_notify(account_index, &account)
890 }
891
892 match self {
893 Root { database, .. } => database.set(addr, account),
894 Unattached {
895 owning_account,
896 token_owners,
897 id_to_addr,
898 last_location,
899 ..
900 }
901 | Attached {
902 owning_account,
903 token_owners,
904 id_to_addr,
905 last_location,
906 ..
907 } => {
908 let account_id = account.id();
909
910 owning_account.insert(account_index, *account);
911 id_to_addr.insert(account_id.clone(), addr.clone());
912 token_owners
913 .as_mut()
914 .map(|to| to.insert(account_id.derive_token_id(), account_id));
915
916 if last_location
917 .as_ref()
918 .map(|l| l.to_index() < addr.to_index())
919 .unwrap_or(true)
920 {
921 *last_location = Some(addr);
922 }
923
924 self.invalidate_hashes(account_index);
925 }
926 }
927 }
928
929 pub(super) fn transfert_hashes(&mut self, new_hashes: HashesMatrix) {
930 match self {
931 Root { database, .. } => database.transfert_hashes(new_hashes),
932 Attached { hashes, .. } | Unattached { hashes, .. } => {
933 hashes.transfert_hashes(new_hashes)
934 }
935 };
936 }
937
938 pub(super) fn remove_accounts_without_notif(&mut self, ids: &[AccountId]) {
939 match self {
940 Root { database, .. } => database.remove_accounts(ids),
941 Unattached { .. } => self.remove_own_account(ids),
942 Attached {
943 parent, id_to_addr, ..
944 } => {
945 let (mask_keys, parent_keys): (Vec<_>, Vec<_>) = ids
946 .iter()
947 .cloned()
948 .partition(|id| id_to_addr.contains_key(id));
949
950 if !parent_keys.is_empty() {
951 parent.remove_accounts_without_notif(&parent_keys);
952 }
953
954 self.remove_own_account(&mask_keys);
955 }
956 }
957 }
958
959 fn recurse_on_childs<F>(&mut self, fun: &mut F)
960 where
961 F: FnMut(&mut MaskImpl),
962 {
963 for child in self.childs().values_mut() {
964 child.with(|child| {
965 fun(child);
966 child.recurse_on_childs(fun)
967 });
968 }
969 }
970
971 pub fn validate_inner_hashes(&mut self) -> Result<(), ()> {
972 use std::collections::VecDeque;
973
974 let tree_depth = self.depth() as usize;
975 let empty_account_hash = self.empty_hash_at_height(0);
976
977 let mut queue = VecDeque::new();
978
979 for index in 0..(2u64.pow(tree_depth as u32)) {
980 let index = AccountIndex(index);
981 match self
982 .get_account_hash(index)
983 .filter(|hash| hash != &empty_account_hash)
984 {
985 None => break,
986 Some(hash) => {
987 let addr = Address::from_index(index, tree_depth);
988 let parent = addr.parent().unwrap();
989 queue.push_back((parent, hash));
990 }
991 }
992 }
993
994 while let Some((addr, left_hash)) = queue.pop_front() {
995 let height = tree_depth - addr.length() - 1;
996 let right_hash = match queue.front().filter(|(addr2, _)| &addr == addr2) {
997 Some(_) => queue.pop_front().unwrap().1,
998 None => self.empty_hash_at_height(height),
999 };
1000
1001 assert_eq!(self.get_hash(addr.child_left()).unwrap(), left_hash);
1002 assert_eq!(self.get_hash(addr.child_right()).unwrap(), right_hash);
1003
1004 let parent = addr.parent();
1005 let hash = V2::hash_node(height, left_hash, right_hash);
1006 if Some(hash) != self.get_hash(addr) {
1007 return Err(());
1008 }
1009 if let Some(parent) = parent {
1010 queue.push_back((parent, hash));
1011 }
1012 }
1013
1014 Ok(())
1015 }
1016
1017 pub fn get_raw_inner_hashes(&self) -> Vec<(u64, Fp)> {
1018 match self {
1019 Root { database, .. } => {
1020 database.with(|this| this.hashes_matrix.get_raw_inner_hashes())
1021 }
1022 Attached { hashes, .. } => hashes.clone().get_raw_inner_hashes(),
1023 Unattached { hashes, .. } => hashes.clone().get_raw_inner_hashes(),
1024 }
1025 }
1026
1027 pub fn set_raw_inner_hashes(&self, raw_hashes: Vec<(u64, Fp)>) {
1028 match self {
1029 Root { database, .. } => {
1030 database.with(|this| this.hashes_matrix.set_raw_inner_hashes(raw_hashes))
1031 }
1032 Attached { hashes, .. } => hashes.clone().set_raw_inner_hashes(raw_hashes),
1033 Unattached { hashes, .. } => hashes.clone().set_raw_inner_hashes(raw_hashes),
1034 }
1035 }
1036
1037 #[cfg(test)]
1039 pub fn test_is_in_mask(&self, addr: &Address) -> bool {
1040 match self {
1041 Root { database, .. } => database.get(addr.clone()).is_some(),
1042 Unattached { owning_account, .. } | Attached { owning_account, .. } => {
1043 let index = addr.to_index();
1044 owning_account.contains_key(&index)
1045 }
1046 }
1047 }
1048
1049 #[cfg(test)]
1051 pub fn test_matrix(&self) -> HashesMatrix {
1052 match self {
1053 Root { database, .. } => database.test_matrix(),
1054 Unattached { hashes, .. } | Attached { hashes, .. } => hashes.clone(),
1055 }
1056 }
1057}
1058
1059impl BaseLedger for MaskImpl {
1060 fn to_list(&self) -> Vec<Account> {
1061 let depth = self.depth() as usize;
1062 let num_accounts = self.num_accounts() as u64;
1063
1064 (0..num_accounts)
1065 .map(AccountIndex)
1066 .filter_map(|index| self.get(Address::from_index(index, depth)))
1067 .map(|account| *account)
1068 .collect()
1069 }
1070
1071 fn iter<F>(&self, mut fun: F)
1072 where
1073 F: FnMut(&Account),
1074 {
1075 let depth = self.depth() as usize;
1076 let num_accounts = self.num_accounts() as u64;
1077
1078 (0..num_accounts)
1079 .map(AccountIndex)
1080 .filter_map(|index| self.get(Address::from_index(index, depth)))
1081 .for_each(|account| fun(&account));
1082 }
1083
1084 fn fold<B, F>(&self, init: B, mut fun: F) -> B
1085 where
1086 F: FnMut(B, &Account) -> B,
1087 {
1088 let depth = self.depth() as usize;
1089 let num_accounts = self.num_accounts() as u64;
1090 let mut accum = init;
1091
1092 for account in (0..num_accounts)
1093 .map(AccountIndex)
1094 .filter_map(|index| self.get(Address::from_index(index, depth)))
1095 {
1096 accum = fun(accum, &account)
1097 }
1098
1099 accum
1100 }
1101
1102 fn fold_with_ignored_accounts<B, F>(
1103 &self,
1104 ignoreds: HashSet<AccountId>,
1105 init: B,
1106 mut fun: F,
1107 ) -> B
1108 where
1109 F: FnMut(B, &Account) -> B,
1110 {
1111 self.fold(init, |accum, account| {
1112 if !ignoreds.contains(&account.id()) {
1113 fun(accum, account)
1114 } else {
1115 accum
1116 }
1117 })
1118 }
1119
1120 fn fold_until<B, F>(&self, init: B, mut fun: F) -> B
1121 where
1122 F: FnMut(B, &Account) -> std::ops::ControlFlow<B, B>,
1123 {
1124 use std::ops::ControlFlow::*;
1125
1126 let depth = self.depth() as usize;
1127 let num_accounts = self.num_accounts() as u64;
1128 let mut accum = init;
1129
1130 for account in (0..num_accounts)
1131 .map(AccountIndex)
1132 .filter_map(|index| self.get(Address::from_index(index, depth)))
1133 {
1134 match fun(accum, &account) {
1135 Continue(acc) => accum = acc,
1136 Break(acc) => {
1137 accum = acc;
1138 break;
1139 }
1140 }
1141 }
1142
1143 accum
1144 }
1145
1146 fn accounts(&self) -> HashSet<AccountId> {
1147 let mut set = HashSet::with_capacity(self.num_accounts());
1148
1149 self.iter(|account| {
1150 set.insert(account.id());
1151 });
1152
1153 set
1154 }
1155
1156 fn token_owner(&self, token_id: TokenId) -> Option<AccountId> {
1157 let (parent, token_owners) = match self {
1158 Root { database, .. } => return database.token_owner(token_id),
1159 Attached {
1160 parent,
1161 token_owners,
1162 ..
1163 } => (Some(parent), token_owners),
1164 Unattached { token_owners, .. } => (None, token_owners),
1165 };
1166
1167 if let Some(account_id) = token_owners
1168 .as_ref()
1169 .and_then(|to| to.get(&token_id).cloned())
1170 {
1171 return Some(account_id);
1172 };
1173
1174 parent.as_ref()?.token_owner(token_id)
1175 }
1176
1177 fn tokens(&self, public_key: CompressedPubKey) -> HashSet<TokenId> {
1178 let mut set = HashSet::with_capacity(1024);
1179
1180 for account in self.to_list() {
1181 if account.public_key == public_key {
1182 set.insert(account.token_id);
1183 }
1184 }
1185
1186 set
1187 }
1188
1189 fn location_of_account(&self, account_id: &AccountId) -> Option<Address> {
1190 let (parent, id_to_addr) = match self {
1191 Root { database, .. } => return database.location_of_account(account_id),
1192 Attached {
1193 parent, id_to_addr, ..
1194 } => (Some(parent), id_to_addr),
1195 Unattached { id_to_addr, .. } => (None, id_to_addr),
1196 };
1197
1198 if let Some(addr) = id_to_addr.get(account_id).cloned() {
1199 return Some(addr);
1200 }
1201
1202 parent.as_ref()?.location_of_account(account_id)
1203 }
1204
1205 fn location_of_account_batch(
1206 &self,
1207 account_ids: &[AccountId],
1208 ) -> Vec<(AccountId, Option<Address>)> {
1209 account_ids
1210 .iter()
1211 .map(|account_id| {
1212 let addr = self.location_of_account(account_id);
1213 (account_id.clone(), addr)
1214 })
1215 .collect()
1216 }
1217
1218 fn get_or_create_account(
1219 &mut self,
1220 account_id: AccountId,
1221 account: Account,
1222 ) -> Result<GetOrCreated, DatabaseError> {
1223 if let Some(addr) = self.location_of_account(&account_id) {
1224 return Ok(GetOrCreated::Existed(addr));
1225 }
1226
1227 let last_filled = self.last_filled();
1228
1229 let result = match self {
1230 Root { database, .. } => database.get_or_create_account(account_id, account)?,
1231 Unattached {
1232 owning_account,
1233 token_owners,
1234 id_to_addr,
1235 last_location,
1236 depth,
1237 ..
1238 }
1239 | Attached {
1240 owning_account,
1241 token_owners,
1242 id_to_addr,
1243 last_location,
1244 depth,
1245 ..
1246 } => {
1247 let location = match last_filled {
1248 Some(last) => last.next().ok_or(DatabaseError::OutOfLeaves)?,
1249 None => Address::first(*depth as usize),
1250 };
1251
1252 let account_index: AccountIndex = location.to_index();
1253
1254 id_to_addr.insert(account_id.clone(), location.clone());
1255 *last_location = Some(location.clone());
1256 token_owners
1257 .as_mut()
1258 .map(|to| to.insert(account_id.derive_token_id(), account_id));
1259 owning_account.insert(account_index, account);
1260
1261 self.invalidate_hashes(account_index);
1262
1263 GetOrCreated::Added(location)
1264 }
1265 };
1266
1267 elog!("get_or_create_account added");
1268
1269 Ok(result)
1278 }
1279
1280 fn close(&self) {
1281 }
1283
1284 fn last_filled(&self) -> Option<Address> {
1285 match self {
1286 Root { database, .. } => database.last_filled(),
1287 Unattached { last_location, .. } => last_location.clone(),
1288 Attached {
1289 parent,
1290 last_location,
1291 ..
1292 } => {
1293 let last_filled_parent = match parent.last_filled() {
1294 Some(last) => last,
1295 None => return last_location.clone(),
1296 };
1297
1298 let last_filled = match last_location {
1299 Some(last) => last,
1300 None => return Some(last_filled_parent),
1301 };
1302
1303 let last_filled_parent_index = last_filled_parent.to_index();
1304 let last_filled_index = last_filled.to_index();
1305
1306 if last_filled_index > last_filled_parent_index {
1307 Some(last_filled.clone())
1308 } else {
1309 Some(last_filled_parent)
1310 }
1311 }
1312 }
1313 }
1314
1315 fn get_uuid(&self) -> Uuid {
1316 match self {
1317 Root { database, .. } => database.get_uuid(),
1318 Attached { uuid, .. } | Unattached { uuid, .. } => uuid.clone(),
1319 }
1320 }
1321
1322 fn get_directory(&self) -> Option<PathBuf> {
1323 match self {
1324 Root { database, .. } => database.get_directory(),
1325 Attached { parent, .. } => parent.get_directory(),
1326 Unattached { .. } => None,
1327 }
1328 }
1329
1330 fn get_account_hash(&mut self, account_index: AccountIndex) -> Option<Fp> {
1331 let (mut parent, owning_account, matrix, depth) = match self {
1332 Root { database, .. } => return database.get_account_hash(account_index),
1333 Attached {
1334 parent,
1335 owning_account,
1336 hashes,
1337 depth,
1338 ..
1339 } => (Some(parent), owning_account, hashes, depth),
1340 Unattached {
1341 owning_account,
1342 hashes,
1343 depth,
1344 ..
1345 } => (None, owning_account, hashes, depth),
1346 };
1347
1348 if let Some(account) = owning_account.get(&account_index) {
1349 let addr = Address::from_index(account_index, *depth as usize);
1350
1351 if let Some(hash) = matrix.get(&addr).cloned() {
1352 return Some(hash);
1353 }
1354
1355 let hash = account.hash();
1356 matrix.set(&addr, hash);
1357
1358 return Some(hash);
1359 }
1360
1361 parent.as_mut()?.get_account_hash(account_index)
1362 }
1363
1364 fn get(&self, addr: Address) -> Option<Box<Account>> {
1365 #[inline(never)]
1367 fn get_account(
1368 addr: &Address,
1369 owning_account: &HashMap<AccountIndex, Account>,
1370 ) -> Option<Box<Account>> {
1371 owning_account.get(&addr.to_index()).cloned().map(Box::new)
1372 }
1373
1374 let (parent, owning_account) = match self {
1375 Root { database, .. } => return database.get(addr),
1376 Attached {
1377 parent,
1378 owning_account,
1379 ..
1380 } => (Some(parent), owning_account),
1381 Unattached { owning_account, .. } => (None, owning_account),
1382 };
1383
1384 if let Some(account) = get_account(&addr, owning_account) {
1385 return Some(account);
1386 }
1387
1388 parent.as_ref()?.get(addr)
1389 }
1390
1391 fn get_batch(&self, addr: &[Address]) -> Vec<(Address, Option<Box<Account>>)> {
1392 addr.iter()
1393 .map(|addr| (addr.clone(), self.get(addr.clone())))
1394 .collect()
1395 }
1396
1397 fn set(&mut self, addr: Address, account: Box<Account>) {
1398 self.set_impl(addr, account, None)
1399 }
1400
1401 fn set_batch(&mut self, list: &[(Address, Box<Account>)]) {
1402 for (addr, account) in list {
1403 self.set(addr.clone(), account.clone())
1404 }
1405 }
1406
1407 fn get_at_index(&self, index: AccountIndex) -> Option<Box<Account>> {
1408 let addr = Address::from_index(index, self.depth() as usize);
1409 self.get(addr)
1410 }
1411
1412 fn set_at_index(&mut self, index: AccountIndex, account: Box<Account>) -> Result<(), ()> {
1413 let addr = Address::from_index(index, self.depth() as usize);
1414 self.set(addr, account);
1415 Ok(())
1416 }
1417
1418 fn index_of_account(&self, account_id: AccountId) -> Option<AccountIndex> {
1419 let (parent, id_to_addr) = match self {
1420 Root { database, .. } => return database.index_of_account(account_id),
1421 Attached {
1422 parent, id_to_addr, ..
1423 } => (Some(parent), id_to_addr),
1424 Unattached { id_to_addr, .. } => (None, id_to_addr),
1425 };
1426
1427 if let Some(addr) = id_to_addr.get(&account_id).cloned() {
1428 return Some(addr.to_index());
1429 };
1430
1431 parent.as_ref()?.index_of_account(account_id)
1432 }
1433
1434 fn merkle_root(&mut self) -> Fp {
1435 let hash = self.emulate_tree_to_get_hash_at(Address::root());
1437 let num_accounts = self.num_accounts();
1440 elog!("merkle_root={} num_accounts={:?}", hash, num_accounts);
1441
1442 hash
1443 }
1444
1445 fn merkle_path(&mut self, addr: Address) -> Vec<MerklePath> {
1446 elog!("merkle_path short={:?}", self.short());
1447 if let Root { database, .. } = self {
1450 return database.merkle_path(addr);
1451 };
1452
1453 let mut merkle_path = Vec::with_capacity(addr.length());
1454 let mut path = addr.into_iter();
1455 let addr = Address::root();
1456
1457 let last_account = self
1458 .last_filled()
1459 .unwrap_or_else(|| Address::first(self.depth() as usize));
1460
1461 self.compute_hash_or_parent_for_merkle_path(
1464 addr,
1465 &last_account,
1466 &mut path,
1467 &mut merkle_path,
1468 true,
1469 );
1470 merkle_path
1473 }
1474
1475 fn merkle_path_at_index(&mut self, index: AccountIndex) -> Vec<MerklePath> {
1476 let addr = Address::from_index(index, self.depth() as usize);
1477 self.merkle_path(addr)
1478 }
1479
1480 fn remove_accounts(&mut self, ids: &[AccountId]) {
1481 let indexes: Vec<_> = ids
1482 .iter()
1483 .filter_map(|id| {
1484 let addr = self.location_of_account(id)?;
1485 Some(addr.to_index())
1486 })
1487 .collect();
1488
1489 self.remove_accounts_without_notif(ids);
1490
1491 self.recurse_on_childs(&mut |child| {
1492 for index in &indexes {
1493 child.invalidate_hashes(*index);
1494 }
1495 });
1496 }
1497
1498 fn detached_signal(&mut self) {
1499 todo!()
1500 }
1501
1502 fn depth(&self) -> u8 {
1503 self.depth()
1504 }
1505
1506 fn num_accounts(&self) -> usize {
1507 self.last_filled()
1508 .map(|addr| addr.to_index().0 as usize + 1)
1509 .unwrap_or(0)
1510 }
1511
1512 fn merkle_path_at_addr(&mut self, addr: Address) -> Vec<MerklePath> {
1513 self.merkle_path(addr)
1514 }
1515
1516 fn get_inner_hash_at_addr(&mut self, addr: Address) -> Result<Fp, String> {
1517 let self_depth = self.depth() as usize;
1518
1519 if addr.length() > self_depth {
1520 return Err("Inner hash not found at address".into());
1521 }
1522
1523 Ok(self.emulate_tree_to_get_hash_at(addr))
1524 }
1525
1526 fn set_inner_hash_at_addr(&mut self, _addr: Address, _hash: Fp) -> Result<(), ()> {
1527 todo!()
1528 }
1529
1530 fn set_all_accounts_rooted_at(
1531 &mut self,
1532 addr: Address,
1533 accounts: &[Box<Account>],
1534 ) -> Result<(), ()> {
1535 let depth = self.depth() as usize;
1536
1537 if addr.length() > depth {
1538 return Err(());
1539 }
1540
1541 for (child_addr, account) in addr.iter_children(depth).zip(accounts) {
1542 self.set(child_addr, account.clone());
1543 }
1544
1545 Ok(())
1546 }
1547
1548 fn get_all_accounts_rooted_at(&self, addr: Address) -> Option<Vec<(Address, Box<Account>)>> {
1549 let self_depth = self.depth() as usize;
1550
1551 if addr.length() > self_depth {
1552 return None;
1553 }
1554
1555 let accounts = addr
1556 .iter_children(self_depth)
1557 .filter_map(|addr| Some((addr.clone(), self.get(addr)?)))
1558 .collect::<Vec<_>>();
1559
1560 if accounts.is_empty() {
1561 None
1562 } else {
1563 Some(accounts)
1564 }
1565 }
1566
1567 fn make_space_for(&mut self, _space: usize) {
1568 }
1570
1571 fn commit(&mut self) {
1572 self.commit()
1573 }
1574}