Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 5 additions & 3 deletions packages/client/examples/private-geth-network.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ In this example, we import the genesis parameters for a private Proof-of-Authori

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).

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.
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.

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

`geth init --datadir data poa.json`

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

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

You should start seeing logs like below:

```bash
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"
INFO [08-26|09:13:16.218] Successfully sealed new block number=1 sealhash=b6eb1d..65ac14 hash=0fa2b5..d62aec elapsed="382.998µs"
Expand All @@ -35,6 +36,7 @@ Start the ethereumjs client with the custom genesis parameters:
`npm run client:start -- --gethGenesis=path/to/poa.json --bootnodes=[enode address of your geth node] --port=30305`

Shortly, you should start seeing the client produce logs showing it importing and executing blocks produced by the geth client!

```bash
INFO [08-26|09:22:46] Imported blocks count=2 number=26 hash=da44b792... hardfork=tangerineWhistle peers=1
INFO [08-26|09:22:46] Imported blocks count=2 number=26 hash=da44b792... hardfork=tangerineWhistle peers=1
```
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
2 changes: 1 addition & 1 deletion packages/client/test/rpc/eth/getLogs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Address, BN, bufferToHex } from 'ethereumjs-util'
import { INVALID_PARAMS } from '../../../lib/rpc/error-code'
import { params, baseRequest, setupChain, runBlockWithTxs, dummy } from '../helpers'
import { checkError } from '../util'
import pow from './../../testdata/pow.json'
import pow from './../../testdata/geth-genesis/pow.json'

const method = 'eth_getLogs'

Expand Down
2 changes: 1 addition & 1 deletion packages/client/test/rpc/eth/getTransactionByHash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
gethGenesisStartLondon,
dummy,
} from '../helpers'
import pow from './../../testdata/pow.json'
import pow from './../../testdata/geth-genesis/pow.json'

const method = 'eth_getTransactionByHash'

Expand Down
2 changes: 1 addition & 1 deletion packages/client/test/rpc/eth/getTransactionReceipt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
gethGenesisStartLondon,
dummy,
} from '../helpers'
import pow from './../../testdata/pow.json'
import pow from './../../testdata/geth-genesis/pow.json'

const method = 'eth_getTransactionReceipt'

Expand Down
2 changes: 1 addition & 1 deletion packages/client/test/rpc/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export function gethGenesisStartLondon(gethGenesis: any) {

/**
* Randomly generated account for testing purposes (signing txs, etc.)
* This address has preallocated balance in gethGenesis file `testdata/pow.json`
* This address has preallocated balance in file `testdata/geth-genesis/pow.json`
*/
export const dummy = {
addr: Address.fromString('0xcde098d93535445768e8a2345a2f869139f45641'),
Expand Down
6 changes: 3 additions & 3 deletions packages/client/test/sync/execution/vmexecution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import VM from '@ethereumjs/vm'
import { Config } from '../../../lib/config'
import { Chain } from '../../../lib/blockchain'
import { VMExecution } from '../../../lib/execution'
import blocksDataMainnet from './../../testdata/blocks_mainnet.json'
import blocksDataGoerli from './../../testdata/blocks_goerli.json'
import testnet from './../../testdata/testnet.json'
import blocksDataMainnet from './../../testdata/blocks/mainnet.json'
import blocksDataGoerli from './../../testdata/blocks/goerli.json'
import testnet from './../../testdata/common/testnet.json'

tape('[VMExecution]', async (t) => {
t.test('Initialization', async (t) => {
Expand Down
37 changes: 37 additions & 0 deletions packages/client/test/testdata/geth-genesis/no-extra-data.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"
}
15 changes: 11 additions & 4 deletions packages/client/test/util/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ tape('[Util/Parse]', (t) => {

t.test('should parse geth params file', async (t) => {
t.plan(3)
const json = require('../testdata/testnet2.json')
const json = require('../testdata/geth-genesis/testnet.json')
const params = await parseCustomParams(json, 'rinkeby')
t.equals(
params.genesis.hash,
Expand All @@ -82,7 +82,7 @@ tape('[Util/Parse]', (t) => {

t.test('should throw with invalid Spurious Dragon blocks', async (t) => {
t.plan(1)
const json = require('../testdata/invalid_spurious_dragon.json')
const json = require('../testdata/geth-genesis/invalid-spurious-dragon.json')
try {
await parseCustomParams(json, 'bad_params')
t.fail('should have thrown')
Expand All @@ -93,7 +93,7 @@ tape('[Util/Parse]', (t) => {

t.test('should import poa network params correctly', async (t) => {
t.plan(2)
const json = require('../testdata/poa.json')
const json = require('../testdata/geth-genesis/poa.json')
const params = await parseCustomParams(json, 'poa')
t.equals(params.genesis.nonce, '0x0000000000000000', 'nonce is formatted correctly')
t.deepEquals(
Expand All @@ -107,7 +107,7 @@ tape('[Util/Parse]', (t) => {
'should generate expected hash with london block zero and base fee per gas defined',
async (t) => {
t.plan(2)
const json = require('../testdata/post-merge.json')
const json = require('../testdata/geth-genesis/post-merge.json')
const params = await parseCustomParams(json, 'post-merge')
t.equals(
params.genesis.hash,
Expand All @@ -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/geth-genesis/no-extra-data.json')
const params = await parseCustomParams(json, 'noExtraData')
st.equals(params.genesis.extraData, '0x', 'extraData set to 0x')
st.equals(params.genesis.timestamp, '0x10', 'timestamp parsed correctly')
})
})