miden_objects/transaction/
ordered_transactions.rs

1use alloc::vec::Vec;
2
3use crate::{
4    Digest, Felt, Hasher, ZERO,
5    account::AccountId,
6    transaction::{TransactionHeader, TransactionId},
7    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
8};
9
10// ORDERED TRANSACTION HEADERS
11// ================================================================================================
12
13/// The ordered set of transaction headers in a [`ProvenBatch`](crate::batch::ProvenBatch) or
14/// [`ProvenBlock`](crate::block::ProvenBlock).
15///
16/// This is a newtype wrapper representing either:
17/// - the set of transactions in a **batch**,
18/// - or the flattened sets of transactions of each proven batch in a **block**.
19///
20/// This type cannot be constructed directly, but can be retrieved through:
21/// - [`ProposedBatch::transaction_headers`](crate::batch::ProposedBatch::transaction_headers),
22/// - [`OrderedBatches::into_transactions`](crate::batch::OrderedBatches::into_transactions).
23///
24/// The rationale for this requirement is that it allows a client to cheaply validate the
25/// correctness of the transactions in a proven block returned by a remote prover.
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct OrderedTransactionHeaders(Vec<TransactionHeader>);
28
29impl OrderedTransactionHeaders {
30    /// Creates a new set of ordered transaction headers from the provided vector.
31    ///
32    /// # Warning
33    ///
34    /// See the type-level documentation for the requirements of the passed transactions.
35    pub fn new_unchecked(transactions: Vec<TransactionHeader>) -> Self {
36        Self(transactions)
37    }
38
39    /// Computes a commitment to the list of transactions.
40    ///
41    /// This is a sequential hash over each transaction's ID and its account ID.
42    pub fn commitment(&self) -> Digest {
43        Self::compute_commitment(self.0.as_slice().iter().map(|tx| (tx.id(), tx.account_id())))
44    }
45
46    /// Returns a reference to the underlying transaction headers.
47    pub fn as_slice(&self) -> &[TransactionHeader] {
48        &self.0
49    }
50
51    /// Consumes self and returns the underlying vector of transaction headers.
52    pub fn into_vec(self) -> Vec<TransactionHeader> {
53        self.0
54    }
55
56    // PUBLIC HELPERS
57    // --------------------------------------------------------------------------------------------
58
59    /// Computes a commitment to the provided list of transactions.
60    ///
61    /// Each transaction is represented by a transaction ID and an account ID which it was executed
62    /// against. The commitment is a sequential hash over (transaction_id, account_id) tuples.
63    pub fn compute_commitment(
64        transactions: impl Iterator<Item = (TransactionId, AccountId)>,
65    ) -> Digest {
66        let mut elements = vec![];
67        for (transaction_id, account_id) in transactions {
68            let [account_id_prefix, account_id_suffix] = <[Felt; 2]>::from(account_id);
69            elements.extend_from_slice(transaction_id.as_elements());
70            elements.extend_from_slice(&[account_id_prefix, account_id_suffix, ZERO, ZERO]);
71        }
72
73        Hasher::hash_elements(&elements)
74    }
75}
76
77// SERIALIZATION
78// ================================================================================================
79
80impl Serializable for OrderedTransactionHeaders {
81    fn write_into<W: ByteWriter>(&self, target: &mut W) {
82        self.0.write_into(target)
83    }
84}
85
86impl Deserializable for OrderedTransactionHeaders {
87    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
88        source.read().map(OrderedTransactionHeaders::new_unchecked)
89    }
90}