mina_tree/scan_state/transaction_logic/
zkapp_statement.rs

1use super::zkapp_command::{self, AccountUpdate, CallForest, Tree};
2use ark_ff::Zero;
3use mina_curves::pasta::Fp;
4use mina_hasher::{Hashable, ROInput};
5use mina_signer::NetworkId;
6use poseidon::hash::{hash_with_kimchi, params::MINA_ACCOUNT_UPDATE_CONS};
7
8#[derive(Copy, Clone, Debug, derive_more::Deref, derive_more::From)]
9pub struct TransactionCommitment(pub Fp);
10
11impl TransactionCommitment {
12    /// <https://github.com/MinaProtocol/mina/blob/3753a8593cc1577bcf4da16620daf9946d88e8e5/src/lib/mina_base/zkapp_command.ml#L1365>
13    pub fn create(account_updates_hash: Fp) -> Self {
14        Self(account_updates_hash)
15    }
16
17    /// <https://github.com/MinaProtocol/mina/blob/3753a8593cc1577bcf4da16620daf9946d88e8e5/src/lib/mina_base/zkapp_command.ml#L1368>
18    pub fn create_complete(&self, memo_hash: Fp, fee_payer_hash: Fp) -> Self {
19        Self(hash_with_kimchi(
20            &MINA_ACCOUNT_UPDATE_CONS,
21            &[memo_hash, fee_payer_hash, self.0],
22        ))
23    }
24
25    pub fn empty() -> Self {
26        Self(Fp::zero())
27    }
28}
29
30impl Hashable for TransactionCommitment {
31    type D = NetworkId;
32
33    fn to_roinput(&self) -> ROInput {
34        let mut roi = ROInput::new();
35        roi = roi.append_field(self.0);
36        roi
37    }
38
39    fn domain_string(network_id: NetworkId) -> Option<String> {
40        match network_id {
41            NetworkId::MAINNET => mina_core::network::mainnet::SIGNATURE_PREFIX,
42            NetworkId::TESTNET => mina_core::network::devnet::SIGNATURE_PREFIX,
43        }
44        .to_string()
45        .into()
46    }
47}
48
49#[derive(Clone, Debug)]
50pub struct ZkappStatement {
51    pub account_update: TransactionCommitment,
52    pub calls: TransactionCommitment,
53}
54
55impl ZkappStatement {
56    pub fn to_field_elements(&self) -> Vec<Fp> {
57        let Self {
58            account_update,
59            calls,
60        } = self;
61
62        vec![**account_update, **calls]
63    }
64
65    pub fn of_tree<AccUpdate: Clone + zkapp_command::AccountUpdateRef>(
66        tree: &Tree<AccUpdate>,
67    ) -> Self {
68        let Tree {
69            account_update: _,
70            account_update_digest,
71            calls,
72        } = tree;
73
74        Self {
75            account_update: TransactionCommitment(account_update_digest.get().unwrap()),
76            calls: TransactionCommitment(calls.hash()),
77        }
78    }
79
80    pub fn zkapp_statements_of_forest_prime<Data: Clone>(
81        forest: CallForest<(AccountUpdate, Data)>,
82    ) -> CallForest<(AccountUpdate, (Data, Self))> {
83        forest.map_with_trees_to(|(account_update, data), tree| {
84            (account_update.clone(), (data.clone(), Self::of_tree(tree)))
85        })
86    }
87
88    fn zkapp_statements_of_forest(
89        forest: CallForest<AccountUpdate>,
90    ) -> CallForest<(AccountUpdate, Self)> {
91        forest
92            .map_with_trees_to(|account_update, tree| (account_update.clone(), Self::of_tree(tree)))
93    }
94}