miden_protocol/transaction/
executed_tx.rs1use alloc::vec::Vec;
2
3use super::{
4 AccountDelta,
5 AccountHeader,
6 AccountId,
7 AdviceInputs,
8 InputNote,
9 InputNotes,
10 NoteId,
11 OutputNotes,
12 TransactionArgs,
13 TransactionId,
14 TransactionOutputs,
15};
16use crate::account::PartialAccount;
17use crate::asset::FungibleAsset;
18use crate::block::{BlockHeader, BlockNumber};
19use crate::transaction::TransactionInputs;
20use crate::utils::serde::{
21 ByteReader,
22 ByteWriter,
23 Deserializable,
24 DeserializationError,
25 Serializable,
26};
27
28#[derive(Debug, Clone, PartialEq)]
42pub struct ExecutedTransaction {
43 id: TransactionId,
44 tx_inputs: TransactionInputs,
45 tx_outputs: TransactionOutputs,
46 account_delta: AccountDelta,
47 tx_measurements: TransactionMeasurements,
48}
49
50impl ExecutedTransaction {
51 pub fn new(
59 tx_inputs: TransactionInputs,
60 tx_outputs: TransactionOutputs,
61 account_delta: AccountDelta,
62 tx_measurements: TransactionMeasurements,
63 ) -> Self {
64 assert_eq!(tx_inputs.account().id(), tx_outputs.account.id());
66
67 let id = TransactionId::new(
70 tx_inputs.account().initial_commitment(),
71 tx_outputs.account.commitment(),
72 tx_inputs.input_notes().commitment(),
73 tx_outputs.output_notes.commitment(),
74 );
75
76 Self {
77 id,
78 tx_inputs,
79 tx_outputs,
80 account_delta,
81 tx_measurements,
82 }
83 }
84
85 pub fn id(&self) -> TransactionId {
90 self.id
91 }
92
93 pub fn account_id(&self) -> AccountId {
95 self.initial_account().id()
96 }
97
98 pub fn initial_account(&self) -> &PartialAccount {
100 self.tx_inputs.account()
101 }
102
103 pub fn final_account(&self) -> &AccountHeader {
105 &self.tx_outputs.account
106 }
107
108 pub fn input_notes(&self) -> &InputNotes<InputNote> {
110 self.tx_inputs.input_notes()
111 }
112
113 pub fn output_notes(&self) -> &OutputNotes {
115 &self.tx_outputs.output_notes
116 }
117
118 pub fn fee(&self) -> FungibleAsset {
120 self.tx_outputs.fee
121 }
122
123 pub fn expiration_block_num(&self) -> BlockNumber {
125 self.tx_outputs.expiration_block_num
126 }
127
128 pub fn tx_args(&self) -> &TransactionArgs {
130 self.tx_inputs.tx_args()
131 }
132
133 pub fn block_header(&self) -> &BlockHeader {
135 self.tx_inputs.block_header()
136 }
137
138 pub fn account_delta(&self) -> &AccountDelta {
140 &self.account_delta
141 }
142
143 pub fn tx_inputs(&self) -> &TransactionInputs {
145 &self.tx_inputs
146 }
147
148 pub fn advice_witness(&self) -> &AdviceInputs {
151 self.tx_inputs.advice_inputs()
152 }
153
154 pub fn measurements(&self) -> &TransactionMeasurements {
157 &self.tx_measurements
158 }
159
160 pub fn into_parts(
165 self,
166 ) -> (TransactionInputs, TransactionOutputs, AccountDelta, TransactionMeasurements) {
167 (self.tx_inputs, self.tx_outputs, self.account_delta, self.tx_measurements)
168 }
169}
170
171impl From<ExecutedTransaction> for TransactionInputs {
172 fn from(tx: ExecutedTransaction) -> Self {
173 tx.tx_inputs
174 }
175}
176
177impl From<ExecutedTransaction> for TransactionMeasurements {
178 fn from(tx: ExecutedTransaction) -> Self {
179 let (_, _, _, tx_progress) = tx.into_parts();
180 tx_progress
181 }
182}
183
184impl Serializable for ExecutedTransaction {
185 fn write_into<W: ByteWriter>(&self, target: &mut W) {
186 self.tx_inputs.write_into(target);
187 self.tx_outputs.write_into(target);
188 self.account_delta.write_into(target);
189 self.tx_measurements.write_into(target);
190 }
191}
192
193impl Deserializable for ExecutedTransaction {
194 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
195 let tx_inputs = TransactionInputs::read_from(source)?;
196 let tx_outputs = TransactionOutputs::read_from(source)?;
197 let account_delta = AccountDelta::read_from(source)?;
198 let tx_measurements = TransactionMeasurements::read_from(source)?;
199
200 Ok(Self::new(tx_inputs, tx_outputs, account_delta, tx_measurements))
201 }
202}
203
204#[derive(Debug, Clone, PartialEq)]
210pub struct TransactionMeasurements {
211 pub prologue: usize,
212 pub notes_processing: usize,
213 pub note_execution: Vec<(NoteId, usize)>,
214 pub tx_script_processing: usize,
215 pub epilogue: usize,
216 pub auth_procedure: usize,
217 pub after_tx_cycles_obtained: usize,
223}
224
225impl TransactionMeasurements {
226 pub fn total_cycles(&self) -> usize {
228 self.prologue + self.notes_processing + self.tx_script_processing + self.epilogue
229 }
230
231 pub fn trace_length(&self) -> usize {
234 let total_cycles = self.total_cycles();
235 total_cycles.next_power_of_two()
236 }
237}
238
239impl Serializable for TransactionMeasurements {
240 fn write_into<W: ByteWriter>(&self, target: &mut W) {
241 self.prologue.write_into(target);
242 self.notes_processing.write_into(target);
243 self.note_execution.write_into(target);
244 self.tx_script_processing.write_into(target);
245 self.epilogue.write_into(target);
246 self.auth_procedure.write_into(target);
247 self.after_tx_cycles_obtained.write_into(target);
248 }
249}
250
251impl Deserializable for TransactionMeasurements {
252 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
253 let prologue = usize::read_from(source)?;
254 let notes_processing = usize::read_from(source)?;
255 let note_execution = Vec::<(NoteId, usize)>::read_from(source)?;
256 let tx_script_processing = usize::read_from(source)?;
257 let epilogue = usize::read_from(source)?;
258 let auth_procedure = usize::read_from(source)?;
259 let after_tx_cycles_obtained = usize::read_from(source)?;
260
261 Ok(Self {
262 prologue,
263 notes_processing,
264 note_execution,
265 tx_script_processing,
266 epilogue,
267 auth_procedure,
268 after_tx_cycles_obtained,
269 })
270 }
271}
272
273#[cfg(test)]
277mod tests {
278 use core::marker::PhantomData;
279
280 use crate::transaction::ExecutedTransaction;
281
282 fn ensure_send<T: Send>(_: PhantomData<T>) {}
283
284 #[allow(dead_code)]
286 fn compiletime_ensure_send_for_types() {
287 ensure_send::<ExecutedTransaction>(PhantomData);
288 }
289}