mina_tree/scan_state/transaction_logic/
transaction_applied.rs1use super::{
2 signed_command, zkapp_command, Coinbase, FeeTransfer, Transaction, TransactionStatus,
3 UserCommand, WithStatus,
4};
5use crate::{
6 scan_state::currency::{Amount, Magnitude, Signed},
7 Account, AccountId,
8};
9use mina_core::constants::ConstraintConstants;
10use mina_curves::pasta::Fp;
11
12pub mod signed_command_applied {
13 use mina_signer::CompressedPubKey;
14
15 use crate::AccountId;
16
17 use super::{signed_command, WithStatus};
18
19 #[derive(Debug, Clone, PartialEq)]
20 pub struct Common {
21 pub user_command: WithStatus<signed_command::SignedCommand>,
22 }
23
24 #[derive(Debug, Clone, PartialEq)]
25 pub enum Body {
26 Payments {
27 new_accounts: Vec<AccountId>,
28 },
29 StakeDelegation {
30 previous_delegate: Option<CompressedPubKey>,
31 },
32 Failed,
33 }
34
35 #[derive(Debug, Clone, PartialEq)]
36 pub struct SignedCommandApplied {
37 pub common: Common,
38 pub body: Body,
39 }
40}
41
42pub use signed_command_applied::SignedCommandApplied;
43
44impl SignedCommandApplied {
45 pub fn new_accounts(&self) -> &[AccountId] {
46 use signed_command_applied::Body::*;
47
48 match &self.body {
49 Payments { new_accounts } => new_accounts.as_slice(),
50 StakeDelegation { .. } | Failed => &[],
51 }
52 }
53}
54
55#[derive(Debug, Clone, PartialEq)]
57pub struct ZkappCommandApplied {
58 pub accounts: Vec<(AccountId, Option<Box<Account>>)>,
59 pub command: WithStatus<zkapp_command::ZkAppCommand>,
60 pub new_accounts: Vec<AccountId>,
61}
62
63#[derive(Debug, Clone, PartialEq)]
65pub enum CommandApplied {
66 SignedCommand(Box<SignedCommandApplied>),
67 ZkappCommand(Box<ZkappCommandApplied>),
68}
69
70#[derive(Debug, Clone, PartialEq)]
72pub struct FeeTransferApplied {
73 pub fee_transfer: WithStatus<FeeTransfer>,
74 pub new_accounts: Vec<AccountId>,
75 pub burned_tokens: Amount,
76}
77
78#[derive(Debug, Clone, PartialEq)]
80pub struct CoinbaseApplied {
81 pub coinbase: WithStatus<Coinbase>,
82 pub new_accounts: Vec<AccountId>,
83 pub burned_tokens: Amount,
84}
85
86#[derive(Debug, Clone, PartialEq)]
88pub enum Varying {
89 Command(CommandApplied),
90 FeeTransfer(FeeTransferApplied),
91 Coinbase(CoinbaseApplied),
92}
93
94#[derive(Debug, Clone, PartialEq)]
96pub struct TransactionApplied {
97 pub previous_hash: Fp,
98 pub varying: Varying,
99}
100
101impl TransactionApplied {
102 pub fn transaction(&self) -> WithStatus<Transaction> {
104 use CommandApplied::*;
105 use Varying::*;
106
107 match &self.varying {
108 Command(SignedCommand(cmd)) => cmd
109 .common
110 .user_command
111 .map(|c| Transaction::Command(UserCommand::SignedCommand(Box::new(c.clone())))),
112 Command(ZkappCommand(cmd)) => cmd
113 .command
114 .map(|c| Transaction::Command(UserCommand::ZkAppCommand(Box::new(c.clone())))),
115 FeeTransfer(f) => f.fee_transfer.map(|f| Transaction::FeeTransfer(f.clone())),
116 Coinbase(c) => c.coinbase.map(|c| Transaction::Coinbase(c.clone())),
117 }
118 }
119
120 pub fn transaction_status(&self) -> &TransactionStatus {
122 use CommandApplied::*;
123 use Varying::*;
124
125 match &self.varying {
126 Command(SignedCommand(cmd)) => &cmd.common.user_command.status,
127 Command(ZkappCommand(cmd)) => &cmd.command.status,
128 FeeTransfer(f) => &f.fee_transfer.status,
129 Coinbase(c) => &c.coinbase.status,
130 }
131 }
132
133 pub fn burned_tokens(&self) -> Amount {
134 match &self.varying {
135 Varying::Command(_) => Amount::zero(),
136 Varying::FeeTransfer(f) => f.burned_tokens,
137 Varying::Coinbase(c) => c.burned_tokens,
138 }
139 }
140
141 pub fn new_accounts(&self) -> &[AccountId] {
142 use CommandApplied::*;
143 use Varying::*;
144
145 match &self.varying {
146 Command(SignedCommand(cmd)) => cmd.new_accounts(),
147 Command(ZkappCommand(cmd)) => cmd.new_accounts.as_slice(),
148 FeeTransfer(f) => f.new_accounts.as_slice(),
149 Coinbase(cb) => cb.new_accounts.as_slice(),
150 }
151 }
152
153 pub fn supply_increase(
155 &self,
156 constraint_constants: &ConstraintConstants,
157 ) -> Result<Signed<Amount>, String> {
158 let burned_tokens = Signed::<Amount>::of_unsigned(self.burned_tokens());
159
160 let account_creation_fees = {
161 let account_creation_fee_int = constraint_constants.account_creation_fee;
162 let num_accounts_created = self.new_accounts().len() as u64;
163
164 let amount = account_creation_fee_int
166 .checked_mul(num_accounts_created)
167 .unwrap();
168 Signed::<Amount>::of_unsigned(Amount::from_u64(amount))
169 };
170
171 let expected_supply_increase = match &self.varying {
172 Varying::Coinbase(cb) => cb.coinbase.data.expected_supply_increase()?,
173 _ => Amount::zero(),
174 };
175 let expected_supply_increase = Signed::<Amount>::of_unsigned(expected_supply_increase);
176
177 let total = [burned_tokens, account_creation_fees]
179 .into_iter()
180 .try_fold(expected_supply_increase, |total, amt| {
181 total.add(&amt.negate())
182 });
183
184 total.ok_or_else(|| "overflow".to_string())
185 }
186}