From 3712a1b4c0338a28c77df0f83d923fdb3cc311ba Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 22 Sep 2022 16:35:13 +0530 Subject: [PATCH] common: Relocate geth genesis, state parsers to common, blockchain respectively (#2300) * common: Relocate geth genesis, state parsers to common, blockchain respectively * lint utils * relocate setForkHashes * update readme * use Common.fromGethGenesis wherever possible * relocate parseGethGenesis tests * remove unnecessary await * fix tests access across common and client * provide abs path * add test for parseGethGenesisState * add test cases for setcommon hashes and correct kiln genesis root * add stateroot match test * fix the storage trie to also use key hashing --- packages/blockchain/README.md | 19 +- .../blockchain/src/genesisStates/index.ts | 2 +- packages/blockchain/src/index.ts | 1 + packages/blockchain/src/utils.ts | 19 + .../test/testdata/geth-genesis-kiln.json | 865 ++++++++++++++++++ packages/blockchain/test/utils.spec.ts | 43 + packages/client/bin/cli.ts | 28 +- packages/client/lib/util/parse.ts | 172 ---- .../test/integration/beaconsync.spec.ts | 7 +- packages/client/test/rpc/helpers.ts | 15 +- .../test/rpc/util/CLConnectionManager.spec.ts | 5 +- .../test/service/fullethereumservice.spec.ts | 4 +- packages/client/test/sync/skeleton.spec.ts | 26 +- packages/client/test/util/parse.spec.ts | 54 +- packages/common/README.md | 16 + packages/common/src/common.ts | 41 + packages/common/src/index.ts | 1 + packages/common/src/types.ts | 6 + packages/common/src/utils.ts | 131 +++ packages/common/tests/utils.spec.ts | 89 ++ 20 files changed, 1252 insertions(+), 292 deletions(-) create mode 100644 packages/blockchain/src/utils.ts create mode 100644 packages/blockchain/test/testdata/geth-genesis-kiln.json create mode 100644 packages/blockchain/test/utils.spec.ts create mode 100644 packages/common/src/utils.ts create mode 100644 packages/common/tests/utils.spec.ts diff --git a/packages/blockchain/README.md b/packages/blockchain/README.md index 85adf3b402..22228aa0bf 100644 --- a/packages/blockchain/README.md +++ b/packages/blockchain/README.md @@ -79,7 +79,24 @@ Starting with v6 responsibility for setting up a custom genesis state moved from A genesis state can be set along `Blockchain` creation by passing in a custom `genesisBlock` and `genesisState`. For `mainnet` and the official test networks like `sepolia` or `goerli` genesis is already provided with the block data coming from `@ethereumjs/common`. The genesis state is being integrated in the `Blockchain` library (see `genesisStates` folder). -TODO: add code example here! +### Custom genesis from a Geth genesis config + +For many custom chains we might come across a genesis configuration, which can be used to build both chain config as well the genesis state (and hence the genesis block as well to start off with) + +```typescript +import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' +import { Common, parseGethGenesis } from '@ethereumjs/common' + +// Load geth genesis json file into lets say `gethGenesisJson` +const common = Common.fromGethGenesis(gethGenesisJson, { chain: 'customChain' }) +const genesisState = parseGethGenesisState(gethGenesisJson) +const blockchain = await Blockchain.create({ + genesisState, + common, +}) +const genesisBlockHash = blockchain.genesisBlock.hash() +common.setForkHashes(genesisBlockHash) +``` The genesis block from the initialized `Blockchain` can be retrieved via the `Blockchain.genesisBlock` getter. For creating a genesis block from the params in `@ethereumjs/common`, the `createGenesisBlock(stateRoot: Buffer): Block` method can be used. diff --git a/packages/blockchain/src/genesisStates/index.ts b/packages/blockchain/src/genesisStates/index.ts index 9fb15880e7..9a00414fa8 100644 --- a/packages/blockchain/src/genesisStates/index.ts +++ b/packages/blockchain/src/genesisStates/index.ts @@ -36,7 +36,7 @@ export async function genesisStateRoot(genesisState: GenesisState) { account.codeHash = Buffer.from(keccak256(toBuffer(code))) } if (storage !== undefined) { - const storageTrie = new Trie() + const storageTrie = new Trie({ useKeyHashing: true }) for (const [k, val] of storage) { const storageKey = isHexPrefixed(k) ? toBuffer(k) : Buffer.from(k, 'hex') const storageVal = Buffer.from( diff --git a/packages/blockchain/src/index.ts b/packages/blockchain/src/index.ts index 47200eef2f..22d6c56397 100644 --- a/packages/blockchain/src/index.ts +++ b/packages/blockchain/src/index.ts @@ -1,3 +1,4 @@ export { Blockchain } from './blockchain' export { CasperConsensus, CliqueConsensus, Consensus, EthashConsensus } from './consensus' export { BlockchainInterface, BlockchainOptions } from './types' +export * from './utils' diff --git a/packages/blockchain/src/utils.ts b/packages/blockchain/src/utils.ts new file mode 100644 index 0000000000..85b0bb7f0f --- /dev/null +++ b/packages/blockchain/src/utils.ts @@ -0,0 +1,19 @@ +import { addHexPrefix, bigIntToHex, isHexPrefixed } from '@ethereumjs/util' + +import type { GenesisState } from './genesisStates' +/** + * Parses the geth genesis state into Blockchain {@link GenesisState} + * @param json representing the `alloc` key in a Geth genesis file + */ +export function parseGethGenesisState(json: any) { + const state: GenesisState = {} + for (let address of Object.keys(json.alloc)) { + let { balance, code, storage } = json.alloc[address] + address = addHexPrefix(address) + balance = isHexPrefixed(balance) ? balance : bigIntToHex(BigInt(balance)) + code = code !== undefined ? addHexPrefix(code) : undefined + storage = storage !== undefined ? Object.entries(storage) : undefined + state[address] = [balance, code, storage] as any + } + return state +} diff --git a/packages/blockchain/test/testdata/geth-genesis-kiln.json b/packages/blockchain/test/testdata/geth-genesis-kiln.json new file mode 100644 index 0000000000..6d99cf2355 --- /dev/null +++ b/packages/blockchain/test/testdata/geth-genesis-kiln.json @@ -0,0 +1,865 @@ +{ + "config": { + "chainId": 1337802, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "mergeForkBlock": 1000, + "terminalTotalDifficulty": 20000000000000 + }, + "alloc": { + "0x0000000000000000000000000000000000000000": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000001": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000002": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000003": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000004": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000005": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000006": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000007": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000008": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000009": { + "balance": "1" + }, + "0x000000000000000000000000000000000000000a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000000b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000000c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000000d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000000e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000000f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000010": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000011": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000012": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000013": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000014": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000015": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000016": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000017": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000018": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000019": { + "balance": "1" + }, + "0x000000000000000000000000000000000000001a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000001b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000001c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000001d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000001e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000001f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000020": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000021": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000022": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000023": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000024": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000025": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000026": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000027": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000028": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000029": { + "balance": "1" + }, + "0x000000000000000000000000000000000000002a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000002b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000002c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000002d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000002e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000002f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000030": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000031": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000032": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000033": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000034": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000035": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000036": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000037": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000038": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000039": { + "balance": "1" + }, + "0x000000000000000000000000000000000000003a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000003b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000003c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000003d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000003e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000003f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000040": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000041": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000042": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000043": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000044": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000045": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000046": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000047": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000048": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000049": { + "balance": "1" + }, + "0x000000000000000000000000000000000000004a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000004b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000004c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000004d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000004e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000004f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000050": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000051": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000052": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000053": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000054": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000055": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000056": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000057": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000058": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000059": { + "balance": "1" + }, + "0x000000000000000000000000000000000000005a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000005b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000005c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000005d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000005e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000005f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000060": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000061": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000062": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000063": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000064": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000065": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000066": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000067": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000068": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000069": { + "balance": "1" + }, + "0x000000000000000000000000000000000000006a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000006b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000006c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000006d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000006e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000006f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000070": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000071": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000072": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000073": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000074": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000075": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000076": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000077": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000078": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000079": { + "balance": "1" + }, + "0x000000000000000000000000000000000000007a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000007b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000007c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000007d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000007e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000007f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000080": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000081": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000082": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000083": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000084": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000085": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000086": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000087": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000088": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000089": { + "balance": "1" + }, + "0x000000000000000000000000000000000000008a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000008b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000008c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000008d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000008e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000008f": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000090": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000091": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000092": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000093": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000094": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000095": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000096": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000097": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000098": { + "balance": "1" + }, + "0x0000000000000000000000000000000000000099": { + "balance": "1" + }, + "0x000000000000000000000000000000000000009a": { + "balance": "1" + }, + "0x000000000000000000000000000000000000009b": { + "balance": "1" + }, + "0x000000000000000000000000000000000000009c": { + "balance": "1" + }, + "0x000000000000000000000000000000000000009d": { + "balance": "1" + }, + "0x000000000000000000000000000000000000009e": { + "balance": "1" + }, + "0x000000000000000000000000000000000000009f": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a0": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a1": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a2": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a3": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a4": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a5": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a6": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a7": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a8": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000a9": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000aa": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ab": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ac": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ad": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ae": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000af": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b0": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b1": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b2": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b3": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b4": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b5": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b6": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b7": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b8": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000b9": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ba": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000bb": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000bc": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000bd": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000be": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000bf": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c0": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c1": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c2": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c3": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c4": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c5": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c6": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c7": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c8": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000c9": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ca": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000cb": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000cc": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000cd": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ce": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000cf": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d0": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d1": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d2": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d3": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d4": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d5": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d6": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d7": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d8": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000d9": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000da": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000db": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000dc": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000dd": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000de": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000df": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e0": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e1": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e2": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e3": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e4": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e5": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e6": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e7": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e8": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000e9": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ea": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000eb": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ec": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ed": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ee": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ef": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f0": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f1": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f2": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f3": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f4": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f5": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f6": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f7": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f8": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000f9": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000fa": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000fb": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000fc": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000fd": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000fe": { + "balance": "1" + }, + "0x00000000000000000000000000000000000000ff": { + "balance": "1" + }, + "0x4242424242424242424242424242424242424242": { + "balance": "0", + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" + } + }, + "0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134": { + "balance": "10000000000000000000000000" + }, + "0x2cA5F489CC1Fd1CEC24747B64E8dE0F4A6A850E1": { + "balance": "10000000000000000000000000" + }, + "0x7203bd333a874D9d329050ecE393820fCD501eaA": { + "balance": "10000000000000000000000000" + }, + "0xA51918aA40D78Ff8be939bf0E8404252875c6aDF": { + "balance": "10000000000000000000000000" + }, + "0xAA81078e6b2121dd7A846690DFdD6b10d7658d8B": { + "balance": "10000000000000000000000000" + }, + "0xFA2d31D8f21c1D1633E9BEB641dF77D21D63ccDd": { + "balance": "10000000000000000000000000" + }, + "0xf751C9c6d60614226fE57D2cAD6e10C856a2ddA3": { + "balance": "10000000000000000000000000" + }, + "0x9cD16887f6A808AEaa65D3c840f059EeA4ca1319": { + "balance": "10000000000000000000000000" + }, + "0x2E07043584F11BFF0AC39c927665DF6c6ebaffFB": { + "balance": "10000000000000000000000000" + }, + "0x60e771E5eCA8E26690920de669520Da210D64A9B": { + "balance": "10000000000000000000000000" + }, + "0xFC4db92C2Cf77CE02fBfd7Da0346d2CbFA66aD59": { + "balance": "10000000000000000000000000" + } + }, + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x01", + "extraData": "", + "gasLimit": "0x400000", + "nonce": "0x1234", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0" +} diff --git a/packages/blockchain/test/utils.spec.ts b/packages/blockchain/test/utils.spec.ts new file mode 100644 index 0000000000..9f23ff3cd0 --- /dev/null +++ b/packages/blockchain/test/utils.spec.ts @@ -0,0 +1,43 @@ +import { Common } from '@ethereumjs/common' +import * as tape from 'tape' + +import { Blockchain } from '../src/blockchain' +import { genesisStateRoot } from '../src/genesisStates' +import { parseGethGenesisState } from '../src/utils' + +async function getBlockchain(gethGenesis: any): Promise { + const common = Common.fromGethGenesis(gethGenesis, { chain: 'kiln' }) + const genesisState = parseGethGenesisState(gethGenesis) + const blockchain = await Blockchain.create({ + genesisState, + common, + }) + return blockchain +} + +tape('[Utils/Parse]', (t) => { + t.test('should properly parse gensis state from gethGenesis', async (t) => { + // kiln genesis with deposit contract storage set + const json = require(`./testdata/geth-genesis-kiln.json`) + const genesisState = parseGethGenesisState(json) + const stateRoot = await genesisStateRoot(genesisState) + t.equal( + stateRoot.toString('hex'), + '52e628c7f35996ba5a0402d02b34535993c89ff7fc4c430b2763ada8554bee62', + 'kiln stateRoot matches' + ) + }) + + t.test('should initialize blockchain from gethGenesis', async (t) => { + // kiln genesis with deposit contract storage set + const json = require(`./testdata/geth-genesis-kiln.json`) + const blockchain = await getBlockchain(json) + const genesisHash = blockchain.genesisBlock.hash() + + t.equal( + genesisHash.toString('hex'), + '51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8', + 'kiln genesis hash matches' + ) + }) +}) diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index df90c296ed..5c078a908d 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node -import { Blockchain } from '@ethereumjs/blockchain' +import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' import { Chain, Common, ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' import { Address, toBuffer } from '@ethereumjs/util' import { randomBytes } from 'crypto' @@ -14,12 +14,7 @@ import * as readline from 'readline' import { EthereumClient } from '../lib/client' import { Config, DataDirectory, SyncMode } from '../lib/config' import { getLogger } from '../lib/logging' -import { - parseCustomParams, - parseGenesisState, - parseMultiaddrs, - setCommonForkHashes, -} from '../lib/util' +import { parseMultiaddrs } from '../lib/util' import { helprpc, startRPCServers } from './startRpc' @@ -389,7 +384,7 @@ async function startClient(config: Config, customGenesisState?: GenesisState) { validateBlocks: true, validateConsensus, }) - setCommonForkHashes(config.chainCommon, blockchain.genesisBlock.hash()) + config.chainCommon.setForkHashes(blockchain.genesisBlock.hash()) } const client = new EthereumClient({ @@ -462,13 +457,8 @@ async function setupDevnet(prefundAddress: Address) { extraData, alloc: { [addr]: { balance: '0x10000000000000000000' } }, } - const chainParams = await parseCustomParams(chainData, 'devnet') - const customGenesisState = await parseGenesisState(chainData) - const common = new Common({ - chain: 'devnet', - customChains: [chainParams], - hardfork: Hardfork.London, - }) + const common = Common.fromGethGenesis(chainData, { chain: 'devnet', hardfork: Hardfork.London }) + const customGenesisState = parseGethGenesisState(chainData) return { common, customGenesisState } } @@ -617,12 +607,8 @@ async function run() { // Use geth genesis parameters file if specified const genesisFile = JSON.parse(readFileSync(args.gethGenesis, 'utf-8')) const chainName = path.parse(args.gethGenesis).base.split('.')[0] - const genesisParams = await parseCustomParams(genesisFile, chainName) - common = new Common({ - chain: genesisParams.name, - customChains: [genesisParams], - }) - customGenesisState = await parseGenesisState(genesisFile) + common = Common.fromGethGenesis(genesisFile, { chain: chainName }) + customGenesisState = parseGethGenesisState(genesisFile) } if (args.mine === true && accounts.length === 0) { diff --git a/packages/client/lib/util/parse.ts b/packages/client/lib/util/parse.ts index 91f8190273..856cf17755 100644 --- a/packages/client/lib/util/parse.ts +++ b/packages/client/lib/util/parse.ts @@ -1,17 +1,7 @@ -import { Hardfork } from '@ethereumjs/common' -import { - addHexPrefix, - bigIntToHex, - intToHex, - isHexPrefixed, - stripHexPrefix, -} from '@ethereumjs/util' import { Multiaddr, multiaddr } from 'multiaddr' import { URL } from 'url' import type { MultiaddrLike } from '../types' -import type { GenesisState } from '@ethereumjs/blockchain/dist/genesisStates' -import type { Common } from '@ethereumjs/common' /** * Parses multiaddrs and bootnodes to multiaddr format. @@ -80,151 +70,6 @@ export function parseTransports(transports: string[]) { }) } -/** - * Transforms Geth formatted nonce (i.e. hex string) to 8 byte 0x-prefixed string used internally - * @param nonce string parsed from the Geth genesis file - * @returns nonce as a 0x-prefixed 8 byte string - */ -function formatNonce(nonce: string): string { - if (!nonce || nonce === '0x0') { - return '0x0000000000000000' - } - if (isHexPrefixed(nonce)) { - return '0x' + stripHexPrefix(nonce).padStart(16, '0') - } - return '0x' + nonce.padStart(16, '0') -} - -/** - * Converts Geth genesis parameters to an EthereumJS compatible `CommonOpts` object - * @param json object representing the Geth genesis file - * @returns genesis parameters in a `CommonOpts` compliant object - */ -async function parseGethParams(json: any) { - const { name, config, difficulty, mixHash, gasLimit, coinbase, baseFeePerGas } = json - let { extraData, timestamp, nonce } = json - const { chainId } = config - - // geth is not strictly putting empty fields with a 0x prefix - if (extraData === '') { - extraData = '0x' - } - // geth may use number for timestamp - if (!isHexPrefixed(timestamp)) { - timestamp = intToHex(parseInt(timestamp)) - } - // geth may not give us a nonce strictly formatted to an 8 byte hex string - if (nonce.length !== 18) { - nonce = formatNonce(nonce) - } - - // EIP155 and EIP158 are both part of Spurious Dragon hardfork and must occur at the same time - // but have different configuration parameters in geth genesis parameters - if (config.eip155Block !== config.eip158Block) { - throw new Error( - 'EIP155 block number must equal EIP 158 block number since both are part of SpuriousDragon hardfork and the client only supports activating the full hardfork' - ) - } - - const params: any = { - name, - chainId, - networkId: chainId, - genesis: { - timestamp, - gasLimit: parseInt(gasLimit), // geth gasLimit and difficulty are hex strings while ours are `number`s - difficulty: parseInt(difficulty), - nonce, - extraData, - mixHash, - coinbase, - baseFeePerGas, - }, - bootstrapNodes: [], - consensus: - config.clique !== undefined - ? { - type: 'poa', - algorithm: 'clique', - clique: { - period: config.clique.period, - epoch: config.clique.epoch, - }, - } - : { - type: 'pow', - algorithm: 'ethash', - ethash: {}, - }, - } - - const forkMap: { [key: string]: string } = { - [Hardfork.Homestead]: 'homesteadBlock', - [Hardfork.Dao]: 'daoForkBlock', - [Hardfork.TangerineWhistle]: 'eip150Block', - [Hardfork.SpuriousDragon]: 'eip155Block', - [Hardfork.Byzantium]: 'byzantiumBlock', - [Hardfork.Constantinople]: 'constantinopleBlock', - [Hardfork.Petersburg]: 'petersburgBlock', - [Hardfork.Istanbul]: 'istanbulBlock', - [Hardfork.MuirGlacier]: 'muirGlacierBlock', - [Hardfork.Berlin]: 'berlinBlock', - [Hardfork.London]: 'londonBlock', - [Hardfork.MergeForkIdTransition]: 'mergeForkBlock', - } - params.hardforks = Object.values(Hardfork) - .map((name) => ({ - name, - block: name === Hardfork.Chainstart ? 0 : config[forkMap[name]] ?? null, - })) - .filter((fork) => fork.block !== null) - if (config.terminalTotalDifficulty !== undefined) { - params.hardforks.push({ - name: Hardfork.Merge, - ttd: config.terminalTotalDifficulty, - block: null, - }) - } - return params -} - -/** - * Parses a genesis.json exported from Geth into parameters for Common instance - * @param json representing the Geth genesis file - * @param name optional chain name - * @returns parsed params - */ -export async function parseCustomParams(json: any, name?: string) { - try { - if (['config', 'difficulty', 'gasLimit', 'alloc'].some((field) => !(field in json))) { - throw new Error('Invalid format, expected geth genesis fields missing') - } - if (name !== undefined) { - json.name = name - } - return await parseGethParams(json) - } catch (e: any) { - throw new Error(`Error parsing parameters file: ${e.message}`) - } -} - -/** - * Parses the geth genesis state into Blockchain {@link GenesisState} - * @param json representing the `alloc` key in a Geth genesis file - */ -export async function parseGenesisState(json: any) { - const state: GenesisState = {} - for (let address of Object.keys(json.alloc)) { - let { balance, code, storage } = json.alloc[address] - address = addHexPrefix(address) - balance = isHexPrefixed(balance) ? balance : bigIntToHex(BigInt(balance)) - code = code !== undefined ? addHexPrefix(code) : undefined - storage = storage !== undefined ? Object.entries(storage) : undefined - state[address] = [balance, code, storage] as any - } - return state -} - /** * Returns Buffer from input hexadecimal string or Buffer * @param input hexadecimal string or Buffer @@ -235,20 +80,3 @@ export function parseKey(input: string | Buffer) { } return Buffer.from(input, 'hex') } - -/** - * Sets any missing forkHashes on the passed-in {@link Common} instance - * @param common The {@link Common} to set the forkHashes for - * @param genesisHash The genesis block hash - */ -export function setCommonForkHashes(common: Common, genesisHash: Buffer) { - for (const hf of (common as any)._chainParams.hardforks) { - if ( - (hf.forkHash === null || hf.forkhash === undefined) && - typeof hf.block !== 'undefined' && - (hf.block !== null || typeof hf.td !== 'undefined') - ) { - hf.forkHash = common.forkHash(hf.name, genesisHash) - } - } -} diff --git a/packages/client/test/integration/beaconsync.spec.ts b/packages/client/test/integration/beaconsync.spec.ts index 4328500bbd..62b1faa75d 100644 --- a/packages/client/test/integration/beaconsync.spec.ts +++ b/packages/client/test/integration/beaconsync.spec.ts @@ -4,7 +4,6 @@ import * as tape from 'tape' import * as td from 'testdouble' import { Event } from '../../lib/types' -import { parseCustomParams } from '../../lib/util' import * as genesisJSON from '../testdata/geth-genesis/post-merge.json' import { destroy, setup, wait } from './util' @@ -12,11 +11,7 @@ import { destroy, setup, wait } from './util' const originalValidate = BlockHeader.prototype._consensusFormatValidation tape('[Integration:BeaconSync]', async (t) => { - const params = await parseCustomParams(genesisJSON, 'post-merge') - const common = new Common({ - chain: params.name, - customChains: [params], - }) + const common = Common.fromGethGenesis(genesisJSON, { chain: 'post-merge' }) common.setHardforkByBlockNumber(BigInt(0), BigInt(0)) t.test('should sync blocks', async (t) => { diff --git a/packages/client/test/rpc/helpers.ts b/packages/client/test/rpc/helpers.ts index 2972aceb1c..458721edcd 100644 --- a/packages/client/test/rpc/helpers.ts +++ b/packages/client/test/rpc/helpers.ts @@ -1,6 +1,6 @@ import { BlockHeader } from '@ethereumjs/block' -import { Blockchain } from '@ethereumjs/blockchain' -import { Chain as ChainEnum, Common } from '@ethereumjs/common' +import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' +import { Chain as ChainEnum, Common, parseGethGenesis } from '@ethereumjs/common' import { Address } from '@ethereumjs/util' import { Server as RPCServer } from 'jayson/promise' import { MemoryLevel } from 'memory-level' @@ -13,12 +13,7 @@ import { RlpxServer } from '../../lib/net/server/rlpxserver' import { RPCManager as Manager } from '../../lib/rpc' import { TxPool } from '../../lib/service/txpool' import { Event } from '../../lib/types' -import { - createRPCServerListener, - createWsRPCServerListener, - parseCustomParams, - parseGenesisState, -} from '../../lib/util' +import { createRPCServerListener, createWsRPCServerListener } from '../../lib/util' import { mockBlockchain } from './mockBlockchain' @@ -203,8 +198,8 @@ export async function baseRequest( * Sets up a custom chain with metaDB enabled (saving receipts, logs, indexes) */ export async function setupChain(genesisFile: any, chainName = 'dev', clientOpts: any = {}) { - const genesisParams = await parseCustomParams(genesisFile, chainName) - const genesisState = await parseGenesisState(genesisFile) + const genesisParams = parseGethGenesis(genesisFile, chainName) + const genesisState = parseGethGenesisState(genesisFile) const common = new Common({ chain: chainName, diff --git a/packages/client/test/rpc/util/CLConnectionManager.spec.ts b/packages/client/test/rpc/util/CLConnectionManager.spec.ts index 7d795d074b..27b681b055 100644 --- a/packages/client/test/rpc/util/CLConnectionManager.spec.ts +++ b/packages/client/test/rpc/util/CLConnectionManager.spec.ts @@ -1,10 +1,9 @@ -import { Common } from '@ethereumjs/common' +import { Common, parseGethGenesis } from '@ethereumjs/common' import * as tape from 'tape' import { Config } from '../../../lib' import { CLConnectionManager } from '../../../lib/rpc/util/CLConnectionManager' import { Event } from '../../../lib/types' -import { parseCustomParams } from '../../../lib/util' import genesisJSON = require('../../testdata/geth-genesis/post-merge.json') const payload = { @@ -44,7 +43,7 @@ tape('[CLConnectionManager]', (t) => { manager.stop() st.ok(!manager.running, 'should stop') ;(genesisJSON.config as any).mergeForkBlock = 0 - const params = await parseCustomParams(genesisJSON, 'post-merge') + const params = parseGethGenesis(genesisJSON, 'post-merge') let common = new Common({ chain: params.name, customChains: [params], diff --git a/packages/client/test/service/fullethereumservice.spec.ts b/packages/client/test/service/fullethereumservice.spec.ts index eeeb88f20f..71febb6c10 100644 --- a/packages/client/test/service/fullethereumservice.spec.ts +++ b/packages/client/test/service/fullethereumservice.spec.ts @@ -5,7 +5,6 @@ import * as td from 'testdouble' import { Chain } from '../../lib/blockchain' import { Config } from '../../lib/config' import { Event } from '../../lib/types' -import { parseCustomParams } from '../../lib/util' import genesisJSON = require('../testdata/geth-genesis/post-merge.json') import type { Log } from '@ethereumjs/evm/dist/types' @@ -195,8 +194,7 @@ tape('[FullEthereumService]', async (t) => { }) t.test('should start on beacon sync when past merge', async (t) => { - const params = await parseCustomParams(genesisJSON, 'post-merge') - const common = new Common({ chain: params.name, customChains: [params] }) + const common = Common.fromGethGenesis(genesisJSON, { chain: 'post-merge' }) common.setHardforkByBlockNumber(BigInt(0), BigInt(0)) const config = new Config({ transports: [], common }) const chain = new Chain({ config }) diff --git a/packages/client/test/sync/skeleton.spec.ts b/packages/client/test/sync/skeleton.spec.ts index 5770d6e22b..10ea81c271 100644 --- a/packages/client/test/sync/skeleton.spec.ts +++ b/packages/client/test/sync/skeleton.spec.ts @@ -7,7 +7,6 @@ import * as td from 'testdouble' import { Chain } from '../../lib/blockchain' import { Config } from '../../lib/config' import { Skeleton, errReorgDenied, errSyncMerged } from '../../lib/sync/skeleton' -import { parseCustomParams } from '../../lib/util' import { wait } from '../integration/util' import * as genesisJSON from '../testdata/geth-genesis/post-merge.json' type Subchain = { @@ -316,11 +315,7 @@ tape('[Skeleton]', async (t) => { extraData: '0x00000000000000000', difficulty: '0x1', } - const params = await parseCustomParams(genesis, 'merge-not-set') - const common = new Common({ - chain: params.name, - customChains: [params], - }) + const common = Common.fromGethGenesis(genesis, { chain: 'merge-not-set' }) const config = new Config({ common, transports: [] }) const chain = new Chain({ config }) ;(chain.blockchain as any)._validateBlocks = false @@ -480,12 +475,7 @@ tape('[Skeleton]', async (t) => { extraData: '0x00000000000000000', difficulty: '0x1', } - const params = await parseCustomParams(genesis, 'post-merge') - const common = new Common({ - chain: params.name, - customChains: [params], - }) - + const common = Common.fromGethGenesis(genesis, { chain: 'post-merge' }) common.setHardforkByBlockNumber(BigInt(0), BigInt(0)) const config = new Config({ transports: [], @@ -590,11 +580,7 @@ tape('[Skeleton]', async (t) => { extraData: '0x00000000000000000', difficulty: '0x1', } - const params = await parseCustomParams(genesis, 'post-merge') - const common = new Common({ - chain: params.name, - customChains: [params], - }) + const common = Common.fromGethGenesis(genesis, { chain: 'post-merge' }) common.setHardforkByBlockNumber(BigInt(0), BigInt(0)) const config = new Config({ transports: [], @@ -656,11 +642,7 @@ tape('[Skeleton]', async (t) => { }, difficulty: '0x1', } - const params = await parseCustomParams(genesis, 'post-merge') - const common = new Common({ - chain: params.name, - customChains: [params], - }) + const common = Common.fromGethGenesis(genesis, { chain: 'post-merge' }) common.setHardforkByBlockNumber(BigInt(0), BigInt(0)) const config = new Config({ transports: [], diff --git a/packages/client/test/util/parse.spec.ts b/packages/client/test/util/parse.spec.ts index bb636a64f2..a707651722 100644 --- a/packages/client/test/util/parse.spec.ts +++ b/packages/client/test/util/parse.spec.ts @@ -1,7 +1,7 @@ import { multiaddr } from 'multiaddr' import * as tape from 'tape' -import { parseCustomParams, parseMultiaddrs, parseTransports } from '../../lib/util' +import { parseMultiaddrs, parseTransports } from '../../lib/util' tape('[Util/Parse]', (t) => { t.test('should parse multiaddrs', (t) => { @@ -57,56 +57,4 @@ tape('[Util/Parse]', (t) => { 'parsed transport with options' ) }) - - t.test('should parse geth params file', async (t) => { - const json = require('../testdata/geth-genesis/testnet.json') - const params = await parseCustomParams(json, 'rinkeby') - t.equals(params.genesis.nonce, '0x0000000000000042', 'nonce should be correctly formatted') - }) - - t.test('should throw with invalid Spurious Dragon blocks', async (t) => { - t.plan(1) - const json = require('../testdata/geth-genesis/invalid-spurious-dragon.json') - try { - await parseCustomParams(json, 'bad_params') - t.fail('should have thrown') - } catch { - t.pass('should throw') - } - }) - - t.test('should import poa network params correctly', async (t) => { - t.plan(3) - const json = require('../testdata/geth-genesis/poa.json') - let params = await parseCustomParams(json, 'poa') - t.equals(params.genesis.nonce, '0x0000000000000000', 'nonce is formatted correctly') - t.deepEquals( - params.consensus, - { type: 'poa', algorithm: 'clique', clique: { period: 15, epoch: 30000 } }, - 'consensus config matches' - ) - json.nonce = '00' - params = await parseCustomParams(json, 'poa') - t.equals( - params.genesis.nonce, - '0x0000000000000000', - 'non-hex prefixed nonce is formatted correctly' - ) - }) - - t.test( - 'should generate expected hash with london block zero and base fee per gas defined', - async (t) => { - const json = require('../testdata/geth-genesis/post-merge.json') - const params = await parseCustomParams(json, 'post-merge') - t.equals(params.genesis.baseFeePerGas, json.baseFeePerGas) - } - ) - t.test('should successfully parse genesis file with no extraData', async (st) => { - st.plan(2) - const json = require('../testdata/geth-genesis/no-extra-data.json') - const params = await parseCustomParams(json, 'noExtraData') - st.equal(params.genesis.extraData, '0x', 'extraData set to 0x') - st.equal(params.genesis.timestamp, '0x10', 'timestamp parsed correctly') - }) }) diff --git a/packages/common/README.md b/packages/common/README.md index 2d7d5ad6b8..ed1ada9739 100644 --- a/packages/common/README.md +++ b/packages/common/README.md @@ -195,6 +195,22 @@ const common1 = new Common({ Starting with v3 custom genesis states should be passed to the [Blockchain](../blockchain/) library directly. +#### Initialize using Geth's genesis json + +For lots of custom chains (for e.g. devnets and testnets), you might come across a genesis json config which +has both config specification for the chain as well as the genesis state specification. You can derive the +common from such configuration in the following manner: + +```typescript +import { Common } from '@ethereumjs/common' + +// Load geth genesis json file into lets say `genesisJson` and optional `chain` and `genesisHash` +const common = Common.fromGethGenesis(genesisJson, { chain: 'customChain', genesisHash }) +// If you don't have `genesisHash` while initiating common, you can later configure common (for e.g. +// post calculating it via `blockchain`) +common.setForkHashes(genesisHash) +``` + ### Hardforks The `hardfork` can be set in constructor like this: diff --git a/packages/common/src/common.ts b/packages/common/src/common.ts index 605fd7b88b..dd1569eb79 100644 --- a/packages/common/src/common.ts +++ b/packages/common/src/common.ts @@ -10,6 +10,7 @@ import * as sepolia from './chains/sepolia.json' import { EIPs } from './eips' import { Chain, CustomChain, Hardfork } from './enums' import { hardforks as HARDFORK_CHANGES } from './hardforks' +import { parseGethGenesis } from './utils' import type { ConsensusAlgorithm, ConsensusType } from './enums' import type { @@ -23,6 +24,7 @@ import type { CustomCommonOpts, EthashConfig, GenesisBlockConfig, + GethConfigOpts, HardforkConfig, } from './types' import type { BigIntLike } from '@ethereumjs/util' @@ -152,6 +154,28 @@ export class Common extends EventEmitter { } } + /** + * Static method to load and set common from a geth genesis json + * @param genesisJson json of geth configuration + * @param { chain, genesisHash, hardfork } to futher configure the common instance + * @returns Common + */ + static fromGethGenesis( + genesisJson: any, + { chain, genesisHash, hardfork }: GethConfigOpts + ): Common { + const genesisParams = parseGethGenesis(genesisJson, chain) + const common = new Common({ + chain: genesisParams.name, + customChains: [genesisParams], + hardfork, + }) + if (genesisHash !== undefined) { + common.setForkHashes(genesisHash) + } + return common + } + /** * Static method to determine if a {@link chainId} is supported as a standard chain * @param chainId bigint id (`1`) of a standard chain @@ -699,6 +723,23 @@ export class Common extends EventEmitter { return resArray.length >= 1 ? resArray[resArray.length - 1] : null } + /** + * Sets any missing forkHashes on the passed-in {@link Common} instance + * @param common The {@link Common} to set the forkHashes for + * @param genesisHash The genesis block hash + */ + setForkHashes(genesisHash: Buffer) { + for (const hf of this.hardforks()) { + if ( + (hf.forkHash === null || hf.forkHash === undefined) && + typeof hf.block !== 'undefined' && + (hf.block !== null || typeof hf.ttd !== 'undefined') + ) { + hf.forkHash = this.forkHash(hf.name, genesisHash) + } + } + } + /** * Returns the Genesis parameters of the current chain * @returns Genesis dictionary diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index bd0b4e8aa5..ce4da6d414 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,3 +1,4 @@ export * from './common' export * from './enums' export * from './types' +export * from './utils' diff --git a/packages/common/src/types.ts b/packages/common/src/types.ts index 611d32bb08..92488e707d 100644 --- a/packages/common/src/types.ts +++ b/packages/common/src/types.ts @@ -113,3 +113,9 @@ export interface CustomCommonOpts extends BaseOpts { */ baseChain?: string | number | Chain | bigint } + +export interface GethConfigOpts { + chain?: string + hardfork?: string | Hardfork + genesisHash?: Buffer +} diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts new file mode 100644 index 0000000000..a262e2f193 --- /dev/null +++ b/packages/common/src/utils.ts @@ -0,0 +1,131 @@ +import { intToHex, isHexPrefixed, stripHexPrefix } from '@ethereumjs/util' + +import { Hardfork } from './enums' + +/** + * Transforms Geth formatted nonce (i.e. hex string) to 8 byte 0x-prefixed string used internally + * @param nonce string parsed from the Geth genesis file + * @returns nonce as a 0x-prefixed 8 byte string + */ +function formatNonce(nonce: string): string { + if (!nonce || nonce === '0x0') { + return '0x0000000000000000' + } + if (isHexPrefixed(nonce)) { + return '0x' + stripHexPrefix(nonce).padStart(16, '0') + } + return '0x' + nonce.padStart(16, '0') +} + +/** + * Converts Geth genesis parameters to an EthereumJS compatible `CommonOpts` object + * @param json object representing the Geth genesis file + * @returns genesis parameters in a `CommonOpts` compliant object + */ +function parseGethParams(json: any) { + const { name, config, difficulty, mixHash, gasLimit, coinbase, baseFeePerGas } = json + let { extraData, timestamp, nonce } = json + const { chainId } = config + + // geth is not strictly putting empty fields with a 0x prefix + if (extraData === '') { + extraData = '0x' + } + // geth may use number for timestamp + if (!isHexPrefixed(timestamp)) { + timestamp = intToHex(parseInt(timestamp)) + } + // geth may not give us a nonce strictly formatted to an 8 byte hex string + if (nonce.length !== 18) { + nonce = formatNonce(nonce) + } + + // EIP155 and EIP158 are both part of Spurious Dragon hardfork and must occur at the same time + // but have different configuration parameters in geth genesis parameters + if (config.eip155Block !== config.eip158Block) { + throw new Error( + 'EIP155 block number must equal EIP 158 block number since both are part of SpuriousDragon hardfork and the client only supports activating the full hardfork' + ) + } + + const params: any = { + name, + chainId, + networkId: chainId, + genesis: { + timestamp, + gasLimit: parseInt(gasLimit), // geth gasLimit and difficulty are hex strings while ours are `number`s + difficulty: parseInt(difficulty), + nonce, + extraData, + mixHash, + coinbase, + baseFeePerGas, + }, + bootstrapNodes: [], + consensus: + config.clique !== undefined + ? { + type: 'poa', + algorithm: 'clique', + clique: { + period: config.clique.period, + epoch: config.clique.epoch, + }, + } + : { + type: 'pow', + algorithm: 'ethash', + ethash: {}, + }, + } + + const forkMap: { [key: string]: string } = { + [Hardfork.Homestead]: 'homesteadBlock', + [Hardfork.Dao]: 'daoForkBlock', + [Hardfork.TangerineWhistle]: 'eip150Block', + [Hardfork.SpuriousDragon]: 'eip155Block', + [Hardfork.Byzantium]: 'byzantiumBlock', + [Hardfork.Constantinople]: 'constantinopleBlock', + [Hardfork.Petersburg]: 'petersburgBlock', + [Hardfork.Istanbul]: 'istanbulBlock', + [Hardfork.MuirGlacier]: 'muirGlacierBlock', + [Hardfork.Berlin]: 'berlinBlock', + [Hardfork.London]: 'londonBlock', + [Hardfork.MergeForkIdTransition]: 'mergeForkBlock', + } + params.hardforks = Object.values(Hardfork) + .map((name) => ({ + name, + block: name === Hardfork.Chainstart ? 0 : config[forkMap[name]] ?? null, + })) + .filter((fork) => fork.block !== null) + if (config.terminalTotalDifficulty !== undefined) { + params.hardforks.push({ + name: Hardfork.Merge, + ttd: config.terminalTotalDifficulty, + block: null, + }) + } + return params +} + +/** + * Parses a genesis.json exported from Geth into parameters for Common instance + * @param json representing the Geth genesis file + * @param name optional chain name + * @returns parsed params + */ +export function parseGethGenesis(json: any, name?: string) { + try { + if (['config', 'difficulty', 'gasLimit', 'alloc'].some((field) => !(field in json))) { + throw new Error('Invalid format, expected geth genesis fields missing') + } + if (name !== undefined) { + json.name = name + } + return parseGethParams(json) + } catch (e: any) { + throw new Error(`Error parsing parameters file: ${e.message}`) + } +} diff --git a/packages/common/tests/utils.spec.ts b/packages/common/tests/utils.spec.ts new file mode 100644 index 0000000000..df6c0b9fac --- /dev/null +++ b/packages/common/tests/utils.spec.ts @@ -0,0 +1,89 @@ +import * as tape from 'tape' + +import { Common } from '../src/common' +import { parseGethGenesis } from '../src/utils' + +tape('[Utils/Parse]', (t) => { + t.test('should parse geth params file', async (t) => { + const json = require(`../../client/test/testdata/geth-genesis/testnet.json`) + const params = parseGethGenesis(json, 'rinkeby') + t.equals(params.genesis.nonce, '0x0000000000000042', 'nonce should be correctly formatted') + }) + + t.test('should throw with invalid Spurious Dragon blocks', async (t) => { + t.plan(1) + const json = require(`../../client/test/testdata/geth-genesis/invalid-spurious-dragon.json`) + try { + parseGethGenesis(json, 'bad_params') + t.fail('should have thrown') + } catch { + t.pass('should throw') + } + }) + + t.test('should import poa network params correctly', async (t) => { + t.plan(3) + const json = require(`../../client/test/testdata/geth-genesis/poa.json`) + let params = parseGethGenesis(json, 'poa') + t.equals(params.genesis.nonce, '0x0000000000000000', 'nonce is formatted correctly') + t.deepEquals( + params.consensus, + { type: 'poa', algorithm: 'clique', clique: { period: 15, epoch: 30000 } }, + 'consensus config matches' + ) + json.nonce = '00' + params = parseGethGenesis(json, 'poa') + t.equals( + params.genesis.nonce, + '0x0000000000000000', + 'non-hex prefixed nonce is formatted correctly' + ) + }) + + t.test( + 'should generate expected hash with london block zero and base fee per gas defined', + async (t) => { + const json = require(`../../client/test/testdata/geth-genesis/post-merge.json`) + const params = parseGethGenesis(json, 'post-merge') + t.equals(params.genesis.baseFeePerGas, json.baseFeePerGas) + } + ) + + t.test('should successfully parse genesis file with no extraData', async (st) => { + st.plan(2) + const json = require(`../../client/test/testdata/geth-genesis/no-extra-data.json`) + const params = parseGethGenesis(json, 'noExtraData') + st.equal(params.genesis.extraData, '0x', 'extraData set to 0x') + st.equal(params.genesis.timestamp, '0x10', 'timestamp parsed correctly') + }) + + t.test('should successfully parse kiln genesis and set forkhash', async (st) => { + const json = require(`../../blockchain/test/testdata/geth-genesis-kiln.json`) + const common = Common.fromGethGenesis(json, { + chain: 'customChain', + genesisHash: Buffer.from( + '51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8', + 'hex' + ), + }) + for (const hf of common.hardforks()) { + /* eslint-disable @typescript-eslint/no-use-before-define */ + st.equal(hf.forkHash, kilnForkHashes[hf.name], `${hf.name} forkHash should match`) + } + }) +}) + +const kilnForkHashes: any = { + chainstart: '0xbcadf543', + homestead: '0xbcadf543', + tangerineWhistle: '0xbcadf543', + spuriousDragon: '0xbcadf543', + byzantium: '0xbcadf543', + constantinople: '0xbcadf543', + petersburg: '0xbcadf543', + istanbul: '0xbcadf543', + berlin: '0xbcadf543', + london: '0xbcadf543', + mergeForkIdTransition: '0x013fd1b5', + merge: '0x013fd1b5', +}