mina_tree/
tree_version.rs1use crate::account::{get_legacy_hash_of, Account, AccountLegacy, TokenId, TokenIdLegacy};
2use mina_curves::pasta::Fp;
3use poseidon::hash::params::get_merkle_param_for_height;
4use std::{fmt::Debug, hash::Hash};
5
6pub trait TreeVersion {
7 type Account: Debug + Clone;
8 type TokenId: Debug + Clone + Hash + PartialEq;
9
10 fn hash_node(depth: usize, left: Fp, right: Fp) -> Fp;
11 fn hash_leaf(leaf: &Self::Account) -> Fp;
12 fn empty_hash_at_height(height: usize) -> Fp;
13}
14
15#[derive(Clone, Debug)]
16pub struct V1;
17
18#[derive(Clone, Debug)]
19pub struct V2;
20
21impl TreeVersion for V2 {
22 type Account = Account;
23 type TokenId = TokenId;
24
25 fn hash_node(height: usize, left: Fp, right: Fp) -> Fp {
26 let param = get_merkle_param_for_height(height);
27 poseidon::hash::hash_with_kimchi(param, &[left, right])
28 }
29
30 fn hash_leaf(leaf: &Self::Account) -> Fp {
31 leaf.hash()
32 }
33
34 fn empty_hash_at_height(height: usize) -> Fp {
35 (0..height).fold(Account::empty().hash(), |prev_hash, height| {
36 Self::hash_node(height, prev_hash, prev_hash)
37 })
38 }
39}
40
41impl TreeVersion for V1 {
42 type Account = AccountLegacy;
43 type TokenId = TokenIdLegacy;
44
45 fn hash_node(depth: usize, left: Fp, right: Fp) -> Fp {
46 use mina_hasher::{create_legacy, Hashable, Hasher, ROInput};
47
48 #[derive(Clone)]
49 struct TwoHashes(Fp, Fp);
50
51 impl Hashable for TwoHashes {
52 type D = u32; fn to_roinput(&self) -> ROInput {
55 let mut roi = ROInput::new();
56 roi = roi.append_field(self.0);
57 roi = roi.append_field(self.1);
58 roi
59 }
60
61 fn domain_string(depth: Self::D) -> Option<String> {
62 Some(format!("CodaMklTree{:03}", depth))
63 }
64 }
65
66 let mut hasher = create_legacy::<TwoHashes>(depth as u32);
67 hasher.update(&TwoHashes(left, right));
68 hasher.digest()
69 }
70
71 fn hash_leaf(leaf: &Self::Account) -> Fp {
72 use mina_hasher::{create_legacy, Hasher};
73
74 let mut hasher = create_legacy::<AccountLegacy>(());
75 hasher.update(leaf);
76 hasher.digest()
77 }
78
79 fn empty_hash_at_height(height: usize) -> Fp {
80 (0..height).fold(account_empty_legacy_hash(), |prev_hash, height| {
81 Self::hash_node(height, prev_hash, prev_hash)
82 })
83 }
84}
85
86pub fn account_empty_legacy_hash() -> Fp {
87 get_legacy_hash_of((), &AccountLegacy::empty())
88}