miden_objects/transaction/executed_tx.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
use alloc::vec::Vec;
use core::cell::OnceCell;
use super::{
Account, AccountDelta, AccountHeader, AccountId, AdviceInputs, BlockHeader, InputNote,
InputNotes, NoteId, OutputNotes, TransactionArgs, TransactionId, TransactionInputs,
TransactionOutputs, TransactionWitness,
};
use crate::accounts::AccountCode;
// EXECUTED TRANSACTION
// ================================================================================================
/// Describes the result of executing a transaction program for the Miden rollup.
///
/// Executed transaction serves two primary purposes:
/// - It contains a complete description of the effects of the transaction. Specifically, it
/// contains all output notes created as the result of the transaction and describes all the
/// changes made to the involved account (i.e., the account delta).
/// - It contains all the information required to re-execute and prove the transaction in a
/// stateless manner. This includes all public transaction inputs, but also all nondeterministic
/// inputs that the host provided to Miden VM while executing the transaction (i.e., advice
/// witness).
#[derive(Debug, Clone)]
pub struct ExecutedTransaction {
id: OnceCell<TransactionId>,
tx_inputs: TransactionInputs,
tx_outputs: TransactionOutputs,
account_codes: Vec<AccountCode>,
account_delta: AccountDelta,
tx_args: TransactionArgs,
advice_witness: AdviceInputs,
tx_measurements: TransactionMeasurements,
}
impl ExecutedTransaction {
// CONSTRUCTOR
// --------------------------------------------------------------------------------------------
/// Returns a new [ExecutedTransaction] instantiated from the provided data.
///
/// # Panics
/// Panics if input and output account IDs are not the same.
pub fn new(
tx_inputs: TransactionInputs,
tx_outputs: TransactionOutputs,
account_codes: Vec<AccountCode>,
account_delta: AccountDelta,
tx_args: TransactionArgs,
advice_witness: AdviceInputs,
tx_measurements: TransactionMeasurements,
) -> Self {
// make sure account IDs are consistent across transaction inputs and outputs
assert_eq!(tx_inputs.account().id(), tx_outputs.account.id());
Self {
id: OnceCell::new(),
tx_inputs,
tx_outputs,
account_codes,
account_delta,
tx_args,
advice_witness,
tx_measurements,
}
}
// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------
/// Returns a unique identifier of this transaction.
pub fn id(&self) -> TransactionId {
*self.id.get_or_init(|| self.into())
}
/// Returns the ID of the account against which this transaction was executed.
pub fn account_id(&self) -> AccountId {
self.initial_account().id()
}
/// Returns the description of the account before the transaction was executed.
pub fn initial_account(&self) -> &Account {
self.tx_inputs.account()
}
/// Returns description of the account after the transaction was executed.
pub fn final_account(&self) -> &AccountHeader {
&self.tx_outputs.account
}
/// Returns the notes consumed in this transaction.
pub fn input_notes(&self) -> &InputNotes<InputNote> {
self.tx_inputs.input_notes()
}
/// Returns the notes created in this transaction.
pub fn output_notes(&self) -> &OutputNotes {
&self.tx_outputs.output_notes
}
/// Returns a reference to the transaction args.
pub fn tx_args(&self) -> &TransactionArgs {
&self.tx_args
}
/// Returns the block header for the block against which the transaction was executed.
pub fn block_header(&self) -> &BlockHeader {
self.tx_inputs.block_header()
}
/// Returns a description of changes between the initial and final account states.
pub fn account_delta(&self) -> &AccountDelta {
&self.account_delta
}
/// Returns a reference to the inputs for this transaction.
pub fn tx_inputs(&self) -> &TransactionInputs {
&self.tx_inputs
}
/// Returns all the data requested by the VM from the advice provider while executing the
/// transaction program.
pub fn advice_witness(&self) -> &AdviceInputs {
&self.advice_witness
}
/// Returns a reference to the transaction measurements which are the cycle counts for
/// each stage.
pub fn measurements(&self) -> &TransactionMeasurements {
&self.tx_measurements
}
// CONVERSIONS
// --------------------------------------------------------------------------------------------
/// Returns individual components of this transaction.
pub fn into_parts(
self,
) -> (AccountDelta, TransactionOutputs, TransactionWitness, TransactionMeasurements) {
let tx_witness = TransactionWitness {
tx_inputs: self.tx_inputs,
tx_args: self.tx_args,
advice_witness: self.advice_witness,
account_codes: self.account_codes,
};
(self.account_delta, self.tx_outputs, tx_witness, self.tx_measurements)
}
}
impl From<ExecutedTransaction> for TransactionWitness {
fn from(tx: ExecutedTransaction) -> Self {
let (_, _, tx_witness, _) = tx.into_parts();
tx_witness
}
}
impl From<ExecutedTransaction> for TransactionMeasurements {
fn from(tx: ExecutedTransaction) -> Self {
let (_, _, _, tx_progress) = tx.into_parts();
tx_progress
}
}
// TRANSACTION MEASUREMENTS
// ================================================================================================
/// Stores the resulting number of cycles for each transaction execution stage obtained from the
/// `TransactionProgress` struct.
#[derive(Debug, Clone)]
pub struct TransactionMeasurements {
pub prologue: usize,
pub notes_processing: usize,
pub note_execution: Vec<(NoteId, usize)>,
pub tx_script_processing: usize,
pub epilogue: usize,
}
impl TransactionMeasurements {
/// Returns the total number of cycles spent executing the transaction.
pub fn total_cycles(&self) -> usize {
self.prologue + self.notes_processing + self.tx_script_processing + self.epilogue
}
/// Returns the trace length of the transaction which is the next power of 2 of the total cycles
/// spent executing the transaction.
pub fn trace_length(&self) -> usize {
let total_cycles = self.total_cycles();
total_cycles.next_power_of_two()
}
}