1use std::{
2 collections::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::{AccountIndex, BaseLedger, GetOrCreated, MerklePath, Uuid},
14 tree_version::V2,
16 TreeVersion,
17};
18
19use crate::HashesMatrix;
20
21use super::database_impl::DatabaseImpl;
22
23#[derive(Debug, PartialEq, Eq)]
24pub enum DatabaseError {
25 OutOfLeaves,
26}
27
28#[derive(Clone, Debug)]
29pub struct Database<T: TreeVersion> {
30 pub inner: Arc<Mutex<DatabaseImpl<T>>>,
32}
33
34impl Database<V2> {
42 pub fn with<F, R>(&self, fun: F) -> R
43 where
44 F: FnOnce(&mut DatabaseImpl<V2>) -> R,
45 {
46 let mut inner = self.inner.try_lock().expect("lock failed");
47 fun(&mut inner)
48 }
49}
50
51impl Database<V2> {
52 pub fn create_with_dir(depth: u8, dir_name: Option<PathBuf>) -> Self {
53 let db = DatabaseImpl::<V2>::create_with_dir(depth, dir_name);
54
55 Self {
56 inner: Arc::new(Mutex::new(db)),
57 }
58 }
59
60 pub fn create(depth: u8) -> Self {
61 Self::create_with_dir(depth, None)
62 }
63
64 pub fn create_with_token_owners(depth: u8) -> Self {
65 let mut db = Self::create_with_dir(depth, None);
66 db.set_token_owners();
67 db
68 }
69
70 pub fn set_token_owners(&mut self) {
71 self.with(|this| this.set_token_owners());
72 }
73
74 pub fn unset_token_owners(&mut self) {
75 self.with(|this| this.unset_token_owners());
76 }
77
78 pub fn root_hash(&mut self) -> Fp {
79 self.with(|this| this.root_hash())
80 }
81
82 pub fn naccounts(&self) -> usize {
84 self.with(|this| this.naccounts())
85 }
86
87 pub fn create_checkpoint(&self, directory_name: String) {
88 self.with(|this| this.create_checkpoint(directory_name))
89 }
90
91 pub fn make_checkpoint(&self, directory_name: String) {
92 self.with(|this| this.make_checkpoint(directory_name))
93 }
94
95 pub fn clone_db(&self, directory_name: PathBuf) -> Self {
96 let db = self.with(|this| this.clone_db(directory_name));
97 Self {
98 inner: Arc::new(Mutex::new(db)),
99 }
100 }
101
102 pub fn get_cached_hash(&self, addr: &Address) -> Option<Fp> {
103 self.with(|this| this.get_cached_hash(addr))
104 }
105
106 pub fn set_cached_hash(&mut self, addr: &Address, hash: Fp) {
107 self.with(|this| this.set_cached_hash(addr, hash))
108 }
109
110 pub fn empty_hash_at_height(&mut self, height: usize) -> Fp {
111 self.with(|this| this.empty_hash_at_height(height))
112 }
113
114 pub fn invalidate_hashes(&mut self, account_index: AccountIndex) {
115 self.with(|this| this.invalidate_hashes(account_index))
116 }
117
118 pub fn transfert_hashes(&mut self, hashes: HashesMatrix) {
119 self.with(|this| this.transfert_hashes(hashes))
120 }
121
122 pub fn has_token_owners(&self) -> bool {
123 self.with(|this| this.has_token_owners())
124 }
125
126 #[cfg(test)]
127 pub fn test_matrix(&self) -> HashesMatrix {
128 self.with(|this| this.hashes_matrix.clone())
129 }
134}
135
136impl BaseLedger for Database<V2> {
137 fn to_list(&self) -> Vec<Account> {
138 self.with(|this| this.to_list())
139 }
140
141 fn iter<F>(&self, fun: F)
142 where
143 F: FnMut(&Account),
144 {
145 self.with(|this| this.iter(fun))
146 }
147
148 fn fold<B, F>(&self, init: B, fun: F) -> B
149 where
150 F: FnMut(B, &Account) -> B,
151 {
152 self.with(|this| this.fold(init, fun))
153 }
154
155 fn fold_with_ignored_accounts<B, F>(&self, ignoreds: HashSet<AccountId>, init: B, fun: F) -> B
156 where
157 F: FnMut(B, &Account) -> B,
158 {
159 self.with(|this| this.fold_with_ignored_accounts(ignoreds, init, fun))
160 }
161
162 fn fold_until<B, F>(&self, init: B, fun: F) -> B
163 where
164 F: FnMut(B, &Account) -> std::ops::ControlFlow<B, B>,
165 {
166 self.with(|this| this.fold_until(init, fun))
167 }
168
169 fn accounts(&self) -> HashSet<AccountId> {
170 self.with(|this| this.accounts())
171 }
172
173 fn token_owner(&self, token_id: TokenId) -> Option<AccountId> {
174 self.with(|this| this.token_owner(token_id))
175 }
176
177 fn tokens(&self, public_key: CompressedPubKey) -> HashSet<TokenId> {
178 self.with(|this| this.tokens(public_key))
179 }
180
181 fn location_of_account(&self, account_id: &AccountId) -> Option<Address> {
182 self.with(|this| this.location_of_account(account_id))
183 }
184
185 fn location_of_account_batch(
186 &self,
187 account_ids: &[AccountId],
188 ) -> Vec<(AccountId, Option<Address>)> {
189 self.with(|this| this.location_of_account_batch(account_ids))
190 }
191
192 fn get_or_create_account(
193 &mut self,
194 account_id: AccountId,
195 account: Account,
196 ) -> Result<GetOrCreated, DatabaseError> {
197 self.with(|this| this.get_or_create_account(account_id, account))
198 }
199
200 fn close(&self) {
201 }
203
204 fn last_filled(&self) -> Option<Address> {
205 self.with(|this| this.last_filled())
206 }
207
208 fn get_uuid(&self) -> Uuid {
209 self.with(|this| this.get_uuid())
210 }
211
212 fn get_directory(&self) -> Option<PathBuf> {
213 self.with(|this| this.get_directory())
214 }
215
216 fn get_account_hash(&mut self, account_index: AccountIndex) -> Option<Fp> {
217 self.with(|this| this.get_account_hash(account_index))
218 }
219
220 fn get(&self, addr: Address) -> Option<Box<Account>> {
221 self.with(|this| this.get(addr))
222 }
223
224 fn get_batch(&self, addr: &[Address]) -> Vec<(Address, Option<Box<Account>>)> {
225 self.with(|this| this.get_batch(addr))
226 }
227
228 fn set(&mut self, addr: Address, account: Box<Account>) {
229 self.with(|this| this.set(addr, account))
230 }
231
232 fn set_batch(&mut self, list: &[(Address, Box<Account>)]) {
233 self.with(|this| this.set_batch(list))
234 }
235
236 fn get_at_index(&self, index: AccountIndex) -> Option<Box<Account>> {
237 self.with(|this| this.get_at_index(index))
238 }
239
240 fn set_at_index(&mut self, index: AccountIndex, account: Box<Account>) -> Result<(), ()> {
241 self.with(|this| this.set_at_index(index, account))
242 }
243
244 fn index_of_account(&self, account_id: AccountId) -> Option<AccountIndex> {
245 self.with(|this| this.index_of_account(account_id))
246 }
247
248 fn merkle_root(&mut self) -> Fp {
249 self.with(|this| this.merkle_root())
250 }
251
252 fn merkle_path(&mut self, addr: Address) -> Vec<MerklePath> {
253 self.with(|this| this.merkle_path(addr))
254 }
255
256 fn merkle_path_at_index(&mut self, index: AccountIndex) -> Vec<MerklePath> {
257 self.with(|this| this.merkle_path_at_index(index))
258 }
259
260 fn remove_accounts(&mut self, ids: &[AccountId]) {
261 self.with(|this| this.remove_accounts(ids))
262 }
263
264 fn detached_signal(&mut self) {
265 self.with(|this| this.detached_signal())
266 }
267
268 fn depth(&self) -> u8 {
269 self.with(|this| this.depth())
270 }
271
272 fn num_accounts(&self) -> usize {
273 self.with(|this| this.num_accounts())
274 }
275
276 fn merkle_path_at_addr(&mut self, addr: Address) -> Vec<MerklePath> {
277 self.with(|this| this.merkle_path_at_addr(addr))
278 }
279
280 fn get_inner_hash_at_addr(&mut self, addr: Address) -> Result<Fp, String> {
281 self.with(|this| this.get_inner_hash_at_addr(addr))
282 }
283
284 fn set_inner_hash_at_addr(&mut self, addr: Address, hash: Fp) -> Result<(), ()> {
285 self.with(|this| this.set_inner_hash_at_addr(addr, hash))
286 }
287
288 fn set_all_accounts_rooted_at(
289 &mut self,
290 addr: Address,
291 accounts: &[Box<Account>],
292 ) -> Result<(), ()> {
293 self.with(|this| this.set_all_accounts_rooted_at(addr, accounts))
294 }
295
296 fn get_all_accounts_rooted_at(&self, addr: Address) -> Option<Vec<(Address, Box<Account>)>> {
297 self.with(|this| this.get_all_accounts_rooted_at(addr))
298 }
299
300 fn make_space_for(&mut self, space: usize) {
301 self.with(|this| this.make_space_for(space))
302 }
303
304 fn commit(&mut self) {
305 }
307}
308
309#[cfg(test)]
310mod tests {
311 use ark_ff::One;
312 use o1_utils::FieldHelpers;
313
314 #[cfg(target_family = "wasm")]
315 use wasm_bindgen_test::wasm_bindgen_test as test;
316
317 use crate::tree_version::{account_empty_legacy_hash, V1};
318
319 use super::*;
320
321 #[test]
345 fn test_matrix() {
346 const DEPTH: usize = 4;
347
348 let mut matrix = HashesMatrix::new(DEPTH);
349 let one = Fp::one();
350
351 for index in 0..16 {
352 let account_index = AccountIndex::from(index);
353 let addr = Address::from_index(account_index, DEPTH);
354 matrix.set(&addr, one);
355
356 elog!("{:?} MATRIX {:#?}", index + 1, matrix);
357 }
358
359 let addr = Address::root();
360
361 matrix.set(&addr, one);
362 elog!("{:?} MATRIX {:#?}", "root", matrix);
363
364 matrix.set(&addr.child_left(), one);
365 elog!("{:?} MATRIX {:#?}", "root", matrix);
366 matrix.set(&addr.child_right(), one);
367 elog!("{:?} MATRIX {:#?}", "root", matrix);
368
369 matrix.set(&addr.child_left().child_left(), one);
370 elog!("{:?} MATRIX {:#?}", "root", matrix);
371 matrix.set(&addr.child_left().child_right(), one);
372 elog!("{:?} MATRIX {:#?}", "root", matrix);
373 matrix.set(&addr.child_right().child_left(), one);
374 elog!("{:?} MATRIX {:#?}", "root", matrix);
375 matrix.set(&addr.child_right().child_right(), one);
376 elog!("{:?} MATRIX {:#?}", "root", matrix);
377 }
378
379 #[test]
380 fn test_db_v2() {
381 let two: usize = 2;
382
383 for depth in 2..15 {
384 let mut db = Database::<V2>::create(depth);
385
386 for _ in 0..two.pow(depth as u32) {
387 let account = Account::rand();
388 let id = account.id();
389 db.get_or_create_account(id, account).unwrap();
390 }
391
392 let naccounts = db.naccounts();
393 assert_eq!(naccounts, two.pow(depth as u32));
394
395 let account = Account::create();
396 let id = account.id();
397 assert_eq!(
398 db.get_or_create_account(id, account).unwrap_err(),
399 DatabaseError::OutOfLeaves
400 );
401
402 elog!("depth={:?} naccounts={:?}", depth, naccounts);
403 }
404 }
405
406 #[cfg(target_family = "wasm")]
408 #[test]
409 fn test_hashing_tree_with_web_workers() {
410 use web_sys::console;
411
412 use openmina_core::thread;
413 use std::time::Duration;
414
415 use crate::account;
416
417 let mut msg = format!("hello");
418
419 const NACCOUNTS: u64 = 1_000;
420 const NTHREADS: usize = 8;
421
422 let mut accounts = (0..NACCOUNTS).map(|_| Account::rand()).collect::<Vec<_>>();
423
424 use wasm_bindgen::prelude::*;
425
426 fn perf_to_duration(amt: f64) -> std::time::Duration {
427 let secs = (amt as u64) / 1_000;
428 let nanos = (((amt as u64) % 1_000) as u32) * 1_000_000;
429 std::time::Duration::new(secs, nanos)
430 }
431
432 #[cfg(target_arch = "wasm32")]
433 #[wasm_bindgen(inline_js = r#"
434export function performance_now() {
435 return performance.now();
436}"#)]
437 extern "C" {
438 fn performance_now() -> f64;
439 }
440
441 thread::spawn(move || {
442 console::time_with_label("threads");
443 console::log_1(&format!("hello from first thread {:?}", thread::current().id()).into());
444
445 let start = performance_now();
446
447 let mut joins = Vec::with_capacity(NTHREADS);
448
449 for _ in 0..NTHREADS {
450 let accounts = accounts.split_off(accounts.len() - (NACCOUNTS as usize / NTHREADS));
451
452 let join = thread::spawn(move || {
453 console::log_1(
454 &format!("hello from thread {:?}", thread::current().id()).into(),
455 );
456
457 let hash = accounts.iter().map(|a| a.hash()).collect::<Vec<_>>();
458
459 console::log_1(
460 &format!("ending from thread {:?}", thread::current().id()).into(),
461 );
462
463 hash.len()
464 });
465
466 joins.push(join);
467 }
468
469 let nhashes: usize = joins.into_iter().map(|j| j.join().unwrap()).sum();
470
471 assert_eq!(nhashes, NACCOUNTS as usize);
472
473 let end = performance_now();
474
475 console::log_1(
476 &format!(
477 "nhashes={:?} nthreads={:?} time={:?}",
478 nhashes,
479 NTHREADS,
480 perf_to_duration(end - start)
481 )
482 .into(),
483 );
484 console::time_end_with_label("threads");
485 });
486 }
487
488 #[cfg(target_family = "wasm")]
489 #[test]
490 fn test_hashing_tree() {
491 use web_sys::console;
492
493 const NACCOUNTS: u64 = 1_000;
494
495 console::time_with_label("generate random accounts");
496
497 let mut db = Database::<V2>::create(20, false);
498
499 console::log_1(&format!("{:?} accounts in nodejs", NACCOUNTS).into());
500
501 let accounts = (0..NACCOUNTS).map(|_| Account::rand()).collect::<Vec<_>>();
502
503 for (index, mut account) in accounts.into_iter().enumerate() {
504 account.token_id = TokenId::from(index as u64);
505 let id = account.id();
506 db.get_or_create_account(id, account).unwrap();
507 }
508
509 console::time_end_with_label("generate random accounts");
510 assert_eq!(db.naccounts(), NACCOUNTS as usize);
511
512 console::time_with_label("compute merkle root");
513 db.merkle_root();
514
515 console::time_end_with_label("compute merkle root");
516 }
517
518 #[cfg(not(target_family = "wasm"))]
519 #[test]
520 fn test_hashing_tree() {
521 const NACCOUNTS: u64 = 1_000;
522
523 let now = redux::Instant::now();
524 let mut db = Database::<V2>::create(20);
525
526 elog!("{:?} accounts natively", NACCOUNTS);
527
528 let accounts = (0..NACCOUNTS).map(|_| Account::rand()).collect::<Vec<_>>();
529
530 for (index, mut account) in accounts.into_iter().enumerate() {
531 account.token_id = TokenId::from(index as u64);
532 let id = account.id();
533 db.get_or_create_account(id, account).unwrap();
534 }
535
536 elog!("generate random accounts {:?}", now.elapsed());
537 assert_eq!(db.naccounts(), NACCOUNTS as usize);
538
539 let now = redux::Instant::now();
540 db.merkle_root();
541 elog!("compute merkle root {:?}", now.elapsed());
542 }
543
544 #[test]
545 fn test_legacy_hash_empty() {
546 let account_empty_hash = account_empty_legacy_hash();
547 assert_eq!(
548 account_empty_hash.to_hex(),
549 "70ccdba14f829608e59a37ed98ffcaeef06dad928d568a9adbde13e3dd104a20"
550 );
551
552 for (height, s) in [
553 (
554 0,
555 "70ccdba14f829608e59a37ed98ffcaeef06dad928d568a9adbde13e3dd104a20",
556 ),
557 (
558 5,
559 "4590712e4bd873ba93d01b665940e0edc48db1a7c90859948b7799f45a443b15",
560 ),
561 (
562 10,
563 "ba083b16b757794c81233d4ebf1ab000ba4a174a8174c1e8ee8bf0846ec2e10d",
564 ),
565 (
566 11,
567 "5d65e7d5f4c5441ac614769b913400aa3201f3bf9c0f33441dbf0a33a1239822",
568 ),
569 (
570 100,
571 "0e4ecb6104658cf8c06fca64f7f1cb3b0f1a830ab50c8c7ed9de544b8e6b2530",
572 ),
573 (
574 2000,
575 "b05105f8281f75efaf3c6b324563685c8be3a01b1c7d3f314ae733d869d95209",
576 ),
577 ] {
578 let hash = V1::empty_hash_at_height(height);
579 assert_eq!(hash.to_hex(), s, "invalid hash at depth={:?}", height);
580 }
581 }
582
583 #[test]
584 fn test_hash_empty() {
585 let heights = [0, 5, 10, 11];
586
587 let hexs = [
588 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
589 "d305ebed68f3d4ff16cfc9c6857c274bfbd4a5e83db6fb26e009f75711005524",
590 "bfae9c6290bcc9cf282889c6b880e4eac236d4e50b22395639731e1465939915",
591 "def7de4e2f2f13aa638f5671eccf9367ab9d39ae49ed683fca0169b33b31c416",
592 ];
593
594 let result: Vec<_> = heights
595 .iter()
596 .map(|height| V2::empty_hash_at_height(*height).to_hex())
597 .collect();
598
599 assert_eq!(result, hexs);
600
601 let account_empty_hash = Account::empty().hash();
602 assert_eq!(account_empty_hash.to_hex(), hexs[0]);
603 }
604
605 #[test]
643 fn test_root_hash_different_orders() {
644 let mut db = Database::<V2>::create(4);
645
646 let accounts = (0..16).map(|_| Account::rand()).collect::<Vec<_>>();
647
648 for account in &accounts {
649 db.get_or_create_account(account.id(), account.clone())
650 .unwrap();
651 }
652 let root_hash_1 = db.merkle_root();
653
654 let mut db = Database::<V2>::create(4);
655 for account in accounts.iter().rev() {
656 db.get_or_create_account(account.id(), account.clone())
657 .unwrap();
658 }
659 let root_hash_2 = db.merkle_root();
660
661 assert_ne!(root_hash_1, root_hash_2);
663
664 let mut db = Database::<V2>::create(4);
665 for account in accounts {
666 db.get_or_create_account(account.id(), account).unwrap();
667 }
668 let root_hash_3 = db.merkle_root();
669
670 assert_eq!(root_hash_1, root_hash_3);
672 }
673
674 }
709
710#[cfg(test)]
711mod tests_ocaml {
712 use std::ops::ControlFlow;
713
714 use o1_utils::FieldHelpers;
715 use rand::Rng;
716
717 #[cfg(target_family = "wasm")]
718 use wasm_bindgen_test::wasm_bindgen_test as test;
719
720 use crate::scan_state::currency::Balance;
721
722 use super::*;
723
724 #[test]
726 fn test_add_retrieve_account() {
727 let mut db = Database::<V2>::create(4);
728
729 let account = Account::rand();
730 let location = db
731 .get_or_create_account(account.id(), account.clone())
732 .unwrap();
733 let get_account = db.get(location.addr()).unwrap();
734
735 assert_eq!(account, *get_account);
736 }
737
738 #[test]
740 fn test_accounts_are_atomic() {
741 let mut db = Database::<V2>::create(4);
742
743 let account = Box::new(Account::rand());
744 let location: Address = db
745 .get_or_create_account(account.id(), *account.clone())
746 .unwrap()
747 .addr();
748
749 db.set(location.clone(), account.clone());
750 let loc = db.location_of_account(&account.id()).unwrap();
751
752 assert_eq!(location, loc);
753 assert_eq!(db.get(location), db.get(loc));
754 }
755
756 #[test]
758 fn test_lengths() {
759 for naccounts in 50..100 {
760 let mut db = Database::<V2>::create(10);
761 let mut unique = HashSet::with_capacity(naccounts);
762
763 for _ in 0..naccounts {
764 let account = loop {
765 let account = Account::rand();
766 if unique.insert(account.id()) {
767 break account;
768 }
769 };
770
771 db.get_or_create_account(account.id(), account).unwrap();
772 }
773
774 assert_eq!(db.num_accounts(), naccounts);
775 }
776 }
777
778 #[test]
780 fn test_no_update_if_exist() {
781 let mut db = Database::<V2>::create(10);
782
783 let mut account1 = Account::rand();
784 account1.balance = Balance::from_u64(100);
785
786 let location1 = db
787 .get_or_create_account(account1.id(), account1.clone())
788 .unwrap();
789
790 let mut account2 = account1;
791 account2.balance = Balance::from_u64(200);
792
793 let location2 = db
794 .get_or_create_account(account2.id(), account2.clone())
795 .unwrap();
796
797 let addr1: Address = location1.clone().addr();
798 let addr2: Address = location2.clone().addr();
799
800 assert_eq!(addr1, addr2);
801 assert!(matches!(location2, GetOrCreated::Existed(_)));
802 assert_ne!(*db.get(location1.addr()).unwrap(), account2);
803 }
804
805 #[test]
807 fn test_location_of_account() {
808 for naccounts in 50..100 {
809 let mut db = Database::<V2>::create(10);
810
811 for _ in 0..naccounts {
812 let account = Account::rand();
813
814 let account_id = account.id();
815 let location = db
816 .get_or_create_account(account_id.clone(), account)
817 .unwrap();
818 let addr: Address = location.addr();
819
820 assert_eq!(addr, db.location_of_account(&account_id).unwrap());
821 }
822 }
823 }
824
825 #[test]
828 fn test_set_inner_hash() {
829 }
831
832 fn create_full_db(depth: usize) -> Database<V2> {
833 let mut db = Database::<V2>::create(depth as u8);
834
835 for _ in 0..2u64.pow(depth as u32) {
836 let account = Account::rand();
837 db.get_or_create_account(account.id(), account).unwrap();
838 }
839
840 db
841 }
842
843 #[test]
846 fn test_get_set_all_same_root_hash() {
847 let mut db = create_full_db(7);
848
849 let merkle_root1 = db.merkle_root();
850 let root = Address::root();
851
852 let accounts = db.get_all_accounts_rooted_at(root.clone()).unwrap();
853 let accounts = accounts.into_iter().map(|acc| acc.1).collect::<Vec<_>>();
854 db.set_all_accounts_rooted_at(root, &accounts).unwrap();
855
856 let merkle_root2 = db.merkle_root();
857
858 assert_eq!(merkle_root1, merkle_root2);
859 }
860
861 #[test]
864 fn test_set_batch_accounts_change_root_hash() {
865 const DEPTH: usize = 7;
866
867 for _ in 0..5 {
868 let mut db = create_full_db(DEPTH);
869
870 let addr = Address::rand_nonleaf(DEPTH);
871 let children = addr.iter_children(DEPTH);
872 let accounts = children
873 .map(|addr| (addr, Box::new(Account::rand())))
874 .collect::<Vec<_>>();
875
876 let merkle_root1 = db.merkle_root();
877 elog!("naccounts={:?}", accounts.len());
878 db.set_batch_accounts(&accounts);
879 let merkle_root2 = db.merkle_root();
880
881 assert_ne!(merkle_root1, merkle_root2);
882 }
883 }
884
885 #[test]
888 fn test_retrieve_account_after_set_batch() {
889 const DEPTH: usize = 7;
890
891 let mut db = Database::<V2>::create(DEPTH as u8);
892
893 let mut addr = Address::root();
894 for _ in 0..63 {
895 let account = Account::rand();
896 addr = db
897 .get_or_create_account(account.id(), account)
898 .unwrap()
899 .addr();
900 }
901
902 let last_location = db.last_filled().unwrap();
903 assert_eq!(addr, last_location);
904
905 let mut accounts = Vec::with_capacity(2u64.pow(DEPTH as u32) as usize);
906
907 while let Some(next_addr) = addr.next() {
908 accounts.push((next_addr.clone(), Box::new(Account::rand())));
909 addr = next_addr;
910 }
911
912 db.set_batch_accounts(&accounts);
913
914 for (addr, account) in &accounts {
915 let account_id = account.id();
916 let location = db.location_of_account(&account_id).unwrap();
917 let queried_account = db.get(location.clone()).unwrap();
918
919 assert_eq!(*addr, location);
920 assert_eq!(account, &queried_account);
921 }
922
923 let expected_last_location = last_location.to_index().0 + accounts.len() as u64;
924 let actual_last_location = db.last_filled().unwrap().to_index().0;
925
926 assert_eq!(expected_last_location, actual_last_location);
927 }
928
929 #[test]
933 fn test_set_accounts_rooted_equal_get_accounts_rooted() {
934 const DEPTH: usize = 7;
935
936 let mut db = create_full_db(DEPTH);
937
938 for _ in 0..5 {
939 let addr = Address::rand_nonleaf(DEPTH);
940 let children = addr.iter_children(DEPTH);
941 let accounts = children
942 .map(|_| Box::new(Account::rand()))
943 .collect::<Vec<_>>();
944
945 db.set_all_accounts_rooted_at(addr.clone(), &accounts)
946 .unwrap();
947 let list = db
948 .get_all_accounts_rooted_at(addr)
949 .unwrap()
950 .into_iter()
951 .map(|(_, acc)| acc)
952 .collect::<Vec<_>>();
953
954 assert!(!accounts.is_empty());
955 assert_eq!(accounts, list);
956 }
957 }
958
959 #[test]
961 fn test_create_empty_doesnt_modify_hash() {
962 const DEPTH: usize = 7;
963
964 let mut db = Database::<V2>::create(DEPTH as u8);
965
966 let start_hash = db.merkle_root();
967
968 let account = Account::empty();
969 assert!(matches!(
970 db.get_or_create_account(account.id(), account).unwrap(),
971 GetOrCreated::Added(_)
972 ));
973
974 assert_eq!(start_hash, db.merkle_root());
975 }
976
977 #[test]
980 fn test_get_indexed() {
981 const DEPTH: usize = 7;
982 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
983
984 let mut db = Database::<V2>::create(DEPTH as u8);
985 let mut accounts = Vec::with_capacity(NACCOUNTS);
986
987 for _ in 0..NACCOUNTS {
988 let account = Account::rand();
989 accounts.push(account.clone());
990 db.get_or_create_account(account.id(), account).unwrap();
991 }
992
993 for account in accounts {
994 let account_id = account.id();
995 let index_of_account = db.index_of_account(account_id).unwrap();
996 let indexed_account = db.get_at_index(index_of_account).unwrap();
997 assert_eq!(account, *indexed_account);
998 }
999 }
1000
1001 #[test]
1004 fn test_set_get_indexed_equal() {
1005 const DEPTH: usize = 7;
1006 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1007
1008 let mut db = create_full_db(DEPTH);
1009
1010 for _ in 0..50 {
1011 let account = Box::new(Account::rand());
1012 let index = rand::thread_rng().gen_range(0..NACCOUNTS);
1013 let index = AccountIndex(index as u64);
1014
1015 db.set_at_index(index, account.clone()).unwrap();
1016 let at_index = db.get_at_index(index).unwrap();
1017 assert_eq!(account, at_index);
1018 }
1019 }
1020
1021 #[test]
1023 fn test_iter() {
1024 const DEPTH: usize = 7;
1025 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1026
1027 let mut db = Database::<V2>::create(DEPTH as u8);
1028 let mut accounts = Vec::with_capacity(NACCOUNTS);
1029
1030 for _ in 0..NACCOUNTS {
1031 let account = Account::rand();
1032 accounts.push(account.clone());
1033 db.get_or_create_account(account.id(), account).unwrap();
1034 }
1035
1036 assert_eq!(accounts, db.to_list(),)
1037 }
1038
1039 #[test]
1041 fn test_retrieve() {
1042 const DEPTH: usize = 7;
1043 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1044
1045 let mut db = Database::<V2>::create(DEPTH as u8);
1046 let mut accounts = Vec::with_capacity(NACCOUNTS);
1047
1048 for _ in 0..NACCOUNTS {
1049 let account = Box::new(Account::rand());
1050 accounts.push(account.clone());
1051 db.get_or_create_account(account.id(), *account).unwrap();
1052 }
1053
1054 let retrieved = db
1055 .get_all_accounts_rooted_at(Address::root())
1056 .unwrap()
1057 .into_iter()
1058 .map(|(_, acc)| acc)
1059 .collect::<Vec<_>>();
1060
1061 assert_eq!(accounts, retrieved);
1062 }
1063
1064 #[test]
1066 fn test_remove_restore_root_hash() {
1067 const DEPTH: usize = 7;
1068 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1069
1070 let mut db = Database::<V2>::create(DEPTH as u8);
1071
1072 let root_hash = db.merkle_root();
1073
1074 let mut accounts = Vec::with_capacity(NACCOUNTS);
1075
1076 for _ in 0..NACCOUNTS {
1077 let account = Account::rand();
1078 accounts.push(account.id());
1079 db.get_or_create_account(account.id(), account).unwrap();
1080 }
1081 assert_ne!(root_hash, db.merkle_root());
1082
1083 db.remove_accounts(&accounts);
1084 assert_eq!(root_hash, db.merkle_root());
1085 }
1086
1087 #[test]
1089 fn test_fold_over_account_balance() {
1090 const DEPTH: usize = 7;
1091 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1092
1093 let mut db = Database::<V2>::create(DEPTH as u8);
1094 let mut total_balance: u128 = 0;
1095
1096 for _ in 0..NACCOUNTS {
1097 let account = Account::rand();
1098 total_balance += account.balance.as_u64() as u128;
1099 db.get_or_create_account(account.id(), account).unwrap();
1100 }
1101
1102 let retrieved = db.fold(0u128, |acc, account| acc + account.balance.as_u64() as u128);
1103 assert_eq!(total_balance, retrieved);
1104 }
1105
1106 #[test]
1108 fn test_fold_until_over_account_balance() {
1109 const DEPTH: usize = 7;
1110 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1111
1112 let mut db = Database::<V2>::create(DEPTH as u8);
1113 let mut total_balance: u128 = 0;
1114 let mut last_id: AccountId = Account::empty().id();
1115
1116 for i in 0..NACCOUNTS {
1117 let account = Account::rand();
1118 if i <= 30 {
1119 total_balance += account.balance.as_u64() as u128;
1120 last_id = account.id();
1121 }
1122 db.get_or_create_account(account.id(), account).unwrap();
1123 }
1124
1125 let retrieved = db.fold_until(0u128, |mut acc, account| {
1126 acc += account.balance.as_u64() as u128;
1127
1128 if account.id() != last_id {
1129 ControlFlow::Continue(acc)
1130 } else {
1131 ControlFlow::Break(acc)
1132 }
1133 });
1134
1135 assert_eq!(total_balance, retrieved);
1136 }
1137
1138 #[test]
1139 fn test_merkle_path_long() {
1140 const DEPTH: usize = 4;
1141 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1142
1143 let mut db = Database::<V2>::create(DEPTH as u8);
1144
1145 for index in 0..NACCOUNTS / 2 {
1146 let mut account = Account::empty();
1147 account.token_id = TokenId::from(index as u64);
1148
1149 let res = db.get_or_create_account(account.id(), account).unwrap();
1152 assert!(matches!(res, GetOrCreated::Added(_)));
1153 }
1154
1155 elog!("naccounts={:?}", db.last_filled());
1156
1157 let expected = [
1158 &[
1159 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1160 "19c428e06065374dcdbb9c2773d59c14a4bc5322b821b616f5ad8b95e3fce83c",
1161 "277bb79d5e2b48e92cf9e3cf169eccf199e66b1b611765bdd190ad914d50f138",
1162 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1163 ][..],
1164 &[
1165 "ea3278ff7f5c0472163846755a94643f9dea2babe2d25848294fd727d83a6630",
1166 "19c428e06065374dcdbb9c2773d59c14a4bc5322b821b616f5ad8b95e3fce83c",
1167 "277bb79d5e2b48e92cf9e3cf169eccf199e66b1b611765bdd190ad914d50f138",
1168 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1169 ][..],
1170 &[
1171 "9c461cf909421302a96f3794f198bae68d14eb542cfdae3c5942d61211cdbc3c",
1172 "c9c043aa20b69f061a06bf27e19e6c7a7c2cb94a5022a614ebfb9209cda11527",
1173 "277bb79d5e2b48e92cf9e3cf169eccf199e66b1b611765bdd190ad914d50f138",
1174 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1175 ][..],
1176 &[
1177 "225381a665a6c436f0750ce907b8077ae3670b17af0acee4a3eb98569692dd10",
1178 "c9c043aa20b69f061a06bf27e19e6c7a7c2cb94a5022a614ebfb9209cda11527",
1179 "277bb79d5e2b48e92cf9e3cf169eccf199e66b1b611765bdd190ad914d50f138",
1180 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1181 ][..],
1182 &[
1183 "6224d72dc65c9b89d5717cb43b9de5a31763192dbe316f46bb0ed2486c46d50a",
1184 "16b9cac5d2aa4e87c46520d88df96ddb6da7e2f52e23ec406fce9a06d3654f10",
1185 "a4c190a90cddf828af5c87b2b9278da29fdf46bab27642c553f281c4cb25ca1f",
1186 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1187 ][..],
1188 &[
1189 "1b1edf8a2bc43639f2dd7fbffc953a5887ca8e2f57afe2474b293e00a0c8fd13",
1190 "16b9cac5d2aa4e87c46520d88df96ddb6da7e2f52e23ec406fce9a06d3654f10",
1191 "a4c190a90cddf828af5c87b2b9278da29fdf46bab27642c553f281c4cb25ca1f",
1192 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1193 ][..],
1194 &[
1195 "bd649e2c20b743b9ecc6235f06016b4aa1263ee7cd6af77afb5358c60ca9143e",
1196 "2580091fe2ab125a78a5d8df8c017d1a0f588b871f50a2a34cd383df3d647503",
1197 "a4c190a90cddf828af5c87b2b9278da29fdf46bab27642c553f281c4cb25ca1f",
1198 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1199 ][..],
1200 &[
1201 "2834b7e93942f095625b96ce9b6b709934bbdd35bc5762f6493db73dd84b242c",
1202 "2580091fe2ab125a78a5d8df8c017d1a0f588b871f50a2a34cd383df3d647503",
1203 "a4c190a90cddf828af5c87b2b9278da29fdf46bab27642c553f281c4cb25ca1f",
1204 "63f92c64075ae8ef4d076fc7d6743e758513e7b958a4d7a6cb6744eda019d019",
1205 ][..],
1206 &[
1207 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1208 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1209 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1210 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1211 ][..],
1212 &[
1213 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1214 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1215 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1216 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1217 ][..],
1218 &[
1219 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1220 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1221 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1222 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1223 ][..],
1224 &[
1225 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1226 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1227 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1228 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1229 ][..],
1230 &[
1231 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1232 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1233 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1234 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1235 ][..],
1236 &[
1237 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1238 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1239 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1240 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1241 ][..],
1242 &[
1243 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1244 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1245 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1246 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1247 ][..],
1248 &[
1249 "f3ee39f42a7b2cac196c8eb1c9fe00f853678c920c0c9ce3724c0b7fe911c731",
1250 "64ea581ca7a7aef2b78d04e4a64d0df1da1aa5c2d32a2a34c3c8d50a2c932f07",
1251 "358495ff9f624ba2ea37d0890b8c14079fb16e3626bed5ff0447ee10ecf5f30f",
1252 "c1da0c74de92bf4c1ae893b0f70524a9c6ff4a7ad754e0fc64f5e00548b4cd3d",
1253 ][..],
1254 ];
1255
1256 let mut hashes = Vec::with_capacity(100);
1257
1258 let root = Address::root();
1259 let nchild = root.iter_children(DEPTH);
1260
1261 for child in nchild {
1262 let path = db.merkle_path(child);
1263 let path = path.iter().map(|p| p.hash().to_hex()).collect::<Vec<_>>();
1264 hashes.push(path);
1265 }
1266
1267 assert_eq!(&expected[..], hashes.as_slice());
1271 }
1272
1273 #[test]
1275 fn test_merkle_path_test2() {
1276 const DEPTH: usize = 20;
1277 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1278
1279 let mut db = Database::<V2>::create(DEPTH as u8);
1280 db.merkle_path(Address::first(20));
1281 }
1282
1283 fn test_merkle_path_test() {
1286 const DEPTH: usize = 4;
1287 const NACCOUNTS: usize = 2u64.pow(DEPTH as u32) as usize;
1288
1289 elog!("empty={}", Account::empty().hash());
1290 elog!("height1={}", V2::empty_hash_at_height(1));
1291 elog!("height2={}", V2::empty_hash_at_height(2));
1292 elog!("height3={}", V2::empty_hash_at_height(3));
1293 elog!("height4={}", V2::empty_hash_at_height(4));
1294
1295 let mut db = Database::<V2>::create(DEPTH as u8);
1308
1309 db.merkle_root();
1315
1316 db.merkle_path(Address::first(DEPTH));
1317
1318 }
1392}