Merge rust-bitcoin/rust-bitcoin#3288: priority: Move txid hash types to `primitives`

0403e52ce3 Move the transaction hash types over to primitives (Tobin C. Harding)
7e454d756d Define extension traits for txid types (Tobin C. Harding)
832b726d03 Stop using all_zeros (Tobin C. Harding)
d69c241b5c Improve docs on associated consts (Tobin C. Harding)
68c9e28165 Do not use private constructor for txid hash types (Tobin C. Harding)
98328b5a7b Use as_byte_array to encode hash type (Tobin C. Harding)

Pull request description:

  Move the `Txid` and `Wtxid` hash wrapper types over to `primitives`. This introduces to `primitves` an unconditional dependency on `hashes`.

ACKs for top commit:
  Kixunil:
    ACK 0403e52ce3
  apoelstra:
    ACK 0403e52ce3 successfully ran local tests

Tree-SHA512: d14fa95bc12c2399d30d4d640b5a3fce625d51adf587a8037158f7d7e7b6288170b2d4418ca2cb68f612086ea0bdd0fae3b577f84f0d60627072fdb2217a6531
This commit is contained in:
merge-script 2024-09-13 03:31:00 +00:00
commit 0c2737f25a
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
14 changed files with 73 additions and 54 deletions

View File

@ -113,6 +113,7 @@ dependencies = [
"bitcoin-internals",
"bitcoin-io",
"bitcoin-units",
"bitcoin_hashes",
"mutagen",
"ordered",
"serde",

View File

@ -112,6 +112,7 @@ dependencies = [
"bitcoin-internals",
"bitcoin-io",
"bitcoin-units",
"bitcoin_hashes",
"mutagen",
"ordered",
"serde",

View File

@ -101,7 +101,7 @@ fn dummy_unspent_transaction_outputs() -> Vec<(OutPoint, TxOut)> {
.script_pubkey();
let out_point_1 = OutPoint {
txid: Txid::all_zeros(), // Obviously invalid.
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
vout: 0,
};
@ -115,7 +115,7 @@ fn dummy_unspent_transaction_outputs() -> Vec<(OutPoint, TxOut)> {
.script_pubkey();
let out_point_2 = OutPoint {
txid: Txid::all_zeros(), // Obviously invalid.
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
vout: 1,
};

View File

@ -119,7 +119,7 @@ fn dummy_unspent_transaction_output(wpkh: WPubkeyHash) -> (OutPoint, TxOut) {
let script_pubkey = ScriptBuf::new_p2wpkh(wpkh);
let out_point = OutPoint {
txid: Txid::all_zeros(), // Obviously invalid.
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
vout: 0,
};

View File

@ -119,7 +119,7 @@ fn dummy_unspent_transaction_output<C: Verification>(
let script_pubkey = ScriptBuf::new_p2tr(secp, internal_key, None);
let out_point = OutPoint {
txid: Txid::all_zeros(), // Obviously invalid.
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
vout: 0,
};

View File

@ -111,7 +111,7 @@ fn dummy_unspent_transaction_outputs() -> Vec<(OutPoint, TxOut)> {
.script_pubkey();
let out_point_1 = OutPoint {
txid: Txid::all_zeros(), // Obviously invalid.
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
vout: 0,
};
@ -125,7 +125,7 @@ fn dummy_unspent_transaction_outputs() -> Vec<(OutPoint, TxOut)> {
.script_pubkey();
let out_point_2 = OutPoint {
txid: Txid::all_zeros(), // Obviously invalid.
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
vout: 1,
};

View File

@ -305,7 +305,7 @@ impl Block {
let hashes = self.txdata.iter().enumerate().map(|(i, t)| {
if i == 0 {
// Replace the first hash with zeroes.
Wtxid::all_zeros()
Wtxid::COINBASE
} else {
t.compute_wtxid()
}

View File

@ -226,7 +226,7 @@ mod test {
assert_eq!(gen.version, transaction::Version::ONE);
assert_eq!(gen.input.len(), 1);
assert_eq!(gen.input[0].previous_output.txid, Txid::all_zeros());
assert_eq!(gen.input[0].previous_output.txid, Txid::COINBASE_PREVOUT);
assert_eq!(gen.input[0].previous_output.vout, 0xFFFFFFFF);
assert_eq!(serialize(&gen.input[0].script_sig),
hex!("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"));

View File

@ -35,47 +35,25 @@ use crate::{Amount, FeeRate, SignedAmount, VarInt};
#[doc(inline)]
pub use primitives::transaction::*;
hashes::hash_newtype! {
/// A bitcoin transaction hash/transaction ID.
///
/// For compatibility with the existing Bitcoin infrastructure and historical and current
/// versions of the Bitcoin Core software itself, this and other [`sha256d::Hash`] types, are
/// serialized in reverse byte order when converted to a hex string via [`std::fmt::Display`]
/// trait operations.
///
/// See [`hashes::Hash::DISPLAY_BACKWARD`] for more details.
pub struct Txid(sha256d::Hash);
/// A bitcoin witness transaction ID.
pub struct Wtxid(sha256d::Hash);
}
impl_hashencode!(Txid);
impl_hashencode!(Wtxid);
impl Txid {
/// The `Txid` used in a coinbase prevout.
///
/// This is used as the "txid" of the dummy input of a coinbase transaction. This is not a real
/// TXID and should not be used in any other contexts. See [`OutPoint::COINBASE_PREVOUT`].
pub const COINBASE_PREVOUT: Self = Self::from_byte_array([0; 32]);
/// The "all zeros" TXID.
#[deprecated(since = "TBD", note = "use Txid::COINBASE_PREVOUT instead")]
pub fn all_zeros() -> Self { Self::COINBASE_PREVOUT }
crate::internal_macros::define_extension_trait! {
/// Extension functionality for the [`Txid`] type.
pub trait TxidExt impl for Txid {
/// The "all zeros" TXID.
#[deprecated(since = "TBD", note = "use Txid::COINBASE_PREVOUT instead")]
fn all_zeros() -> Self { Self::COINBASE_PREVOUT }
}
}
impl Wtxid {
/// The `Wtxid` of a coinbase transaction.
///
/// This is used as the wTXID for the coinbase transaction when constructing blocks,
/// since the coinbase transaction contains a commitment to all transactions' wTXIDs
/// but naturally cannot commit to its own. It is not a real wTXID and should not be
/// used in other contexts.
pub const COINBASE: Self = Self::from_byte_array([0; 32]);
/// The "all zeros" wTXID.
#[deprecated(since = "TBD", note = "use Wtxid::COINBASE instead")]
pub fn all_zeros() -> Self { Self::COINBASE }
crate::internal_macros::define_extension_trait! {
/// Extension functionality for the [`Wtxid`] type.
pub trait WtxidExt impl for Wtxid {
/// The "all zeros" wTXID.
#[deprecated(since = "TBD", note = "use Wtxid::COINBASE instead")]
fn all_zeros() -> Self { Self::COINBASE }
}
}
/// Trait that abstracts over a transaction identifier i.e., `Txid` and `Wtxid`.
@ -117,7 +95,7 @@ impl OutPoint {
/// The `OutPoint` used in a coinbase prevout.
///
/// This is used as the dummy input for coinbase transactions because they don't have any
/// previous outputs. This is not a real outpoint and should not be used in any other contexts.
/// previous outputs. In other words, does not point to a real transaction.
pub const COINBASE_PREVOUT: Self = Self { txid: Txid::COINBASE_PREVOUT, vout: u32::MAX };
/// Creates a new [`OutPoint`].
@ -583,7 +561,7 @@ impl Transaction {
self.input.consensus_encode(&mut enc).expect("engines don't error");
self.output.consensus_encode(&mut enc).expect("engines don't error");
self.lock_time.consensus_encode(&mut enc).expect("engines don't error");
Txid(sha256d::Hash::from_engine(enc))
Txid::from_byte_array(sha256d::Hash::from_engine(enc).to_byte_array())
}
/// Computes the segwit version of the transaction id.
@ -604,7 +582,7 @@ impl Transaction {
pub fn compute_wtxid(&self) -> Wtxid {
let mut enc = sha256d::Hash::engine();
self.consensus_encode(&mut enc).expect("engines don't error");
Wtxid(sha256d::Hash::from_engine(enc))
Wtxid::from_byte_array(sha256d::Hash::from_engine(enc).to_byte_array())
}
/// Returns the weight of this transaction, as defined by BIP-141.

View File

@ -181,7 +181,7 @@ macro_rules! impl_hashencode {
($hashtype:ident) => {
impl $crate::consensus::Encodable for $hashtype {
fn consensus_encode<W: $crate::io::Write + ?Sized>(&self, w: &mut W) -> core::result::Result<usize, $crate::io::Error> {
self.0.consensus_encode(w)
self.as_byte_array().consensus_encode(w)
}
}

View File

@ -8,8 +8,8 @@
//! # use bitcoin::Txid;
//! # use bitcoin::merkle_tree::{MerkleNode as _, TxMerkleNode};
//! # use bitcoin::hashes::Hash;
//! # let tx1 = Txid::all_zeros(); // Dummy hash values.
//! # let tx2 = Txid::all_zeros();
//! # let tx1 = Txid::from_byte_array([0xAA; 32]); // Arbitrary dummy hash values.
//! # let tx2 = Txid::from_byte_array([0xFF; 32]);
//! let tx_hashes = vec![tx1, tx2]; // All the hashes we wish to merkelize.
//! let root = TxMerkleNode::calculate_root(tx_hashes.into_iter());
//! ```

View File

@ -16,11 +16,12 @@ exclude = ["tests", "contrib"]
[features]
default = ["std"]
std = ["alloc", "internals/std", "io/std", "units/std"]
alloc = ["internals/alloc", "io/alloc", "units/alloc"]
serde = ["dep:serde", "internals/serde", "units/serde", "alloc"]
std = ["alloc", "hashes/std", "internals/std", "io/std", "units/std"]
alloc = ["hashes/alloc", "internals/alloc", "io/alloc", "units/alloc"]
serde = ["dep:serde", "hashes/serde", "internals/serde", "units/serde", "alloc"]
[dependencies]
hashes = { package = "bitcoin_hashes", version = "0.14.0", default-features = false, features = ["bitcoin-io"] }
internals = { package = "bitcoin-internals", version = "0.3.0" }
io = { package = "bitcoin-io", version = "0.1.1", default-features = false }
units = { package = "bitcoin-units", version = "0.1.0", default-features = false }

View File

@ -42,7 +42,11 @@ pub use units::*;
#[cfg(feature = "alloc")]
pub use self::locktime::{absolute, relative};
#[doc(inline)]
pub use self::{pow::CompactTarget, sequence::Sequence};
pub use self::{
pow::CompactTarget,
sequence::Sequence,
transaction::{Txid, Wtxid},
};
#[rustfmt::skip]
#[allow(unused_imports)]

View File

@ -12,6 +12,40 @@
use core::fmt;
use hashes::sha256d;
hashes::hash_newtype! {
/// A bitcoin transaction hash/transaction ID.
///
/// For compatibility with the existing Bitcoin infrastructure and historical and current
/// versions of the Bitcoin Core software itself, this and other [`sha256d::Hash`] types, are
/// serialized in reverse byte order when converted to a hex string via [`std::fmt::Display`]
/// trait operations.
///
/// See [`hashes::Hash::DISPLAY_BACKWARD`] for more details.
pub struct Txid(sha256d::Hash);
/// A bitcoin witness transaction ID.
pub struct Wtxid(sha256d::Hash);
}
impl Txid {
/// The `Txid` used in a coinbase prevout.
///
/// This is used as the "txid" of the dummy input of a coinbase transaction. This is not a real
/// TXID and should not be used in any other contexts. See `OutPoint::COINBASE_PREVOUT`.
pub const COINBASE_PREVOUT: Self = Self::from_byte_array([0; 32]);
}
impl Wtxid {
/// The `Wtxid` of a coinbase transaction.
///
/// This is used as the wTXID for the coinbase transaction when constructing blocks (in the
/// witness commitment tree) since the coinbase transaction contains a commitment to all
/// transactions' wTXIDs but naturally cannot commit to its own.
pub const COINBASE: Self = Self::from_byte_array([0; 32]);
}
/// The transaction version.
///
/// Currently, as specified by [BIP-68], only version 1 and 2 are considered standard.