1use std::{
2 collections::{HashMap, HashSet},
3 ops::ControlFlow,
4 path::PathBuf,
5};
6
7use mina_curves::pasta::Fp;
8use mina_signer::CompressedPubKey;
9
10use crate::{
11 next_uuid, Account, AccountId, AccountIndex, AccountLegacy, Address, AddressIterator,
12 BaseLedger, Direction, GetOrCreated, HashesMatrix, MerklePath, TokenId, TreeVersion, Uuid, V1,
13 V2,
14};
15
16use super::DatabaseError;
17
18#[derive(Clone)]
19pub struct DatabaseImpl<T: TreeVersion> {
20 accounts: Vec<Option<T::Account>>,
21 pub hashes_matrix: HashesMatrix,
22 id_to_addr: HashMap<AccountId, Address>,
23 token_owners: Option<HashMap<T::TokenId, AccountId>>,
24 depth: u8,
25 last_location: Option<Address>,
26 naccounts: usize,
27 uuid: Uuid,
28 directory: PathBuf,
29}
30
31impl<T: TreeVersion> std::fmt::Debug for DatabaseImpl<T> {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("Database")
34 .field("hashes_matrix", &self.hashes_matrix)
36 .field("naccounts", &self.naccounts)
41 .field("uuid", &self.uuid)
42 .field("directory", &self.directory)
43 .finish()
44 }
45}
46
47impl DatabaseImpl<V2> {
53 pub fn clone_db(&self, new_directory: PathBuf) -> Self {
54 Self {
55 accounts: self.accounts.clone(),
57 id_to_addr: self.id_to_addr.clone(),
58 token_owners: self.token_owners.clone(),
59 depth: self.depth,
60 last_location: self.last_location.clone(),
61 naccounts: self.naccounts,
62 uuid: next_uuid(),
63 directory: new_directory,
64 hashes_matrix: self.hashes_matrix.clone(),
65 }
67 }
68
69 fn remove(&mut self, addr: Address) -> Option<Account> {
70 let index = addr.to_index();
71 let index: usize = index.0 as usize;
72
73 if let Some(account) = self.accounts.get_mut(index) {
74 return account.take();
75 }
76
77 None
78 }
79
80 fn create_account(
81 &mut self,
82 account_id: AccountId,
83 account: Account,
84 ) -> Result<GetOrCreated, DatabaseError> {
85 if let Some(addr) = self.id_to_addr.get(&account_id).cloned() {
90 return Ok(GetOrCreated::Existed(addr));
91 }
92
93 let token_id = account.token_id.clone();
94 let location = match self.last_location.as_ref() {
95 Some(last) => last.next().ok_or(DatabaseError::OutOfLeaves)?,
96 None => Address::first(self.depth as usize),
97 };
98
99 assert_eq!(location.to_index(), self.accounts.len());
100 self.accounts.push(Some(account));
101
102 self.last_location = Some(location.clone());
106 self.naccounts += 1;
107
108 if !token_id.is_default() {
109 if let Some(token_owners) = self.token_owners.as_mut() {
110 token_owners.insert(account_id.derive_token_id(), account_id.clone());
111 }
112 }
113 self.id_to_addr.insert(account_id, location.clone());
114
115 Ok(GetOrCreated::Added(location))
118 }
119
120 pub fn iter_with_addr<F>(&self, mut fun: F)
121 where
122 F: FnMut(Address, &Account),
123 {
124 let depth = self.depth as usize;
125
126 for (index, account) in self.accounts.iter().enumerate() {
127 let account = match account {
128 Some(account) => account,
129 None => continue,
130 };
131
132 let addr = Address::from_index(index.into(), depth);
133 fun(addr, account);
134 }
135 }
136
137 fn emulate_tree_to_get_hash_at(&mut self, addr: Address) -> Fp {
138 if let Some(hash) = self.hashes_matrix.get(&addr) {
139 return *hash;
140 };
141
142 let last_account = self
152 .last_filled()
153 .unwrap_or_else(|| Address::first(self.depth as usize));
154
155 self.emulate_tree_recursive(addr, &last_account)
156 }
157
158 pub fn emulate_tree_recursive(&mut self, addr: Address, last_account: &Address) -> Fp {
160 let tree_depth = self.depth as usize;
161 let current_depth = tree_depth - addr.length();
162
163 if current_depth == 0 {
164 return self
165 .get_account_hash(addr.to_index())
166 .unwrap_or_else(|| self.hashes_matrix.empty_hash_at_height(0));
167 }
168
169 let mut get_child_hash = |addr: Address| {
170 if let Some(hash) = self.hashes_matrix.get(&addr) {
171 *hash
172 } else if addr.is_before(last_account) {
173 self.emulate_tree_recursive(addr, last_account)
174 } else {
175 self.hashes_matrix.empty_hash_at_height(current_depth - 1)
176 }
177 };
178
179 let left_hash = get_child_hash(addr.child_left());
180 let right_hash = get_child_hash(addr.child_right());
181
182 match self.hashes_matrix.get(&addr) {
183 Some(hash) => *hash,
184 None => {
185 let hash = V2::hash_node(current_depth - 1, left_hash, right_hash);
186 self.hashes_matrix.set(&addr, hash);
187 hash
188 }
189 }
190 }
191
192 pub fn emulate_tree_to_get_path(
193 &mut self,
194 addr: Address,
195 last_account: &Address,
196 path: &mut AddressIterator,
197 merkle_path: &mut Vec<MerklePath>,
198 ) -> Fp {
199 let tree_depth = self.depth as usize;
200
201 if addr.length() == self.depth as usize {
202 return self
203 .get_account_hash(addr.to_index())
204 .unwrap_or_else(|| self.hashes_matrix.empty_hash_at_height(0));
205 }
206
207 let next_direction = path.next();
208
209 if let Some(direction) = next_direction.as_ref() {
211 let child = match direction {
212 Direction::Left => addr.child_left(),
213 Direction::Right => addr.child_right(),
214 };
215 self.emulate_tree_to_get_path(child, last_account, path, merkle_path);
216 };
217
218 let depth_in_tree = tree_depth - addr.length();
219
220 let mut get_child_hash = |addr: Address| match self.hashes_matrix.get(&addr) {
221 Some(hash) => *hash,
222 None => {
223 if let Some(hash) = self.hashes_matrix.get(&addr) {
224 *hash
225 } else if addr.is_before(last_account) {
226 self.emulate_tree_to_get_path(addr, last_account, path, merkle_path)
227 } else {
228 self.hashes_matrix.empty_hash_at_height(depth_in_tree - 1)
229 }
230 }
231 };
232
233 let left = get_child_hash(addr.child_left());
234 let right = get_child_hash(addr.child_right());
235
236 if let Some(direction) = next_direction {
237 let hash = match direction {
238 Direction::Left => MerklePath::Left(right),
239 Direction::Right => MerklePath::Right(left),
240 };
241 merkle_path.push(hash);
242 };
243
244 match self.hashes_matrix.get(&addr) {
245 Some(hash) => *hash,
246 None => {
247 let hash = V2::hash_node(depth_in_tree - 1, left, right);
248 self.hashes_matrix.set(&addr, hash);
249 hash
250 }
251 }
252 }
253
254 pub fn create_checkpoint(&self, directory_name: String) {
255 elog!("create_checkpoint {}", directory_name);
256 }
257
258 pub fn make_checkpoint(&self, directory_name: String) {
259 elog!("make_checkpoint {}", directory_name);
260 }
261
262 pub fn get_cached_hash(&self, addr: &Address) -> Option<Fp> {
263 self.hashes_matrix.get(addr).copied()
264 }
265
266 pub fn set_cached_hash(&mut self, addr: &Address, hash: Fp) {
267 self.hashes_matrix.set(addr, hash);
268 }
269
270 pub fn empty_hash_at_height(&mut self, height: usize) -> Fp {
271 self.hashes_matrix.empty_hash_at_height(height)
272 }
273
274 pub fn invalidate_hashes(&mut self, account_index: AccountIndex) {
275 self.hashes_matrix.invalidate_hashes(account_index)
276 }
277
278 pub fn transfert_hashes(&mut self, hashes: HashesMatrix) {
279 self.hashes_matrix.transfert_hashes(hashes)
280 }
281
282 pub fn has_token_owners(&self) -> bool {
283 self.token_owners.is_some()
284 }
285}
286
287impl DatabaseImpl<V1> {
288 pub fn create_account(
289 &mut self,
290 _account_id: (),
291 account: AccountLegacy,
292 ) -> Result<Address, DatabaseError> {
293 let location = match self.last_location.as_ref() {
298 Some(last) => last.next().ok_or(DatabaseError::OutOfLeaves)?,
299 None => Address::first(self.depth as usize),
300 };
301
302 assert_eq!(location.to_index(), self.accounts.len());
303 self.accounts.push(Some(account));
304
305 self.last_location = Some(location.clone());
310 self.naccounts += 1;
311
312 Ok(location)
313 }
314}
315
316impl DatabaseImpl<V2> {
317 const NACCOUNTS: usize = 10_000;
318 const NTOKENS: usize = 10;
319
320 pub fn create_with_dir(depth: u8, dir_name: Option<PathBuf>) -> Self {
321 assert!((1..0xfe).contains(&depth));
322
323 let uuid = next_uuid();
324
325 let path = match dir_name {
326 Some(dir_name) => dir_name,
327 None => {
328 let directory = format!("minadb-{uuid}");
329
330 let mut path = PathBuf::from("/tmp");
331 path.push(&directory);
332 path
333 }
334 };
335
336 Self {
347 depth,
348 accounts: Vec::with_capacity(Self::NACCOUNTS),
349 last_location: None,
350 naccounts: 0,
351 id_to_addr: HashMap::with_capacity(Self::NACCOUNTS),
352 token_owners: None,
353 uuid,
354 directory: path,
355 hashes_matrix: HashesMatrix::new(depth as usize),
356 }
358 }
359
360 pub fn create(depth: u8) -> Self {
361 Self::create_with_dir(depth, None)
362 }
363
364 pub fn create_with_token_owners(depth: u8) -> Self {
365 let mut db = Self::create_with_dir(depth, None);
366 db.set_token_owners();
367 db
368 }
369
370 pub fn set_token_owners(&mut self) {
371 if self.token_owners.is_none() {
372 self.token_owners = Some(HashMap::with_capacity(Self::NTOKENS));
373 }
374 }
375
376 pub fn unset_token_owners(&mut self) {
377 self.token_owners = None;
378 }
379
380 pub fn root_hash(&mut self) -> Fp {
381 self.emulate_tree_to_get_hash_at(Address::root())
382 }
383
384 pub fn naccounts(&self) -> usize {
386 self.accounts.iter().filter_map(Option::as_ref).count()
387 }
388
389 fn get_account_ref(&self, addr: Address) -> Option<&Account> {
404 let index = addr.to_index();
405 let index: usize = index.0 as usize;
406
407 self.accounts.get(index)?.as_ref()
408 }
409}
410
411impl BaseLedger for DatabaseImpl<V2> {
412 fn to_list(&self) -> Vec<Account> {
413 self.accounts
414 .iter()
415 .filter_map(Option::as_ref)
416 .cloned()
417 .collect()
418 }
432
433 fn iter<F>(&self, fun: F)
434 where
435 F: FnMut(&Account),
436 {
437 self.accounts
438 .iter()
439 .filter_map(Option::as_ref)
440 .for_each(fun);
441
442 }
452
453 fn fold<B, F>(&self, init: B, mut fun: F) -> B
454 where
455 F: FnMut(B, &Account) -> B,
456 {
457 let mut accum = init;
458 for account in self.accounts.iter().filter_map(Option::as_ref) {
459 accum = fun(accum, account);
460 }
461 accum
462
463 }
477
478 fn fold_with_ignored_accounts<B, F>(
479 &self,
480 ignoreds: HashSet<AccountId>,
481 init: B,
482 mut fun: F,
483 ) -> B
484 where
485 F: FnMut(B, &Account) -> B,
486 {
487 let mut accum = init;
488 for account in self.accounts.iter().filter_map(Option::as_ref) {
489 let account_id = account.id();
490
491 if !ignoreds.contains(&account_id) {
492 accum = fun(accum, account);
493 }
494 }
495 accum
496 }
506
507 fn fold_until<B, F>(&self, init: B, mut fun: F) -> B
508 where
509 F: FnMut(B, &Account) -> ControlFlow<B, B>,
510 {
511 let mut accum = init;
512 for account in self.accounts.iter().filter_map(Option::as_ref) {
513 match fun(accum, account) {
514 ControlFlow::Continue(v) => {
515 accum = v;
516 }
517 ControlFlow::Break(v) => {
518 accum = v;
519 break;
520 }
521 }
522 }
523 accum
524
525 }
544
545 fn accounts(&self) -> HashSet<AccountId> {
546 self.id_to_addr.keys().cloned().collect()
547 }
548
549 fn token_owner(&self, token_id: TokenId) -> Option<AccountId> {
550 self.token_owners
551 .as_ref()
552 .and_then(|token_owners| token_owners.get(&token_id).cloned())
553 }
554
555 fn tokens(&self, public_key: CompressedPubKey) -> HashSet<TokenId> {
556 let mut set = HashSet::with_capacity(100);
557
558 for account in self.accounts.iter().filter_map(Option::as_ref) {
559 if account.public_key == public_key {
560 set.insert(account.token_id.clone());
561 }
562 }
563
564 set
580 }
581
582 fn location_of_account(&self, account_id: &AccountId) -> Option<Address> {
583 let res = self.id_to_addr.get(account_id).cloned();
584
585 res
588 }
589
590 fn location_of_account_batch(
591 &self,
592 account_ids: &[AccountId],
593 ) -> Vec<(AccountId, Option<Address>)> {
594 let res: Vec<_> = account_ids
595 .iter()
596 .map(|account_id| {
597 let addr = self.id_to_addr.get(account_id).cloned();
598 (account_id.clone(), addr)
599 })
600 .collect();
601
602 elog!(
603 "location_of_account_batch ids={:?}\nres={:?}={:?}",
604 account_ids,
605 res.len(),
606 res
607 );
608
609 res
610 }
611
612 fn get_or_create_account(
613 &mut self,
614 account_id: AccountId,
615 account: Account,
616 ) -> Result<GetOrCreated, DatabaseError> {
617 let result = self.create_account(account_id, account);
618
619 if let Ok(GetOrCreated::Added(addr)) = result.as_ref() {
620 let account_index = addr.to_index();
621 self.hashes_matrix.invalidate_hashes(account_index);
622 };
623
624 result
625 }
626
627 fn close(&self) {
628 elog!(
629 "close pid={:?} uuid={:?} path={:?}",
630 crate::util::pid(),
631 self.uuid,
632 self.directory
633 );
634 }
636
637 fn last_filled(&self) -> Option<Address> {
638 self.last_location.clone()
639 }
640
641 fn get_uuid(&self) -> crate::base::Uuid {
642 self.uuid.clone()
643 }
644
645 fn get_directory(&self) -> Option<PathBuf> {
646 Some(self.directory.clone())
647 }
648
649 fn get_account_hash(&mut self, account_index: AccountIndex) -> Option<Fp> {
650 let addr = Address::from_index(account_index, self.depth as usize);
651
652 if let Some(hash) = self.hashes_matrix.get(&addr) {
653 return Some(*hash);
654 }
655
656 let account = self.get_account_ref(addr.clone())?;
657 let hash = account.hash();
658
659 self.hashes_matrix.set(&addr, hash);
660
661 Some(hash)
662 }
663
664 #[inline(never)]
665 fn get(&self, addr: Address) -> Option<Box<Account>> {
666 self.get_account_ref(addr).cloned().map(Box::new)
667 }
668
669 fn get_batch(&self, addr: &[Address]) -> Vec<(Address, Option<Box<Account>>)> {
670 let res: Vec<_> = addr
671 .iter()
672 .map(|addr| (addr.clone(), self.get(addr.clone())))
673 .collect();
674
675 elog!("get_batch addrs={:?}\nres={:?}={:?}", addr, res.len(), res);
686
687 res
688 }
689
690 fn set(&mut self, addr: Address, account: Box<Account>) {
691 let index = addr.to_index();
692
693 self.hashes_matrix.invalidate_hashes(index);
694
695 let index: usize = index.0 as usize;
696
697 if self.accounts.len() <= index {
698 self.accounts.resize(index + 1, None);
699 }
700
701 let id = account.id();
706 if let Some(account) = self.get(addr.clone()) {
710 let id = account.id();
711 self.id_to_addr.remove(&id);
712 if !id.token_id.is_default() {
713 if let Some(token_owners) = self.token_owners.as_mut() {
714 token_owners.remove(&id.derive_token_id());
715 }
716 }
717 } else {
718 self.naccounts += 1;
719 }
720
721 if !account.token_id.is_default() {
722 if let Some(token_owners) = self.token_owners.as_mut() {
723 token_owners.insert(account.id().derive_token_id(), id.clone());
724 }
725 }
726 self.id_to_addr.insert(id, addr.clone());
727 self.accounts[index] = Some(*account);
728 if self
731 .last_location
732 .as_ref()
733 .map(|l| l.to_index() < addr.to_index())
734 .unwrap_or(true)
735 {
736 self.last_location = Some(addr);
737 }
738
739 }
741
742 fn set_batch(&mut self, list: &[(Address, Box<Account>)]) {
743 elog!("SET_BATCH {:?}", list.len());
744 for (addr, account) in list {
746 assert_eq!(addr.length(), self.depth as usize, "addr={:?}", addr);
747 self.set(addr.clone(), account.clone());
748 }
749 }
750
751 fn get_at_index(&self, index: AccountIndex) -> Option<Box<Account>> {
752 let addr = Address::from_index(index, self.depth as usize);
753 self.get(addr)
754 }
755
756 fn set_at_index(&mut self, index: AccountIndex, account: Box<Account>) -> Result<(), ()> {
757 let addr = Address::from_index(index, self.depth as usize);
758 self.set(addr, account);
759
760 Ok(())
763 }
764
765 fn index_of_account(&self, account_id: AccountId) -> Option<AccountIndex> {
766 self.id_to_addr.get(&account_id).map(Address::to_index)
767 }
768
769 fn merkle_root(&mut self) -> Fp {
770 self.root_hash()
773
774 }
795
796 fn merkle_path(&mut self, addr: Address) -> Vec<MerklePath> {
797 elog!("merkle_path called depth={:?} addr={:?}", self.depth, addr);
798
799 let mut merkle_path = Vec::with_capacity(addr.length());
800 let mut path = addr.into_iter();
801 let addr = Address::root();
802
803 let last_account = self
804 .last_filled()
805 .unwrap_or_else(|| Address::first(self.depth as usize));
806
807 self.emulate_tree_to_get_path(addr, &last_account, &mut path, &mut merkle_path);
810
811 merkle_path
812 }
813
814 fn merkle_path_at_index(&mut self, index: AccountIndex) -> Vec<MerklePath> {
815 let addr = Address::from_index(index, self.depth as usize);
816 self.merkle_path(addr)
817 }
818
819 fn remove_accounts(&mut self, ids: &[AccountId]) {
820 let mut addrs = ids
826 .iter()
827 .map(|accound_id| self.id_to_addr.remove(accound_id).unwrap())
828 .collect::<Vec<_>>();
829 addrs.sort_by_key(Address::to_index);
830
831 for addr in addrs.iter().rev() {
832 let account_index = addr.to_index();
843 self.hashes_matrix.invalidate_hashes(account_index);
844
845 let account = match self.remove(addr.clone()) {
846 Some(account) => account,
847 None => continue,
848 };
849
850 let id = account.id();
854 self.id_to_addr.remove(&id);
855 if !id.token_id.is_default() {
856 if let Some(token_owners) = self.token_owners.as_mut() {
857 token_owners.remove(&id.derive_token_id());
858 }
859 }
860
861 self.naccounts = self
862 .naccounts
863 .checked_sub(1)
864 .expect("invalid naccounts counter");
865
866 if self
867 .last_location
868 .as_ref()
869 .map(|last| last == addr)
870 .unwrap_or(false)
871 {
872 self.last_location = addr.prev();
873 }
874 }
875
876 }
878
879 fn detached_signal(&mut self) {
880 todo!()
881 }
882
883 fn depth(&self) -> u8 {
884 self.depth
885 }
886
887 fn num_accounts(&self) -> usize {
888 self.naccounts
889 }
890
891 fn merkle_path_at_addr(&mut self, addr: Address) -> Vec<MerklePath> {
892 self.merkle_path(addr)
893 }
894
895 fn get_inner_hash_at_addr(&mut self, addr: Address) -> Result<Fp, String> {
896 let res = self.emulate_tree_to_get_hash_at(addr.clone());
897
898 elog!("get_inner_hash_at_addr addr={:?} hash={}", addr, res);
899
900 Ok(res)
901 }
902
903 fn set_inner_hash_at_addr(&mut self, _addr: Address, _hash: Fp) -> Result<(), ()> {
904 Ok(())
906 }
907
908 fn set_all_accounts_rooted_at(
909 &mut self,
910 addr: Address,
911 accounts: &[Box<Account>],
912 ) -> Result<(), ()> {
913 if addr.length() > self.depth as usize {
914 return Err(());
915 }
916
917 for (child_addr, account) in addr.iter_children(self.depth as usize).zip(accounts) {
918 self.set(child_addr, account.clone());
919 }
920
921 Ok(())
922 }
923
924 fn get_all_accounts_rooted_at(&self, addr: Address) -> Option<Vec<(Address, Box<Account>)>> {
925 if addr.length() > self.depth as usize {
926 return None;
927 }
928
929 let children = addr.iter_children(self.depth as usize);
935 let mut accounts = Vec::with_capacity(children.len());
936
937 for child_addr in children {
938 let account = match self.get(child_addr.clone()) {
939 Some(account) => account,
940 None => continue,
941 };
942 accounts.push((child_addr, account));
943 }
944
945 if accounts.is_empty() {
946 None
947 } else {
948 Some(accounts)
949 }
950 }
951
952 fn make_space_for(&mut self, _space: usize) {
953 }
955
956 fn commit(&mut self) {
957 }
959}