use alloc::vec::Vec;
use super::{
AccountDelta,
AccountHeader,
AccountId,
AdviceInputs,
BlockHeader,
InputNote,
InputNotes,
NoteId,
OutputNotes,
TransactionArgs,
TransactionId,
TransactionOutputs,
};
use crate::account::PartialAccount;
use crate::asset::FungibleAsset;
use crate::block::BlockNumber;
use crate::transaction::TransactionInputs;
use crate::utils::serde::{
ByteReader,
ByteWriter,
Deserializable,
DeserializationError,
Serializable,
};
#[derive(Debug, Clone, PartialEq)]
pub struct ExecutedTransaction {
id: TransactionId,
tx_inputs: TransactionInputs,
tx_outputs: TransactionOutputs,
account_delta: AccountDelta,
tx_measurements: TransactionMeasurements,
}
impl ExecutedTransaction {
pub fn new(
tx_inputs: TransactionInputs,
tx_outputs: TransactionOutputs,
account_delta: AccountDelta,
tx_measurements: TransactionMeasurements,
) -> Self {
assert_eq!(tx_inputs.account().id(), tx_outputs.account.id());
let id = TransactionId::new(
tx_inputs.account().initial_commitment(),
tx_outputs.account.commitment(),
tx_inputs.input_notes().commitment(),
tx_outputs.output_notes.commitment(),
);
Self {
id,
tx_inputs,
tx_outputs,
account_delta,
tx_measurements,
}
}
pub fn id(&self) -> TransactionId {
self.id
}
pub fn account_id(&self) -> AccountId {
self.initial_account().id()
}
pub fn initial_account(&self) -> &PartialAccount {
self.tx_inputs.account()
}
pub fn final_account(&self) -> &AccountHeader {
&self.tx_outputs.account
}
pub fn input_notes(&self) -> &InputNotes<InputNote> {
self.tx_inputs.input_notes()
}
pub fn output_notes(&self) -> &OutputNotes {
&self.tx_outputs.output_notes
}
pub fn fee(&self) -> FungibleAsset {
self.tx_outputs.fee
}
pub fn expiration_block_num(&self) -> BlockNumber {
self.tx_outputs.expiration_block_num
}
pub fn tx_args(&self) -> &TransactionArgs {
self.tx_inputs.tx_args()
}
pub fn block_header(&self) -> &BlockHeader {
self.tx_inputs.block_header()
}
pub fn account_delta(&self) -> &AccountDelta {
&self.account_delta
}
pub fn tx_inputs(&self) -> &TransactionInputs {
&self.tx_inputs
}
pub fn advice_witness(&self) -> &AdviceInputs {
self.tx_inputs.advice_inputs()
}
pub fn measurements(&self) -> &TransactionMeasurements {
&self.tx_measurements
}
pub fn into_parts(
self,
) -> (TransactionInputs, TransactionOutputs, AccountDelta, TransactionMeasurements) {
(self.tx_inputs, self.tx_outputs, self.account_delta, self.tx_measurements)
}
}
impl From<ExecutedTransaction> for TransactionInputs {
fn from(tx: ExecutedTransaction) -> Self {
tx.tx_inputs
}
}
impl From<ExecutedTransaction> for TransactionMeasurements {
fn from(tx: ExecutedTransaction) -> Self {
let (_, _, _, tx_progress) = tx.into_parts();
tx_progress
}
}
impl Serializable for ExecutedTransaction {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.tx_inputs.write_into(target);
self.tx_outputs.write_into(target);
self.account_delta.write_into(target);
self.tx_measurements.write_into(target);
}
}
impl Deserializable for ExecutedTransaction {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let tx_inputs = TransactionInputs::read_from(source)?;
let tx_outputs = TransactionOutputs::read_from(source)?;
let account_delta = AccountDelta::read_from(source)?;
let tx_measurements = TransactionMeasurements::read_from(source)?;
Ok(Self::new(tx_inputs, tx_outputs, account_delta, tx_measurements))
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TransactionMeasurements {
pub prologue: usize,
pub notes_processing: usize,
pub note_execution: Vec<(NoteId, usize)>,
pub tx_script_processing: usize,
pub epilogue: usize,
pub auth_procedure: usize,
pub after_tx_cycles_obtained: usize,
}
impl TransactionMeasurements {
pub fn total_cycles(&self) -> usize {
self.prologue + self.notes_processing + self.tx_script_processing + self.epilogue
}
pub fn trace_length(&self) -> usize {
let total_cycles = self.total_cycles();
total_cycles.next_power_of_two()
}
}
impl Serializable for TransactionMeasurements {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.prologue.write_into(target);
self.notes_processing.write_into(target);
self.note_execution.write_into(target);
self.tx_script_processing.write_into(target);
self.epilogue.write_into(target);
self.auth_procedure.write_into(target);
self.after_tx_cycles_obtained.write_into(target);
}
}
impl Deserializable for TransactionMeasurements {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let prologue = usize::read_from(source)?;
let notes_processing = usize::read_from(source)?;
let note_execution = Vec::<(NoteId, usize)>::read_from(source)?;
let tx_script_processing = usize::read_from(source)?;
let epilogue = usize::read_from(source)?;
let auth_procedure = usize::read_from(source)?;
let after_tx_cycles_obtained = usize::read_from(source)?;
Ok(Self {
prologue,
notes_processing,
note_execution,
tx_script_processing,
epilogue,
auth_procedure,
after_tx_cycles_obtained,
})
}
}
#[cfg(test)]
mod tests {
use core::marker::PhantomData;
use crate::transaction::ExecutedTransaction;
fn ensure_send<T: Send>(_: PhantomData<T>) {}
#[allow(dead_code)]
fn compiletime_ensure_send_for_types() {
ensure_send::<ExecutedTransaction>(PhantomData);
}
}