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