zebra_chain/transaction/
txid.rs

1//! Transaction ID computation. Contains code for generating the Transaction ID
2//! from the transaction.
3
4use super::{Hash, Transaction};
5use crate::serialization::{sha256d, ZcashSerialize};
6
7/// A Transaction ID builder. It computes the transaction ID by hashing
8/// different parts of the transaction, depending on the transaction version.
9/// For V5 transactions, it follows [ZIP-244] and [ZIP-225].
10///
11/// [ZIP-244]: https://zips.z.cash/zip-0244
12/// [ZIP-225]: https://zips.z.cash/zip-0225
13pub(super) struct TxIdBuilder<'a> {
14    trans: &'a Transaction,
15}
16
17impl<'a> TxIdBuilder<'a> {
18    /// Return a new TxIdBuilder for the given transaction.
19    pub fn new(trans: &'a Transaction) -> Self {
20        TxIdBuilder { trans }
21    }
22
23    /// Compute the Transaction ID for the previously specified transaction.
24    pub(super) fn txid(self) -> Option<Hash> {
25        match self.trans {
26            Transaction::V1 { .. }
27            | Transaction::V2 { .. }
28            | Transaction::V3 { .. }
29            | Transaction::V4 { .. } => self.txid_v1_to_v4(),
30            Transaction::V5 { .. } => self.txid_v5(),
31            #[cfg(feature = "tx_v6")]
32            Transaction::V6 { .. } => self.txid_v6(),
33        }
34    }
35
36    /// Compute the Transaction ID for transactions V1 to V4.
37    /// In these cases it's simply the hash of the serialized transaction.
38    fn txid_v1_to_v4(self) -> Option<Hash> {
39        let mut hash_writer = sha256d::Writer::default();
40        self.trans.zcash_serialize(&mut hash_writer).ok()?;
41        Some(Hash(hash_writer.finish()))
42    }
43
44    /// Compute the Transaction ID for a V5 transaction in the given network upgrade.
45    /// In this case it's the hash of a tree of hashes of specific parts of the
46    /// transaction, as specified in ZIP-244 and ZIP-225.
47    fn txid_v5(self) -> Option<Hash> {
48        let nu = self.trans.network_upgrade()?;
49
50        // We compute v5 txid (from ZIP-244) using librustzcash.
51        Some(Hash(*self.trans.to_librustzcash(nu).ok()?.txid().as_ref()))
52    }
53
54    /// Passthrough to txid_v5 for V6 transactions.
55    #[cfg(feature = "tx_v6")]
56    fn txid_v6(self) -> Option<Hash> {
57        self.txid_v5()
58    }
59}