mina_tree/account/
legacy.rs

1use std::borrow::Cow;
2
3use ark_ff::Zero;
4use mina_hasher::{create_legacy, Fp, Hashable, Hasher, ROInput};
5use mina_signer::CompressedPubKey;
6use o1_utils::FieldHelpers;
7
8use crate::scan_state::currency::{Balance, Magnitude, Nonce};
9
10use super::common::*;
11
12#[derive(Clone, Debug, Hash, PartialEq, Eq)]
13pub struct TokenIdLegacy(pub u64);
14
15impl Default for TokenIdLegacy {
16    fn default() -> Self {
17        Self(1)
18    }
19}
20
21#[derive(Clone, Debug)]
22pub struct PermissionsLegacy<Controller> {
23    pub stake: bool,
24    pub edit_state: Controller,
25    pub send: Controller,
26    pub receive: Controller,
27    pub set_delegate: Controller,
28    pub set_permissions: Controller,
29    pub set_verification_key: Controller,
30}
31
32impl PermissionsLegacy<AuthRequired> {
33    pub fn user_default() -> Self {
34        use AuthRequired::*;
35
36        Self {
37            stake: true,
38            edit_state: Signature,
39            send: Signature,
40            receive: None,
41            set_delegate: Signature,
42            set_permissions: Signature,
43            set_verification_key: Signature,
44        }
45    }
46
47    pub fn empty() -> Self {
48        use AuthRequired::*;
49
50        Self {
51            stake: false,
52            edit_state: None,
53            send: None,
54            receive: None,
55            set_delegate: None,
56            set_permissions: None,
57            set_verification_key: None,
58        }
59    }
60}
61
62impl Default for PermissionsLegacy<AuthRequired> {
63    fn default() -> Self {
64        Self::user_default()
65    }
66}
67
68#[derive(Clone, Debug)]
69pub struct SnappAccount {
70    pub app_state: Vec<Fp>,
71    pub verification_key: Option<Fp>,
72}
73
74impl Default for SnappAccount {
75    fn default() -> Self {
76        Self {
77            app_state: vec![Fp::zero(); 8],
78            verification_key: None,
79        }
80    }
81}
82
83impl Hashable for SnappAccount {
84    type D = ();
85
86    fn to_roinput(&self) -> ROInput {
87        let mut roi = ROInput::new();
88
89        if let Some(vk) = self.verification_key.as_ref() {
90            roi = roi.append_field(*vk);
91        } else {
92            roi = roi.append_field(
93                // Value of `dummy_vk_hash`:
94                // <https://github.com/MinaProtocol/mina/blob/4f765c866b81fa6fed66be52707fd91fd915041d/src/lib/mina_base/snapp_account.ml#L116>
95                Fp::from_hex("77a430a03efafd14d72e1a3c45a1fdca8267fcce9a729a1d25128bb5dec69d3f")
96                    .unwrap(),
97            );
98        }
99
100        for field in &self.app_state {
101            roi = roi.append_field(*field);
102        }
103
104        // elog!("ROInput={:?}", roi);
105
106        roi
107    }
108
109    fn domain_string(_domain_param: Self::D) -> Option<String> {
110        Some("CodaSnappAccount****".to_string())
111    }
112}
113
114// <https://github.com/MinaProtocol/mina/blob/1765ba6bdfd7c454e5ae836c49979fa076de1bea/src/lib/mina_base/account.ml#L368>
115#[derive(Clone, Debug)]
116pub struct AccountLegacy {
117    pub public_key: CompressedPubKey,         // Public_key.Compressed.t
118    pub token_id: TokenIdLegacy,              // Token_id.t
119    pub token_permissions: TokenPermissions,  // Token_permissions.t
120    pub balance: Balance,                     // Balance.t
121    pub nonce: Nonce,                         // Nonce.t
122    pub receipt_chain_hash: ReceiptChainHash, // Receipt.Chain_hash.t
123    pub delegate: Option<CompressedPubKey>,   // Public_key.Compressed.t option
124    pub voting_for: VotingFor,                // State_hash.t
125    pub timing: Timing,                       // Timing.t
126    pub permissions: PermissionsLegacy<AuthRequired>, // Permissions.t
127    pub snap: Option<SnappAccount>,
128    // Below fields are for `develop` branch
129    // pub token_symbol: TokenSymbol,            // Token_symbol.t
130    // pub zkapp: Option<ZkAppAccount>,          // Zkapp_account.t
131    // pub zkapp_uri: String,                    // string
132}
133
134pub fn get_legacy_hash_of<T: Hashable>(init_value: T::D, item: &T) -> Fp {
135    let mut hasher = create_legacy::<T>(init_value);
136    hasher.update(item);
137    hasher.digest()
138}
139
140impl Hashable for AccountLegacy {
141    type D = ();
142
143    fn to_roinput(&self) -> ROInput {
144        let mut roi = ROInput::new();
145
146        // Self::token_symbol
147
148        // <https://github.com/MinaProtocol/mina/blob/2fac5d806a06af215dbab02f7b154b4f032538b7/src/lib/mina_base/account.ml#L97>
149        // assert!(self.token_symbol.len() <= 6);
150
151        // if !self.token_symbol.is_empty() {
152        //     let mut s = <[u8; 6]>::default();
153        //     let len = self.token_symbol.len();
154
155        //     s[..len].copy_from_slice(&self.token_symbol.as_bytes());
156        //     roi.append_bytes(self.token_symbol.as_bytes());
157        // } else {
158        //     roi.append_bytes(&[0; 6]);
159        // }
160
161        // Self::snapp
162        let snapp_accout = match self.snap.as_ref() {
163            Some(snapp) => Cow::Borrowed(snapp),
164            None => Cow::Owned(SnappAccount::default()),
165        };
166        let snapp_digest = get_legacy_hash_of((), snapp_accout.as_ref());
167
168        roi = roi.append_field(snapp_digest);
169
170        // elog!("ROINPUT={:?}", roi);
171
172        // Self::permissions
173        for auth in [
174            self.permissions.set_verification_key,
175            self.permissions.set_permissions,
176            self.permissions.set_delegate,
177            self.permissions.receive,
178            self.permissions.send,
179            self.permissions.edit_state,
180        ] {
181            for bit in auth.encode().to_bits() {
182                roi = roi.append_bool(bit);
183            }
184        }
185        roi = roi.append_bool(self.permissions.stake);
186
187        // Self::timing
188        match &self.timing {
189            Timing::Untimed => {
190                roi = roi.append_bool(false);
191                roi = roi.append_u64(0); // initial_minimum_balance
192                roi = roi.append_u32(0); // cliff_time
193                roi = roi.append_u64(0); // cliff_amount
194                roi = roi.append_u32(1); // vesting_period
195                roi = roi.append_u64(0); // vesting_increment
196            }
197            Timing::Timed {
198                initial_minimum_balance,
199                cliff_time,
200                cliff_amount,
201                vesting_period,
202                vesting_increment,
203            } => {
204                roi = roi.append_bool(true);
205                roi = roi.append_u64(initial_minimum_balance.as_u64());
206                roi = roi.append_u32(cliff_time.as_u32());
207                roi = roi.append_u64(cliff_amount.as_u64());
208                roi = roi.append_u32(vesting_period.as_u32());
209                roi = roi.append_u64(vesting_increment.as_u64());
210            }
211        }
212
213        // Self::voting_for
214        roi = roi.append_field(self.voting_for.0);
215
216        // Self::delegate
217        match self.delegate.as_ref() {
218            Some(delegate) => {
219                roi = roi.append_field(delegate.x);
220                roi = roi.append_bool(delegate.is_odd);
221            }
222            None => {
223                // Public_key.Compressed.empty
224                roi = roi.append_field(Fp::zero());
225                roi = roi.append_bool(false);
226            }
227        }
228
229        // Self::receipt_chain_hash
230        roi = roi.append_field(self.receipt_chain_hash.0);
231
232        // Self::nonce
233        roi = roi.append_u32(self.nonce.as_u32());
234
235        // Self::balance
236        roi = roi.append_u64(self.balance.as_u64());
237
238        // Self::token_permissions
239        match self.token_permissions {
240            TokenPermissions::TokenOwned {
241                disable_new_accounts,
242            } => {
243                roi = roi.append_bool(true);
244                roi = roi.append_bool(disable_new_accounts);
245            }
246            TokenPermissions::NotOwned { account_disabled } => {
247                roi = roi.append_bool(false);
248                roi = roi.append_bool(account_disabled);
249            }
250        }
251
252        // Self::token_id
253        roi = roi.append_u64(self.token_id.0);
254
255        // Self::public_key
256        roi = roi.append_field(self.public_key.x);
257        roi = roi.append_bool(self.public_key.is_odd);
258
259        roi
260    }
261
262    // fn to_roinput(&self) -> ROInput {
263    //     let mut roi = ROInput::new();
264
265    //     // Self::public_key
266    //     roi.append_field(self.public_key.x);
267    //     roi.append_bool(self.public_key.is_odd);
268
269    //     // Self::token_id
270    //     roi.append_u64(self.token_id.0);
271
272    //     // Self::token_permissions
273    //     match self.token_permissions {
274    //         TokenPermissions::TokenOwned { disable_new_accounts } => {
275    //             roi.append_bool(true);
276    //             roi.append_bool(disable_new_accounts);
277    //         },
278    //         TokenPermissions::NotOwned { account_disabled } => {
279    //             roi.append_bool(false);
280    //             roi.append_bool(account_disabled);
281    //         },
282    //     }
283
284    //     // Self::balance
285    //     roi.append_u64(self.balance);
286
287    //     // Self::token_symbol
288
289    //     // <https://github.com/MinaProtocol/mina/blob/2fac5d806a06af215dbab02f7b154b4f032538b7/src/lib/mina_base/account.ml#L97>
290    //     // assert!(self.token_symbol.len() <= 6);
291
292    //     // if !self.token_symbol.is_empty() {
293    //     //     let mut s = <[u8; 6]>::default();
294    //     //     let len = self.token_symbol.len();
295
296    //     //     s[..len].copy_from_slice(&self.token_symbol.as_bytes());
297    //     //     roi.append_bytes(self.token_symbol.as_bytes());
298    //     // } else {
299    //     //     roi.append_bytes(&[0; 6]);
300    //     // }
301
302    //     // Self::nonce
303    //     roi.append_u32(self.nonce);
304
305    //     // Self::receipt_chain_hash
306    //     roi.append_field(self.receipt_chain_hash.0);
307
308    //     // Self::delegate
309    //     match self.delegate.as_ref() {
310    //         Some(delegate) => {
311    //             roi.append_field(delegate.x);
312    //             roi.append_bool(delegate.is_odd);
313    //         },
314    //         None => {
315    //             // Public_key.Compressed.empty
316    //             roi.append_field(Fp::zero());
317    //             roi.append_bool(false);
318    //         },
319    //     }
320
321    //     // Self::voting_for
322    //     roi.append_field(self.voting_for.0);
323
324    //     // Self::timing
325    //     match self.timing {
326    //         Timing::Untimed => {
327    //             roi.append_bool(false);
328    //             roi.append_u64(0); // initial_minimum_balance
329    //             roi.append_u32(0); // cliff_time
330    //             roi.append_u64(0); // cliff_amount
331    //             roi.append_u32(1); // vesting_period
332    //             roi.append_u64(0); // vesting_increment
333    //         },
334    //         Timing::Timed { initial_minimum_balance, cliff_time, cliff_amount, vesting_period, vesting_increment } => {
335    //             roi.append_bool(true);
336    //             roi.append_u64(initial_minimum_balance);
337    //             roi.append_u32(cliff_time);
338    //             roi.append_u64(cliff_amount);
339    //             roi.append_u32(vesting_period);
340    //             roi.append_u64(vesting_increment);
341    //         },
342    //     }
343
344    //     // Self::permissions
345    //     for auth in [
346    //         self.permissions.set_verification_key,
347    //         self.permissions.set_permissions,
348    //         self.permissions.set_delegate,
349    //         self.permissions.receive,
350    //         self.permissions.send,
351    //         self.permissions.edit_state,
352    //     ] {
353    //         for bit in auth.encode().to_bits() {
354    //             roi.append_bool(bit);
355    //         }
356    //     }
357    //     roi.append_bool(self.permissions.stake);
358
359    //     // Self::snapp
360    //     let snapp_accout = match self.snap.as_ref() {
361    //         Some(snapp) => Cow::Borrowed(snapp),
362    //         None => Cow::Owned(SnappAccount::default()),
363    //     };
364    //     let mut hasher = create_legacy::<SnappAccount>(());
365    //     hasher.update(snapp_accout.as_ref());
366    //     let snapp_digest = hasher.digest();
367
368    //     roi.append_field(snapp_digest);
369
370    //     elog!("ROINPUT={:?}", roi);
371
372    //     roi
373    // }
374
375    fn domain_string(_: ()) -> Option<String> {
376        Some("CodaAccount*********".to_string())
377    }
378}
379
380// mina_hasher::poseidon::
381
382impl AccountLegacy {
383    pub fn create() -> Self {
384        // use o1_utils::field_helpers::FieldHelpers;
385
386        // let token_id = bs58::decode("wSHV2S4qX9jFsLjQo8r1BsMLH2ZRKsZx6EJd1sbozGPieEC4Jf").into_vec().unwrap();
387        // let token_id = Fp::from_bytes(&token_id).unwrap();
388
389        // elog!("token_id={:?}", token_id.to_string());
390
391        // let t = bs58::encode(token_id).into_string();
392        // let t = bs58::encode(token_id.to_bytes()).into_string();
393        // elog!("token_id={:?}", t);
394
395        let pubkey = CompressedPubKey::from_address(
396            "B62qnzbXmRNo9q32n4SNu2mpB8e7FYYLH8NmaX6oFCBYjjQ8SbD7uzV",
397            // "B62qiTKpEPjGTSHZrtM8uXiKgn8So916pLmNJKDhKeyBQL9TDb3nvBG", // Public_key.Compressed.empty
398        )
399        .unwrap();
400
401        Self {
402            public_key: pubkey.clone(),
403            token_id: TokenIdLegacy::default(),
404            token_permissions: TokenPermissions::NotOwned {
405                account_disabled: false,
406            },
407            // token_symbol: "".to_string(),
408            // token_symbol: String::new(),
409            balance: Balance::from_u64(10101),
410            nonce: Nonce::from_u32(62772),
411            receipt_chain_hash: ReceiptChainHash::default(),
412            delegate: Some(pubkey),
413            // delegate: None,
414            voting_for: VotingFor::default(),
415            timing: Timing::Untimed,
416            permissions: PermissionsLegacy::user_default(),
417            snap: None,
418            // zkapp: None,
419            // zkapp_uri: String::new(),
420        }
421    }
422
423    pub fn empty() -> Self {
424        Self {
425            public_key: CompressedPubKey {
426                x: Fp::zero(),
427                is_odd: false,
428            },
429            token_id: TokenIdLegacy::default(),
430            token_permissions: TokenPermissions::default(),
431            balance: Balance::zero(),
432            nonce: Nonce::zero(),
433            receipt_chain_hash: ReceiptChainHash::empty_legacy(),
434            delegate: None,
435            voting_for: VotingFor::dummy(),
436            timing: Timing::Untimed,
437            permissions: PermissionsLegacy::user_default(),
438            snap: None,
439        }
440    }
441}