Skip to content

Commit 1876890

Browse files
ryanioacolytec3
andauthored
client: improve geth genesis parse (#1741)
* client: improve geth genesis parse * Add tests for extradata/timestamp chcks * update tests to use st.equals * organize client testdata into subfolders and normalize json file names Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com>
1 parent b0354e4 commit 1876890

File tree

17 files changed

+98
-73
lines changed

17 files changed

+98
-73
lines changed

packages/client/examples/private-geth-network.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ In this example, we import the genesis parameters for a private Proof-of-Authori
66

77
First, create a signer account and place in the `data` directory to use with geth to seal blocks following [these instructions](https://geth.ethereum.org/docs/interface/managing-your-accounts).
88

9-
Next, open [these genesis parameters](../test/testdata/poa.json) and replace "728bb68502bfcd91ce4c7a692a0c0773ced5cff0" with your signer address in both the `extradata` property and in the `alloc` section.
9+
Next, open [these genesis parameters](../test/testdata/geth-genesis/poa.json) and replace "728bb68502bfcd91ce4c7a692a0c0773ced5cff0" with your signer address in both the `extraData` property and in the `alloc` section.
1010

1111
Second, get geth configured to use the genesis parameters file just updated.
1212

1313
`geth init --datadir data poa.json`
1414

15-
Now, let's run geth and ensure that its sealing blocks. Note, geth will prompt you for a password to unlock your signer account.
15+
Now, let's run geth and ensure that its sealing blocks. Note, geth will prompt you for a password to unlock your signer account.
1616

1717
`geth --datadir data --nat extip:[your local ip address here] --networkid 15470 --unlock [the signer account you created] --mine --nodiscover`
1818

1919
You should start seeing logs like below:
20+
2021
```bash
2122
INFO [08-26|09:13:16.218] Commit new mining work number=1 sealhash=b6eb1d..65ac14 uncles=0 txs=0 gas=0 fees=0 elapsed="91.644µs"
2223
INFO [08-26|09:13:16.218] Successfully sealed new block number=1 sealhash=b6eb1d..65ac14 hash=0fa2b5..d62aec elapsed="382.998µs"
@@ -35,6 +36,7 @@ Start the ethereumjs client with the custom genesis parameters:
3536
`npm run client:start -- --gethGenesis=path/to/poa.json --bootnodes=[enode address of your geth node] --port=30305`
3637

3738
Shortly, you should start seeing the client produce logs showing it importing and executing blocks produced by the geth client!
39+
3840
```bash
39-
INFO [08-26|09:22:46] Imported blocks count=2 number=26 hash=da44b792... hardfork=tangerineWhistle peers=1
41+
INFO [08-26|09:22:46] Imported blocks count=2 number=26 hash=da44b792... hardfork=tangerineWhistle peers=1
4042
```

packages/client/lib/util/parse.ts

Lines changed: 38 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
bnToHex,
1616
bufferToHex,
1717
addHexPrefix,
18+
intToHex,
1819
} from 'ethereumjs-util'
1920
import type { MultiaddrLike } from '../types'
2021
import type { GenesisState } from '@ethereumjs/common/dist/types'
@@ -128,34 +129,29 @@ async function createGethGenesisStateTrie(alloc: any) {
128129
}
129130

130131
async function createGethGenesisBlockHeader(json: any) {
131-
const {
132-
gasLimit,
133-
difficulty,
134-
extraData,
135-
number,
136-
nonce,
137-
timestamp,
138-
mixHash,
139-
alloc,
140-
baseFeePerGas,
141-
} = json
132+
const { gasLimit, difficulty, extraData, nonce, timestamp, mixHash, alloc, baseFeePerGas } = json
142133
const storageTrie = await createGethGenesisStateTrie(alloc)
143134
const stateRoot = storageTrie.root
144135
const headerData = {
136+
number: 0,
145137
gasLimit,
146138
difficulty,
147139
extraData,
148-
number,
149140
nonce,
150141
timestamp,
151142
mixHash,
152143
stateRoot,
153144
baseFeePerGas,
154145
}
155146
let common
156-
if (baseFeePerGas !== undefined && baseFeePerGas !== null) {
157-
// chainId is not important here, we just need London enabled to set baseFeePerGas
158-
common = new Common({ chain: 1, hardfork: Hardfork.London })
147+
if (json.config.londonBlock === 0) {
148+
// chainId is not important here, we just want to set
149+
// hardfork to London for baseFeePerGas support
150+
const hardforks = new Common({ chain: 1 })
151+
.hardforks()
152+
.map((h) => (h.name === 'london' ? { ...h, block: 0 } : h))
153+
common = Common.custom({ chainId: 1, hardforks })
154+
common.setHardforkByBlockNumber(0)
159155
}
160156
return BlockHeader.fromHeaderData(headerData, { common })
161157
}
@@ -166,16 +162,18 @@ async function createGethGenesisBlockHeader(json: any) {
166162
* @returns genesis parameters in a `CommonOpts` compliant object
167163
*/
168164
async function parseGethParams(json: any) {
169-
const { name, config, difficulty, nonce, mixHash, coinbase, baseFeePerGas } = json
170-
171-
let { gasLimit, extraData, timestamp } = json
165+
const { name, config, difficulty, nonce, mixHash, gasLimit, coinbase, baseFeePerGas } = json
166+
let { extraData, timestamp } = json
167+
const { chainId } = config
172168

173-
// geth stores gasLimit as a hex string while our gasLimit is a `number`
174-
json['gasLimit'] = gasLimit = parseInt(gasLimit)
175-
// geth is not strictly putting in empty fields with a 0x prefix
176-
json['extraData'] = extraData = extraData === '' ? '0x' : extraData
169+
// geth is not strictly putting empty fields with a 0x prefix
170+
if (extraData === '') {
171+
extraData = '0x'
172+
}
177173
// geth may use number for timestamp
178-
json['timestamp'] = timestamp = isHexPrefixed(timestamp) ? timestamp : bnToHex(new BN(timestamp))
174+
if (!isHexPrefixed(timestamp)) {
175+
timestamp = intToHex(parseInt(timestamp))
176+
}
179177

180178
// EIP155 and EIP158 are both part of Spurious Dragon hardfork and must occur at the same time
181179
// but have different configuration parameters in geth genesis parameters
@@ -185,24 +183,21 @@ async function parseGethParams(json: any) {
185183
)
186184
}
187185

188-
const { chainId } = config
189-
const header = await createGethGenesisBlockHeader(json)
190-
const { stateRoot } = header
191-
const hash = bufferToHex(header.hash())
186+
const header = await createGethGenesisBlockHeader({ ...json, extraData, timestamp })
192187
const params: any = {
193188
name,
194189
chainId,
195190
networkId: chainId,
196191
genesis: {
197-
hash,
192+
hash: bufferToHex(header.hash()),
198193
timestamp,
199-
gasLimit,
200-
difficulty,
194+
gasLimit: parseInt(gasLimit), // geth gasLimit and difficulty are hex strings while ours are `number`s
195+
difficulty: parseInt(difficulty),
201196
nonce,
202197
extraData,
203198
mixHash,
204199
coinbase,
205-
stateRoot: bufferToHex(stateRoot),
200+
stateRoot: bufferToHex(header.stateRoot),
206201
baseFeePerGas,
207202
},
208203
bootstrapNodes: [],
@@ -222,36 +217,20 @@ async function parseGethParams(json: any) {
222217
},
223218
}
224219

225-
const hardforks = [
226-
'chainstart',
227-
'homestead',
228-
'dao',
229-
'tangerineWhistle',
230-
'spuriousDragon',
231-
'byzantium',
232-
'constantinople',
233-
'petersburg',
234-
'istanbul',
235-
'muirGlacier',
236-
'berlin',
237-
'london',
238-
'preMerge',
239-
]
240220
const forkMap: { [key: string]: string } = {
241-
homestead: 'homesteadBlock',
242-
dao: 'daoForkBlock',
243-
tangerineWhistle: 'eip150Block',
244-
spuriousDragon: 'eip155Block',
245-
byzantium: 'byzantiumBlock',
246-
constantinople: 'constantinopleBlock',
247-
petersburg: 'petersburgBlock',
248-
istanbul: 'istanbulBlock',
249-
muirGlacier: 'muirGlacierBlock',
250-
berlin: 'berlinBlock',
251-
london: 'londonBlock',
252-
preMerge: 'mergeForkBlock',
221+
[Hardfork.Homestead]: 'homesteadBlock',
222+
[Hardfork.Dao]: 'daoForkBlock',
223+
[Hardfork.TangerineWhistle]: 'eip150Block',
224+
[Hardfork.SpuriousDragon]: 'eip155Block',
225+
[Hardfork.Byzantium]: 'byzantiumBlock',
226+
[Hardfork.Constantinople]: 'constantinopleBlock',
227+
[Hardfork.Petersburg]: 'petersburgBlock',
228+
[Hardfork.Istanbul]: 'istanbulBlock',
229+
[Hardfork.MuirGlacier]: 'muirGlacierBlock',
230+
[Hardfork.Berlin]: 'berlinBlock',
231+
[Hardfork.London]: 'londonBlock',
253232
}
254-
params.hardforks = hardforks
233+
params.hardforks = Object.values(Hardfork)
255234
.map((name) => ({
256235
name,
257236
block: name === 'chainstart' ? 0 : config[forkMap[name]] ?? null,

packages/client/test/rpc/eth/getLogs.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Address, BN, bufferToHex } from 'ethereumjs-util'
44
import { INVALID_PARAMS } from '../../../lib/rpc/error-code'
55
import { params, baseRequest, setupChain, runBlockWithTxs, dummy } from '../helpers'
66
import { checkError } from '../util'
7-
import pow from './../../testdata/pow.json'
7+
import pow from './../../testdata/geth-genesis/pow.json'
88

99
const method = 'eth_getLogs'
1010

packages/client/test/rpc/eth/getTransactionByHash.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
gethGenesisStartLondon,
1010
dummy,
1111
} from '../helpers'
12-
import pow from './../../testdata/pow.json'
12+
import pow from './../../testdata/geth-genesis/pow.json'
1313

1414
const method = 'eth_getTransactionByHash'
1515

packages/client/test/rpc/eth/getTransactionReceipt.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
gethGenesisStartLondon,
1010
dummy,
1111
} from '../helpers'
12-
import pow from './../../testdata/pow.json'
12+
import pow from './../../testdata/geth-genesis/pow.json'
1313

1414
const method = 'eth_getTransactionReceipt'
1515

packages/client/test/rpc/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export function gethGenesisStartLondon(gethGenesis: any) {
248248

249249
/**
250250
* Randomly generated account for testing purposes (signing txs, etc.)
251-
* This address has preallocated balance in gethGenesis file `testdata/pow.json`
251+
* This address has preallocated balance in file `testdata/geth-genesis/pow.json`
252252
*/
253253
export const dummy = {
254254
addr: Address.fromString('0xcde098d93535445768e8a2345a2f869139f45641'),

packages/client/test/sync/execution/vmexecution.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import VM from '@ethereumjs/vm'
55
import { Config } from '../../../lib/config'
66
import { Chain } from '../../../lib/blockchain'
77
import { VMExecution } from '../../../lib/execution'
8-
import blocksDataMainnet from './../../testdata/blocks_mainnet.json'
9-
import blocksDataGoerli from './../../testdata/blocks_goerli.json'
10-
import testnet from './../../testdata/testnet.json'
8+
import blocksDataMainnet from './../../testdata/blocks/mainnet.json'
9+
import blocksDataGoerli from './../../testdata/blocks/goerli.json'
10+
import testnet from './../../testdata/common/testnet.json'
1111

1212
tape('[VMExecution]', async (t) => {
1313
t.test('Initialization', async (t) => {
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)