miden_protocol/transaction/
executed_tx.rs1use alloc::vec::Vec;
2
3use super::{
4 AccountHeader,
5 AccountId,
6 AdviceInputs,
7 InputNote,
8 InputNotes,
9 NoteId,
10 RawOutputNotes,
11 TransactionArgs,
12 TransactionId,
13 TransactionOutputs,
14};
15use crate::account::{AccountPatch, PartialAccount};
16use crate::block::{BlockHeader, BlockNumber};
17use crate::transaction::TransactionInputs;
18use crate::utils::serde::{
19 ByteReader,
20 ByteWriter,
21 Deserializable,
22 DeserializationError,
23 Serializable,
24};
25
26#[derive(Debug, Clone, PartialEq)]
40pub struct ExecutedTransaction {
41 id: TransactionId,
42 tx_inputs: TransactionInputs,
43 tx_outputs: TransactionOutputs,
44 account_patch: AccountPatch,
45 tx_measurements: TransactionMeasurements,
46}
47
48impl ExecutedTransaction {
49 pub fn new(
57 tx_inputs: TransactionInputs,
58 tx_outputs: TransactionOutputs,
59 account_patch: AccountPatch,
60 tx_measurements: TransactionMeasurements,
61 ) -> Self {
62 assert_eq!(tx_inputs.account().id(), tx_outputs.account().id());
64
65 let id = TransactionId::new(
68 tx_inputs.account().initial_commitment(),
69 tx_outputs.account().to_commitment(),
70 tx_inputs.input_notes().commitment(),
71 tx_outputs.output_notes().commitment(),
72 );
73
74 Self {
75 id,
76 tx_inputs,
77 tx_outputs,
78 account_patch,
79 tx_measurements,
80 }
81 }
82
83 pub fn id(&self) -> TransactionId {
88 self.id
89 }
90
91 pub fn account_id(&self) -> AccountId {
93 self.initial_account().id()
94 }
95
96 pub fn initial_account(&self) -> &PartialAccount {
98 self.tx_inputs.account()
99 }
100
101 pub fn final_account(&self) -> &AccountHeader {
103 self.tx_outputs.account()
104 }
105
106 pub fn input_notes(&self) -> &InputNotes<InputNote> {
108 self.tx_inputs.input_notes()
109 }
110
111 pub fn output_notes(&self) -> &RawOutputNotes {
113 self.tx_outputs.output_notes()
114 }
115
116 pub fn expiration_block_num(&self) -> BlockNumber {
118 self.tx_outputs.expiration_block_num()
119 }
120
121 pub fn tx_args(&self) -> &TransactionArgs {
123 self.tx_inputs.tx_args()
124 }
125
126 pub fn block_header(&self) -> &BlockHeader {
128 self.tx_inputs.block_header()
129 }
130
131 pub fn account_patch(&self) -> &AccountPatch {
134 &self.account_patch
135 }
136
137 pub fn tx_inputs(&self) -> &TransactionInputs {
139 &self.tx_inputs
140 }
141
142 pub fn advice_witness(&self) -> &AdviceInputs {
145 self.tx_inputs.advice_inputs()
146 }
147
148 pub fn measurements(&self) -> &TransactionMeasurements {
151 &self.tx_measurements
152 }
153
154 pub fn into_parts(
159 self,
160 ) -> (TransactionInputs, TransactionOutputs, AccountPatch, TransactionMeasurements) {
161 (self.tx_inputs, self.tx_outputs, self.account_patch, self.tx_measurements)
162 }
163}
164
165impl From<ExecutedTransaction> for TransactionInputs {
166 fn from(tx: ExecutedTransaction) -> Self {
167 tx.tx_inputs
168 }
169}
170
171impl From<ExecutedTransaction> for TransactionMeasurements {
172 fn from(tx: ExecutedTransaction) -> Self {
173 let (_, _, _, tx_progress) = tx.into_parts();
174 tx_progress
175 }
176}
177
178impl Serializable for ExecutedTransaction {
179 fn write_into<W: ByteWriter>(&self, target: &mut W) {
180 self.tx_inputs.write_into(target);
181 self.tx_outputs.write_into(target);
182 self.account_patch.write_into(target);
183 self.tx_measurements.write_into(target);
184 }
185}
186
187impl Deserializable for ExecutedTransaction {
188 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
189 let tx_inputs = TransactionInputs::read_from(source)?;
190 let tx_outputs = TransactionOutputs::read_from(source)?;
191 let account_patch = AccountPatch::read_from(source)?;
192 let tx_measurements = TransactionMeasurements::read_from(source)?;
193
194 Ok(Self::new(tx_inputs, tx_outputs, account_patch, tx_measurements))
195 }
196}
197
198#[derive(Debug, Clone, PartialEq)]
204pub struct TransactionMeasurements {
205 pub prologue: usize,
206 pub notes_processing: usize,
207 pub note_execution: Vec<(NoteId, usize)>,
208 pub tx_script_processing: usize,
209 pub epilogue: usize,
210 pub auth_procedure: usize,
211}
212
213impl TransactionMeasurements {
214 pub fn total_cycles(&self) -> usize {
216 self.prologue + self.notes_processing + self.tx_script_processing + self.epilogue
217 }
218
219 pub fn trace_length(&self) -> usize {
222 let total_cycles = self.total_cycles();
223 total_cycles.next_power_of_two()
224 }
225}
226
227impl Serializable for TransactionMeasurements {
228 fn write_into<W: ByteWriter>(&self, target: &mut W) {
229 self.prologue.write_into(target);
230 self.notes_processing.write_into(target);
231 self.note_execution.write_into(target);
232 self.tx_script_processing.write_into(target);
233 self.epilogue.write_into(target);
234 self.auth_procedure.write_into(target);
235 }
236}
237
238impl Deserializable for TransactionMeasurements {
239 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
240 let prologue = usize::read_from(source)?;
241 let notes_processing = usize::read_from(source)?;
242 let note_execution = Vec::<(NoteId, usize)>::read_from(source)?;
243 let tx_script_processing = usize::read_from(source)?;
244 let epilogue = usize::read_from(source)?;
245 let auth_procedure = usize::read_from(source)?;
246
247 Ok(Self {
248 prologue,
249 notes_processing,
250 note_execution,
251 tx_script_processing,
252 epilogue,
253 auth_procedure,
254 })
255 }
256}
257
258#[cfg(test)]
262mod tests {
263 use core::marker::PhantomData;
264
265 use crate::transaction::ExecutedTransaction;
266
267 fn ensure_send<T: Send>(_: PhantomData<T>) {}
268
269 #[allow(dead_code)]
271 fn compiletime_ensure_send_for_types() {
272 ensure_send::<ExecutedTransaction>(PhantomData);
273 }
274}