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
use core::cell::OnceCell;
use super::{
Account, AccountDelta, AccountId, AccountStub, AdviceInputs, BlockHeader, InputNote,
InputNotes, OutputNotes, Program, TransactionArgs, TransactionId, TransactionInputs,
TransactionOutputs, TransactionWitness,
};
// 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>,
program: Program,
tx_inputs: TransactionInputs,
tx_outputs: TransactionOutputs,
account_delta: AccountDelta,
tx_args: TransactionArgs,
advice_witness: AdviceInputs,
}
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(
program: Program,
tx_inputs: TransactionInputs,
tx_outputs: TransactionOutputs,
account_delta: AccountDelta,
tx_args: TransactionArgs,
advice_witness: AdviceInputs,
) -> 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(),
program,
tx_inputs,
tx_outputs,
account_delta,
tx_args,
advice_witness,
}
}
// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------
/// Returns a unique identifier of this transaction.
pub fn id(&self) -> TransactionId {
*self.id.get_or_init(|| self.into())
}
/// Returns a reference the program defining this transaction.
pub fn program(&self) -> &Program {
&self.program
}
/// 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) -> &AccountStub {
&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
}
// CONVERSIONS
// --------------------------------------------------------------------------------------------
/// Returns individual components of this transaction.
pub fn into_parts(self) -> (AccountDelta, TransactionOutputs, TransactionWitness) {
let tx_witness = TransactionWitness::new(
self.program,
self.tx_inputs,
self.tx_args,
self.advice_witness,
);
(self.account_delta, self.tx_outputs, tx_witness)
}
}
impl From<ExecutedTransaction> for TransactionWitness {
fn from(tx: ExecutedTransaction) -> Self {
let (_, _, tx_witness) = tx.into_parts();
tx_witness
}
}