From a738754f6721335330b0335d53bc4706c33d2861 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 9 Jul 2024 12:07:43 +1000 Subject: [PATCH] Add TxIdentifier trait Add a new trait `TxIdentifier` that abstracts over the `Txid` and `Wtxid` types. We make `AsRef` a super trait so that the new trait needs no methods. Seal the trait so consumers of the library cannot implement it. Use the new trait in: - the `bip152` module to tighten up the `with_siphash_keys` function - as a trait bound on the `Leaf` associated type in the `MerkleNode` trait --- bitcoin/src/bip152.rs | 16 +++++++--------- bitcoin/src/blockdata/transaction.rs | 12 ++++++++++++ bitcoin/src/merkle_tree/mod.rs | 3 ++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index dbe6426a8..33c7e1368 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -15,6 +15,7 @@ use io::{BufRead, Write}; use crate::consensus::encode::{self, Decodable, Encodable, VarInt}; use crate::internal_macros::{impl_array_newtype_stringify, impl_consensus_encoding}; use crate::prelude::Vec; +use crate::transaction::TxIdentifier; use crate::{block, Block, BlockHash, Transaction}; /// A BIP-152 error @@ -116,7 +117,7 @@ impl ShortId { } /// Calculates the short ID with the given (w)txid and using the provided SipHash keys. - pub fn with_siphash_keys>(txid: &T, siphash_keys: (u64, u64)) -> ShortId { + pub fn with_siphash_keys(txid: &T, siphash_keys: (u64, u64)) -> ShortId { // 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) // set to the first two little-endian 64-bit integers from the above hash, respectively. let hash = siphash24::Hash::hash_with_keys(siphash_keys.0, siphash_keys.1, txid.as_ref()); @@ -217,14 +218,11 @@ impl HeaderAndShortIds { }, }); } else { - short_ids.push(ShortId::with_siphash_keys( - &match version { - 1 => tx.compute_txid().to_raw_hash(), - 2 => tx.compute_wtxid().to_raw_hash(), - _ => unreachable!(), - }, - siphash_keys, - )); + match version { + 1 => short_ids.push(ShortId::with_siphash_keys(&tx.compute_txid(), siphash_keys)), + 2 => short_ids.push(ShortId::with_siphash_keys(&tx.compute_wtxid(), siphash_keys)), + _ => unreachable!(), + } } } diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 7b716108a..f0da5df31 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -67,6 +67,18 @@ impl Wtxid { pub fn all_zeros() -> Self { Self::from_byte_array([0; 32]) } } +/// Trait that abstracts over a transaction identifier i.e., `Txid` and `Wtxid`. +pub trait TxIdentifier: sealed::Sealed + AsRef<[u8]> {} + +impl TxIdentifier for Txid {} +impl TxIdentifier for Wtxid {} + +mod sealed { + pub trait Sealed {} + impl Sealed for super::Txid {} + impl Sealed for super::Wtxid {} +} + /// The marker MUST be a 1-byte zero value: 0x00. (BIP-141) const SEGWIT_MARKER: u8 = 0x00; /// The flag MUST be a 1-byte non-zero value. Currently, 0x01 MUST be used. (BIP-141) diff --git a/bitcoin/src/merkle_tree/mod.rs b/bitcoin/src/merkle_tree/mod.rs index 14055cef2..333ec53f4 100644 --- a/bitcoin/src/merkle_tree/mod.rs +++ b/bitcoin/src/merkle_tree/mod.rs @@ -20,6 +20,7 @@ use hashes::{sha256d, HashEngine as _}; use crate::internal_macros::impl_hashencode; use crate::prelude::Vec; +use crate::transaction::TxIdentifier; use crate::{Txid, Wtxid}; #[rustfmt::skip] @@ -46,7 +47,7 @@ impl_hashencode!(WitnessMerkleNode); /// do not use this algorithm and cannot use this trait. pub trait MerkleNode: Copy { /// The hash (TXID or WTXID) of a transaciton in the tree. - type Leaf; + type Leaf: TxIdentifier; /// Convert a hash to a leaf node of the tree. fn from_leaf(leaf: Self::Leaf) -> Self;