1use std::{collections::BTreeMap, fmt::Debug, sync::Mutex};
2
3use crate::{
4 address::Address,
5 base::AccountIndex,
6 tree_version::{TreeVersion, V2},
7};
8use mina_curves::pasta::Fp;
9use once_cell::sync::Lazy;
10
11#[derive(Clone, Debug)]
12struct Leaf<T: TreeVersion> {
13 account: Option<Box<T::Account>>,
14}
15
16#[derive(PartialEq)]
17pub struct HashesMatrix {
18 matrix: BTreeMap<u64, Fp>,
21 empty_hashes: Vec<Option<Fp>>,
22 ledger_depth: usize,
23 nhashes: usize,
24}
25
26impl Clone for HashesMatrix {
27 fn clone(&self) -> Self {
28 Self {
29 matrix: self.matrix.clone(),
30 empty_hashes: self.empty_hashes.clone(),
31 ledger_depth: self.ledger_depth,
32 nhashes: self.nhashes,
33 }
34 }
35}
36
37impl Debug for HashesMatrix {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 f.debug_struct("HashesMatrix")
62 .field("matrix_len", &self.matrix.len())
64 .field("nhashes", &self.nhashes)
68 .finish()
70 }
71}
72
73impl HashesMatrix {
74 pub fn new(ledger_depth: usize) -> Self {
75 Self {
78 matrix: BTreeMap::new(),
80 ledger_depth,
81 empty_hashes: vec![None; ledger_depth],
82 nhashes: 0,
83 }
84 }
85
86 pub fn get(&self, addr: &Address) -> Option<&Fp> {
87 let linear: u64 = addr.to_linear_index();
88
89 self.matrix.get(&linear)
91 }
92
93 pub fn set(&mut self, addr: &Address, hash: Fp) {
94 let linear: u64 = addr.to_linear_index();
95
96 let old = self.matrix.insert(linear, hash);
103 assert!(old.is_none());
104 self.nhashes += 1;
105 }
106
107 pub fn set_raw_index(&mut self, idx: u64, hash: Fp) {
110 let old = self.matrix.insert(idx, hash);
111 assert!(old.is_none());
112 self.nhashes += 1;
113 }
114
115 pub fn remove(&mut self, addr: &Address) {
116 let linear: u64 = addr.to_linear_index();
117 self.remove_at_index(linear);
118 }
119
120 fn remove_at_index(&mut self, linear: u64) {
121 let old = self.matrix.remove(&linear);
122 if old.is_some() {
123 self.nhashes -= 1;
124 }
125
126 }
136
137 pub(super) fn transfert_hashes(&mut self, hashes: HashesMatrix) {
138 for (index, hash) in hashes.matrix {
139 let old = self.matrix.insert(index, hash);
140 if old.is_none() {
141 self.nhashes += 1;
142 }
143 }
144 }
145
146 pub fn invalidate_hashes(&mut self, account_index: AccountIndex) {
147 let mut addr = Address::from_index(account_index, self.ledger_depth);
148
149 loop {
150 let index = addr.to_linear_index();
151 self.remove_at_index(index);
152 addr = match addr.parent() {
153 Some(addr) => addr,
154 None => break,
155 }
156 }
157 }
158
159 pub fn empty_hash_at_height(&mut self, height: usize) -> Fp {
160 if let Some(Some(hash)) = self.empty_hashes.get(height) {
161 return *hash;
162 };
163
164 let hash = HASH_EMPTIES.lock().unwrap()[height];
166 self.empty_hashes[height] = Some(hash);
167
168 hash
169 }
170
171 pub fn clear(&mut self) {
172 let ledger_depth = self.ledger_depth;
173 *self = Self {
176 matrix: BTreeMap::new(),
178 ledger_depth,
179 empty_hashes: vec![None; ledger_depth],
180 nhashes: 0,
181 }
182 }
186
187 pub fn take(&mut self) -> Self {
188 let Self {
189 matrix,
190 empty_hashes,
191 ledger_depth,
192 nhashes,
193 } = self;
194
195 Self {
196 matrix: std::mem::take(matrix),
197 empty_hashes: std::mem::take(empty_hashes),
198 ledger_depth: *ledger_depth,
199 nhashes: *nhashes,
200 }
201 }
202
203 pub fn get_raw_inner_hashes(&self) -> Vec<(u64, Fp)> {
204 self.matrix.clone().into_iter().collect()
205 }
206
207 pub fn set_raw_inner_hashes(&mut self, hashes: Vec<(u64, Fp)>) {
208 for (idx, hash) in hashes {
209 self.set_raw_index(idx, hash);
210 }
211 }
212}
213
214static HASH_EMPTIES: Lazy<Mutex<Vec<Fp>>> = Lazy::new(|| {
215 const RANGE_HEIGHT: std::ops::Range<usize> = 0..36;
217
218 Mutex::new((RANGE_HEIGHT).map(V2::empty_hash_at_height).collect())
219});