From 24984f095f96ad34b8984134b86500d4f6acc6f0 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 27 Oct 2022 12:55:06 +1100 Subject: [PATCH] Make block::Version inner value private The Bitcoin block version is a signed integer for historical reasons, but we bit twiddle it like an unsigned integer and during consensus encode/decode we cast the signed value to an unsigned value. In order to hide this confusion, make the inner value private and add a couple of constants for v1 and v2 block versions. --- bitcoin/src/bip152.rs | 2 +- bitcoin/src/blockdata/block.rs | 12 ++++++++++-- bitcoin/src/blockdata/constants.rs | 14 +++++++------- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 857a150a..943f47a3 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -395,7 +395,7 @@ mod test { fn dummy_block() -> Block { Block { header: block::Header { - version: block::Version(1), + version: block::Version::ONE, prev_blockhash: BlockHash::hash(&[0]), merkle_root: TxMerkleNode::hash(&[1]), time: 2, diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 9a80406c..ef09e480 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -112,13 +112,21 @@ impl Header { #[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct Version(pub i32); +pub struct Version(i32); impl Version { + /// The original Bitcoin Block v1. + pub const ONE: Self = Self(1); + + /// BIP-34 Block v2. + pub const TWO: Self = Self(2); + /// BIP-9 compatible version number that does not signal for any softforks. pub const NO_SOFT_FORK_SIGNALLING: Self = Self(Self::USE_VERSION_BITS as i32); + /// BIP-9 soft fork signal bits mask. const VERSION_BITS_MASK: u32 = 0x1FFF_FFFF; + /// 32bit value starting with `001` to use version bits. /// /// The value has the top three bits `001` which enables the use of version bits to signal for soft forks. @@ -302,7 +310,7 @@ impl Block { // number (including a sign bit). Height is the height of the mined // block in the block chain, where the genesis block is height zero (0). - if self.header.version < Version(2) { + if self.header.version < Version::TWO { return Err(Bip34Error::Unsupported); } diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index 1ff7c97b..c74fd88f 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -112,7 +112,7 @@ pub fn genesis_block(network: Network) -> Block { Network::Bitcoin => { Block { header: block::Header { - version: block::Version(1), + version: block::Version::ONE, prev_blockhash: Hash::all_zeros(), merkle_root, time: 1231006505, @@ -125,7 +125,7 @@ pub fn genesis_block(network: Network) -> Block { Network::Testnet => { Block { header: block::Header { - version: block::Version(1), + version: block::Version::ONE, prev_blockhash: Hash::all_zeros(), merkle_root, time: 1296688602, @@ -138,7 +138,7 @@ pub fn genesis_block(network: Network) -> Block { Network::Signet => { Block { header: block::Header { - version: block::Version(1), + version: block::Version::ONE, prev_blockhash: Hash::all_zeros(), merkle_root, time: 1598918400, @@ -151,7 +151,7 @@ pub fn genesis_block(network: Network) -> Block { Network::Regtest => { Block { header: block::Header { - version: block::Version(1), + version: block::Version::ONE, prev_blockhash: Hash::all_zeros(), merkle_root, time: 1296688602, @@ -224,7 +224,7 @@ mod test { fn bitcoin_genesis_full_block() { let gen = genesis_block(Network::Bitcoin); - assert_eq!(gen.header.version, block::Version(1)); + assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); @@ -237,7 +237,7 @@ mod test { #[test] fn testnet_genesis_full_block() { let gen = genesis_block(Network::Testnet); - assert_eq!(gen.header.version, block::Version(1)); + assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); assert_eq!(gen.header.time, 1296688602); @@ -249,7 +249,7 @@ mod test { #[test] fn signet_genesis_full_block() { let gen = genesis_block(Network::Signet); - assert_eq!(gen.header.version, block::Version(1)); + assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); assert_eq!(gen.header.time, 1598918400);