From d06d7cc8fcd04a7913d8a3369de3d859ae2ef53b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 20 Sep 2022 18:33:55 +1000 Subject: [PATCH] Remove primitives::constants module Inline the code out of `primitives/constants.rs` into `primitives/mod.rs`. Refactor only, no logic changes. --- bitcoin/src/address.rs | 2 +- bitcoin/src/lib.rs | 1 - bitcoin/src/policy.rs | 2 +- bitcoin/src/primitives/block.rs | 2 +- bitcoin/src/primitives/constants.rs | 314 -------------------------- bitcoin/src/primitives/mod.rs | 305 ++++++++++++++++++++++++- bitcoin/src/primitives/transaction.rs | 10 +- bitcoin/src/util/merkleblock.rs | 2 +- 8 files changed, 313 insertions(+), 325 deletions(-) delete mode 100644 bitcoin/src/primitives/constants.rs diff --git a/bitcoin/src/address.rs b/bitcoin/src/address.rs index b57998178b..0952c75d4c 100644 --- a/bitcoin/src/address.rs +++ b/bitcoin/src/address.rs @@ -36,7 +36,7 @@ use crate::hashes::{sha256, Hash, HashEngine}; use crate::internal_macros::serde_string_impl; use crate::network::constants::Network; use crate::prelude::*; -use crate::primitives::constants::{ +use crate::primitives::{ MAX_SCRIPT_ELEMENT_SIZE, PUBKEY_ADDRESS_PREFIX_MAIN, PUBKEY_ADDRESS_PREFIX_TEST, SCRIPT_ADDRESS_PREFIX_MAIN, SCRIPT_ADDRESS_PREFIX_TEST, }; diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index b9ad97ea7a..c499d53720 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -100,7 +100,6 @@ pub use crate::consensus::encode::VarInt; pub use crate::hash_types::*; pub use crate::network::constants::Network; pub use crate::primitives::block::{self, Block, BlockHeader, BlockVersion}; -pub use crate::primitives::constants; pub use crate::primitives::locktime::{self, absolute, relative}; pub use crate::primitives::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut}; pub use crate::primitives::witness::{self, Witness}; diff --git a/bitcoin/src/policy.rs b/bitcoin/src/policy.rs index 4e4742d3b3..4ae233d905 100644 --- a/bitcoin/src/policy.rs +++ b/bitcoin/src/policy.rs @@ -15,7 +15,7 @@ use core::cmp; -use super::primitives::constants::{MAX_BLOCK_SIGOPS_COST, WITNESS_SCALE_FACTOR}; +use super::primitives::{MAX_BLOCK_SIGOPS_COST, WITNESS_SCALE_FACTOR}; /// Maximum weight of a transaction for it to be relayed by most nodes on the network pub const MAX_STANDARD_TX_WEIGHT: u32 = 400_000; diff --git a/bitcoin/src/primitives/block.rs b/bitcoin/src/primitives/block.rs index 5c56dbded4..e4a8edc79a 100644 --- a/bitcoin/src/primitives/block.rs +++ b/bitcoin/src/primitives/block.rs @@ -22,7 +22,7 @@ use crate::util::uint::Uint256; use crate::consensus::{encode, Encodable, Decodable}; use crate::network::constants::Network; use crate::primitives::transaction::Transaction; -use crate::primitives::constants::{max_target, WITNESS_SCALE_FACTOR}; +use crate::primitives::{max_target, WITNESS_SCALE_FACTOR}; use crate::script; use crate::VarInt; use crate::internal_macros::impl_consensus_encoding; diff --git a/bitcoin/src/primitives/constants.rs b/bitcoin/src/primitives/constants.rs deleted file mode 100644 index 1936d477c2..0000000000 --- a/bitcoin/src/primitives/constants.rs +++ /dev/null @@ -1,314 +0,0 @@ -// Written in 2014 by Andrew Poelstra -// SPDX-License-Identifier: CC0-1.0 - -//! Blockdata constants. -//! -//! This module provides various constants relating to the blockchain and -//! consensus code. In particular, it defines the genesis block and its -//! single transaction. -//! - -use crate::prelude::*; - -use core::default::Default; - -use crate::hashes::hex::{self, HexIterator}; -use crate::hashes::{Hash, sha256d}; -use crate::script::{self, opcodes}; -use crate::primitives::locktime::absolute; -use crate::primitives::transaction::{OutPoint, Transaction, TxOut, TxIn, Sequence}; -use crate::primitives::block::{Block, BlockHeader, BlockVersion}; -use crate::primitives::witness::Witness; -use crate::network::constants::Network; -use crate::util::uint::Uint256; -use crate::internal_macros::{impl_array_newtype, impl_bytes_newtype}; - -/// How many satoshis are in "one bitcoin" -pub const COIN_VALUE: u64 = 100_000_000; -/// How many seconds between blocks we expect on average -pub const TARGET_BLOCK_SPACING: u32 = 600; -/// How many blocks between diffchanges -pub const DIFFCHANGE_INTERVAL: u32 = 2016; -/// How much time on average should occur between diffchanges -pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600; -/// The maximum allowed weight for a block, see BIP 141 (network rule) -pub const MAX_BLOCK_WEIGHT: u32 = 4_000_000; -/// The minimum transaction weight for a valid serialized transaction -pub const MIN_TRANSACTION_WEIGHT: u32 = 4 * 60; -/// The factor that non-witness serialization data is multiplied by during weight calculation -pub const WITNESS_SCALE_FACTOR: usize = 4; -/// The maximum allowed number of signature check operations in a block -pub const MAX_BLOCK_SIGOPS_COST: i64 = 80_000; -/// Mainnet (bitcoin) pubkey address prefix. -pub const PUBKEY_ADDRESS_PREFIX_MAIN: u8 = 0; // 0x00 -/// Mainnet (bitcoin) script address prefix. -pub const SCRIPT_ADDRESS_PREFIX_MAIN: u8 = 5; // 0x05 -/// Test (tesnet, signet, regtest) pubkey address prefix. -pub const PUBKEY_ADDRESS_PREFIX_TEST: u8 = 111; // 0x6f -/// Test (tesnet, signet, regtest) script address prefix. -pub const SCRIPT_ADDRESS_PREFIX_TEST: u8 = 196; // 0xc4 -/// The maximum allowed script size. -pub const MAX_SCRIPT_ELEMENT_SIZE: usize = 520; -/// How may blocks between halvings. -pub const SUBSIDY_HALVING_INTERVAL: u32 = 210_000; -/// Maximum allowed value for an integer in Script. -pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31 - -/// In Bitcoind this is insanely described as ~((u256)0 >> 32) -pub fn max_target(_: Network) -> Uint256 { - Uint256::from_u64(0xFFFF).unwrap() << 208 -} - -/// The maximum value allowed in an output (useful for sanity checking, -/// since keeping everything below this value should prevent overflows -/// if you are doing anything remotely sane with monetary values). -pub fn max_money(_: Network) -> u64 { - 21_000_000 * COIN_VALUE -} - -/// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block -fn bitcoin_genesis_tx() -> Transaction { - // Base - let mut ret = Transaction { - version: 1, - lock_time: absolute::PackedLockTime::ZERO, - input: vec![], - output: vec![], - }; - - // Inputs - let in_script = script::Builder::new().push_scriptint(486604799) - .push_scriptint(4) - .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") - .into_script(); - ret.input.push(TxIn { - previous_output: OutPoint::null(), - script_sig: in_script, - sequence: Sequence::MAX, - witness: Witness::default(), - }); - - // Outputs - let script_bytes: Result, hex::Error> = - HexIterator::new("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap() - .collect(); - let out_script = script::Builder::new() - .push_slice(script_bytes.unwrap().as_slice()) - .push_opcode(opcodes::all::OP_CHECKSIG) - .into_script(); - ret.output.push(TxOut { - value: 50 * COIN_VALUE, - script_pubkey: out_script - }); - - // end - ret -} - -/// Constructs and returns the genesis block -pub fn genesis_block(network: Network) -> Block { - let txdata = vec![bitcoin_genesis_tx()]; - let hash: sha256d::Hash = txdata[0].txid().into(); - let merkle_root = hash.into(); - match network { - Network::Bitcoin => { - Block { - header: BlockHeader { - version: BlockVersion(1), - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1231006505, - bits: 0x1d00ffff, - nonce: 2083236893 - }, - txdata, - } - } - Network::Testnet => { - Block { - header: BlockHeader { - version: BlockVersion(1), - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1296688602, - bits: 0x1d00ffff, - nonce: 414098458 - }, - txdata, - } - } - Network::Signet => { - Block { - header: BlockHeader { - version: BlockVersion(1), - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1598918400, - bits: 0x1e0377ae, - nonce: 52613770 - }, - txdata, - } - } - Network::Regtest => { - Block { - header: BlockHeader { - version: BlockVersion(1), - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1296688602, - bits: 0x207fffff, - nonce: 2 - }, - txdata, - } - } - } -} - -/// The uniquely identifying hash of the target blockchain. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ChainHash([u8; 32]); -impl_array_newtype!(ChainHash, u8, 32); -impl_bytes_newtype!(ChainHash, 32); - -impl ChainHash { - // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md - /// `ChainHash` for mainnet bitcoin. - pub const BITCOIN: Self = Self([111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0]); - /// `ChainHash` for testnet bitcoin. - pub const TESTNET: Self = Self([67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0]); - /// `ChainHash` for signet bitcoin. - pub const SIGNET: Self = Self([246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, 240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0]); - /// `ChainHash` for regtest bitcoin. - pub const REGTEST: Self = Self([6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15]); - - /// Returns the hash of the `network` genesis block for use as a chain hash. - /// - /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash) - /// for specification. - pub const fn using_genesis_block(network: Network) -> Self { - let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST]; - hashes[network as usize] - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::hashes::hex::{ToHex, FromHex}; - use crate::network::constants::Network; - use crate::consensus::encode::serialize; - use crate::primitives::locktime::absolute; - - #[test] - fn bitcoin_genesis_first_transaction() { - let gen = bitcoin_genesis_tx(); - - assert_eq!(gen.version, 1); - assert_eq!(gen.input.len(), 1); - assert_eq!(gen.input[0].previous_output.txid, Hash::all_zeros()); - assert_eq!(gen.input[0].previous_output.vout, 0xFFFFFFFF); - assert_eq!(serialize(&gen.input[0].script_sig), - Vec::from_hex("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73").unwrap()); - - assert_eq!(gen.input[0].sequence, Sequence::MAX); - assert_eq!(gen.output.len(), 1); - assert_eq!(serialize(&gen.output[0].script_pubkey), - Vec::from_hex("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac").unwrap()); - assert_eq!(gen.output[0].value, 50 * COIN_VALUE); - assert_eq!(gen.lock_time, absolute::PackedLockTime::ZERO); - - assert_eq!(gen.wtxid().to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); - } - - #[test] - fn bitcoin_genesis_full_block() { - let gen = genesis_block(Network::Bitcoin); - - assert_eq!(gen.header.version, BlockVersion(1)); - assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); - - assert_eq!(gen.header.time, 1231006505); - assert_eq!(gen.header.bits, 0x1d00ffff); - assert_eq!(gen.header.nonce, 2083236893); - assert_eq!(gen.header.block_hash().to_hex(), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); - } - - #[test] - fn testnet_genesis_full_block() { - let gen = genesis_block(Network::Testnet); - assert_eq!(gen.header.version, BlockVersion(1)); - assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); - assert_eq!(gen.header.time, 1296688602); - assert_eq!(gen.header.bits, 0x1d00ffff); - assert_eq!(gen.header.nonce, 414098458); - assert_eq!(gen.header.block_hash().to_hex(), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); - } - - #[test] - fn signet_genesis_full_block() { - let gen = genesis_block(Network::Signet); - assert_eq!(gen.header.version, BlockVersion(1)); - assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); - assert_eq!(gen.header.time, 1598918400); - assert_eq!(gen.header.bits, 0x1e0377ae); - assert_eq!(gen.header.nonce, 52613770); - assert_eq!(gen.header.block_hash().to_hex(), "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6"); - } - - // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array - // representing the genesis block is the same as that created by hashing the genesis block. - fn chain_hash_and_genesis_block(network: Network) { - use crate::hashes::sha256; - - // The genesis block hash is a double-sha256 and it is displayed backwards. - let genesis_hash = genesis_block(network).block_hash(); - // We abuse the sha256 hash here so we get a LowerHex impl that does not print the hex backwards. - let hash = sha256::Hash::from_slice(&genesis_hash.into_inner()).unwrap(); - let want = format!("{:02x}", hash); - - let chain_hash = ChainHash::using_genesis_block(network); - let got = format!("{:02x}", chain_hash); - - // Compare strings because the spec specifically states how the chain hash must encode to hex. - assert_eq!(got, want); - - match network { - Network::Bitcoin => {}, - Network::Testnet => {}, - Network::Signet => {}, - Network::Regtest => {}, - // Update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants. - } - } - - macro_rules! chain_hash_genesis_block { - ($($test_name:ident, $network:expr);* $(;)*) => { - $( - #[test] - fn $test_name() { - chain_hash_and_genesis_block($network); - } - )* - } - } - - chain_hash_genesis_block! { - mainnet_chain_hash_genesis_block, Network::Bitcoin; - testnet_chain_hash_genesis_block, Network::Testnet; - signet_chain_hash_genesis_block, Network::Signet; - regtest_chain_hash_genesis_block, Network::Regtest; - } - - // Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md - #[test] - fn mainnet_chain_hash_test_vector() { - let got = ChainHash::using_genesis_block(Network::Bitcoin).to_hex(); - let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"; - assert_eq!(got, want); - } -} diff --git a/bitcoin/src/primitives/mod.rs b/bitcoin/src/primitives/mod.rs index 73c923ab36..e816665896 100644 --- a/bitcoin/src/primitives/mod.rs +++ b/bitcoin/src/primitives/mod.rs @@ -7,8 +7,311 @@ //! transactions which make up the Bitcoin system. //! -pub mod constants; pub mod locktime; pub mod transaction; pub mod block; pub mod witness; +use crate::prelude::*; + +use core::default::Default; + +use crate::hashes::hex::{self, HexIterator}; +use crate::hashes::{Hash, sha256d}; +use crate::script::{self, opcodes}; +use crate::primitives::locktime::absolute; +use crate::primitives::transaction::{OutPoint, Transaction, TxOut, TxIn, Sequence}; +use crate::primitives::block::{Block, BlockHeader, BlockVersion}; +use crate::primitives::witness::Witness; +use crate::network::constants::Network; +use crate::util::uint::Uint256; +use crate::internal_macros::{impl_array_newtype, impl_bytes_newtype}; + +/// How many satoshis are in "one bitcoin" +pub const COIN_VALUE: u64 = 100_000_000; +/// How many seconds between blocks we expect on average +pub const TARGET_BLOCK_SPACING: u32 = 600; +/// How many blocks between diffchanges +pub const DIFFCHANGE_INTERVAL: u32 = 2016; +/// How much time on average should occur between diffchanges +pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600; +/// The maximum allowed weight for a block, see BIP 141 (network rule) +pub const MAX_BLOCK_WEIGHT: u32 = 4_000_000; +/// The minimum transaction weight for a valid serialized transaction +pub const MIN_TRANSACTION_WEIGHT: u32 = 4 * 60; +/// The factor that non-witness serialization data is multiplied by during weight calculation +pub const WITNESS_SCALE_FACTOR: usize = 4; +/// The maximum allowed number of signature check operations in a block +pub const MAX_BLOCK_SIGOPS_COST: i64 = 80_000; +/// Mainnet (bitcoin) pubkey address prefix. +pub const PUBKEY_ADDRESS_PREFIX_MAIN: u8 = 0; // 0x00 +/// Mainnet (bitcoin) script address prefix. +pub const SCRIPT_ADDRESS_PREFIX_MAIN: u8 = 5; // 0x05 +/// Test (tesnet, signet, regtest) pubkey address prefix. +pub const PUBKEY_ADDRESS_PREFIX_TEST: u8 = 111; // 0x6f +/// Test (tesnet, signet, regtest) script address prefix. +pub const SCRIPT_ADDRESS_PREFIX_TEST: u8 = 196; // 0xc4 +/// The maximum allowed script size. +pub const MAX_SCRIPT_ELEMENT_SIZE: usize = 520; +/// How may blocks between halvings. +pub const SUBSIDY_HALVING_INTERVAL: u32 = 210_000; +/// Maximum allowed value for an integer in Script. +pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31 + +/// In Bitcoind this is insanely described as ~((u256)0 >> 32) +pub fn max_target(_: Network) -> Uint256 { + Uint256::from_u64(0xFFFF).unwrap() << 208 +} + +/// The maximum value allowed in an output (useful for sanity checking, +/// since keeping everything below this value should prevent overflows +/// if you are doing anything remotely sane with monetary values). +pub fn max_money(_: Network) -> u64 { + 21_000_000 * COIN_VALUE +} + +/// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block +fn bitcoin_genesis_tx() -> Transaction { + // Base + let mut ret = Transaction { + version: 1, + lock_time: absolute::PackedLockTime::ZERO, + input: vec![], + output: vec![], + }; + + // Inputs + let in_script = script::Builder::new().push_scriptint(486604799) + .push_scriptint(4) + .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") + .into_script(); + ret.input.push(TxIn { + previous_output: OutPoint::null(), + script_sig: in_script, + sequence: Sequence::MAX, + witness: Witness::default(), + }); + + // Outputs + let script_bytes: Result, hex::Error> = + HexIterator::new("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f").unwrap() + .collect(); + let out_script = script::Builder::new() + .push_slice(script_bytes.unwrap().as_slice()) + .push_opcode(opcodes::all::OP_CHECKSIG) + .into_script(); + ret.output.push(TxOut { + value: 50 * COIN_VALUE, + script_pubkey: out_script + }); + + // end + ret +} + +/// Constructs and returns the genesis block +pub fn genesis_block(network: Network) -> Block { + let txdata = vec![bitcoin_genesis_tx()]; + let hash: sha256d::Hash = txdata[0].txid().into(); + let merkle_root = hash.into(); + match network { + Network::Bitcoin => { + Block { + header: BlockHeader { + version: BlockVersion(1), + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1231006505, + bits: 0x1d00ffff, + nonce: 2083236893 + }, + txdata, + } + } + Network::Testnet => { + Block { + header: BlockHeader { + version: BlockVersion(1), + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1296688602, + bits: 0x1d00ffff, + nonce: 414098458 + }, + txdata, + } + } + Network::Signet => { + Block { + header: BlockHeader { + version: BlockVersion(1), + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1598918400, + bits: 0x1e0377ae, + nonce: 52613770 + }, + txdata, + } + } + Network::Regtest => { + Block { + header: BlockHeader { + version: BlockVersion(1), + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1296688602, + bits: 0x207fffff, + nonce: 2 + }, + txdata, + } + } + } +} + +/// The uniquely identifying hash of the target blockchain. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ChainHash([u8; 32]); +impl_array_newtype!(ChainHash, u8, 32); +impl_bytes_newtype!(ChainHash, 32); + +impl ChainHash { + // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md + /// `ChainHash` for mainnet bitcoin. + pub const BITCOIN: Self = Self([111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0]); + /// `ChainHash` for testnet bitcoin. + pub const TESTNET: Self = Self([67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0]); + /// `ChainHash` for signet bitcoin. + pub const SIGNET: Self = Self([246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, 240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0]); + /// `ChainHash` for regtest bitcoin. + pub const REGTEST: Self = Self([6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15]); + + /// Returns the hash of the `network` genesis block for use as a chain hash. + /// + /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash) + /// for specification. + pub const fn using_genesis_block(network: Network) -> Self { + let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST]; + hashes[network as usize] + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::hashes::hex::{ToHex, FromHex}; + use crate::network::constants::Network; + use crate::consensus::encode::serialize; + use crate::primitives::locktime::absolute; + + #[test] + fn bitcoin_genesis_first_transaction() { + let gen = bitcoin_genesis_tx(); + + assert_eq!(gen.version, 1); + assert_eq!(gen.input.len(), 1); + assert_eq!(gen.input[0].previous_output.txid, Hash::all_zeros()); + assert_eq!(gen.input[0].previous_output.vout, 0xFFFFFFFF); + assert_eq!(serialize(&gen.input[0].script_sig), + Vec::from_hex("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73").unwrap()); + + assert_eq!(gen.input[0].sequence, Sequence::MAX); + assert_eq!(gen.output.len(), 1); + assert_eq!(serialize(&gen.output[0].script_pubkey), + Vec::from_hex("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac").unwrap()); + assert_eq!(gen.output[0].value, 50 * COIN_VALUE); + assert_eq!(gen.lock_time, absolute::PackedLockTime::ZERO); + + assert_eq!(gen.wtxid().to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + } + + #[test] + fn bitcoin_genesis_full_block() { + let gen = genesis_block(Network::Bitcoin); + + assert_eq!(gen.header.version, BlockVersion(1)); + assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); + assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + + assert_eq!(gen.header.time, 1231006505); + assert_eq!(gen.header.bits, 0x1d00ffff); + assert_eq!(gen.header.nonce, 2083236893); + assert_eq!(gen.header.block_hash().to_hex(), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); + } + + #[test] + fn testnet_genesis_full_block() { + let gen = genesis_block(Network::Testnet); + assert_eq!(gen.header.version, BlockVersion(1)); + assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); + assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + assert_eq!(gen.header.time, 1296688602); + assert_eq!(gen.header.bits, 0x1d00ffff); + assert_eq!(gen.header.nonce, 414098458); + assert_eq!(gen.header.block_hash().to_hex(), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); + } + + #[test] + fn signet_genesis_full_block() { + let gen = genesis_block(Network::Signet); + assert_eq!(gen.header.version, BlockVersion(1)); + assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); + assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + assert_eq!(gen.header.time, 1598918400); + assert_eq!(gen.header.bits, 0x1e0377ae); + assert_eq!(gen.header.nonce, 52613770); + assert_eq!(gen.header.block_hash().to_hex(), "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6"); + } + + // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array + // representing the genesis block is the same as that created by hashing the genesis block. + fn chain_hash_and_genesis_block(network: Network) { + use crate::hashes::sha256; + + // The genesis block hash is a double-sha256 and it is displayed backwards. + let genesis_hash = genesis_block(network).block_hash(); + // We abuse the sha256 hash here so we get a LowerHex impl that does not print the hex backwards. + let hash = sha256::Hash::from_slice(&genesis_hash.into_inner()).unwrap(); + let want = format!("{:02x}", hash); + + let chain_hash = ChainHash::using_genesis_block(network); + let got = format!("{:02x}", chain_hash); + + // Compare strings because the spec specifically states how the chain hash must encode to hex. + assert_eq!(got, want); + + match network { + Network::Bitcoin => {}, + Network::Testnet => {}, + Network::Signet => {}, + Network::Regtest => {}, + // Update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants. + } + } + + macro_rules! chain_hash_genesis_block { + ($($test_name:ident, $network:expr);* $(;)*) => { + $( + #[test] + fn $test_name() { + chain_hash_and_genesis_block($network); + } + )* + } + } + + chain_hash_genesis_block! { + mainnet_chain_hash_genesis_block, Network::Bitcoin; + testnet_chain_hash_genesis_block, Network::Testnet; + signet_chain_hash_genesis_block, Network::Signet; + regtest_chain_hash_genesis_block, Network::Regtest; + } + + // Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md + #[test] + fn mainnet_chain_hash_test_vector() { + let got = ChainHash::using_genesis_block(Network::Bitcoin).to_hex(); + let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"; + assert_eq!(got, want); + } +} diff --git a/bitcoin/src/primitives/transaction.rs b/bitcoin/src/primitives/transaction.rs index 79e8b0e1d7..8859f8c439 100644 --- a/bitcoin/src/primitives/transaction.rs +++ b/bitcoin/src/primitives/transaction.rs @@ -23,7 +23,7 @@ use bitcoin_internals::write_err; use crate::hashes::{self, Hash, sha256d}; use crate::hashes::hex::FromHex; -use crate::primitives::constants::WITNESS_SCALE_FACTOR; +use crate::primitives::WITNESS_SCALE_FACTOR; #[cfg(feature="bitcoinconsensus")] use crate::script; use crate::script::Script; use crate::primitives::witness::Witness; @@ -75,7 +75,7 @@ impl OutPoint { /// # Examples /// /// ```rust - /// use bitcoin::constants::genesis_block; + /// use bitcoin::primitives::genesis_block; /// use bitcoin::network::constants::Network; /// /// let block = genesis_block(Network::Bitcoin); @@ -1027,7 +1027,7 @@ mod tests { use core::str::FromStr; - use crate::primitives::constants::WITNESS_SCALE_FACTOR; + use crate::primitives::WITNESS_SCALE_FACTOR; use crate::script::Script; use crate::primitives::locktime::absolute; use crate::consensus::encode::serialize; @@ -1102,9 +1102,9 @@ mod tests { #[test] fn test_is_coinbase () { use crate::network::constants::Network; - use crate::primitives::constants; + use crate::primitives; - let genesis = constants::genesis_block(Network::Bitcoin); + let genesis = primitives::genesis_block(Network::Bitcoin); assert! (genesis.txdata[0].is_coin_base()); let tx_bytes = Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); let tx: Transaction = deserialize(&tx_bytes).unwrap(); diff --git a/bitcoin/src/util/merkleblock.rs b/bitcoin/src/util/merkleblock.rs index 0b8d9d676e..8db58d2b30 100644 --- a/bitcoin/src/util/merkleblock.rs +++ b/bitcoin/src/util/merkleblock.rs @@ -50,7 +50,7 @@ use crate::hashes::Hash; use crate::hash_types::{Txid, TxMerkleNode}; use crate::primitives::transaction::Transaction; -use crate::primitives::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; +use crate::primitives::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT}; use crate::consensus::encode::{self, Decodable, Encodable}; use crate::util::merkleblock::MerkleBlockError::*; use crate::{Block, BlockHeader};