kaspa_consensus_core/config/
genesis.rs

1use crate::{block::Block, header::Header, subnets::SUBNETWORK_ID_COINBASE, tx::Transaction};
2use kaspa_hashes::{Hash, ZERO_HASH};
3use kaspa_muhash::EMPTY_MUHASH;
4
5/// The constants uniquely representing the genesis block
6#[derive(Clone, Debug)]
7pub struct GenesisBlock {
8    pub hash: Hash,
9    pub version: u16,
10    pub hash_merkle_root: Hash,
11    pub utxo_commitment: Hash,
12    pub timestamp: u64,
13    pub bits: u32,
14    pub nonce: u64,
15    pub daa_score: u64,
16    pub coinbase_payload: &'static [u8],
17}
18
19impl GenesisBlock {
20    pub fn build_genesis_transactions(&self) -> Vec<Transaction> {
21        vec![Transaction::new(0, Vec::new(), Vec::new(), 0, SUBNETWORK_ID_COINBASE, 0, self.coinbase_payload.to_vec())]
22    }
23}
24
25impl From<&GenesisBlock> for Header {
26    fn from(genesis: &GenesisBlock) -> Self {
27        Header::new_finalized(
28            genesis.version,
29            Vec::new(),
30            genesis.hash_merkle_root,
31            ZERO_HASH,
32            genesis.utxo_commitment,
33            genesis.timestamp,
34            genesis.bits,
35            genesis.nonce,
36            genesis.daa_score,
37            0.into(),
38            0,
39            ZERO_HASH,
40        )
41    }
42}
43
44impl From<&GenesisBlock> for Block {
45    fn from(genesis: &GenesisBlock) -> Self {
46        Block::new(genesis.into(), genesis.build_genesis_transactions())
47    }
48}
49
50impl From<(&Header, &'static [u8])> for GenesisBlock {
51    fn from((header, payload): (&Header, &'static [u8])) -> Self {
52        Self {
53            hash: header.hash,
54            version: header.version,
55            hash_merkle_root: header.hash_merkle_root,
56            utxo_commitment: header.utxo_commitment,
57            timestamp: header.timestamp,
58            bits: header.bits,
59            nonce: header.nonce,
60            daa_score: header.daa_score,
61            coinbase_payload: payload,
62        }
63    }
64}
65
66/// The genesis block of the block-DAG which serves as the public transaction ledger for the main network.
67pub const GENESIS: GenesisBlock = GenesisBlock {
68    hash: Hash::from_bytes([
69        0x58, 0xc2, 0xd4, 0x19, 0x9e, 0x21, 0xf9, 0x10, 0xd1, 0x57, 0x1d, 0x11, 0x49, 0x69, 0xce, 0xce, 0xf4, 0x8f, 0x9, 0xf9, 0x34,
70        0xd4, 0x2c, 0xcb, 0x6a, 0x28, 0x1a, 0x15, 0x86, 0x8f, 0x29, 0x99,
71    ]),
72    version: 0,
73    hash_merkle_root: Hash::from_bytes([
74        0x8e, 0xc8, 0x98, 0x56, 0x8c, 0x68, 0x1, 0xd1, 0x3d, 0xf4, 0xee, 0x6e, 0x2a, 0x1b, 0x54, 0xb7, 0xe6, 0x23, 0x6f, 0x67, 0x1f,
75        0x20, 0x95, 0x4f, 0x5, 0x30, 0x64, 0x10, 0x51, 0x8e, 0xeb, 0x32,
76    ]),
77    utxo_commitment: Hash::from_bytes([
78        0x71, 0x0f, 0x27, 0xdf, 0x42, 0x3e, 0x63, 0xaa, 0x6c, 0xdb, 0x72, 0xb8, 0x9e, 0xa5, 0xa0, 0x6c, 0xff, 0xa3, 0x99, 0xd6, 0x6f,
79        0x16, 0x77, 0x04, 0x45, 0x5b, 0x5a, 0xf5, 0x9d, 0xef, 0x8e, 0x20,
80    ]),
81    timestamp: 1637609671037,
82    bits: 486722099,
83    nonce: 0x3392c,
84    daa_score: 1312860, // Checkpoint DAA score
85    #[rustfmt::skip]
86    coinbase_payload: &[
87        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
88        0x00, 0xE1, 0xF5, 0x05, 0x00, 0x00, 0x00, 0x00, // Subsidy
89        0x00, 0x00, //script version
90        0x01,                                           // Varint
91        0x00,                                           // OP-FALSE
92        0xd7, 0x95, 0xd7, 0x9e, 0xd7, 0x94, 0x20, 0xd7, // ומה די עליך ועל אחיך ייטב בשאר כספא ודהבה למעבד כרעות אלהכם תעבדון
93        0x93, 0xd7, 0x99, 0x20, 0xd7, 0xa2, 0xd7, 0x9c,
94        0xd7, 0x99, 0xd7, 0x9a, 0x20, 0xd7, 0x95, 0xd7,
95        0xa2, 0xd7, 0x9c, 0x20, 0xd7, 0x90, 0xd7, 0x97,
96        0xd7, 0x99, 0xd7, 0x9a, 0x20, 0xd7, 0x99, 0xd7,
97        0x99, 0xd7, 0x98, 0xd7, 0x91, 0x20, 0xd7, 0x91,
98        0xd7, 0xa9, 0xd7, 0x90, 0xd7, 0xa8, 0x20, 0xd7,
99        0x9b, 0xd7, 0xa1, 0xd7, 0xa4, 0xd7, 0x90, 0x20,
100        0xd7, 0x95, 0xd7, 0x93, 0xd7, 0x94, 0xd7, 0x91,
101        0xd7, 0x94, 0x20, 0xd7, 0x9c, 0xd7, 0x9e, 0xd7,
102        0xa2, 0xd7, 0x91, 0xd7, 0x93, 0x20, 0xd7, 0x9b,
103        0xd7, 0xa8, 0xd7, 0xa2, 0xd7, 0x95, 0xd7, 0xaa,
104        0x20, 0xd7, 0x90, 0xd7, 0x9c, 0xd7, 0x94, 0xd7,
105        0x9b, 0xd7, 0x9d, 0x20, 0xd7, 0xaa, 0xd7, 0xa2,
106        0xd7, 0x91, 0xd7, 0x93, 0xd7, 0x95, 0xd7, 0x9f,
107        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Bitcoin block hash 0000000000000000000b1f8e1c17b0133d439174e52efbb0c41c3583a8aa66b0
108        0x00, 0x0b, 0x1f, 0x8e, 0x1c, 0x17, 0xb0, 0x13,
109        0x3d, 0x43, 0x91, 0x74, 0xe5, 0x2e, 0xfb, 0xb0,
110        0xc4, 0x1c, 0x35, 0x83, 0xa8, 0xaa, 0x66, 0xb0,
111        0x0f, 0xca, 0x37, 0xca, 0x66, 0x7c, 0x2d, 0x55, // Checkpoint block hash 0fca37ca667c2d550a6c4416dad9717e50927128c424fa4edbebc436ab13aeef
112        0x0a, 0x6c, 0x44, 0x16, 0xda, 0xd9, 0x71, 0x7e,
113        0x50, 0x92, 0x71, 0x28, 0xc4, 0x24, 0xfa, 0x4e,
114        0xdb, 0xeb, 0xc4, 0x36, 0xab, 0x13, 0xae, 0xef,
115    ],
116};
117
118pub const TESTNET_GENESIS: GenesisBlock = GenesisBlock {
119    hash: Hash::from_bytes([
120        0xf8, 0x96, 0xa3, 0x03, 0x48, 0x73, 0xbe, 0x17, 0x39, 0xfc, 0x43, 0x59, 0x23, 0x68, 0x99, 0xfd, 0x3d, 0x65, 0xd2, 0xbc, 0x94,
121        0xf9, 0x78, 0x0d, 0xf0, 0xd0, 0xda, 0x3e, 0xb1, 0xcc, 0x43, 0x70,
122    ]),
123    version: 0,
124    hash_merkle_root: Hash::from_bytes([
125        0x17, 0x34, 0x14, 0x08, 0xa5, 0x72, 0x45, 0x56, 0x50, 0x4d, 0xf4, 0xd6, 0xcf, 0x51, 0x5c, 0xbf, 0xbb, 0x22, 0x04, 0x30, 0xdc,
126        0x45, 0x1c, 0x74, 0x3c, 0x22, 0xd5, 0xe9, 0x11, 0x72, 0x0c, 0x2a,
127    ]),
128    utxo_commitment: EMPTY_MUHASH,
129    timestamp: 0x17c5f62fbb6,
130    bits: 0x1e7fffff,
131    nonce: 0x14582,
132    daa_score: 0,
133    #[rustfmt::skip]
134    coinbase_payload: &[
135        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
136        0x00, 0xE1, 0xF5, 0x05, 0x00, 0x00, 0x00, 0x00, // Subsidy
137        0x00, 0x00, // Script version
138        0x01,                                                                         // Varint
139        0x00,                                                                         // OP-FALSE
140        0x6b, 0x61, 0x73, 0x70, 0x61, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x6e, 0x65, 0x74, // kaspa-testnet
141    ],
142};
143
144pub const TESTNET11_GENESIS: GenesisBlock = GenesisBlock {
145    hash: Hash::from_bytes([
146        0xcf, 0xa2, 0xa7, 0xeb, 0xfb, 0x8b, 0x4e, 0xa3, 0x45, 0x30, 0x7b, 0xc2, 0x5e, 0xf9, 0x42, 0x1b, 0x23, 0x91, 0xf0, 0x9c, 0x8b,
147        0x2c, 0xf2, 0x15, 0xf0, 0x75, 0x60, 0xaf, 0x0d, 0x4d, 0x71, 0x64,
148    ]),
149    hash_merkle_root: Hash::from_bytes([
150        0x3c, 0x35, 0xdb, 0x98, 0x02, 0x7e, 0x84, 0x6e, 0x02, 0xcc, 0x60, 0xb7, 0xa7, 0xfa, 0xb1, 0x6d, 0x6c, 0xf2, 0xa5, 0x42, 0xd8,
151        0xe1, 0x60, 0xad, 0x9c, 0xd9, 0x08, 0x5f, 0x51, 0x0c, 0x47, 0xbb,
152    ]),
153    bits: 504155340, // see `gen_testnet11_genesis`
154    #[rustfmt::skip]
155    coinbase_payload: &[
156        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
157        0x00, 0xE1, 0xF5, 0x05, 0x00, 0x00, 0x00, 0x00, // Subsidy
158        0x00, 0x00, // Script version
159        0x01,                                                                         // Varint
160        0x00,                                                                         // OP-FALSE
161        0x6b, 0x61, 0x73, 0x70, 0x61, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x6e, 0x65, 0x74, // kaspa-testnet
162        11, 4                                                                         // TN11, Relaunch 4
163    ],
164    ..TESTNET_GENESIS
165};
166
167pub const SIMNET_GENESIS: GenesisBlock = GenesisBlock {
168    hash: Hash::from_bytes([
169        0x41, 0x1f, 0x8c, 0xd2, 0x6f, 0x3d, 0x41, 0xae, 0xa3, 0x9e, 0x78, 0x57, 0x39, 0x27, 0xda, 0x24, 0xd2, 0x39, 0x95, 0x70, 0x5b,
170        0x57, 0x9f, 0x30, 0x95, 0x9b, 0x91, 0x27, 0xe9, 0x6b, 0x79, 0xe3,
171    ]),
172    version: 0,
173    hash_merkle_root: Hash::from_bytes([
174        0x19, 0x46, 0xd6, 0x29, 0xf7, 0xe9, 0x22, 0xa7, 0xbc, 0xed, 0x59, 0x19, 0x05, 0x21, 0xc3, 0x77, 0x1f, 0x73, 0xd3, 0x52, 0xdd,
175        0xbb, 0xb6, 0x86, 0x56, 0x4a, 0xd7, 0xfd, 0x56, 0x85, 0x7c, 0x1b,
176    ]),
177    utxo_commitment: EMPTY_MUHASH,
178    timestamp: 0x17c5f62fbb6,
179    bits: 0x207fffff,
180    nonce: 0x2,
181    daa_score: 0,
182    #[rustfmt::skip]
183    coinbase_payload: &[
184        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
185        0x00, 0xE1, 0xF5, 0x05, 0x00, 0x00, 0x00, 0x00, // Subsidy
186        0x00, 0x00, // Script version
187        0x01,                                                                   // Varint
188        0x00,                                                                   // OP-FALSE
189        0x6b, 0x61, 0x73, 0x70, 0x61, 0x2d, 0x73, 0x69, 0x6d, 0x6e, 0x65, 0x74, // kaspa-simnet
190    ],
191};
192
193pub const DEVNET_GENESIS: GenesisBlock = GenesisBlock {
194    hash: Hash::from_bytes([
195        // Golang devnet genesis hash
196        // 0xb3, 0x13, 0x87, 0x0a, 0x32, 0xc7, 0x04, 0xbd, 0xf1, 0x21, 0x4a, 0x3b, 0x27, 0x0c, 0xc4, 0x75, 0xd9, 0x42, 0xc2, 0x09, 0x2d,
197        // 0x37, 0x9b, 0xc8, 0x70, 0x0a, 0xb0, 0x43, 0x31, 0x9e, 0xf8,
198        // 0x46,
199        // New rust devnet genesis hash updated according to the modified bits field (see below)
200        0x4c, 0xb4, 0x8d, 0x0b, 0x20, 0x73, 0xb8, 0x02, 0x36, 0x01, 0x45, 0xa1, 0x5a, 0xd1, 0xab, 0xdc, 0x01, 0xd8, 0x9b, 0x5c, 0x2f,
201        0xe4, 0x72, 0x26, 0x30, 0xab, 0x9b, 0x5f, 0xe9, 0xdf, 0xc4, 0xf2,
202    ]),
203    version: 0,
204    hash_merkle_root: Hash::from_bytes([
205        0x58, 0xab, 0xf2, 0x03, 0x21, 0xd7, 0x07, 0x16, 0x16, 0x2b, 0x6b, 0xf8, 0xd9, 0xf5, 0x89, 0xca, 0x33, 0xae, 0x6e, 0x32, 0xb3,
206        0xb1, 0x9a, 0xbb, 0x7f, 0xa6, 0x5d, 0x11, 0x41, 0xa3, 0xf9, 0x4d,
207    ]),
208    utxo_commitment: EMPTY_MUHASH,
209    timestamp: 0x11e9db49828,
210    // bits: 525264379, // Golang devnet genesis bits
211    bits: 0x1e21bc1c, // Bits with ~testnet-like difficulty for slow devnet start
212    nonce: 0x48e5e,
213    daa_score: 0,
214    #[rustfmt::skip]
215    coinbase_payload: &[
216        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Blue score
217        0x00, 0xE1, 0xF5, 0x05, 0x00, 0x00, 0x00, 0x00, // Subsidy
218        0x00, 0x00, // Script version
219        0x01,                                                                   // Varint
220        0x00,                                                                   // OP-FALSE
221        0x6b, 0x61, 0x73, 0x70, 0x61, 0x2d, 0x64, 0x65, 0x76, 0x6e, 0x65, 0x74, // kaspa-devnet
222    ],
223};
224
225#[cfg(test)]
226mod tests {
227    use super::*;
228    use crate::{config::bps::Testnet11Bps, merkle::calc_hash_merkle_root};
229
230    #[test]
231    fn test_genesis_hashes() {
232        [GENESIS, TESTNET_GENESIS, TESTNET11_GENESIS, SIMNET_GENESIS, DEVNET_GENESIS].into_iter().for_each(|genesis| {
233            let block: Block = (&genesis).into();
234            assert_hashes_eq(calc_hash_merkle_root(block.transactions.iter(), false), block.header.hash_merkle_root);
235            assert_hashes_eq(block.hash(), genesis.hash);
236        });
237    }
238
239    #[test]
240    fn gen_testnet11_genesis() {
241        let bps = Testnet11Bps::bps();
242        let mut genesis = TESTNET_GENESIS;
243        let target = kaspa_math::Uint256::from_compact_target_bits(genesis.bits);
244        let scaled_target = target * bps / 100;
245        let scaled_bits = scaled_target.compact_target_bits();
246        genesis.bits = scaled_bits;
247        if genesis.bits != TESTNET11_GENESIS.bits {
248            panic!("Testnet 11: new bits: {}\nnew hash: {:#04x?}", scaled_bits, Block::from(&genesis).hash().as_bytes());
249        }
250    }
251
252    fn assert_hashes_eq(got: Hash, expected: Hash) {
253        if got != expected {
254            // Special hex print to ease changing the genesis hash according to the print if needed
255            panic!("Got hash {:#04x?} while expecting {:#04x?}", got.as_bytes(), expected.as_bytes());
256        }
257    }
258}