1use std::{
2 collections::HashSet,
3 ops::{ControlFlow, Deref},
4 path::PathBuf,
5 sync::atomic::AtomicU64,
6};
7
8use mina_curves::pasta::Fp;
9use mina_signer::CompressedPubKey;
10use serde::{Deserialize, Serialize};
11
12use crate::{
13 account::{Account, AccountId, TokenId},
14 address::Address,
15 database::DatabaseError,
16 scan_state::transaction_logic::AccountState,
17 sparse_ledger::LedgerIntf,
18 Mask,
19};
20
21pub type Uuid = String;
22
23static UUID_GENERATOR: AtomicU64 = AtomicU64::new(0);
24
25pub fn next_uuid() -> Uuid {
26 uuid::Uuid::new_v4().to_string()
29
30 }
33
34#[derive(PartialEq, Eq)]
35pub enum MerklePath {
36 Left(Fp),
37 Right(Fp),
38}
39
40impl MerklePath {
41 pub fn hash(&self) -> &Fp {
42 match self {
43 MerklePath::Left(h) => h,
44 MerklePath::Right(h) => h,
45 }
46 }
47}
48
49impl std::fmt::Debug for MerklePath {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 match self {
52 Self::Left(arg0) => f.write_fmt(format_args!("Left({:?})", arg0)),
53 Self::Right(arg0) => f.write_fmt(format_args!("Right({:?})", arg0)),
54 }
55 }
56}
57
58pub trait BaseLedger {
59 fn to_list(&self) -> Vec<Account>;
61
62 fn iter<F>(&self, fun: F)
64 where
65 F: FnMut(&Account);
66
67 fn fold<B, F>(&self, init: B, fun: F) -> B
69 where
70 F: FnMut(B, &Account) -> B;
71
72 fn fold_with_ignored_accounts<B, F>(&self, ignoreds: HashSet<AccountId>, init: B, fun: F) -> B
75 where
76 F: FnMut(B, &Account) -> B;
77
78 fn fold_until<B, F>(&self, init: B, fun: F) -> B
80 where
81 F: FnMut(B, &Account) -> ControlFlow<B, B>;
82
83 fn accounts(&self) -> HashSet<AccountId>;
85
86 fn token_owner(&self, token_id: TokenId) -> Option<AccountId>;
88
89 fn tokens(&self, public_key: CompressedPubKey) -> HashSet<TokenId>;
91
92 fn location_of_account(&self, account_id: &AccountId) -> Option<Address>;
93
94 fn location_of_account_batch(
95 &self,
96 account_ids: &[AccountId],
97 ) -> Vec<(AccountId, Option<Address>)>;
98
99 fn get_or_create_account(
101 &mut self,
102 account_id: AccountId,
103 account: Account,
104 ) -> Result<GetOrCreated, DatabaseError>;
105
106 fn close(&self);
108
109 fn last_filled(&self) -> Option<Address>;
111
112 fn get_uuid(&self) -> Uuid;
113
114 fn get_directory(&self) -> Option<PathBuf>;
116
117 fn get(&self, addr: Address) -> Option<Box<Account>>;
118
119 fn get_batch(&self, addr: &[Address]) -> Vec<(Address, Option<Box<Account>>)>;
120
121 fn set(&mut self, addr: Address, account: Box<Account>);
122
123 fn set_batch(&mut self, list: &[(Address, Box<Account>)]);
124
125 fn get_at_index(&self, index: AccountIndex) -> Option<Box<Account>>;
126
127 fn set_at_index(&mut self, index: AccountIndex, account: Box<Account>) -> Result<(), ()>;
128
129 fn index_of_account(&self, account_id: AccountId) -> Option<AccountIndex>;
130
131 fn merkle_root(&mut self) -> Fp;
134
135 fn merkle_path(&mut self, addr: Address) -> Vec<MerklePath>;
136
137 fn merkle_path_at_index(&mut self, index: AccountIndex) -> Vec<MerklePath>;
138
139 fn remove_accounts(&mut self, ids: &[AccountId]);
140
141 fn detached_signal(&mut self);
144
145 fn depth(&self) -> u8;
148
149 fn num_accounts(&self) -> usize;
150
151 fn merkle_path_at_addr(&mut self, addr: Address) -> Vec<MerklePath>;
152
153 fn get_inner_hash_at_addr(&mut self, addr: Address) -> Result<Fp, String>;
154
155 fn set_inner_hash_at_addr(&mut self, addr: Address, hash: Fp) -> Result<(), ()>;
156
157 fn set_all_accounts_rooted_at(
158 &mut self,
159 addr: Address,
160 accounts: &[Box<Account>],
161 ) -> Result<(), ()>;
162
163 fn set_batch_accounts(&mut self, list: &[(Address, Box<Account>)]) {
164 Self::set_batch(self, list)
165 }
166
167 fn get_all_accounts_rooted_at(&self, addr: Address) -> Option<Vec<(Address, Box<Account>)>>;
170
171 fn make_space_for(&mut self, space: usize);
172
173 fn get_account_hash(&mut self, account_index: AccountIndex) -> Option<Fp>;
175 fn commit(&mut self);
178}
179
180#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
181#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema), schema(value_type = u64))]
182pub struct AccountIndex(pub u64);
183
184impl AccountIndex {
185 pub fn as_u64(&self) -> u64 {
186 self.0
187 }
188}
189
190impl PartialEq<u64> for AccountIndex {
191 fn eq(&self, other: &u64) -> bool {
192 self.0 == *other
193 }
194}
195
196impl PartialEq<usize> for AccountIndex {
197 fn eq(&self, other: &usize) -> bool {
198 let other: u64 = (*other).try_into().unwrap();
199 self.0 == other
200 }
201}
202
203impl From<usize> for AccountIndex {
204 fn from(n: usize) -> Self {
205 Self(n.try_into().unwrap())
206 }
207}
208
209#[derive(Clone, Debug)]
210pub enum GetOrCreated {
211 Added(Address),
212 Existed(Address),
213}
214
215impl GetOrCreated {
216 pub fn addr(self) -> Address {
217 match self {
218 GetOrCreated::Added(addr) => addr,
219 GetOrCreated::Existed(addr) => addr,
220 }
221 }
222}
223
224impl Deref for GetOrCreated {
225 type Target = Address;
226
227 fn deref(&self) -> &Self::Target {
228 match self {
229 GetOrCreated::Added(addr) => addr,
230 GetOrCreated::Existed(addr) => addr,
231 }
232 }
233}
234
235impl LedgerIntf for Mask {
236 type Location = Address;
237
238 fn get(&self, addr: &Address) -> Option<Box<Account>> {
239 BaseLedger::get(self, addr.clone())
240 }
241
242 fn location_of_account(&self, account_id: &AccountId) -> Option<Address> {
243 BaseLedger::location_of_account(self, account_id)
244 }
245
246 fn set(&mut self, addr: &Address, account: Box<Account>) {
247 BaseLedger::set(self, addr.clone(), account)
248 }
249
250 fn get_or_create(
252 &mut self,
253 account_id: &AccountId,
254 ) -> Result<(AccountState, Box<Account>, Address), String> {
255 let location = BaseLedger::get_or_create_account(
256 self,
257 account_id.clone(),
258 Account::initialize(account_id),
259 )
260 .map_err(|e| format!("{:?}", e))?;
261
262 let action = match location {
263 GetOrCreated::Added(_) => AccountState::Added,
264 GetOrCreated::Existed(_) => AccountState::Existed,
265 };
266
267 let addr = location.addr();
268 let account = BaseLedger::get(self, addr.clone()).ok_or_else(|| {
269 "get_or_create: Account was not found in the ledger after creation".to_string()
270 })?;
271
272 Ok((action, account, addr))
273 }
274
275 fn create_new_account(&mut self, account_id: AccountId, account: Account) -> Result<(), ()> {
277 match BaseLedger::get_or_create_account(self, account_id, account).unwrap() {
278 GetOrCreated::Added(_) => {}
279 GetOrCreated::Existed(_) => panic!(),
280 }
281 Ok(())
282 }
283
284 fn remove_accounts_exn(&mut self, account_ids: &[AccountId]) {
285 BaseLedger::remove_accounts(self, account_ids)
286 }
287
288 fn merkle_root(&mut self) -> Fp {
289 BaseLedger::merkle_root(self)
290 }
291
292 fn empty(depth: usize) -> Self {
293 let root = Mask::new_unattached(depth);
294 root.make_child()
295 }
296
297 fn create_masked(&self) -> Self {
304 let mut mask = Mask::new_unattached(self.depth() as usize);
305
306 if self.has_token_owners() {
307 mask.set_token_owners();
308 }
309
310 mask.set_parent(self.clone(), None)
315 }
316
317 fn apply_mask(&mut self, mask: Self) {
318 mask.commit()
321 }
322
323 fn account_locations(&self) -> Vec<Self::Location> {
324 let mut addrs: Vec<Address> = self
325 .accounts()
326 .into_iter()
327 .map(|account_id| BaseLedger::location_of_account(self, &account_id).unwrap())
328 .collect();
329
330 addrs.sort_by_key(Address::to_index);
331
332 addrs
333 }
334}