1use 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
25pub const TARGET_BLOCK_SPACING: u32 = 600;
27pub const DIFFCHANGE_INTERVAL: u32 = 2016;
29pub const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600;
31
32pub const WITNESS_SCALE_FACTOR: usize = units::weight::WITNESS_SCALE_FACTOR;
34pub const MAX_BLOCK_SIGOPS_COST: i64 = 80_000;
36pub const PUBKEY_ADDRESS_PREFIX_MAIN: u8 = 0; pub const SCRIPT_ADDRESS_PREFIX_MAIN: u8 = 5; pub const PUBKEY_ADDRESS_PREFIX_TEST: u8 = 111; pub const SCRIPT_ADDRESS_PREFIX_TEST: u8 = 196; pub const MAX_SCRIPT_ELEMENT_SIZE: usize = 520;
46pub const SUBSIDY_HALVING_INTERVAL: u32 = 210_000;
48pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; pub const COINBASE_MATURITY: u32 = 100;
52
53#[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
73fn bitcoin_genesis_tx(params: &Params) -> Transaction {
75 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 ret
115}
116
117pub 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#[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 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 #[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 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 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 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 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 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 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 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 let _ = genesis_block(¶ms::MAINNET);
295 let _ = genesis_block(&Network::Bitcoin);
297 let _ = genesis_block(Network::Bitcoin);
298 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(¶ms::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(¶ms::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(¶ms::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 fn chain_hash_and_genesis_block(network: Network) {
362 use hashes::sha256;
363
364 let genesis_hash = genesis_block(network).block_hash();
366 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 assert_eq!(got, want);
375
376 #[allow(unreachable_patterns)] 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]
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}