bitcoin/blockdata/
constants.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Blockdata constants.
4//!
5//! This module provides various constants relating to the blockchain and
6//! consensus code. In particular, it defines the genesis block and its
7//! single transaction.
8//!
9
10use hashes::{sha256d, Hash};
11use internals::impl_array_newtype;
12
13use crate::blockdata::block::{self, Block};
14use crate::blockdata::locktime::absolute;
15use crate::blockdata::opcodes::all::*;
16use crate::blockdata::script;
17use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut};
18use crate::blockdata::witness::Witness;
19use crate::consensus::Params;
20use crate::internal_macros::impl_bytes_newtype;
21use crate::network::Network;
22use crate::pow::CompactTarget;
23use crate::Amount;
24
25/// How many seconds between blocks we expect on average.
26pub const TARGET_BLOCK_SPACING: u32 = 600;
27/// How many blocks between diffchanges.
28pub const DIFFCHANGE_INTERVAL: u32 = 2016;
29/// How much time on average should occur between diffchanges.
30pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600;
31
32/// The factor that non-witness serialization data is multiplied by during weight calculation.
33pub const WITNESS_SCALE_FACTOR: usize = units::weight::WITNESS_SCALE_FACTOR;
34/// The maximum allowed number of signature check operations in a block.
35pub const MAX_BLOCK_SIGOPS_COST: i64 = 80_000;
36/// Mainnet (bitcoin) pubkey address prefix.
37pub const PUBKEY_ADDRESS_PREFIX_MAIN: u8 = 0; // 0x00
38/// Mainnet (bitcoin) script address prefix.
39pub const SCRIPT_ADDRESS_PREFIX_MAIN: u8 = 5; // 0x05
40/// Test (tesnet, signet, regtest) pubkey address prefix.
41pub const PUBKEY_ADDRESS_PREFIX_TEST: u8 = 111; // 0x6f
42/// Test (tesnet, signet, regtest) script address prefix.
43pub const SCRIPT_ADDRESS_PREFIX_TEST: u8 = 196; // 0xc4
44/// The maximum allowed script size.
45pub const MAX_SCRIPT_ELEMENT_SIZE: usize = 520;
46/// How may blocks between halvings.
47pub const SUBSIDY_HALVING_INTERVAL: u32 = 210_000;
48/// Maximum allowed value for an integer in Script.
49pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31
50/// Number of blocks needed for an output from a coinbase transaction to be spendable.
51pub const COINBASE_MATURITY: u32 = 100;
52
53// This is the 65 byte (uncompressed) pubkey used as the one-and-only output of the genesis transaction.
54//
55// ref: https://blockstream.info/tx/4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b?expand
56// Note output script includes a leading 0x41 and trailing 0xac (added below using the `script::Builder`).
57#[rustfmt::skip]
58const GENESIS_OUTPUT_PK: [u8; 65] = [
59    0x04,
60    0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27,
61    0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7, 0x10,
62    0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6,
63    0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde, 0xb6,
64    0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4,
65    0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12, 0xde,
66    0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57,
67    0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f
68];
69
70#[rustfmt::skip]
71const TESTNET4_GENESIS_OUTPUT_PK: [u8; 33] = [0x00; 33];
72
73/// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block.
74fn bitcoin_genesis_tx(params: &Params) -> Transaction {
75    // Base
76    let mut ret = Transaction {
77        version: transaction::Version::ONE,
78        lock_time: absolute::LockTime::ZERO,
79        input: vec![],
80        output: vec![],
81    };
82
83    let (in_script, out_script) = {
84        match params.network {
85            Network::Testnet4 => (
86                script::Builder::new()
87                .push_int(486604799)
88                .push_int_non_minimal(4)
89                .push_slice(b"03/May/2024 000000000000000000001ebd58c244970b3aa9d783bb001011fbe8ea8e98e00e")
90                .into_script(),
91                script::Builder::new().push_slice(TESTNET4_GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(),
92
93            ),
94            _ => (
95                script::Builder::new()
96                .push_int(486604799)
97                .push_int_non_minimal(4)
98                .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks")
99                .into_script(),
100                script::Builder::new().push_slice(GENESIS_OUTPUT_PK).push_opcode(OP_CHECKSIG).into_script(),
101            ),
102        }
103    };
104
105    ret.input.push(TxIn {
106        previous_output: OutPoint::null(),
107        script_sig: in_script,
108        sequence: Sequence::MAX,
109        witness: Witness::default(),
110    });
111    ret.output.push(TxOut { value: Amount::from_sat(50 * 100_000_000), script_pubkey: out_script });
112
113    // end
114    ret
115}
116
117/// Constructs and returns the genesis block.
118pub fn genesis_block(params: impl AsRef<Params>) -> Block {
119    let params = params.as_ref();
120    let txdata = vec![bitcoin_genesis_tx(params)];
121    let hash: sha256d::Hash = txdata[0].compute_txid().into();
122    let merkle_root: crate::TxMerkleNode = hash.into();
123
124    match params.network {
125        Network::Bitcoin => Block {
126            header: block::Header {
127                version: block::Version::ONE,
128                prev_blockhash: Hash::all_zeros(),
129                merkle_root,
130                time: 1231006505,
131                bits: CompactTarget::from_consensus(0x1d00ffff),
132                nonce: 2083236893,
133            },
134            txdata,
135        },
136        Network::Testnet => Block {
137            header: block::Header {
138                version: block::Version::ONE,
139                prev_blockhash: Hash::all_zeros(),
140                merkle_root,
141                time: 1296688602,
142                bits: CompactTarget::from_consensus(0x1d00ffff),
143                nonce: 414098458,
144            },
145            txdata,
146        },
147        Network::Testnet4 => Block {
148            header: block::Header {
149                version: block::Version::ONE,
150                prev_blockhash: Hash::all_zeros(),
151                merkle_root,
152                time: 1714777860,
153                bits: CompactTarget::from_consensus(0x1d00ffff),
154                nonce: 393743547,
155            },
156            txdata,
157        },
158        Network::Signet => Block {
159            header: block::Header {
160                version: block::Version::ONE,
161                prev_blockhash: Hash::all_zeros(),
162                merkle_root,
163                time: 1598918400,
164                bits: CompactTarget::from_consensus(0x1e0377ae),
165                nonce: 52613770,
166            },
167            txdata,
168        },
169        Network::Regtest => Block {
170            header: block::Header {
171                version: block::Version::ONE,
172                prev_blockhash: Hash::all_zeros(),
173                merkle_root,
174                time: 1296688602,
175                bits: CompactTarget::from_consensus(0x207fffff),
176                nonce: 2,
177            },
178            txdata,
179        },
180    }
181}
182
183/// The uniquely identifying hash of the target blockchain.
184#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
185pub struct ChainHash([u8; 32]);
186impl_array_newtype!(ChainHash, u8, 32);
187impl_bytes_newtype!(ChainHash, 32);
188
189impl ChainHash {
190    // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md
191    /// `ChainHash` for mainnet bitcoin.
192    pub const BITCOIN: Self = Self([
193        111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131,
194        101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0,
195    ]);
196    /// `ChainHash` for testnet3 bitcoin.
197    #[deprecated(since = "0.32.4", note = "Use TESTNET3 instead")]
198    pub const TESTNET: Self = Self([
199        67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151,
200        32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0,
201    ]);
202    /// `ChainHash` for testnet3 bitcoin.
203    pub const TESTNET3: Self = Self([
204        67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151,
205        32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0,
206    ]);
207    /// `ChainHash` for testnet4 bitcoin.
208    pub const TESTNET4: Self = Self([
209        67, 240, 139, 218, 176, 80, 227, 91, 86, 124, 134, 75, 145, 244, 127, 80, 174, 114, 90,
210        226, 222, 83, 188, 251, 186, 242, 132, 218, 0, 0, 0, 0,
211    ]);
212    /// `ChainHash` for signet bitcoin.
213    pub const SIGNET: Self = Self([
214        246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249,
215        240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0,
216    ]);
217    /// `ChainHash` for regtest bitcoin.
218    pub const REGTEST: Self = Self([
219        6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94,
220        51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15,
221    ]);
222
223    /// Returns the hash of the `network` genesis block for use as a chain hash.
224    ///
225    /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
226    /// for specification.
227    pub fn using_genesis_block(params: impl AsRef<Params>) -> Self {
228        match params.as_ref().network {
229            Network::Bitcoin => Self::BITCOIN,
230            Network::Testnet => Self::TESTNET3,
231            Network::Testnet4 => Self::TESTNET4,
232            Network::Signet => Self::SIGNET,
233            Network::Regtest => Self::REGTEST,
234        }
235    }
236
237    /// Returns the hash of the `network` genesis block for use as a chain hash.
238    ///
239    /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash)
240    /// for specification.
241    pub const fn using_genesis_block_const(network: Network) -> Self {
242        match network {
243            Network::Bitcoin => Self::BITCOIN,
244            Network::Testnet => Self::TESTNET3,
245            Network::Testnet4 => Self::TESTNET4,
246            Network::Signet => Self::SIGNET,
247            Network::Regtest => Self::REGTEST,
248        }
249    }
250
251    /// Converts genesis block hash into `ChainHash`.
252    pub fn from_genesis_block_hash(block_hash: crate::BlockHash) -> Self {
253        ChainHash(block_hash.to_byte_array())
254    }
255}
256
257#[cfg(test)]
258mod test {
259    use core::str::FromStr;
260
261    use hex::test_hex_unwrap as hex;
262
263    use super::*;
264    use crate::consensus::params;
265    use crate::consensus::encode::serialize;
266
267    #[test]
268    fn bitcoin_genesis_first_transaction() {
269        let gen = bitcoin_genesis_tx(&Params::MAINNET);
270
271        assert_eq!(gen.version, transaction::Version::ONE);
272        assert_eq!(gen.input.len(), 1);
273        assert_eq!(gen.input[0].previous_output.txid, Hash::all_zeros());
274        assert_eq!(gen.input[0].previous_output.vout, 0xFFFFFFFF);
275        assert_eq!(serialize(&gen.input[0].script_sig),
276                   hex!("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"));
277
278        assert_eq!(gen.input[0].sequence, Sequence::MAX);
279        assert_eq!(gen.output.len(), 1);
280        assert_eq!(serialize(&gen.output[0].script_pubkey),
281                   hex!("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac"));
282        assert_eq!(gen.output[0].value, Amount::from_str("50 BTC").unwrap());
283        assert_eq!(gen.lock_time, absolute::LockTime::ZERO);
284
285        assert_eq!(
286            gen.compute_wtxid().to_string(),
287            "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
288        );
289    }
290
291    #[test]
292    fn bitcoin_genesis_block_calling_convention() {
293        // This is the best.
294        let _ = genesis_block(&params::MAINNET);
295        // this works and is ok too.
296        let _ = genesis_block(&Network::Bitcoin);
297        let _ = genesis_block(Network::Bitcoin);
298        // This works too, but is suboptimal because it inlines the const.
299        let _ = genesis_block(Params::MAINNET);
300        let _ = genesis_block(&Params::MAINNET);
301    }
302
303    #[test]
304    fn bitcoin_genesis_full_block() {
305        let gen = genesis_block(&params::MAINNET);
306
307        assert_eq!(gen.header.version, block::Version::ONE);
308        assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
309        assert_eq!(
310            gen.header.merkle_root.to_string(),
311            "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
312        );
313
314        assert_eq!(gen.header.time, 1231006505);
315        assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff));
316        assert_eq!(gen.header.nonce, 2083236893);
317        assert_eq!(
318            gen.header.block_hash().to_string(),
319            "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
320        );
321    }
322
323    #[test]
324    fn testnet_genesis_full_block() {
325        let gen = genesis_block(&params::TESTNET3);
326        assert_eq!(gen.header.version, block::Version::ONE);
327        assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
328        assert_eq!(
329            gen.header.merkle_root.to_string(),
330            "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
331        );
332        assert_eq!(gen.header.time, 1296688602);
333        assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff));
334        assert_eq!(gen.header.nonce, 414098458);
335        assert_eq!(
336            gen.header.block_hash().to_string(),
337            "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
338        );
339    }
340
341    #[test]
342    fn signet_genesis_full_block() {
343        let gen = genesis_block(&params::SIGNET);
344        assert_eq!(gen.header.version, block::Version::ONE);
345        assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
346        assert_eq!(
347            gen.header.merkle_root.to_string(),
348            "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
349        );
350        assert_eq!(gen.header.time, 1598918400);
351        assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1e0377ae));
352        assert_eq!(gen.header.nonce, 52613770);
353        assert_eq!(
354            gen.header.block_hash().to_string(),
355            "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6"
356        );
357    }
358
359    // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array
360    // representing the genesis block is the same as that created by hashing the genesis block.
361    fn chain_hash_and_genesis_block(network: Network) {
362        use hashes::sha256;
363
364        // The genesis block hash is a double-sha256 and it is displayed backwards.
365        let genesis_hash = genesis_block(network).block_hash();
366        // We abuse the sha256 hash here so we get a LowerHex impl that does not print the hex backwards.
367        let hash = sha256::Hash::from_slice(genesis_hash.as_byte_array()).unwrap();
368        let want = format!("{:02x}", hash);
369
370        let chain_hash = ChainHash::using_genesis_block_const(network);
371        let got = format!("{:02x}", chain_hash);
372
373        // Compare strings because the spec specifically states how the chain hash must encode to hex.
374        assert_eq!(got, want);
375
376        #[allow(unreachable_patterns)] // This is specifically trying to catch later added variants.
377        match network {
378            Network::Bitcoin => {},
379            Network::Testnet => {},
380            Network::Testnet4 => {},
381            Network::Signet => {},
382            Network::Regtest => {},
383            _ => panic!("Update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants"),
384        }
385    }
386
387    macro_rules! chain_hash_genesis_block {
388        ($($test_name:ident, $network:expr);* $(;)*) => {
389            $(
390                #[test]
391                fn $test_name() {
392                    chain_hash_and_genesis_block($network);
393                }
394            )*
395        }
396    }
397
398    chain_hash_genesis_block! {
399        mainnet_chain_hash_genesis_block, Network::Bitcoin;
400        testnet_chain_hash_genesis_block, Network::Testnet;
401        testnet4_chain_hash_genesis_block, Network::Testnet4;
402        signet_chain_hash_genesis_block, Network::Signet;
403        regtest_chain_hash_genesis_block, Network::Regtest;
404    }
405
406    // Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md
407    #[test]
408    fn mainnet_chain_hash_test_vector() {
409        let got = ChainHash::using_genesis_block_const(Network::Bitcoin).to_string();
410        let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000";
411        assert_eq!(got, want);
412    }
413}