// SPDX-License-Identifier: CC0-1.0 //! Bitcoin blocks. //! //! A block is a bundle of transactions with a proof-of-work attached, //! which commits to an earlier block to form the blockchain. This //! module describes structures and functions needed to describe //! these blocks and the blockchain. #[cfg(feature = "arbitrary")] use arbitrary::{Arbitrary, Unstructured}; use hashes::sha256d; /// Bitcoin block version number. /// /// Originally used as a protocol version, but repurposed for soft-fork signaling. /// /// The inner value is a signed integer in Bitcoin Core for historical reasons, if version bits is /// being used the top three bits must be 001, this gives us a useful range of [0x20000000...0x3FFFFFFF]. /// /// > When a block nVersion does not have top bits 001, it is treated as if all bits are 0 for the purposes of deployments. /// /// ### Relevant BIPs /// /// * [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) /// * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki) #[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 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. const USE_VERSION_BITS: u32 = 0x2000_0000; /// Creates a [`Version`] from a signed 32 bit integer value. /// /// This is the data type used in consensus code in Bitcoin Core. #[inline] pub const fn from_consensus(v: i32) -> Self { Version(v) } /// Returns the inner `i32` value. /// /// This is the data type used in consensus code in Bitcoin Core. pub fn to_consensus(self) -> i32 { self.0 } /// Checks whether the version number is signalling a soft fork at the given bit. /// /// A block is signalling for a soft fork under BIP-9 if the first 3 bits are `001` and /// the version bit for the specific soft fork is toggled on. pub fn is_signalling_soft_fork(&self, bit: u8) -> bool { // Only bits [0, 28] inclusive are used for signalling. if bit > 28 { return false; } // To signal using version bits, the first three bits must be `001`. if (self.0 as u32) & !Self::VERSION_BITS_MASK != Self::USE_VERSION_BITS { return false; } // The bit is set if signalling a soft fork. (self.0 as u32 & Self::VERSION_BITS_MASK) & (1 << bit) > 0 } } impl Default for Version { fn default() -> Version { Self::NO_SOFT_FORK_SIGNALLING } } hashes::hash_newtype! { /// A bitcoin block hash. pub struct BlockHash(sha256d::Hash); /// A hash corresponding to the witness structure commitment in the coinbase transaction. pub struct WitnessCommitment(sha256d::Hash); } impl BlockHash { /// Dummy hash used as the previous blockhash of the genesis block. pub const GENESIS_PREVIOUS_BLOCK_HASH: Self = Self::from_byte_array([0; 32]); } #[cfg(feature = "arbitrary")] impl<'a> Arbitrary<'a> for Version { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { // Equally weight known versions and arbitrary versions let choice = u.int_in_range(0..=3)?; match choice { 0 => Ok(Version::ONE), 1 => Ok(Version::TWO), 2 => Ok(Version::NO_SOFT_FORK_SIGNALLING), _ => Ok(Version::from_consensus(u.arbitrary()?)), } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_version_is_not_signalling_with_invalid_bit() { let arbitrary_version = Version::from_consensus(1234567890); // The max bit number to signal is 28. assert!(!Version::is_signalling_soft_fork(&arbitrary_version, 29)); } #[test] fn test_version_is_not_signalling_when_use_version_bit_not_set() { let version = Version::from_consensus(0b01000000000000000000000000000000); // Top three bits must be 001 to signal. assert!(!Version::is_signalling_soft_fork(&version, 1)); } #[test] fn test_version_is_signalling() { let version = Version::from_consensus(0b00100000000000000000000000000010); assert!(Version::is_signalling_soft_fork(&version, 1)); } #[test] fn test_version_is_not_signalling() { let version = Version::from_consensus(0b00100000000000000000000000000010); assert!(!Version::is_signalling_soft_fork(&version, 0)); } }