mina_tree/mask/
mask_impl.rs

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(&copy.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/// For debug purpose only
177#[derive(Debug)]
178pub enum MaskImplShort {
179    Root______(Uuid),
180    Attached__(Uuid),
181    Unattached(Uuid),
182}
183
184impl MaskImpl {
185    /// For debug purpose only
186    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    /// Make `mask` a child of `self`
249    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    /// Detach this mask from its parent
262    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        // Remove only when our parent is not unregistering us
289        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 root_hash = self.merkle_root();
299
300        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        // we can only reparent if merkle roots are the same
314        // assert_eq!(parent.merkle_root(), root_hash);
315
316        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(), // This will lock the parent,
359                };
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            // TODO: Async.Ivar.fill_if_empty t.detached_parent_signal () ;
389        }
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    /// get hash from mask, if present, else from its parent
401    pub fn get_hash(&mut self, addr: Address) -> Option<Fp> {
402        self.get_inner_hash_at_addr(addr).ok()
403    }
404
405    /// commit all state to the parent, flush state locally
406    pub fn commit(&mut self) {
407        let depth = self.depth() as usize;
408        let self_uuid = self.uuid();
409        // let old_root_hash = self.merkle_root();
410
411        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                // Parent merkle root after committing should be the same as the \
440                // old one in the mask
441                // assert_eq!(old_root_hash, parent.merkle_root()); // TODO: Assert this only in #[cfg(test)]
442            }
443        }
444    }
445
446    pub fn commit_and_reparent(&mut self) -> Option<Mask> {
447        self.commit();
448        self.remove_and_reparent()
449    }
450
451    /// commit all the masks from this mask all the way upto the root
452    /// and return root mask while also detaching all intermediary masks.
453    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    /// called when parent sets an account; update local state
474    ///
475    /// if the mask's parent sets an account, we can prune an entry in the mask
476    /// if the account in the parent is the same in the mask *)
477    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                    // Do not delete our account if it is different than the parent one
508                    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            // We previously checked it's an attached mask
536            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        // Check if we have any children accounts in our mask
640        // When we don't have accounts here, delegate to parent
641        // TODO: Make that faster
642        let hash = if own.values().any(|a| addr.is_parent_of(a)) {
643            self.emulate_tree_recursive(addr, last_account)
644        } else {
645            // Recurse to parents until we found a mask having accounts on this address
646            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        // Check if we have any children accounts in our mask
684        // When we don't have accounts here, delegate to parent
685        // TODO: Make that faster
686        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            // Recurse to parents until we found a mask having accounts on this address
690            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        // self.emulate_tree_recursive(addr, &last_account)
724    }
725
726    // fn emulate_recursive(&mut self, addr: Address, nremaining: &mut usize) -> Fp {
727    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        // We go until the end of the path
778        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    /// For tests only, check if the address is in the mask, without checking parent
1038    #[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    /// For tests only
1050    #[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        // let addr = result.clone();
1270        // let account_index = addr.to_index();
1271        // self.recurse_on_childs(&mut |child| {
1272        //     child.with(|child| {
1273        //         child.invalidate_hashes(account_index.clone());
1274        //     })
1275        // });
1276
1277        Ok(result)
1278    }
1279
1280    fn close(&self) {
1281        // Drop
1282    }
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        // Avoid stack overflow
1366        #[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        // elog!("MERKLE_ROOT={:?}", self.short());
1436        let hash = self.emulate_tree_to_get_hash_at(Address::root());
1437        // self.emulate_tree_to_get_hash()
1438
1439        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        // elog!("merkle_path num_accounts={:?} addr={:?}", self.num_accounts(), addr);
1448
1449        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        // elog!("merkle_path last_account={:?}", last_account);
1462
1463        self.compute_hash_or_parent_for_merkle_path(
1464            addr,
1465            &last_account,
1466            &mut path,
1467            &mut merkle_path,
1468            true,
1469        );
1470        // self.emulate_merkle_path_recursive(addr, &last_account, &mut path, &mut merkle_path);
1471
1472        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        // No op, we're in memory
1569    }
1570
1571    fn commit(&mut self) {
1572        self.commit()
1573    }
1574}