1use std::{collections::HashMap, str::FromStr};
2
3use crate::{
4 types::{
5 serde_helpers::{
6 deserialize_stringified_eth_u64, deserialize_stringified_eth_u64_opt,
7 deserialize_stringified_numeric, deserialize_stringified_numeric_opt,
8 deserialize_stringified_u64_opt, Numeric,
9 },
10 Address, Bytes, H256, U256, U64,
11 },
12 utils::from_unformatted_hex_map,
13};
14use serde::{Deserialize, Serialize};
15
16#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
19#[serde(rename_all = "camelCase")]
20pub struct Genesis {
21 #[serde(default)]
23 pub config: ChainConfig,
24
25 #[serde(default, deserialize_with = "deserialize_stringified_eth_u64")]
27 pub nonce: U64,
28
29 #[serde(default, deserialize_with = "deserialize_stringified_eth_u64")]
31 pub timestamp: U64,
32
33 #[serde(default)]
35 pub extra_data: Bytes,
36
37 #[serde(default, deserialize_with = "deserialize_stringified_eth_u64")]
39 pub gas_limit: U64,
40
41 #[serde(deserialize_with = "deserialize_stringified_numeric")]
43 pub difficulty: U256,
44
45 #[serde(default)]
47 pub mix_hash: H256,
48
49 #[serde(default)]
51 pub coinbase: Address,
52
53 pub alloc: HashMap<Address, GenesisAccount>,
55
56 #[serde(
60 skip_serializing_if = "Option::is_none",
61 deserialize_with = "deserialize_stringified_eth_u64_opt",
62 default
63 )]
64 pub number: Option<U64>,
65
66 #[serde(
68 skip_serializing_if = "Option::is_none",
69 deserialize_with = "deserialize_stringified_eth_u64_opt",
70 default
71 )]
72 pub gas_used: Option<U64>,
73
74 #[serde(skip_serializing_if = "Option::is_none", default)]
76 pub parent_hash: Option<H256>,
77
78 #[serde(
80 skip_serializing_if = "Option::is_none",
81 deserialize_with = "deserialize_stringified_numeric_opt",
82 default
83 )]
84 pub base_fee_per_gas: Option<U256>,
85}
86
87impl Genesis {
88 pub fn new(chain_id: u64, signer_addr: Address) -> Genesis {
93 let clique_config = CliqueConfig { period: Some(0), epoch: Some(8) };
95
96 let config = ChainConfig {
97 chain_id,
98 eip155_block: Some(0),
99 eip150_block: Some(0),
100 eip158_block: Some(0),
101
102 homestead_block: Some(0),
103 byzantium_block: Some(0),
104 constantinople_block: Some(0),
105 petersburg_block: Some(0),
106 istanbul_block: Some(0),
107 muir_glacier_block: Some(0),
108 berlin_block: Some(0),
109 london_block: Some(0),
110 clique: Some(clique_config),
111 ..Default::default()
112 };
113
114 let mut alloc = HashMap::new();
116 alloc.insert(
117 signer_addr,
118 GenesisAccount { balance: U256::MAX, nonce: None, code: None, storage: None },
119 );
120
121 let extra_data_bytes = [&[0u8; 32][..], signer_addr.as_bytes(), &[0u8; 65][..]].concat();
131 let extra_data = Bytes::from(extra_data_bytes);
132
133 Genesis {
134 config,
135 alloc,
136 difficulty: U256::one(),
137 gas_limit: U64::from(5000000),
138 extra_data,
139 ..Default::default()
140 }
141 }
142}
143
144#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
146pub struct GenesisAccount {
147 #[serde(
148 skip_serializing_if = "Option::is_none",
149 deserialize_with = "deserialize_stringified_u64_opt",
150 default
151 )]
152 pub nonce: Option<u64>,
153 #[serde(deserialize_with = "deserialize_stringified_numeric")]
154 pub balance: U256,
155 #[serde(skip_serializing_if = "Option::is_none", default)]
156 pub code: Option<Bytes>,
157 #[serde(
158 skip_serializing_if = "Option::is_none",
159 deserialize_with = "from_unformatted_hex_map",
160 default
161 )]
162 pub storage: Option<HashMap<H256, H256>>,
163}
164
165#[derive(Clone, Debug, Deserialize, Serialize, Default, PartialEq, Eq)]
171#[serde(default, rename_all = "camelCase")]
172pub struct ChainConfig {
173 #[serde(default = "one")]
175 pub chain_id: u64,
176
177 #[serde(
179 skip_serializing_if = "Option::is_none",
180 deserialize_with = "deserialize_stringified_u64_opt"
181 )]
182 pub homestead_block: Option<u64>,
183
184 #[serde(
186 skip_serializing_if = "Option::is_none",
187 deserialize_with = "deserialize_stringified_u64_opt"
188 )]
189 pub dao_fork_block: Option<u64>,
190
191 pub dao_fork_support: bool,
193
194 #[serde(
196 skip_serializing_if = "Option::is_none",
197 deserialize_with = "deserialize_stringified_u64_opt"
198 )]
199 pub eip150_block: Option<u64>,
200
201 #[serde(skip_serializing_if = "Option::is_none")]
203 pub eip150_hash: Option<H256>,
204
205 #[serde(
207 skip_serializing_if = "Option::is_none",
208 deserialize_with = "deserialize_stringified_u64_opt"
209 )]
210 pub eip155_block: Option<u64>,
211
212 #[serde(
214 skip_serializing_if = "Option::is_none",
215 deserialize_with = "deserialize_stringified_u64_opt"
216 )]
217 pub eip158_block: Option<u64>,
218
219 #[serde(
221 skip_serializing_if = "Option::is_none",
222 deserialize_with = "deserialize_stringified_u64_opt"
223 )]
224 pub byzantium_block: Option<u64>,
225
226 #[serde(
228 skip_serializing_if = "Option::is_none",
229 deserialize_with = "deserialize_stringified_u64_opt"
230 )]
231 pub constantinople_block: Option<u64>,
232
233 #[serde(
235 skip_serializing_if = "Option::is_none",
236 deserialize_with = "deserialize_stringified_u64_opt"
237 )]
238 pub petersburg_block: Option<u64>,
239
240 #[serde(
242 skip_serializing_if = "Option::is_none",
243 deserialize_with = "deserialize_stringified_u64_opt"
244 )]
245 pub istanbul_block: Option<u64>,
246
247 #[serde(
249 skip_serializing_if = "Option::is_none",
250 deserialize_with = "deserialize_stringified_u64_opt"
251 )]
252 pub muir_glacier_block: Option<u64>,
253
254 #[serde(
256 skip_serializing_if = "Option::is_none",
257 deserialize_with = "deserialize_stringified_u64_opt"
258 )]
259 pub berlin_block: Option<u64>,
260
261 #[serde(
263 skip_serializing_if = "Option::is_none",
264 deserialize_with = "deserialize_stringified_u64_opt"
265 )]
266 pub london_block: Option<u64>,
267
268 #[serde(
270 skip_serializing_if = "Option::is_none",
271 deserialize_with = "deserialize_stringified_u64_opt"
272 )]
273 pub arrow_glacier_block: Option<u64>,
274
275 #[serde(
277 skip_serializing_if = "Option::is_none",
278 deserialize_with = "deserialize_stringified_u64_opt"
279 )]
280 pub gray_glacier_block: Option<u64>,
281
282 #[serde(
284 skip_serializing_if = "Option::is_none",
285 deserialize_with = "deserialize_stringified_u64_opt"
286 )]
287 pub merge_netsplit_block: Option<u64>,
288
289 #[serde(
291 skip_serializing_if = "Option::is_none",
292 deserialize_with = "deserialize_stringified_u64_opt"
293 )]
294 pub shanghai_time: Option<u64>,
295
296 #[serde(
298 skip_serializing_if = "Option::is_none",
299 deserialize_with = "deserialize_stringified_u64_opt"
300 )]
301 pub cancun_time: Option<u64>,
302
303 #[serde(skip_serializing_if = "Option::is_none", deserialize_with = "deserialize_ttd")]
305 pub terminal_total_difficulty: Option<U256>,
306
307 pub terminal_total_difficulty_passed: bool,
310
311 #[serde(skip_serializing_if = "Option::is_none")]
313 pub ethash: Option<EthashConfig>,
314
315 #[serde(skip_serializing_if = "Option::is_none")]
317 pub clique: Option<CliqueConfig>,
318}
319
320#[inline]
322const fn one() -> u64 {
323 1
324}
325
326#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
328pub struct EthashConfig {}
329
330#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
332pub struct CliqueConfig {
333 #[serde(
335 default,
336 skip_serializing_if = "Option::is_none",
337 deserialize_with = "deserialize_stringified_u64_opt"
338 )]
339 pub period: Option<u64>,
340
341 #[serde(
343 default,
344 skip_serializing_if = "Option::is_none",
345 deserialize_with = "deserialize_stringified_u64_opt"
346 )]
347 pub epoch: Option<u64>,
348}
349
350fn deserialize_ttd<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
351where
352 D: serde::Deserializer<'de>,
353{
354 match Option::<serde_json::Value>::deserialize(deserializer)? {
355 None => Ok(None),
356 Some(val) => {
357 if let Some(num) = val.as_str() {
358 return Numeric::from_str(num)
359 .map(U256::from)
360 .map(Some)
361 .map_err(serde::de::Error::custom)
362 }
363
364 if let serde_json::Value::Number(num) = val {
365 if num.as_f64() == Some(5.875e22) {
368 Ok(Some(U256::from(58750000000000000000000u128)))
369 } else {
370 num.as_u64()
371 .map(U256::from)
372 .ok_or_else(|| {
373 serde::de::Error::custom(format!("expected a number got {num}"))
374 })
375 .map(Some)
376 }
377 } else {
378 Err(serde::de::Error::custom(format!("expected a number, got {:?}", val)))
379 }
380 }
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::{ChainConfig, Genesis, GenesisAccount, H256};
387 use crate::{
388 types::{Address, Bytes, H160, U256},
389 utils::EthashConfig,
390 };
391 use std::{collections::HashMap, str::FromStr};
392
393 #[test]
394 fn parse_hive_genesis() {
395 let geth_genesis = r#"
396 {
397 "difficulty": "0x20000",
398 "gasLimit": "0x1",
399 "alloc": {},
400 "config": {
401 "ethash": {},
402 "chainId": 1
403 }
404 }
405 "#;
406
407 let _genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
408 }
409
410 #[test]
411 fn parse_hive_clique_smoke_genesis() {
412 let geth_genesis = r#"
413 {
414 "difficulty": "0x1",
415 "gasLimit": "0x400000",
416 "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
417 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
418 "nonce": "0x0",
419 "timestamp": "0x5c51a607",
420 "alloc": {}
421 }
422 "#;
423
424 let _genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
425 }
426
427 #[test]
428 fn parse_non_hex_prefixed_balance() {
429 let example_balance_json = r#"
431 {
432 "nonce": "0x0000000000000042",
433 "difficulty": "34747478",
434 "mixHash": "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234",
435 "coinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
436 "timestamp": "0x123456",
437 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
438 "extraData": "0xfafbfcfd",
439 "gasLimit": "0x2fefd8",
440 "alloc": {
441 "0x3E951C9f69a06Bc3AD71fF7358DbC56bEd94b9F2": {
442 "balance": "1000000000000000000000000000"
443 },
444 "0xe228C30d4e5245f967ac21726d5412dA27aD071C": {
445 "balance": "1000000000000000000000000000"
446 },
447 "0xD59Ce7Ccc6454a2D2C2e06bbcf71D0Beb33480eD": {
448 "balance": "1000000000000000000000000000"
449 },
450 "0x1CF4D54414eF51b41f9B2238c57102ab2e61D1F2": {
451 "balance": "1000000000000000000000000000"
452 },
453 "0x249bE3fDEd872338C733cF3975af9736bdCb9D4D": {
454 "balance": "1000000000000000000000000000"
455 },
456 "0x3fCd1bff94513712f8cD63d1eD66776A67D5F78e": {
457 "balance": "1000000000000000000000000000"
458 }
459 },
460 "config": {
461 "ethash": {},
462 "chainId": 10,
463 "homesteadBlock": 0,
464 "eip150Block": 0,
465 "eip155Block": 0,
466 "eip158Block": 0,
467 "byzantiumBlock": 0,
468 "constantinopleBlock": 0,
469 "petersburgBlock": 0,
470 "istanbulBlock": 0
471 }
472 }
473 "#;
474
475 let genesis: Genesis = serde_json::from_str(example_balance_json).unwrap();
476
477 let expected_difficulty = U256::from_str("0x2123456").unwrap();
479 assert_eq!(expected_difficulty, genesis.difficulty);
480
481 let dec_balance = U256::from_dec_str("1000000000000000000000000000").unwrap();
483 for alloc in &genesis.alloc {
484 assert_eq!(alloc.1.balance, dec_balance);
485 }
486 }
487
488 #[test]
489 fn parse_hive_rpc_genesis() {
490 let geth_genesis = r#"
491 {
492 "config": {
493 "chainId": 7,
494 "homesteadBlock": 0,
495 "eip150Block": 0,
496 "eip150Hash": "0x5de1ee4135274003348e80b788e5afa4b18b18d320a5622218d5c493fedf5689",
497 "eip155Block": 0,
498 "eip158Block": 0
499 },
500 "coinbase": "0x0000000000000000000000000000000000000000",
501 "difficulty": "0x20000",
502 "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
503 "gasLimit": "0x2fefd8",
504 "nonce": "0x0000000000000000",
505 "timestamp": "0x1234",
506 "alloc": {
507 "cf49fda3be353c69b41ed96333cd24302da4556f": {
508 "balance": "0x123450000000000000000"
509 },
510 "0161e041aad467a890839d5b08b138c1e6373072": {
511 "balance": "0x123450000000000000000"
512 },
513 "87da6a8c6e9eff15d703fc2773e32f6af8dbe301": {
514 "balance": "0x123450000000000000000"
515 },
516 "b97de4b8c857e4f6bc354f226dc3249aaee49209": {
517 "balance": "0x123450000000000000000"
518 },
519 "c5065c9eeebe6df2c2284d046bfc906501846c51": {
520 "balance": "0x123450000000000000000"
521 },
522 "0000000000000000000000000000000000000314": {
523 "balance": "0x0",
524 "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
525 "storage": {
526 "0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234",
527 "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01"
528 }
529 },
530 "0000000000000000000000000000000000000315": {
531 "balance": "0x9999999999999999999999999999999",
532 "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029"
533 }
534 }
535 }
536 "#;
537
538 let _genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
539 }
540
541 #[test]
542 fn parse_hive_graphql_genesis() {
543 let geth_genesis = r#"
544 {
545 "config" : {},
546 "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1",
547 "difficulty" : "0x020000",
548 "extraData" : "0x42",
549 "gasLimit" : "0x2fefd8",
550 "mixHash" : "0x2c85bcbce56429100b2108254bb56906257582aeafcbd682bc9af67a9f5aee46",
551 "nonce" : "0x78cc16f7b4f65485",
552 "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
553 "timestamp" : "0x54c98c81",
554 "alloc" : {
555 "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
556 "balance" : "0x09184e72a000"
557 }
558 }
559 }
560 "#;
561
562 let _genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
563 }
564
565 #[test]
566 fn parse_hive_engine_genesis() {
567 let geth_genesis = r#"
568 {
569 "config": {
570 "chainId": 7,
571 "homesteadBlock": 0,
572 "eip150Block": 0,
573 "eip150Hash": "0x5de1ee4135274003348e80b788e5afa4b18b18d320a5622218d5c493fedf5689",
574 "eip155Block": 0,
575 "eip158Block": 0,
576 "byzantiumBlock": 0,
577 "constantinopleBlock": 0,
578 "petersburgBlock": 0,
579 "istanbulBlock": 0,
580 "muirGlacierBlock": 0,
581 "berlinBlock": 0,
582 "yolov2Block": 0,
583 "yolov3Block": 0,
584 "londonBlock": 0
585 },
586 "coinbase": "0x0000000000000000000000000000000000000000",
587 "difficulty": "0x30000",
588 "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
589 "gasLimit": "0x2fefd8",
590 "nonce": "0x0000000000000000",
591 "timestamp": "0x1234",
592 "alloc": {
593 "cf49fda3be353c69b41ed96333cd24302da4556f": {
594 "balance": "0x123450000000000000000"
595 },
596 "0161e041aad467a890839d5b08b138c1e6373072": {
597 "balance": "0x123450000000000000000"
598 },
599 "87da6a8c6e9eff15d703fc2773e32f6af8dbe301": {
600 "balance": "0x123450000000000000000"
601 },
602 "b97de4b8c857e4f6bc354f226dc3249aaee49209": {
603 "balance": "0x123450000000000000000"
604 },
605 "c5065c9eeebe6df2c2284d046bfc906501846c51": {
606 "balance": "0x123450000000000000000"
607 },
608 "0000000000000000000000000000000000000314": {
609 "balance": "0x0",
610 "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
611 "storage": {
612 "0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234",
613 "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01"
614 }
615 },
616 "0000000000000000000000000000000000000315": {
617 "balance": "0x9999999999999999999999999999999",
618 "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029"
619 },
620 "0000000000000000000000000000000000000316": {
621 "balance": "0x0",
622 "code": "0x444355"
623 },
624 "0000000000000000000000000000000000000317": {
625 "balance": "0x0",
626 "code": "0x600160003555"
627 }
628 }
629 }
630 "#;
631
632 let _genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
633 }
634
635 #[test]
636 fn parse_hive_devp2p_genesis() {
637 let geth_genesis = r#"
638 {
639 "config": {
640 "chainId": 19763,
641 "homesteadBlock": 0,
642 "eip150Block": 0,
643 "eip155Block": 0,
644 "eip158Block": 0,
645 "byzantiumBlock": 0,
646 "ethash": {}
647 },
648 "nonce": "0xdeadbeefdeadbeef",
649 "timestamp": "0x0",
650 "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
651 "gasLimit": "0x80000000",
652 "difficulty": "0x20000",
653 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
654 "coinbase": "0x0000000000000000000000000000000000000000",
655 "alloc": {
656 "71562b71999873db5b286df957af199ec94617f7": {
657 "balance": "0xffffffffffffffffffffffffff"
658 }
659 },
660 "number": "0x0",
661 "gasUsed": "0x0",
662 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
663 }
664 "#;
665
666 let _genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
667 }
668
669 #[test]
670 fn parse_execution_apis_genesis() {
671 let geth_genesis = r#"
672 {
673 "config": {
674 "chainId": 1337,
675 "homesteadBlock": 0,
676 "eip150Block": 0,
677 "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
678 "eip155Block": 0,
679 "eip158Block": 0,
680 "byzantiumBlock": 0,
681 "constantinopleBlock": 0,
682 "petersburgBlock": 0,
683 "istanbulBlock": 0,
684 "muirGlacierBlock": 0,
685 "berlinBlock": 0,
686 "londonBlock": 0,
687 "arrowGlacierBlock": 0,
688 "grayGlacierBlock": 0,
689 "shanghaiTime": 0,
690 "terminalTotalDifficulty": 0,
691 "terminalTotalDifficultyPassed": true,
692 "ethash": {}
693 },
694 "nonce": "0x0",
695 "timestamp": "0x0",
696 "extraData": "0x",
697 "gasLimit": "0x4c4b40",
698 "difficulty": "0x1",
699 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
700 "coinbase": "0x0000000000000000000000000000000000000000",
701 "alloc": {
702 "658bdf435d810c91414ec09147daa6db62406379": {
703 "balance": "0x487a9a304539440000"
704 },
705 "aa00000000000000000000000000000000000000": {
706 "code": "0x6042",
707 "storage": {
708 "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000",
709 "0x0100000000000000000000000000000000000000000000000000000000000000": "0x0100000000000000000000000000000000000000000000000000000000000000",
710 "0x0200000000000000000000000000000000000000000000000000000000000000": "0x0200000000000000000000000000000000000000000000000000000000000000",
711 "0x0300000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000303"
712 },
713 "balance": "0x1",
714 "nonce": "0x1"
715 },
716 "bb00000000000000000000000000000000000000": {
717 "code": "0x600154600354",
718 "storage": {
719 "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000000",
720 "0x0100000000000000000000000000000000000000000000000000000000000000": "0x0100000000000000000000000000000000000000000000000000000000000000",
721 "0x0200000000000000000000000000000000000000000000000000000000000000": "0x0200000000000000000000000000000000000000000000000000000000000000",
722 "0x0300000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000303"
723 },
724 "balance": "0x2",
725 "nonce": "0x1"
726 }
727 },
728 "number": "0x0",
729 "gasUsed": "0x0",
730 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
731 "baseFeePerGas": "0x3b9aca00"
732 }
733 "#;
734
735 let genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
736
737 assert_eq!(genesis.base_fee_per_gas, Some(1000000000.into()));
739 assert_eq!(genesis.number, Some(0.into()));
740 assert_eq!(genesis.gas_used, Some(0.into()));
741 assert_eq!(genesis.parent_hash, Some(H256::zero()));
742 }
743
744 #[test]
745 fn parse_hive_rpc_genesis_full() {
746 let geth_genesis = r#"
747 {
748 "config": {
749 "clique": {
750 "period": 1
751 },
752 "chainId": 7,
753 "homesteadBlock": 0,
754 "eip150Block": 0,
755 "eip155Block": 0,
756 "eip158Block": 0
757 },
758 "coinbase": "0x0000000000000000000000000000000000000000",
759 "difficulty": "0x020000",
760 "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
761 "gasLimit": "0x2fefd8",
762 "nonce": "0x0000000000000000",
763 "timestamp": "0x1234",
764 "alloc": {
765 "cf49fda3be353c69b41ed96333cd24302da4556f": {
766 "balance": "0x123450000000000000000"
767 },
768 "0161e041aad467a890839d5b08b138c1e6373072": {
769 "balance": "0x123450000000000000000"
770 },
771 "87da6a8c6e9eff15d703fc2773e32f6af8dbe301": {
772 "balance": "0x123450000000000000000"
773 },
774 "b97de4b8c857e4f6bc354f226dc3249aaee49209": {
775 "balance": "0x123450000000000000000"
776 },
777 "c5065c9eeebe6df2c2284d046bfc906501846c51": {
778 "balance": "0x123450000000000000000"
779 },
780 "0000000000000000000000000000000000000314": {
781 "balance": "0x0",
782 "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029",
783 "storage": {
784 "0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234",
785 "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01"
786 }
787 },
788 "0000000000000000000000000000000000000315": {
789 "balance": "0x9999999999999999999999999999999",
790 "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029"
791 }
792 },
793 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
794 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
795 }
796 "#;
797
798 let genesis: Genesis = serde_json::from_str(geth_genesis).unwrap();
799 let alloc_entry = genesis
800 .alloc
801 .get(&H160::from_str("0000000000000000000000000000000000000314").unwrap())
802 .expect("missing account for parsed genesis");
803 let storage = alloc_entry.storage.as_ref().expect("missing storage for parsed genesis");
804 let expected_storage = HashMap::from_iter(vec![
805 (
806 H256::from_str(
807 "0x0000000000000000000000000000000000000000000000000000000000000000",
808 )
809 .unwrap(),
810 H256::from_str(
811 "0x0000000000000000000000000000000000000000000000000000000000001234",
812 )
813 .unwrap(),
814 ),
815 (
816 H256::from_str(
817 "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9",
818 )
819 .unwrap(),
820 H256::from_str(
821 "0x0000000000000000000000000000000000000000000000000000000000000001",
822 )
823 .unwrap(),
824 ),
825 ]);
826 assert_eq!(storage, &expected_storage);
827
828 let expected_code = Bytes::from_str("0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029").unwrap();
829 let code = alloc_entry.code.as_ref().expect("missing code for parsed genesis");
830 assert_eq!(code, &expected_code);
831 }
832
833 #[test]
834 fn test_hive_smoke_alloc_deserialize() {
835 let hive_genesis = r#"
836 {
837 "nonce": "0x0000000000000042",
838 "difficulty": "0x2123456",
839 "mixHash": "0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234",
840 "coinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
841 "timestamp": "0x123456",
842 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
843 "extraData": "0xfafbfcfd",
844 "gasLimit": "0x2fefd8",
845 "alloc": {
846 "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": {
847 "balance": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
848 },
849 "e6716f9544a56c530d868e4bfbacb172315bdead": {
850 "balance": "0x11",
851 "code": "0x12"
852 },
853 "b9c015918bdaba24b4ff057a92a3873d6eb201be": {
854 "balance": "0x21",
855 "storage": {
856 "0x0000000000000000000000000000000000000000000000000000000000000001": "0x22"
857 }
858 },
859 "1a26338f0d905e295fccb71fa9ea849ffa12aaf4": {
860 "balance": "0x31",
861 "nonce": "0x32"
862 },
863 "0000000000000000000000000000000000000001": {
864 "balance": "0x41"
865 },
866 "0000000000000000000000000000000000000002": {
867 "balance": "0x51"
868 },
869 "0000000000000000000000000000000000000003": {
870 "balance": "0x61"
871 },
872 "0000000000000000000000000000000000000004": {
873 "balance": "0x71"
874 }
875 },
876 "config": {
877 "ethash": {},
878 "chainId": 10,
879 "homesteadBlock": 0,
880 "eip150Block": 0,
881 "eip155Block": 0,
882 "eip158Block": 0,
883 "byzantiumBlock": 0,
884 "constantinopleBlock": 0,
885 "petersburgBlock": 0,
886 "istanbulBlock": 0
887 }
888 }
889 "#;
890
891 let expected_genesis = Genesis {
892 nonce: 0x0000000000000042.into(),
893 difficulty: 0x2123456.into(),
894 mix_hash: H256::from_str("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234").unwrap(),
895 coinbase: Address::from_str("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(),
896 timestamp: 0x123456.into(),
897 parent_hash: Some(H256::from_str("0x0000000000000000000000000000000000000000000000000000000000000000").unwrap()),
898 extra_data: Bytes::from_str("0xfafbfcfd").unwrap(),
899 gas_limit: 0x2fefd8.into(),
900 alloc: HashMap::from_iter(vec![
901 (
902 Address::from_str("0xdbdbdb2cbd23b783741e8d7fcf51e459b497e4a6").unwrap(),
903 GenesisAccount {
904 balance: U256::from_str("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(),
905 nonce: None,
906 code: None,
907 storage: None,
908 },
909 ),
910 (
911 Address::from_str("0xe6716f9544a56c530d868e4bfbacb172315bdead").unwrap(),
912 GenesisAccount {
913 balance: U256::from_str("0x11").unwrap(),
914 nonce: None,
915 code: Some(Bytes::from_str("0x12").unwrap()),
916 storage: None,
917 },
918 ),
919 (
920 Address::from_str("0xb9c015918bdaba24b4ff057a92a3873d6eb201be").unwrap(),
921 GenesisAccount {
922 balance: U256::from_str("0x21").unwrap(),
923 nonce: None,
924 code: None,
925 storage: Some(HashMap::from_iter(vec![
926 (
927 H256::from_str("0x0000000000000000000000000000000000000000000000000000000000000001").unwrap(),
928 H256::from_str("0x0000000000000000000000000000000000000000000000000000000000000022").unwrap(),
929 ),
930 ])),
931 },
932 ),
933 (
934 Address::from_str("0x1a26338f0d905e295fccb71fa9ea849ffa12aaf4").unwrap(),
935 GenesisAccount {
936 balance: U256::from_str("0x31").unwrap(),
937 nonce: Some(0x32u64),
938 code: None,
939 storage: None,
940 },
941 ),
942 (
943 Address::from_str("0x0000000000000000000000000000000000000001").unwrap(),
944 GenesisAccount {
945 balance: U256::from_str("0x41").unwrap(),
946 nonce: None,
947 code: None,
948 storage: None,
949 },
950 ),
951 (
952 Address::from_str("0x0000000000000000000000000000000000000002").unwrap(),
953 GenesisAccount {
954 balance: U256::from_str("0x51").unwrap(),
955 nonce: None,
956 code: None,
957 storage: None,
958 },
959 ),
960 (
961 Address::from_str("0x0000000000000000000000000000000000000003").unwrap(),
962 GenesisAccount {
963 balance: U256::from_str("0x61").unwrap(),
964 nonce: None,
965 code: None,
966 storage: None,
967 },
968 ),
969 (
970 Address::from_str("0x0000000000000000000000000000000000000004").unwrap(),
971 GenesisAccount {
972 balance: U256::from_str("0x71").unwrap(),
973 nonce: None,
974 code: None,
975 storage: None,
976 },
977 ),
978 ]),
979 config: ChainConfig {
980 ethash: Some(EthashConfig{}),
981 chain_id: 10,
982 homestead_block: Some(0),
983 eip150_block: Some(0),
984 eip155_block: Some(0),
985 eip158_block: Some(0),
986 byzantium_block: Some(0),
987 constantinople_block: Some(0),
988 petersburg_block: Some(0),
989 istanbul_block: Some(0),
990 ..Default::default()
991 },
992 ..Default::default()
993 };
994
995 let deserialized_genesis: Genesis = serde_json::from_str(hive_genesis).unwrap();
996 assert_eq!(deserialized_genesis, expected_genesis, "deserialized genesis {deserialized_genesis:#?} does not match expected {expected_genesis:#?}");
997 }
998}