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 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 roi
105 }
106
107 fn domain_string(_domain_param: Self::D) -> Option<String> {
108 Some("CodaSnappAccount****".to_string())
109 }
110}
111
112#[derive(Clone, Debug)]
114pub struct AccountLegacy {
115 pub public_key: CompressedPubKey, pub token_id: TokenIdLegacy, pub token_permissions: TokenPermissions, pub balance: Balance, pub nonce: Nonce, pub receipt_chain_hash: ReceiptChainHash, pub delegate: Option<CompressedPubKey>, pub voting_for: VotingFor, pub timing: Timing, pub permissions: PermissionsLegacy<AuthRequired>, pub snap: Option<SnappAccount>,
126}
127
128pub fn get_legacy_hash_of<T: Hashable>(init_value: T::D, item: &T) -> Fp {
129 let mut hasher = create_legacy::<T>(init_value);
130 hasher.update(item);
131 hasher.digest()
132}
133
134impl Hashable for AccountLegacy {
135 type D = ();
136
137 fn to_roinput(&self) -> ROInput {
138 let mut roi = ROInput::new();
139
140 let snapp_accout = match self.snap.as_ref() {
142 Some(snapp) => Cow::Borrowed(snapp),
143 None => Cow::Owned(SnappAccount::default()),
144 };
145 let snapp_digest = get_legacy_hash_of((), snapp_accout.as_ref());
146
147 roi = roi.append_field(snapp_digest);
148
149 for auth in [
151 self.permissions.set_verification_key,
152 self.permissions.set_permissions,
153 self.permissions.set_delegate,
154 self.permissions.receive,
155 self.permissions.send,
156 self.permissions.edit_state,
157 ] {
158 for bit in auth.encode().to_bits() {
159 roi = roi.append_bool(bit);
160 }
161 }
162 roi = roi.append_bool(self.permissions.stake);
163
164 match &self.timing {
166 Timing::Untimed => {
167 roi = roi.append_bool(false);
168 roi = roi.append_u64(0); roi = roi.append_u32(0); roi = roi.append_u64(0); roi = roi.append_u32(1); roi = roi.append_u64(0); }
174 Timing::Timed {
175 initial_minimum_balance,
176 cliff_time,
177 cliff_amount,
178 vesting_period,
179 vesting_increment,
180 } => {
181 roi = roi.append_bool(true);
182 roi = roi.append_u64(initial_minimum_balance.as_u64());
183 roi = roi.append_u32(cliff_time.as_u32());
184 roi = roi.append_u64(cliff_amount.as_u64());
185 roi = roi.append_u32(vesting_period.as_u32());
186 roi = roi.append_u64(vesting_increment.as_u64());
187 }
188 }
189
190 roi = roi.append_field(self.voting_for.0);
192
193 match self.delegate.as_ref() {
195 Some(delegate) => {
196 roi = roi.append_field(delegate.x);
197 roi = roi.append_bool(delegate.is_odd);
198 }
199 None => {
200 roi = roi.append_field(Fp::zero());
202 roi = roi.append_bool(false);
203 }
204 }
205
206 roi = roi.append_field(self.receipt_chain_hash.0);
208
209 roi = roi.append_u32(self.nonce.as_u32());
211
212 roi = roi.append_u64(self.balance.as_u64());
214
215 match self.token_permissions {
217 TokenPermissions::TokenOwned {
218 disable_new_accounts,
219 } => {
220 roi = roi.append_bool(true);
221 roi = roi.append_bool(disable_new_accounts);
222 }
223 TokenPermissions::NotOwned { account_disabled } => {
224 roi = roi.append_bool(false);
225 roi = roi.append_bool(account_disabled);
226 }
227 }
228
229 roi = roi.append_u64(self.token_id.0);
231
232 roi = roi.append_field(self.public_key.x);
234 roi = roi.append_bool(self.public_key.is_odd);
235
236 roi
237 }
238
239 fn domain_string(_: ()) -> Option<String> {
240 Some("CodaAccount*********".to_string())
241 }
242}
243
244impl AccountLegacy {
245 pub fn create() -> Self {
246 let pubkey = CompressedPubKey::from_address(
247 "B62qnzbXmRNo9q32n4SNu2mpB8e7FYYLH8NmaX6oFCBYjjQ8SbD7uzV",
248 )
249 .unwrap();
250
251 Self {
252 public_key: pubkey.clone(),
253 token_id: TokenIdLegacy::default(),
254 token_permissions: TokenPermissions::NotOwned {
255 account_disabled: false,
256 },
257 balance: Balance::from_u64(10101),
258 nonce: Nonce::from_u32(62772),
259 receipt_chain_hash: ReceiptChainHash::default(),
260 delegate: Some(pubkey),
261 voting_for: VotingFor::default(),
262 timing: Timing::Untimed,
263 permissions: PermissionsLegacy::user_default(),
264 snap: None,
265 }
266 }
267
268 pub fn empty() -> Self {
269 Self {
270 public_key: CompressedPubKey {
271 x: Fp::zero(),
272 is_odd: false,
273 },
274 token_id: TokenIdLegacy::default(),
275 token_permissions: TokenPermissions::default(),
276 balance: Balance::zero(),
277 nonce: Nonce::zero(),
278 receipt_chain_hash: ReceiptChainHash::empty_legacy(),
279 delegate: None,
280 voting_for: VotingFor::dummy(),
281 timing: Timing::Untimed,
282 permissions: PermissionsLegacy::user_default(),
283 snap: None,
284 }
285 }
286}