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