miden_objects/transaction/
executed_tx.rs1use alloc::vec::Vec;
2
3use super::{
4    Account,
5    AccountDelta,
6    AccountHeader,
7    AccountId,
8    AdviceInputs,
9    BlockHeader,
10    InputNote,
11    InputNotes,
12    NoteId,
13    OutputNotes,
14    TransactionArgs,
15    TransactionId,
16    TransactionInputs,
17    TransactionOutputs,
18    TransactionWitness,
19};
20use crate::asset::FungibleAsset;
21use crate::block::BlockNumber;
22use crate::utils::serde::{
23    ByteReader,
24    ByteWriter,
25    Deserializable,
26    DeserializationError,
27    Serializable,
28};
29
30#[derive(Debug, Clone, PartialEq)]
44pub struct ExecutedTransaction {
45    id: TransactionId,
46    tx_inputs: TransactionInputs,
47    tx_outputs: TransactionOutputs,
48    account_delta: AccountDelta,
49    tx_args: TransactionArgs,
50    advice_witness: AdviceInputs,
51    tx_measurements: TransactionMeasurements,
52}
53
54impl ExecutedTransaction {
55    pub fn new(
63        tx_inputs: TransactionInputs,
64        tx_outputs: TransactionOutputs,
65        account_delta: AccountDelta,
66        tx_args: TransactionArgs,
67        advice_witness: AdviceInputs,
68        tx_measurements: TransactionMeasurements,
69    ) -> Self {
70        assert_eq!(tx_inputs.account().id(), tx_outputs.account.id());
72
73        let id = TransactionId::new(
76            tx_inputs.account().init_commitment(),
77            tx_outputs.account.commitment(),
78            tx_inputs.input_notes().commitment(),
79            tx_outputs.output_notes.commitment(),
80        );
81
82        Self {
83            id,
84            tx_inputs,
85            tx_outputs,
86            account_delta,
87            tx_args,
88            advice_witness,
89            tx_measurements,
90        }
91    }
92
93    pub fn id(&self) -> TransactionId {
98        self.id
99    }
100
101    pub fn account_id(&self) -> AccountId {
103        self.initial_account().id()
104    }
105
106    pub fn initial_account(&self) -> &Account {
108        self.tx_inputs.account()
109    }
110
111    pub fn final_account(&self) -> &AccountHeader {
113        &self.tx_outputs.account
114    }
115
116    pub fn input_notes(&self) -> &InputNotes<InputNote> {
118        self.tx_inputs.input_notes()
119    }
120
121    pub fn output_notes(&self) -> &OutputNotes {
123        &self.tx_outputs.output_notes
124    }
125
126    pub fn fee(&self) -> FungibleAsset {
128        self.tx_outputs.fee
129    }
130
131    pub fn expiration_block_num(&self) -> BlockNumber {
133        self.tx_outputs.expiration_block_num
134    }
135
136    pub fn tx_args(&self) -> &TransactionArgs {
138        &self.tx_args
139    }
140
141    pub fn block_header(&self) -> &BlockHeader {
143        self.tx_inputs.block_header()
144    }
145
146    pub fn account_delta(&self) -> &AccountDelta {
148        &self.account_delta
149    }
150
151    pub fn tx_inputs(&self) -> &TransactionInputs {
153        &self.tx_inputs
154    }
155
156    pub fn advice_witness(&self) -> &AdviceInputs {
159        &self.advice_witness
160    }
161
162    pub fn measurements(&self) -> &TransactionMeasurements {
165        &self.tx_measurements
166    }
167
168    pub fn into_parts(
173        self,
174    ) -> (AccountDelta, TransactionOutputs, TransactionWitness, TransactionMeasurements) {
175        let tx_witness = TransactionWitness {
176            tx_inputs: self.tx_inputs,
177            tx_args: self.tx_args,
178            advice_witness: self.advice_witness,
179        };
180        (self.account_delta, self.tx_outputs, tx_witness, self.tx_measurements)
181    }
182}
183
184impl From<ExecutedTransaction> for TransactionWitness {
185    fn from(tx: ExecutedTransaction) -> Self {
186        let (_, _, tx_witness, _) = tx.into_parts();
187        tx_witness
188    }
189}
190
191impl From<ExecutedTransaction> for TransactionMeasurements {
192    fn from(tx: ExecutedTransaction) -> Self {
193        let (_, _, _, tx_progress) = tx.into_parts();
194        tx_progress
195    }
196}
197
198impl Serializable for ExecutedTransaction {
199    fn write_into<W: ByteWriter>(&self, target: &mut W) {
200        self.tx_inputs.write_into(target);
201        self.tx_outputs.write_into(target);
202        self.account_delta.write_into(target);
203        self.tx_args.write_into(target);
204        self.advice_witness.write_into(target);
205        self.tx_measurements.write_into(target);
206    }
207}
208
209impl Deserializable for ExecutedTransaction {
210    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
211        let tx_inputs = TransactionInputs::read_from(source)?;
212        let tx_outputs = TransactionOutputs::read_from(source)?;
213        let account_delta = AccountDelta::read_from(source)?;
214        let tx_args = TransactionArgs::read_from(source)?;
215        let advice_witness = AdviceInputs::read_from(source)?;
216        let tx_measurements = TransactionMeasurements::read_from(source)?;
217
218        Ok(Self::new(
219            tx_inputs,
220            tx_outputs,
221            account_delta,
222            tx_args,
223            advice_witness,
224            tx_measurements,
225        ))
226    }
227}
228
229#[derive(Debug, Clone, PartialEq)]
235pub struct TransactionMeasurements {
236    pub prologue: usize,
237    pub notes_processing: usize,
238    pub note_execution: Vec<(NoteId, usize)>,
239    pub tx_script_processing: usize,
240    pub epilogue: usize,
241    pub after_tx_cycles_obtained: usize,
247}
248
249impl TransactionMeasurements {
250    pub fn total_cycles(&self) -> usize {
252        self.prologue + self.notes_processing + self.tx_script_processing + self.epilogue
253    }
254
255    pub fn trace_length(&self) -> usize {
258        let total_cycles = self.total_cycles();
259        total_cycles.next_power_of_two()
260    }
261}
262
263impl Serializable for TransactionMeasurements {
264    fn write_into<W: ByteWriter>(&self, target: &mut W) {
265        self.prologue.write_into(target);
266        self.notes_processing.write_into(target);
267        self.note_execution.write_into(target);
268        self.tx_script_processing.write_into(target);
269        self.epilogue.write_into(target);
270        self.after_tx_cycles_obtained.write_into(target);
271    }
272}
273
274impl Deserializable for TransactionMeasurements {
275    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
276        let prologue = usize::read_from(source)?;
277        let notes_processing = usize::read_from(source)?;
278        let note_execution = Vec::<(NoteId, usize)>::read_from(source)?;
279        let tx_script_processing = usize::read_from(source)?;
280        let epilogue = usize::read_from(source)?;
281        let after_tx_cycles_obtained = usize::read_from(source)?;
282
283        Ok(Self {
284            prologue,
285            notes_processing,
286            note_execution,
287            tx_script_processing,
288            epilogue,
289            after_tx_cycles_obtained,
290        })
291    }
292}
293
294#[cfg(test)]
298mod tests {
299    use core::marker::PhantomData;
300
301    use crate::transaction::ExecutedTransaction;
302
303    fn ensure_send<T: Send>(_: PhantomData<T>) {}
304
305    #[allow(dead_code)]
307    fn compiletime_ensure_send_for_types() {
308        ensure_send::<ExecutedTransaction>(PhantomData);
309    }
310}