Merge rust-bitcoin/rust-bitcoin#2987: Add `TxIdentifier` trait

a738754f67 Add TxIdentifier trait (Tobin C. Harding)

Pull request description:

  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

ACKs for top commit:
  apoelstra:
    ACK a738754f67
  Kixunil:
    ACK a738754f67

Tree-SHA512: a7bda26a4a5107f96b24ea3c163286a7ab21a817bdec3434b3ab27d78e99c0548a7362a2271d362b89038c80d9251767c0d62e1df702ef57d9edaf141ab55cd6
This commit is contained in:
merge-script 2024-07-10 18:28:31 +00:00
commit 5ad78ccc6b
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 21 additions and 10 deletions

View File

@ -15,6 +15,7 @@ use io::{BufRead, Write};
use crate::consensus::encode::{self, Decodable, Encodable, VarInt}; use crate::consensus::encode::{self, Decodable, Encodable, VarInt};
use crate::internal_macros::{impl_array_newtype_stringify, impl_consensus_encoding}; use crate::internal_macros::{impl_array_newtype_stringify, impl_consensus_encoding};
use crate::prelude::Vec; use crate::prelude::Vec;
use crate::transaction::TxIdentifier;
use crate::{block, Block, BlockHash, Transaction}; use crate::{block, Block, BlockHash, Transaction};
/// A BIP-152 error /// 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. /// Calculates the short ID with the given (w)txid and using the provided SipHash keys.
pub fn with_siphash_keys<T: AsRef<[u8]>>(txid: &T, siphash_keys: (u64, u64)) -> ShortId { pub fn with_siphash_keys<T: TxIdentifier>(txid: &T, siphash_keys: (u64, u64)) -> ShortId {
// 2. Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) // 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. // 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()); let hash = siphash24::Hash::hash_with_keys(siphash_keys.0, siphash_keys.1, txid.as_ref());
@ -242,14 +243,11 @@ impl HeaderAndShortIds {
}, },
}); });
} else { } else {
short_ids.push(ShortId::with_siphash_keys( match version {
&match version { 1 => short_ids.push(ShortId::with_siphash_keys(&tx.compute_txid(), siphash_keys)),
1 => tx.compute_txid().to_raw_hash(), 2 => short_ids.push(ShortId::with_siphash_keys(&tx.compute_wtxid(), siphash_keys)),
2 => tx.compute_wtxid().to_raw_hash(), _ => unreachable!(),
_ => unreachable!(), }
},
siphash_keys,
));
} }
} }

View File

@ -67,6 +67,18 @@ impl Wtxid {
pub fn all_zeros() -> Self { Self::from_byte_array([0; 32]) } 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) /// The marker MUST be a 1-byte zero value: 0x00. (BIP-141)
const SEGWIT_MARKER: u8 = 0x00; const SEGWIT_MARKER: u8 = 0x00;
/// The flag MUST be a 1-byte non-zero value. Currently, 0x01 MUST be used. (BIP-141) /// The flag MUST be a 1-byte non-zero value. Currently, 0x01 MUST be used. (BIP-141)

View File

@ -20,6 +20,7 @@ use hashes::{sha256d, HashEngine as _};
use crate::internal_macros::impl_hashencode; use crate::internal_macros::impl_hashencode;
use crate::prelude::Vec; use crate::prelude::Vec;
use crate::transaction::TxIdentifier;
use crate::{Txid, Wtxid}; use crate::{Txid, Wtxid};
#[rustfmt::skip] #[rustfmt::skip]
@ -46,7 +47,7 @@ impl_hashencode!(WitnessMerkleNode);
/// do not use this algorithm and cannot use this trait. /// do not use this algorithm and cannot use this trait.
pub trait MerkleNode: Copy { pub trait MerkleNode: Copy {
/// The hash (TXID or WTXID) of a transaciton in the tree. /// 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. /// Convert a hash to a leaf node of the tree.
fn from_leaf(leaf: Self::Leaf) -> Self; fn from_leaf(leaf: Self::Leaf) -> Self;