mina_tree/mask/
mask.rs

1use std::{
2    collections::{HashMap, HashSet},
3    path::PathBuf,
4    sync::{Arc, Mutex},
5};
6
7use mina_curves::pasta::Fp;
8use mina_signer::CompressedPubKey;
9
10use crate::{
11    account::{Account, AccountId, TokenId},
12    address::Address,
13    base::{next_uuid, AccountIndex, BaseLedger, GetOrCreated, MerklePath, Uuid},
14    database::{Database, DatabaseError},
15    tree_version::V2,
16    HashesMatrix,
17};
18
19use super::mask_impl::{MaskImpl, MaskImplShort};
20
21#[derive(Clone, Debug)]
22pub struct Mask {
23    // Using a mutex for now but this can be replaced with a RefCell
24    pub inner: Arc<Mutex<MaskImpl>>,
25}
26
27impl Drop for Mask {
28    fn drop(&mut self) {
29        if Arc::strong_count(&self.inner) > 2 {
30            // Don't drop because of counter
31            return;
32        }
33
34        let Ok(inner) = self.inner.try_lock() else {
35            // The Mask is used somewhere else
36            return;
37        };
38
39        if inner.any_child_alive() {
40            // Still got childs, don't do anything
41            return;
42        }
43
44        let Some(parent) = inner.get_parent() else {
45            // No parent, we don't need to do anything
46            return;
47        };
48
49        // We reached a point where we don't have childs, and it remains at most 2
50        // pointers of our mask:
51        // - 1 pointer from the parent (having us in its `MaskImpl::childs` )
52        // - 1 currently dropping pointer
53        //
54        // Unregister our mask from the parent (remove us from its `MaskImpl::childs`)
55        // It will recursively drop/deallocate any parent with the same conditions
56
57        // Note:
58        // There is a case where the parent does not have any pointer of us:
59        // During transaction application, we don't call `register_mask`
60        // In that case, the `remove_child_uuid` below has no effect
61        // <https://github.com/MinaProtocol/mina/blob/f6756507ff7380a691516ce02a3cf7d9d32915ae/src/lib/mina_ledger/ledger.ml#L204>
62
63        parent.remove_child_uuid(inner.get_uuid());
64    }
65}
66
67#[derive(Debug)]
68pub enum UnregisterBehavior {
69    Check,
70    Recursive,
71    IPromiseIAmReparentingThisMask,
72}
73
74impl Mask {
75    pub(super) fn with<F, R>(&self, fun: F) -> R
76    where
77        F: FnOnce(&mut MaskImpl) -> R,
78    {
79        let mut inner = self.inner.try_lock().expect("lock failed");
80        fun(&mut inner)
81    }
82}
83
84impl Mask {
85    pub fn new_root(db: Database<V2>) -> Self {
86        let uuid = db.get_uuid();
87        let mask = Self {
88            inner: Arc::new(Mutex::new(MaskImpl::Root {
89                database: db,
90                childs: HashMap::with_capacity(2),
91            })),
92        };
93        super::alive_add(&uuid);
94        mask
95    }
96
97    pub fn new_unattached(depth: usize) -> Self {
98        let uuid = next_uuid();
99
100        let mask = Self {
101            inner: Arc::new(Mutex::new(MaskImpl::Unattached {
102                owning_account: Default::default(),
103                token_owners: Default::default(),
104                id_to_addr: Default::default(),
105                last_location: None,
106                depth: depth as u8,
107                childs: HashMap::with_capacity(2),
108                uuid: uuid.clone(),
109                hashes: HashesMatrix::new(depth),
110            })),
111        };
112
113        super::alive_add(&uuid);
114
115        mask
116    }
117
118    pub fn create(depth: usize) -> Self {
119        Self::new_root(Database::create(depth as u8))
120    }
121
122    pub fn create_with_token_owners(depth: usize) -> Self {
123        Self::new_root(Database::create_with_token_owners(depth as u8))
124    }
125
126    pub fn set_token_owners(&mut self) {
127        self.with(|this| this.set_token_owners());
128    }
129
130    // Note: This should be only called on startup
131    pub fn unset_token_owners(&mut self) {
132        self.with(|this| this.unset_token_owners());
133    }
134
135    pub fn make_child(&self) -> Mask {
136        let mut new_mask = Mask::new_unattached(self.depth() as usize);
137
138        if self.has_token_owners() {
139            new_mask.set_token_owners();
140        }
141
142        self.register_mask(new_mask)
143    }
144
145    pub fn set_parent(&self, parent: Mask, parent_last_filled: Option<Option<Address>>) -> Mask {
146        let this = self.clone();
147        self.with(|this| this.set_parent(parent, parent_last_filled));
148        this
149    }
150
151    pub(crate) fn nmasks_to_root(&self) -> usize {
152        self.with(|this| this.nmasks_to_root())
153    }
154
155    pub fn copy(&self) -> Mask {
156        let mask = self.with(|this| this.clone());
157        Self {
158            inner: Arc::new(Mutex::new(mask)),
159        }
160    }
161
162    /// Make `mask` a child of `self`
163    pub fn register_mask(&self, mask: Mask) -> Mask {
164        // elog!("self={:p} mask={:p}", &self.inner, &mask.inner);
165
166        let self_mask = self.clone();
167        self.with(|this| this.register_mask(self_mask, mask))
168    }
169
170    /// Detach this mask from its parent
171    pub fn unregister_mask(&self, behavior: UnregisterBehavior) -> Mask {
172        self.unregister_mask_impl(behavior, true)
173    }
174
175    pub(super) fn unregister_mask_impl(
176        &self,
177        behavior: UnregisterBehavior,
178        remove_from_parent: bool,
179    ) -> Mask {
180        let this = self.clone();
181        self.with(|this| this.unregister_mask(behavior, remove_from_parent));
182        this
183    }
184
185    pub(super) fn remove_child_uuid(&self, uuid: Uuid) -> Option<Mask> {
186        self.with(|this| this.remove_child_uuid(uuid))
187    }
188
189    pub fn is_root(&self) -> bool {
190        self.with(|this| this.is_root())
191    }
192
193    pub fn is_attached(&self) -> bool {
194        self.with(|this| this.is_attached())
195    }
196
197    fn uuid(&self) -> Uuid {
198        self.with(|this| this.get_uuid())
199    }
200
201    pub fn get_parent(&self) -> Option<Mask> {
202        self.with(|this| this.get_parent())
203    }
204
205    pub fn unset_parent(&self, trigger_detach_signal: bool) {
206        self.with(|this| this.unset_parent(trigger_detach_signal))
207    }
208
209    /// //             o
210    /// //            /
211    /// //           /
212    /// //  o --- o -
213    /// //  ^     ^  \
214    /// // parent |   \
215    /// //       mask  o
216    /// //           children
217    ///
218    /// Removes the attached mask from its parent and attaches the children to the
219    /// parent instead. Raises an exception if the merkle roots of the mask and the
220    /// parent are not the same.
221    pub fn remove_and_reparent(&self) -> Option<Mask> {
222        self.with(|this| this.remove_and_reparent())
223    }
224
225    /// get hash from mask, if present, else from its parent
226    pub fn get_hash(&self, addr: Address) -> Option<Fp> {
227        self.with(|this| this.get_hash(addr))
228    }
229
230    /// commit all state to the parent, flush state locally
231    pub fn commit(&self) {
232        self.with(|this| this.commit())
233    }
234
235    /// commit all the masks from this mask all the way upto the root
236    /// and return root mask while also detaching all intermediary masks.
237    pub fn commit_and_reparent_to_root(&mut self) -> Option<Mask> {
238        self.with(|this| this.commit_and_reparent_to_root())
239    }
240
241    /// called when parent sets an account; update local state
242    ///
243    /// if the mask's parent sets an account, we can prune an entry in the mask
244    /// if the account in the parent is the same in the mask *)
245    pub fn parent_set_notify(&self, account_index: AccountIndex, account: &Account) {
246        self.with(|this| this.parent_set_notify(account_index, account))
247    }
248
249    pub fn remove_parent(&self) -> Option<Mask> {
250        self.with(|this| this.remove_parent())
251    }
252
253    pub fn depth(&self) -> u8 {
254        self.with(|this| this.depth())
255    }
256
257    pub fn get_cached_hash(&mut self, addr: &Address) -> Option<Fp> {
258        self.with(|this| this.get_cached_hash(addr))
259    }
260
261    pub fn set_cached_hash_unchecked(&mut self, addr: &Address, hash: Fp) {
262        self.with(|this| this.set_cached_hash_unchecked(addr, hash))
263    }
264
265    pub(super) fn set_impl(&mut self, addr: Address, account: Box<Account>, ignore: Option<Uuid>) {
266        self.with(|this| this.set_impl(addr, account, ignore))
267    }
268
269    pub(super) fn transfert_hashes(&mut self, hashes: HashesMatrix) {
270        self.with(|this| this.transfert_hashes(hashes))
271    }
272
273    pub(super) fn remove_accounts_without_notif(&mut self, ids: &[AccountId]) {
274        self.with(|this| this.remove_accounts_without_notif(ids))
275    }
276
277    pub fn short(&self) -> MaskImplShort {
278        self.with(|this| this.short())
279    }
280
281    /// Validate inner hashes by rehashing everything.
282    /// Returns `Ok(())` if recalculated hashes matched the existing ones.
283    ///
284    /// Warning: Heavy operation.
285    pub fn validate_inner_hashes(&mut self) -> Result<(), ()> {
286        self.with(|this| this.validate_inner_hashes())
287    }
288
289    /// Returns a vector of tuples of (index, hash) of all the hashes contained
290    /// in this mask.
291    pub fn get_raw_inner_hashes(&self) -> Vec<(u64, Fp)> {
292        self.with(|this| this.get_raw_inner_hashes())
293    }
294
295    /// Sets the contents of this mask's hash matrix using raw data.
296    pub fn set_raw_inner_hashes(&self, hashes: Vec<(u64, Fp)>) {
297        self.with(|this| this.set_raw_inner_hashes(hashes))
298    }
299    pub fn has_token_owners(&self) -> bool {
300        self.with(|this| this.has_token_owners())
301    }
302
303    /// For tests only, check if the address is in the mask, without checking parent
304    #[cfg(test)]
305    fn test_is_in_mask(&self, addr: &Address) -> bool {
306        self.with(|this| this.test_is_in_mask(addr))
307    }
308
309    /// For tests only
310    #[cfg(test)]
311    fn test_matrix(&self) -> HashesMatrix {
312        self.with(|this| this.test_matrix())
313    }
314
315    /// Use for fuzzing only
316    #[cfg(feature = "fuzzing")]
317    pub fn fuzzing_to_root(&self) -> Mask {
318        let accounts = self.to_list();
319        let mut new_root = Self::create(self.depth() as usize);
320
321        for account in accounts {
322            new_root
323                .get_or_create_account(account.id(), account)
324                .unwrap();
325        }
326
327        new_root
328    }
329}
330
331impl BaseLedger for Mask {
332    fn to_list(&self) -> Vec<Account> {
333        self.with(|this| this.to_list())
334    }
335
336    fn iter<F>(&self, fun: F)
337    where
338        F: FnMut(&Account),
339    {
340        self.with(|this| this.iter(fun))
341    }
342
343    fn fold<B, F>(&self, init: B, fun: F) -> B
344    where
345        F: FnMut(B, &Account) -> B,
346    {
347        self.with(|this| this.fold(init, fun))
348    }
349
350    fn fold_with_ignored_accounts<B, F>(&self, ignoreds: HashSet<AccountId>, init: B, fun: F) -> B
351    where
352        F: FnMut(B, &Account) -> B,
353    {
354        self.with(|this| this.fold_with_ignored_accounts(ignoreds, init, fun))
355    }
356
357    fn fold_until<B, F>(&self, init: B, fun: F) -> B
358    where
359        F: FnMut(B, &Account) -> std::ops::ControlFlow<B, B>,
360    {
361        self.with(|this| this.fold_until(init, fun))
362    }
363
364    fn accounts(&self) -> HashSet<AccountId> {
365        self.with(|this| this.accounts())
366    }
367
368    fn token_owner(&self, token_id: TokenId) -> Option<AccountId> {
369        self.with(|this| this.token_owner(token_id))
370    }
371
372    fn tokens(&self, public_key: CompressedPubKey) -> HashSet<TokenId> {
373        self.with(|this| this.tokens(public_key))
374    }
375
376    fn location_of_account(&self, account_id: &AccountId) -> Option<Address> {
377        self.with(|this| this.location_of_account(account_id))
378    }
379
380    fn location_of_account_batch(
381        &self,
382        account_ids: &[AccountId],
383    ) -> Vec<(AccountId, Option<Address>)> {
384        self.with(|this| this.location_of_account_batch(account_ids))
385    }
386
387    fn get_or_create_account(
388        &mut self,
389        account_id: AccountId,
390        account: Account,
391    ) -> Result<GetOrCreated, DatabaseError> {
392        self.with(|this| this.get_or_create_account(account_id, account))
393    }
394
395    fn close(&self) {
396        // Drop self
397    }
398
399    fn last_filled(&self) -> Option<Address> {
400        self.with(|this| this.last_filled())
401    }
402
403    fn get_uuid(&self) -> Uuid {
404        self.with(|this| this.get_uuid())
405    }
406
407    fn get_directory(&self) -> Option<PathBuf> {
408        self.with(|this| this.get_directory())
409    }
410
411    fn get_account_hash(&mut self, account_index: AccountIndex) -> Option<Fp> {
412        self.with(|this| this.get_account_hash(account_index))
413    }
414
415    fn get(&self, addr: Address) -> Option<Box<Account>> {
416        self.with(|this| this.get(addr))
417    }
418
419    fn get_batch(&self, addr: &[Address]) -> Vec<(Address, Option<Box<Account>>)> {
420        self.with(|this| this.get_batch(addr))
421    }
422
423    fn set(&mut self, addr: Address, account: Box<Account>) {
424        self.with(|this| this.set(addr, account))
425    }
426
427    fn set_batch(&mut self, list: &[(Address, Box<Account>)]) {
428        self.with(|this| this.set_batch(list))
429    }
430
431    fn get_at_index(&self, index: AccountIndex) -> Option<Box<Account>> {
432        self.with(|this| this.get_at_index(index))
433    }
434
435    fn set_at_index(&mut self, index: AccountIndex, account: Box<Account>) -> Result<(), ()> {
436        self.with(|this| this.set_at_index(index, account))
437    }
438
439    fn index_of_account(&self, account_id: AccountId) -> Option<AccountIndex> {
440        self.with(|this| this.index_of_account(account_id))
441    }
442
443    fn merkle_root(&mut self) -> Fp {
444        self.with(|this| this.merkle_root())
445    }
446
447    fn merkle_path(&mut self, addr: Address) -> Vec<MerklePath> {
448        let addr_length = addr.length();
449        let res = self.with(|this| this.merkle_path(addr.clone()));
450        assert_eq!(res.len(), addr_length);
451        res
452    }
453
454    fn merkle_path_at_index(&mut self, index: AccountIndex) -> Vec<MerklePath> {
455        self.with(|this| this.merkle_path_at_index(index))
456    }
457
458    fn remove_accounts(&mut self, ids: &[AccountId]) {
459        self.with(|this| this.remove_accounts(ids))
460    }
461
462    fn detached_signal(&mut self) {
463        self.with(|this| this.detached_signal())
464    }
465
466    fn depth(&self) -> u8 {
467        self.with(|this| this.depth())
468    }
469
470    fn num_accounts(&self) -> usize {
471        self.with(|this| this.num_accounts())
472    }
473
474    fn merkle_path_at_addr(&mut self, addr: Address) -> Vec<MerklePath> {
475        self.with(|this| this.merkle_path_at_addr(addr))
476    }
477
478    fn get_inner_hash_at_addr(&mut self, addr: Address) -> Result<Fp, String> {
479        self.with(|this| this.get_inner_hash_at_addr(addr))
480    }
481
482    fn set_inner_hash_at_addr(&mut self, addr: Address, hash: Fp) -> Result<(), ()> {
483        self.with(|this| this.set_inner_hash_at_addr(addr, hash))
484    }
485
486    fn set_all_accounts_rooted_at(
487        &mut self,
488        addr: Address,
489        accounts: &[Box<Account>],
490    ) -> Result<(), ()> {
491        self.with(|this| this.set_all_accounts_rooted_at(addr, accounts))
492    }
493
494    fn get_all_accounts_rooted_at(&self, addr: Address) -> Option<Vec<(Address, Box<Account>)>> {
495        self.with(|this| this.get_all_accounts_rooted_at(addr))
496    }
497
498    fn make_space_for(&mut self, space: usize) {
499        self.with(|this| this.make_space_for(space))
500    }
501
502    fn commit(&mut self) {
503        self.with(|this| this.commit())
504    }
505}
506
507#[cfg(test)]
508mod tests {
509    use super::*;
510    use tests_mask_ocaml::*;
511
512    #[cfg(target_family = "wasm")]
513    use wasm_bindgen_test::wasm_bindgen_test as test;
514
515    #[test]
516    fn test_drop_mask() {
517        let root_uuid;
518        let child1_uuid;
519        let child2_uuid;
520
521        let child = {
522            let child = {
523                println!("A");
524                let root = Mask::new_unattached(25);
525                root_uuid = root.get_uuid();
526                println!("root={:?}", root.get_uuid());
527                // let root = Mask::new_root(crate::Database::create(35.try_into().unwrap()));
528                println!("B");
529                let child = root.make_child();
530                println!("child={:?}", child.get_uuid());
531                child1_uuid = child.get_uuid();
532                child
533            };
534            println!("C");
535            assert!(child.is_attached());
536
537            let child = child.make_child();
538            child2_uuid = child.get_uuid();
539            child
540        };
541
542        println!("D");
543        println!("child2={:?}", child.get_uuid());
544        assert!(child.is_attached());
545
546        {
547            let parent = child.get_parent().unwrap();
548            let parent = parent.get_parent().unwrap();
549            assert_eq!(parent.get_uuid(), root_uuid);
550        }
551
552        // The 3 masks should still be alive
553        assert!(crate::mask::is_alive(&root_uuid));
554        assert!(crate::mask::is_alive(&child1_uuid));
555        assert!(crate::mask::is_alive(&child2_uuid));
556
557        std::mem::drop(child);
558
559        // Now they are all drop/deallocated
560        assert!(!crate::mask::is_alive(&root_uuid));
561        assert!(!crate::mask::is_alive(&child1_uuid));
562        assert!(!crate::mask::is_alive(&child2_uuid));
563    }
564
565    #[test]
566    fn test_merkle_path_one_account() {
567        let (mut root, mask) = new_instances(DEPTH);
568        let mut mask = root.register_mask(mask);
569
570        let account = Account::rand();
571
572        let addr = root
573            .get_or_create_account(account.id(), account)
574            .unwrap()
575            .addr();
576
577        let path = mask.merkle_path(addr);
578        assert_eq!(path.len(), DEPTH);
579    }
580
581    #[test]
582    fn test_masks() {
583        const DEPTH: usize = 20;
584
585        let root = Mask::new_unattached(DEPTH);
586        let mask = Mask::new_unattached(DEPTH);
587
588        let mut mask = root.register_mask(mask);
589
590        let accounts: Vec<_> = (0..18).map(|_| Account::rand()).collect();
591
592        for account in &accounts {
593            mask.get_or_create_account(account.id(), account.clone())
594                .unwrap();
595        }
596
597        let mask_paths: Vec<_> = (0..18)
598            .map(|index| {
599                let index: AccountIndex = index.into();
600                let addr = Address::from_index(index, DEPTH);
601                mask.merkle_path(addr)
602            })
603            .collect();
604
605        let mask_root_hash = mask.merkle_root();
606
607        let mut db = Database::create(DEPTH as u8);
608        for account in &accounts {
609            db.get_or_create_account(account.id(), account.clone())
610                .unwrap();
611        }
612
613        let db_paths: Vec<_> = (0..18)
614            .map(|index| {
615                let index: AccountIndex = index.into();
616                let addr = Address::from_index(index, DEPTH);
617                mask.merkle_path(addr)
618            })
619            .collect();
620
621        let db_root_hash = db.merkle_root();
622
623        assert_eq!(mask_root_hash, db_root_hash);
624        assert_eq!(mask_paths, db_paths);
625    }
626
627    #[test]
628    fn test_masks_unregister_recursive() {
629        let (_root, layer1, layer2) = new_chain(DEPTH);
630
631        let layer3 = layer2.make_child();
632        let layer4 = layer2.make_child();
633
634        for mask in [&layer1, &layer2, &layer3, &layer4] {
635            assert!(mask.get_parent().is_some());
636        }
637
638        // This should not panic
639        layer1.unregister_mask(UnregisterBehavior::Recursive);
640
641        for mask in [&layer1, &layer2, &layer3, &layer4] {
642            assert!(mask.get_parent().is_none());
643        }
644    }
645
646    // Make sure hashes are correctly invalided in masks (parents/childs)
647    #[test]
648    fn test_masks_cached_hashes() {
649        for case in 0..2 {
650            let (mut root, mut layer1, mut layer2) = new_chain(DEPTH);
651
652            let acc1 = Account::rand();
653            let acc2 = Account::rand();
654            let acc3 = Account::rand();
655
656            let _loc1 = root.get_or_create_account(acc1.id(), acc1).unwrap().addr();
657            let _loc2 = layer1
658                .get_or_create_account(acc2.id(), acc2.clone())
659                .unwrap()
660                .addr();
661            let _loc3 = layer2
662                .get_or_create_account(acc3.id(), acc3)
663                .unwrap()
664                .addr();
665
666            let root_hash = layer2.merkle_root();
667
668            // Different cases where is should result in a different hash for the childs
669
670            if case == 0 {
671                layer1.remove_accounts(&[acc2.id()]);
672            } else if case == 1 {
673                let account_index = AccountIndex::from(1);
674                let addr = Address::from_index(account_index, DEPTH);
675                let new_account = Account::rand();
676
677                assert_ne!(*layer1.get(addr.clone()).unwrap(), new_account);
678
679                layer1.set(addr, Box::new(new_account));
680            }
681
682            assert_ne!(root_hash, layer2.merkle_root(), "case {:?}", case);
683        }
684    }
685
686    #[test]
687    fn test_cached_merkle_path() {
688        let (mut root, mask) = new_instances(DEPTH);
689        let mut mask = root.register_mask(mask);
690
691        let account = Account::rand();
692        let addr = Address::first(DEPTH);
693
694        mask.set(addr.clone(), Box::new(account.clone()));
695        mask.merkle_root();
696        let mask_merkle_path = mask.merkle_path(addr.clone());
697
698        root.set(addr.clone(), Box::new(account));
699        root.merkle_root();
700        let root_merkle_path = root.merkle_path(addr);
701
702        assert!(!mask_merkle_path.is_empty());
703        assert_eq!(mask_merkle_path, root_merkle_path);
704        elog!("path={:?}", mask_merkle_path);
705    }
706}
707
708#[cfg(test)]
709mod tests_mask_ocaml {
710    use crate::scan_state::currency::{Balance, Magnitude};
711
712    use super::*;
713
714    use rand::{thread_rng, Rng};
715
716    #[cfg(target_family = "wasm")]
717    use wasm_bindgen_test::wasm_bindgen_test as test;
718
719    pub const DEPTH: usize = 4;
720    pub const FIRST_LOC: Address = Address::first(DEPTH);
721
722    pub fn new_instances(depth: usize) -> (Mask, Mask) {
723        let db = Database::<V2>::create(depth as u8);
724        (Mask::new_root(db), Mask::new_unattached(depth))
725    }
726
727    pub fn new_chain(depth: usize) -> (Mask, Mask, Mask) {
728        let db = Database::<V2>::create(depth as u8);
729        let layer1 = Mask::new_unattached(depth);
730        let layer2 = Mask::new_unattached(depth);
731
732        let root = Mask::new_root(db);
733        let layer1 = root.register_mask(layer1);
734        let layer2 = layer1.register_mask(layer2);
735
736        (root, layer1, layer2)
737    }
738
739    fn make_full_accounts(depth: usize) -> Vec<Account> {
740        (0..2u64.pow(depth as u32))
741            .map(|_| Account::rand())
742            .collect()
743    }
744
745    // "parent, mask agree on set"
746    #[test]
747    fn test_parent_mask_agree_on_set() {
748        let (mut root, mask) = new_instances(DEPTH);
749        let mask = root.register_mask(mask);
750
751        root.set(FIRST_LOC, Box::new(Account::rand()));
752
753        let root_account = root.get(FIRST_LOC).unwrap();
754        let mask_account = mask.get(FIRST_LOC).unwrap();
755
756        assert_eq!(root_account, mask_account);
757    }
758
759    // "parent, mask agree on set"
760    #[test]
761    fn test_parent_mask_agree_on_set2() {
762        let (mut root, mask) = new_instances(DEPTH);
763        let mut mask = root.register_mask(mask);
764
765        let account = Box::new(Account::rand());
766        root.set(FIRST_LOC, account.clone());
767        mask.set(FIRST_LOC, account);
768
769        let root_account = root.get(FIRST_LOC).unwrap();
770        let mask_account = mask.get(FIRST_LOC).unwrap();
771
772        assert_eq!(root_account, mask_account);
773    }
774
775    // "parent, mask agree on hashes; set in both mask and parent"
776    #[test]
777    fn test_parent_mask_agree_on_hashes() {
778        let (mut root, mask) = new_instances(DEPTH);
779        let mut mask = root.register_mask(mask);
780
781        let account = Box::new(Account::rand());
782        root.set(FIRST_LOC, account.clone());
783        mask.set(FIRST_LOC, account);
784
785        assert_eq!(root.merkle_root(), mask.merkle_root());
786    }
787
788    // "parent, mask agree on hashes; set only in parent"
789    #[test]
790    fn test_parent_mask_agree_on_hashes_set_parent_only() {
791        let (mut root, mask) = new_instances(DEPTH);
792        let mut mask = root.register_mask(mask);
793
794        let account = Box::new(Account::rand());
795        root.set(FIRST_LOC, account);
796
797        assert_eq!(root.merkle_root(), mask.merkle_root());
798    }
799
800    // "mask delegates to parent"
801    #[test]
802    fn test_mask_delegate_to_parent() {
803        let (mut root, mask) = new_instances(DEPTH);
804        let mask = root.register_mask(mask);
805
806        let account = Box::new(Account::rand());
807        root.set(FIRST_LOC, account.clone());
808
809        let child_account = mask.get(FIRST_LOC).unwrap();
810
811        assert_eq!(account, child_account);
812    }
813
814    // "mask prune after parent notification"
815    #[test]
816    fn test_mask_prune_after_parent_notif() {
817        let (mut root, mask) = new_instances(DEPTH);
818        let mut mask = root.register_mask(mask);
819
820        // Set in mask
821        let account = Box::new(Account::rand());
822        mask.set(FIRST_LOC, account.clone());
823
824        assert!(mask.test_is_in_mask(&FIRST_LOC));
825
826        root.set(FIRST_LOC, account);
827
828        // The address is no more in the mask
829        assert!(!mask.test_is_in_mask(&FIRST_LOC));
830    }
831
832    // "commit puts mask contents in parent, flushes mask"
833    #[test]
834    fn test_commit_puts_mask_in_parent_and_flush_mask() {
835        let (root, mask) = new_instances(DEPTH);
836        let mut mask = root.register_mask(mask);
837
838        let account = Box::new(Account::rand());
839        mask.set(FIRST_LOC, account);
840
841        assert!(mask.test_is_in_mask(&FIRST_LOC));
842
843        mask.commit();
844
845        // No more in mask
846        assert!(!mask.test_is_in_mask(&FIRST_LOC));
847        // The parent get the account
848        assert!(root.get(FIRST_LOC).is_some());
849    }
850
851    // "commit at layer2, dumps to layer1, not in base"
852    #[test]
853    fn test_commit_layer2_dumps_to_layer1_not_in_base() {
854        let (root, layer1, mut layer2) = new_chain(DEPTH);
855
856        let account = Box::new(Account::rand());
857
858        layer2.set(FIRST_LOC, account);
859        assert!(layer2.test_is_in_mask(&FIRST_LOC));
860        assert!(!layer1.test_is_in_mask(&FIRST_LOC));
861
862        layer2.commit();
863        assert!(!layer2.test_is_in_mask(&FIRST_LOC));
864        assert!(layer1.test_is_in_mask(&FIRST_LOC));
865        assert!(!root.test_is_in_mask(&FIRST_LOC));
866    }
867
868    // "commit at layer2, dumps to layer1, not in base"
869    #[test]
870    fn test_commit_layer2_to_root_dumps_to_base_not_in_layer1() {
871        let (root, mut layer1, mut layer2) = new_chain(DEPTH);
872
873        let (addr1, addr2) = (FIRST_LOC, FIRST_LOC.next().unwrap());
874        let (account1, account2) = (Box::new(Account::rand()), Box::new(Account::rand()));
875
876        layer1.set(addr1.clone(), account1);
877        layer2.set(addr2.clone(), account2);
878
879        assert!(layer1.test_is_in_mask(&addr1));
880        assert!(!layer1.test_is_in_mask(&addr2));
881        assert!(layer2.test_is_in_mask(&addr2));
882        assert!(!layer2.test_is_in_mask(&addr1));
883
884        layer2.commit_and_reparent_to_root();
885        assert!(!layer1.test_is_in_mask(&addr1));
886        assert!(!layer1.test_is_in_mask(&addr2));
887        assert!(!layer2.test_is_in_mask(&addr1));
888        assert!(!layer2.test_is_in_mask(&addr2));
889
890        assert!(!layer1.is_attached());
891        assert!(!layer2.is_attached());
892        assert!(root.test_is_in_mask(&addr1));
893        assert!(root.test_is_in_mask(&addr2));
894    }
895
896    // "register and unregister mask"
897    #[test]
898    fn test_register_unregister_mask() {
899        let (root, mask) = new_instances(DEPTH);
900        let mask = root.register_mask(mask);
901        mask.unregister_mask(UnregisterBehavior::Recursive);
902    }
903
904    // "mask and parent agree on Merkle path"
905    #[test]
906    fn test_mask_and_parent_agree_on_merkle_path() {
907        let (mut root, mask) = new_instances(DEPTH);
908        let mut mask = root.register_mask(mask);
909
910        let account = Box::new(Account::rand());
911        let addr = Address::first(DEPTH);
912
913        mask.set(addr.clone(), account.clone());
914        let mask_merkle_path = mask.merkle_path(addr.clone());
915
916        root.set(addr.clone(), account);
917        let root_merkle_path = root.merkle_path(addr);
918
919        assert!(!mask_merkle_path.is_empty());
920        assert_eq!(mask_merkle_path, root_merkle_path);
921        elog!("path={:?}", mask_merkle_path);
922    }
923
924    // "mask and parent agree on Merkle root before set"
925    #[test]
926    fn test_agree_on_root_hash_before_set() {
927        let (mut root, mask) = new_instances(DEPTH);
928        let mut mask = root.register_mask(mask);
929
930        assert_eq!(root.merkle_root(), mask.merkle_root());
931    }
932
933    // "mask and parent agree on Merkle root after set"
934    #[test]
935    fn test_agree_on_root_hash_after_set() {
936        let (mut root, mask) = new_instances(DEPTH);
937        let mut mask = root.register_mask(mask);
938
939        let account = Box::new(Account::rand());
940
941        // the order of sets matters here; if we set in the mask first,
942        // the set in the maskable notifies the mask, which then removes
943        // the account, changing the Merkle root to what it was before the set
944
945        root.set(FIRST_LOC, account.clone());
946        mask.set(FIRST_LOC, account);
947
948        assert!(root.test_is_in_mask(&FIRST_LOC));
949        assert!(mask.test_is_in_mask(&FIRST_LOC));
950        assert_eq!(root.merkle_root(), mask.merkle_root());
951    }
952
953    // "add and retrieve a block of accounts"
954    #[test]
955    fn test_add_retrieve_block_of_accounts() {
956        let (root, mask) = new_instances(DEPTH);
957        let mut mask = root.register_mask(mask);
958
959        let accounts = make_full_accounts(DEPTH);
960
961        for account in &accounts {
962            let account_id = account.id();
963            let res = mask
964                .get_or_create_account(account_id, account.clone())
965                .unwrap();
966            assert!(matches!(res, GetOrCreated::Added(_)));
967        }
968
969        let retrieved_accounts = mask
970            .get_all_accounts_rooted_at(Address::root())
971            .unwrap()
972            .into_iter()
973            .map(|(_, acc)| acc)
974            .collect::<Vec<_>>();
975
976        assert_eq!(
977            accounts.into_iter().map(Box::new).collect::<Vec<_>>(),
978            retrieved_accounts
979        );
980    }
981
982    // "removing accounts from mask restores Merkle root"
983    #[test]
984    fn test_removing_accounts_from_mask_restore_root_hash() {
985        let (root, mask) = new_instances(DEPTH);
986        let mut mask = root.register_mask(mask);
987
988        let accounts = (0..5).map(|_| Account::rand()).collect::<Vec<_>>();
989        let accounts_ids = accounts.iter().map(Account::id).collect::<Vec<_>>();
990        let root_hash0 = mask.merkle_root();
991
992        for account in accounts {
993            mask.get_or_create_account(account.id(), account).unwrap();
994        }
995        assert_ne!(root_hash0, mask.merkle_root());
996
997        mask.remove_accounts(&accounts_ids);
998        assert_eq!(root_hash0, mask.merkle_root());
999    }
1000
1001    // "removing accounts from parent restores Merkle root"
1002    #[test]
1003    fn test_removing_accounts_from_parent_restore_root_hash() {
1004        let (mut root, mask) = new_instances(DEPTH);
1005        let mut mask = root.register_mask(mask);
1006
1007        let accounts = (0..5).map(|_| Account::rand()).collect::<Vec<_>>();
1008        let accounts_ids = accounts.iter().map(Account::id).collect::<Vec<_>>();
1009        let root_hash0 = mask.merkle_root();
1010
1011        for account in accounts {
1012            root.get_or_create_account(account.id(), account).unwrap();
1013        }
1014        assert_ne!(root_hash0, mask.merkle_root());
1015
1016        mask.remove_accounts(&accounts_ids);
1017        assert_eq!(root_hash0, mask.merkle_root());
1018    }
1019
1020    // "removing accounts from parent and mask restores Merkle root"
1021    #[test]
1022    fn test_removing_accounts_from_parent_and_mask_restore_root_hash() {
1023        let (mut root, mask) = new_instances(DEPTH);
1024        let mut mask = root.register_mask(mask);
1025
1026        let accounts = (0..10).map(|_| Account::rand()).collect::<Vec<_>>();
1027        let (accounts_parent, accounts_mask) = accounts.split_at(5);
1028        let accounts_ids = accounts.iter().map(Account::id).collect::<Vec<_>>();
1029
1030        let root_hash0 = mask.merkle_root();
1031
1032        for account in accounts_parent {
1033            root.get_or_create_account(account.id(), account.clone())
1034                .unwrap();
1035        }
1036        for account in accounts_mask {
1037            mask.get_or_create_account(account.id(), account.clone())
1038                .unwrap();
1039        }
1040        assert_ne!(root_hash0, mask.merkle_root());
1041
1042        mask.remove_accounts(&accounts_ids);
1043        assert_eq!(root_hash0, mask.merkle_root());
1044    }
1045
1046    // "fold of addition over account balances in parent and mask"
1047    #[test]
1048    fn test_fold_of_addition_over_account_balance_in_parent_and_mask() {
1049        let (mut root, mask) = new_instances(DEPTH);
1050        let mut mask = root.register_mask(mask);
1051
1052        let accounts = (0..10).map(|_| Account::rand()).collect::<Vec<_>>();
1053        let balance = accounts
1054            .iter()
1055            .fold(0u128, |acc, account| acc + account.balance.as_u64() as u128);
1056
1057        let (accounts_parent, accounts_mask) = accounts.split_at(5);
1058
1059        for account in accounts_parent {
1060            root.get_or_create_account(account.id(), account.clone())
1061                .unwrap();
1062        }
1063        for account in accounts_mask {
1064            mask.get_or_create_account(account.id(), account.clone())
1065                .unwrap();
1066        }
1067
1068        let retrieved_balance =
1069            mask.fold(0u128, |acc, account| acc + account.balance.as_u64() as u128);
1070        assert_eq!(balance, retrieved_balance);
1071    }
1072
1073    fn create_existing_account(mask: &mut Mask, account: Account) {
1074        match mask
1075            .get_or_create_account(account.id(), account.clone())
1076            .unwrap()
1077        {
1078            GetOrCreated::Added(_) => panic!("Should add an existing account"),
1079            GetOrCreated::Existed(addr) => {
1080                mask.set(addr, Box::new(account));
1081            }
1082        }
1083    }
1084
1085    // "masking in to_list"
1086    #[test]
1087    fn test_masking_in_to_list() {
1088        let (mut root, mask) = new_instances(DEPTH);
1089        let mut mask = root.register_mask(mask);
1090
1091        let mut accounts = (0..10).map(|_| Account::rand()).collect::<Vec<_>>();
1092        // Make balances non-zero
1093        let one = Balance::from_u64(1);
1094        accounts
1095            .iter_mut()
1096            .for_each(|account| account.balance = account.balance.checked_add(&one).unwrap_or(one));
1097
1098        for account in &accounts {
1099            root.get_or_create_account(account.id(), account.clone())
1100                .unwrap();
1101        }
1102
1103        let parent_list = root.to_list();
1104
1105        // Make balances to zero for those same account
1106        accounts
1107            .iter_mut()
1108            .for_each(|account| account.balance = Balance::zero());
1109
1110        for account in accounts {
1111            create_existing_account(&mut mask, account);
1112        }
1113
1114        let mask_list = mask.to_list();
1115
1116        assert_eq!(parent_list.len(), mask_list.len());
1117        // Same accounts and order
1118        assert_eq!(
1119            parent_list.iter().map(Account::id).collect::<Vec<_>>(),
1120            mask_list.iter().map(Account::id).collect::<Vec<_>>(),
1121        );
1122        // Balances of mask are zero
1123        assert_eq!(
1124            mask_list
1125                .iter()
1126                .fold(0u128, |acc, account| acc + account.balance.as_u64() as u128),
1127            0
1128        );
1129    }
1130
1131    // "masking in foldi"
1132    #[test]
1133    fn test_masking_in_to_foldi() {
1134        let (mut root, mask) = new_instances(DEPTH);
1135        let mut mask = root.register_mask(mask);
1136
1137        let mut accounts = (0..10).map(|_| Account::rand()).collect::<Vec<_>>();
1138        // Make balances non-zero
1139        let one = Balance::from_u64(1);
1140        accounts
1141            .iter_mut()
1142            .for_each(|account| account.balance = account.balance.checked_add(&one).unwrap_or(one));
1143
1144        for account in &accounts {
1145            root.get_or_create_account(account.id(), account.clone())
1146                .unwrap();
1147        }
1148
1149        let parent_sum_balance =
1150            root.fold(0u128, |acc, account| acc + account.balance.as_u64() as u128);
1151        assert_ne!(parent_sum_balance, 0);
1152
1153        // Make balances to zero for those same account
1154        accounts
1155            .iter_mut()
1156            .for_each(|account| account.balance = Balance::zero());
1157
1158        for account in accounts {
1159            create_existing_account(&mut mask, account);
1160        }
1161
1162        let mask_sum_balance =
1163            mask.fold(0u128, |acc, account| acc + account.balance.as_u64() as u128);
1164        assert_eq!(mask_sum_balance, 0);
1165    }
1166
1167    // "create_empty doesn't modify the hash"
1168    #[test]
1169    fn test_create_empty_doesnt_modify_the_hash() {
1170        let (root, mask) = new_instances(DEPTH);
1171        let mut mask = root.register_mask(mask);
1172
1173        let start_hash = mask.merkle_root();
1174
1175        let account = Account::empty();
1176        mask.get_or_create_account(account.id(), account).unwrap();
1177
1178        assert_eq!(mask.num_accounts(), 1);
1179        assert_eq!(start_hash, mask.merkle_root());
1180    }
1181
1182    // "reuse of locations for removed accounts"
1183    #[test]
1184    fn test_reuse_of_locations_for_removed_accounts() {
1185        let (root, mask) = new_instances(DEPTH);
1186        let mut mask = root.register_mask(mask);
1187
1188        let accounts = (0..10).map(|_| Account::rand()).collect::<Vec<_>>();
1189        let accounts_ids = accounts.iter().map(Account::id).collect::<Vec<_>>();
1190
1191        assert!(mask.last_filled().is_none());
1192        for account in accounts {
1193            mask.get_or_create_account(account.id(), account.clone())
1194                .unwrap();
1195        }
1196        assert!(mask.last_filled().is_some());
1197
1198        mask.remove_accounts(&accounts_ids);
1199        assert!(mask.last_filled().is_none());
1200    }
1201
1202    // "num_accounts for unique keys in mask and parent"
1203    #[test]
1204    fn test_num_accounts_for_unique_keys_in_mask_and_parent() {
1205        let (mut root, mask) = new_instances(DEPTH);
1206        let mut mask = root.register_mask(mask);
1207
1208        let accounts = (0..10).map(|_| Account::rand()).collect::<Vec<_>>();
1209
1210        for account in &accounts {
1211            mask.get_or_create_account(account.id(), account.clone())
1212                .unwrap();
1213        }
1214
1215        let mask_num_accounts_before = mask.num_accounts();
1216
1217        // Add same accounts to parent
1218        for account in &accounts {
1219            root.get_or_create_account(account.id(), account.clone())
1220                .unwrap();
1221        }
1222
1223        let parent_num_accounts = root.num_accounts();
1224        let mask_num_accounts_after = mask.num_accounts();
1225
1226        assert_eq!(accounts.len(), parent_num_accounts);
1227        assert_eq!(parent_num_accounts, mask_num_accounts_before);
1228        assert_eq!(parent_num_accounts, mask_num_accounts_after);
1229    }
1230
1231    // "Mask reparenting works"
1232    #[test]
1233    fn test_mask_reparenting_works() {
1234        let (mut root, mut layer1, mut layer2) = new_chain(DEPTH);
1235
1236        let acc1 = Account::rand();
1237        let acc2 = Account::rand();
1238        let acc3 = Account::rand();
1239
1240        let loc1 = root.get_or_create_account(acc1.id(), acc1).unwrap().addr();
1241        let loc2 = layer1
1242            .get_or_create_account(acc2.id(), acc2)
1243            .unwrap()
1244            .addr();
1245        let loc3 = layer2
1246            .get_or_create_account(acc3.id(), acc3)
1247            .unwrap()
1248            .addr();
1249
1250        // All accounts are accessible from layer2
1251        assert!(layer2.get(loc1.clone()).is_some());
1252        assert!(layer2.get(loc2.clone()).is_some());
1253        assert!(layer2.get(loc3.clone()).is_some());
1254
1255        // acc1 is in root
1256        assert!(root.get(loc1.clone()).is_some());
1257
1258        layer1.commit();
1259
1260        // acc2 is in root
1261        assert!(root.get(loc2.clone()).is_some());
1262
1263        layer1.remove_and_reparent();
1264
1265        // acc1, acc2 are in root
1266        assert!(root.get(loc1.clone()).is_some());
1267        assert!(root.get(loc2.clone()).is_some());
1268
1269        // acc3 not in root
1270        assert!(root.get(loc3.clone()).is_none());
1271
1272        // All accounts are accessible from layer2
1273        assert!(layer2.get(loc1).is_some());
1274        assert!(layer2.get(loc2).is_some());
1275        assert!(layer2.get(loc3).is_some());
1276    }
1277
1278    // "setting an account in the parent doesn't remove the masked
1279    // copy if the mask is still dirty for that account"
1280    #[test]
1281    fn test_set_account_in_parent_doesnt_remove_if_mask_is_dirty() {
1282        let (mut root, mask) = new_instances(DEPTH);
1283        let mut mask = root.register_mask(mask);
1284
1285        let mut account = Box::new(Account::rand());
1286        let mut account2 = account.clone();
1287
1288        account.balance = Balance::from_u64(10);
1289        account2.balance = Balance::from_u64(5);
1290
1291        let loc = mask
1292            .get_or_create_account(account.id(), *account.clone())
1293            .unwrap()
1294            .addr();
1295
1296        root.set(loc.clone(), account2);
1297
1298        assert_eq!(mask.get(loc).unwrap(), account);
1299    }
1300
1301    // "get_all_accounts should preserve the ordering of accounts by
1302    // location with noncontiguous updates of accounts on the mask"
1303    #[test]
1304    fn test_get_all_accounts_should_preserve_ordering() {
1305        let (_root, mut layer1, mut layer2) = new_chain(DEPTH);
1306
1307        let accounts = make_full_accounts(DEPTH);
1308
1309        for account in &accounts {
1310            layer1
1311                .get_or_create_account(account.id(), account.clone())
1312                .unwrap();
1313        }
1314
1315        let mut updated_accounts = accounts.clone();
1316        let mut rng = thread_rng();
1317        let mut nmodified = 0;
1318
1319        for account in updated_accounts.iter_mut() {
1320            if rng.gen::<u8>() >= 150 {
1321                continue;
1322            }
1323            account.balance = rng.gen();
1324
1325            create_existing_account(&mut layer2, account.clone());
1326            nmodified += 1;
1327        }
1328
1329        assert!(nmodified > 0);
1330        assert_eq!(
1331            updated_accounts
1332                .into_iter()
1333                .map(Box::new)
1334                .collect::<Vec<_>>(),
1335            layer2
1336                .get_all_accounts_rooted_at(Address::root())
1337                .unwrap()
1338                .into_iter()
1339                .map(|(_, account)| account)
1340                .collect::<Vec<_>>()
1341        );
1342        assert_eq!(
1343            accounts.into_iter().map(Box::new).collect::<Vec<_>>(),
1344            layer1
1345                .get_all_accounts_rooted_at(Address::root())
1346                .unwrap()
1347                .into_iter()
1348                .map(|(_, account)| account)
1349                .collect::<Vec<_>>()
1350        );
1351    }
1352
1353    #[test]
1354    fn test_validate_inner_hashes() {
1355        let l = Address::first(1);
1356        assert_eq!(l.parent().unwrap(), Address::root());
1357        assert_eq!(l.parent(), l.next().unwrap().parent());
1358        let (root, layer1, layer2) = new_chain(DEPTH);
1359
1360        let accounts = make_full_accounts(DEPTH);
1361
1362        for (i, mut mask) in [root, layer1, layer2].into_iter().enumerate() {
1363            for account in accounts.iter().skip(i) {
1364                mask.get_or_create_account(account.id(), account.clone())
1365                    .unwrap();
1366            }
1367            dbg!(mask.merkle_root());
1368            mask.validate_inner_hashes().unwrap();
1369        }
1370    }
1371
1372    #[test]
1373    fn test_nmasks_to_root() {
1374        let (root, layer1, layer2) = new_chain(DEPTH);
1375        assert_eq!(root.nmasks_to_root(), 0);
1376        assert_eq!(layer1.nmasks_to_root(), 1);
1377        assert_eq!(layer2.nmasks_to_root(), 2);
1378
1379        let mut mask = layer2;
1380        for index in 0..300 {
1381            assert_eq!(mask.nmasks_to_root(), 2 + index);
1382            mask = mask.make_child();
1383        }
1384    }
1385}