Skip to main content

miden_protocol/transaction/
transaction_id.rs

1use core::fmt::{Debug, Display};
2
3use miden_crypto_derive::WordWrapper;
4
5use super::{Hasher, ProvenTransaction, WORD_SIZE, Word, ZERO};
6use crate::utils::serde::{
7    ByteReader,
8    ByteWriter,
9    Deserializable,
10    DeserializationError,
11    Serializable,
12};
13
14// TRANSACTION ID
15// ================================================================================================
16
17/// A unique identifier of a transaction.
18///
19/// Transaction ID is computed as:
20///
21/// hash(
22///     INIT_ACCOUNT_COMMITMENT,
23///     FINAL_ACCOUNT_COMMITMENT,
24///     INPUT_NOTES_COMMITMENT,
25///     OUTPUT_NOTES_COMMITMENT,
26/// )
27///
28/// This achieves the following properties:
29/// - Transactions are identical if and only if they have the same ID.
30/// - Computing transaction ID can be done solely from public transaction data.
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, WordWrapper)]
32pub struct TransactionId(Word);
33
34impl TransactionId {
35    /// Returns a new [TransactionId] instantiated from the provided transaction components.
36    pub fn new(
37        init_account_commitment: Word,
38        final_account_commitment: Word,
39        input_notes_commitment: Word,
40        output_notes_commitment: Word,
41    ) -> Self {
42        let mut elements = [ZERO; 4 * WORD_SIZE];
43        elements[..4].copy_from_slice(init_account_commitment.as_elements());
44        elements[4..8].copy_from_slice(final_account_commitment.as_elements());
45        elements[8..12].copy_from_slice(input_notes_commitment.as_elements());
46        elements[12..16].copy_from_slice(output_notes_commitment.as_elements());
47        Self(Hasher::hash_elements(&elements))
48    }
49}
50
51impl Debug for TransactionId {
52    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53        write!(f, "{}", self.to_hex())
54    }
55}
56
57impl Display for TransactionId {
58    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
59        write!(f, "{}", self.to_hex())
60    }
61}
62
63// CONVERSIONS INTO TRANSACTION ID
64// ================================================================================================
65
66impl From<&ProvenTransaction> for TransactionId {
67    fn from(tx: &ProvenTransaction) -> Self {
68        Self::new(
69            tx.account_update().initial_state_commitment(),
70            tx.account_update().final_state_commitment(),
71            tx.input_notes().commitment(),
72            tx.output_notes().commitment(),
73        )
74    }
75}
76
77// SERIALIZATION
78// ================================================================================================
79
80impl Serializable for TransactionId {
81    fn write_into<W: ByteWriter>(&self, target: &mut W) {
82        target.write_bytes(&self.0.to_bytes());
83    }
84}
85
86impl Deserializable for TransactionId {
87    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
88        let id = Word::read_from(source)?;
89        Ok(Self(id))
90    }
91}