Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 38 additions & 59 deletions packages/client/lib/util/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
bnToHex,
bufferToHex,
addHexPrefix,
intToHex,
} from 'ethereumjs-util'
import type { MultiaddrLike } from '../types'
import type { GenesisState } from '@ethereumjs/common/dist/types'
Expand Down Expand Up @@ -128,34 +129,29 @@ async function createGethGenesisStateTrie(alloc: any) {
}

async function createGethGenesisBlockHeader(json: any) {
const {
gasLimit,
difficulty,
extraData,
number,
nonce,
timestamp,
mixHash,
alloc,
baseFeePerGas,
} = json
const { gasLimit, difficulty, extraData, nonce, timestamp, mixHash, alloc, baseFeePerGas } = json
const storageTrie = await createGethGenesisStateTrie(alloc)
const stateRoot = storageTrie.root
const headerData = {
number: 0,
gasLimit,
difficulty,
extraData,
number,
nonce,
timestamp,
mixHash,
stateRoot,
baseFeePerGas,
}
let common
if (baseFeePerGas !== undefined && baseFeePerGas !== null) {
// chainId is not important here, we just need London enabled to set baseFeePerGas
common = new Common({ chain: 1, hardfork: Hardfork.London })
if (json.config.londonBlock === 0) {
// chainId is not important here, we just want to set
// hardfork to London for baseFeePerGas support
const hardforks = new Common({ chain: 1 })
.hardforks()
.map((h) => (h.name === 'london' ? { ...h, block: 0 } : h))
common = Common.custom({ chainId: 1, hardforks })
common.setHardforkByBlockNumber(0)
}
return BlockHeader.fromHeaderData(headerData, { common })
}
Expand All @@ -166,16 +162,18 @@ async function createGethGenesisBlockHeader(json: any) {
* @returns genesis parameters in a `CommonOpts` compliant object
*/
async function parseGethParams(json: any) {
const { name, config, difficulty, nonce, mixHash, coinbase, baseFeePerGas } = json

let { gasLimit, extraData, timestamp } = json
const { name, config, difficulty, nonce, mixHash, gasLimit, coinbase, baseFeePerGas } = json
let { extraData, timestamp } = json
const { chainId } = config

// geth stores gasLimit as a hex string while our gasLimit is a `number`
json['gasLimit'] = gasLimit = parseInt(gasLimit)
// geth is not strictly putting in empty fields with a 0x prefix
json['extraData'] = extraData = extraData === '' ? '0x' : extraData
// geth is not strictly putting empty fields with a 0x prefix
if (extraData === '') {
extraData = '0x'
}
// geth may use number for timestamp
json['timestamp'] = timestamp = isHexPrefixed(timestamp) ? timestamp : bnToHex(new BN(timestamp))
if (!isHexPrefixed(timestamp)) {
timestamp = intToHex(parseInt(timestamp))
}

// 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
Expand All @@ -185,24 +183,21 @@ async function parseGethParams(json: any) {
)
}

const { chainId } = config
const header = await createGethGenesisBlockHeader(json)
const { stateRoot } = header
const hash = bufferToHex(header.hash())
const header = await createGethGenesisBlockHeader({ ...json, extraData, timestamp })
const params: any = {
name,
chainId,
networkId: chainId,
genesis: {
hash,
hash: bufferToHex(header.hash()),
timestamp,
gasLimit,
difficulty,
gasLimit: parseInt(gasLimit), // geth gasLimit and difficulty are hex strings while ours are `number`s
difficulty: parseInt(difficulty),
nonce,
extraData,
mixHash,
coinbase,
stateRoot: bufferToHex(stateRoot),
stateRoot: bufferToHex(header.stateRoot),
baseFeePerGas,
},
bootstrapNodes: [],
Expand All @@ -222,36 +217,20 @@ async function parseGethParams(json: any) {
},
}

const hardforks = [
'chainstart',
'homestead',
'dao',
'tangerineWhistle',
'spuriousDragon',
'byzantium',
'constantinople',
'petersburg',
'istanbul',
'muirGlacier',
'berlin',
'london',
'preMerge',
]
const forkMap: { [key: string]: string } = {
homestead: 'homesteadBlock',
dao: 'daoForkBlock',
tangerineWhistle: 'eip150Block',
spuriousDragon: 'eip155Block',
byzantium: 'byzantiumBlock',
constantinople: 'constantinopleBlock',
petersburg: 'petersburgBlock',
istanbul: 'istanbulBlock',
muirGlacier: 'muirGlacierBlock',
berlin: 'berlinBlock',
london: 'londonBlock',
preMerge: 'mergeForkBlock',
[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',
}
params.hardforks = hardforks
params.hardforks = Object.values(Hardfork)
.map((name) => ({
name,
block: name === 'chainstart' ? 0 : config[forkMap[name]] ?? null,
Expand Down
37 changes: 37 additions & 0 deletions packages/client/test/testdata/noExtraData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"config": {
"chainId": 1,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"clique": {
"period": 5,
"epoch": 30000
},
"terminalTotalDifficulty": 0
},
"nonce": "0x42",
"timestamp": "16",
"extraData": "",
"gasLimit": "0x1C9C380",
"difficulty": "0x400000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0x6d6172697573766477000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas": "0x7"
}
7 changes: 7 additions & 0 deletions packages/client/test/util/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,11 @@ tape('[Util/Parse]', (t) => {
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/noExtraData.json')
const params = await parseCustomParams(json, 'noExtraData')
st.ok(params.genesis.extraData === '0x', 'extraData set to 0x')
st.ok(params.genesis.timestamp === '0x10', 'timestamp parsed correctly')
})
})