mina_tree/account/
legacy.rs

1use super::common::*;
2use crate::scan_state::currency::{Balance, Magnitude, Nonce};
3use ark_ff::Zero;
4use mina_hasher::{create_legacy, Fp, Hashable, Hasher, ROInput};
5use mina_signer::CompressedPubKey;
6use o1_utils::FieldHelpers;
7use std::borrow::Cow;
8
9#[derive(Clone, Debug, Hash, PartialEq, Eq)]
10pub struct TokenIdLegacy(pub u64);
11
12impl Default for TokenIdLegacy {
13    fn default() -> Self {
14        Self(1)
15    }
16}
17
18#[derive(Clone, Debug)]
19pub struct PermissionsLegacy<Controller> {
20    pub stake: bool,
21    pub edit_state: Controller,
22    pub send: Controller,
23    pub receive: Controller,
24    pub set_delegate: Controller,
25    pub set_permissions: Controller,
26    pub set_verification_key: Controller,
27}
28
29impl PermissionsLegacy<AuthRequired> {
30    pub fn user_default() -> Self {
31        use AuthRequired::*;
32
33        Self {
34            stake: true,
35            edit_state: Signature,
36            send: Signature,
37            receive: None,
38            set_delegate: Signature,
39            set_permissions: Signature,
40            set_verification_key: Signature,
41        }
42    }
43
44    pub fn empty() -> Self {
45        use AuthRequired::*;
46
47        Self {
48            stake: false,
49            edit_state: None,
50            send: None,
51            receive: None,
52            set_delegate: None,
53            set_permissions: None,
54            set_verification_key: None,
55        }
56    }
57}
58
59impl Default for PermissionsLegacy<AuthRequired> {
60    fn default() -> Self {
61        Self::user_default()
62    }
63}
64
65#[derive(Clone, Debug)]
66pub struct SnappAccount {
67    pub app_state: Vec<Fp>,
68    pub verification_key: Option<Fp>,
69}
70
71impl Default for SnappAccount {
72    fn default() -> Self {
73        Self {
74            app_state: vec![Fp::zero(); 8],
75            verification_key: None,
76        }
77    }
78}
79
80impl Hashable for SnappAccount {
81    type D = ();
82
83    fn to_roinput(&self) -> ROInput {
84        let mut roi = ROInput::new();
85
86        if let Some(vk) = self.verification_key.as_ref() {
87            roi = roi.append_field(*vk);
88        } else {
89            roi = roi.append_field(
90                // Value of `dummy_vk_hash`:
91                // <https://github.com/MinaProtocol/mina/blob/4f765c866b81fa6fed66be52707fd91fd915041d/src/lib/mina_base/snapp_account.ml#L116>
92                Fp::from_hex("77a430a03efafd14d72e1a3c45a1fdca8267fcce9a729a1d25128bb5dec69d3f")
93                    .unwrap(),
94            );
95        }
96
97        for field in &self.app_state {
98            roi = roi.append_field(*field);
99        }
100
101        roi
102    }
103
104    fn domain_string(_domain_param: Self::D) -> Option<String> {
105        Some("CodaSnappAccount****".to_string())
106    }
107}
108
109// <https://github.com/MinaProtocol/mina/blob/1765ba6bdfd7c454e5ae836c49979fa076de1bea/src/lib/mina_base/account.ml#L368>
110#[derive(Clone, Debug)]
111pub struct AccountLegacy {
112    pub public_key: CompressedPubKey,         // Public_key.Compressed.t
113    pub token_id: TokenIdLegacy,              // Token_id.t
114    pub token_permissions: TokenPermissions,  // Token_permissions.t
115    pub balance: Balance,                     // Balance.t
116    pub nonce: Nonce,                         // Nonce.t
117    pub receipt_chain_hash: ReceiptChainHash, // Receipt.Chain_hash.t
118    pub delegate: Option<CompressedPubKey>,   // Public_key.Compressed.t option
119    pub voting_for: VotingFor,                // State_hash.t
120    pub timing: Timing,                       // Timing.t
121    pub permissions: PermissionsLegacy<AuthRequired>, // Permissions.t
122    pub snap: Option<SnappAccount>,
123}
124
125pub fn get_legacy_hash_of<T: Hashable>(init_value: T::D, item: &T) -> Fp {
126    let mut hasher = create_legacy::<T>(init_value);
127    hasher.update(item);
128    hasher.digest()
129}
130
131impl Hashable for AccountLegacy {
132    type D = ();
133
134    fn to_roinput(&self) -> ROInput {
135        let mut roi = ROInput::new();
136
137        // Self::snapp
138        let snapp_accout = match self.snap.as_ref() {
139            Some(snapp) => Cow::Borrowed(snapp),
140            None => Cow::Owned(SnappAccount::default()),
141        };
142        let snapp_digest = get_legacy_hash_of((), snapp_accout.as_ref());
143
144        roi = roi.append_field(snapp_digest);
145
146        // Self::permissions
147        for auth in [
148            self.permissions.set_verification_key,
149            self.permissions.set_permissions,
150            self.permissions.set_delegate,
151            self.permissions.receive,
152            self.permissions.send,
153            self.permissions.edit_state,
154        ] {
155            for bit in auth.encode().to_bits() {
156                roi = roi.append_bool(bit);
157            }
158        }
159        roi = roi.append_bool(self.permissions.stake);
160
161        // Self::timing
162        match &self.timing {
163            Timing::Untimed => {
164                roi = roi.append_bool(false);
165                roi = roi.append_u64(0); // initial_minimum_balance
166                roi = roi.append_u32(0); // cliff_time
167                roi = roi.append_u64(0); // cliff_amount
168                roi = roi.append_u32(1); // vesting_period
169                roi = roi.append_u64(0); // vesting_increment
170            }
171            Timing::Timed {
172                initial_minimum_balance,
173                cliff_time,
174                cliff_amount,
175                vesting_period,
176                vesting_increment,
177            } => {
178                roi = roi.append_bool(true);
179                roi = roi.append_u64(initial_minimum_balance.as_u64());
180                roi = roi.append_u32(cliff_time.as_u32());
181                roi = roi.append_u64(cliff_amount.as_u64());
182                roi = roi.append_u32(vesting_period.as_u32());
183                roi = roi.append_u64(vesting_increment.as_u64());
184            }
185        }
186
187        // Self::voting_for
188        roi = roi.append_field(self.voting_for.0);
189
190        // Self::delegate
191        match self.delegate.as_ref() {
192            Some(delegate) => {
193                roi = roi.append_field(delegate.x);
194                roi = roi.append_bool(delegate.is_odd);
195            }
196            None => {
197                // Public_key.Compressed.empty
198                roi = roi.append_field(Fp::zero());
199                roi = roi.append_bool(false);
200            }
201        }
202
203        // Self::receipt_chain_hash
204        roi = roi.append_field(self.receipt_chain_hash.0);
205
206        // Self::nonce
207        roi = roi.append_u32(self.nonce.as_u32());
208
209        // Self::balance
210        roi = roi.append_u64(self.balance.as_u64());
211
212        // Self::token_permissions
213        match self.token_permissions {
214            TokenPermissions::TokenOwned {
215                disable_new_accounts,
216            } => {
217                roi = roi.append_bool(true);
218                roi = roi.append_bool(disable_new_accounts);
219            }
220            TokenPermissions::NotOwned { account_disabled } => {
221                roi = roi.append_bool(false);
222                roi = roi.append_bool(account_disabled);
223            }
224        }
225
226        // Self::token_id
227        roi = roi.append_u64(self.token_id.0);
228
229        // Self::public_key
230        roi = roi.append_field(self.public_key.x);
231        roi = roi.append_bool(self.public_key.is_odd);
232
233        roi
234    }
235
236    fn domain_string(_: ()) -> Option<String> {
237        Some("CodaAccount*********".to_string())
238    }
239}
240
241impl AccountLegacy {
242    pub fn create() -> Self {
243        let pubkey = CompressedPubKey::from_address(
244            "B62qnzbXmRNo9q32n4SNu2mpB8e7FYYLH8NmaX6oFCBYjjQ8SbD7uzV",
245        )
246        .unwrap();
247
248        Self {
249            public_key: pubkey.clone(),
250            token_id: TokenIdLegacy::default(),
251            token_permissions: TokenPermissions::NotOwned {
252                account_disabled: false,
253            },
254            balance: Balance::from_u64(10101),
255            nonce: Nonce::from_u32(62772),
256            receipt_chain_hash: ReceiptChainHash::default(),
257            delegate: Some(pubkey),
258            voting_for: VotingFor::default(),
259            timing: Timing::Untimed,
260            permissions: PermissionsLegacy::user_default(),
261            snap: None,
262        }
263    }
264
265    pub fn empty() -> Self {
266        Self {
267            public_key: CompressedPubKey {
268                x: Fp::zero(),
269                is_odd: false,
270            },
271            token_id: TokenIdLegacy::default(),
272            token_permissions: TokenPermissions::default(),
273            balance: Balance::zero(),
274            nonce: Nonce::zero(),
275            receipt_chain_hash: ReceiptChainHash::empty_legacy(),
276            delegate: None,
277            voting_for: VotingFor::dummy(),
278            timing: Timing::Untimed,
279            permissions: PermissionsLegacy::user_default(),
280            snap: None,
281        }
282    }
283}