Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Common: Genesis state logic improved #1755

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 2 additions & 0 deletions packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ async function run() {
const chainName = path.parse(args.gethGenesis).base.split('.')[0]
const genesisParams = await parseCustomParams(genesisFile, chainName)
const genesisState = genesisFile.alloc ? await parseGenesisState(genesisFile) : {}
console.log('Genesis block hash: ', genesisParams.genesis.hash)
console.log('Genesis state root: ', genesisParams.genesis.stateRoot)
common = new Common({
chain: genesisParams.name,
customChains: [[genesisParams, genesisState]],
Expand Down
1 change: 1 addition & 0 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"lint:fix": "../../config/cli/lint-fix.sh",
"tape": "tape -r ts-node/register",
"test": "npm run test:node && npm run test:browser",
"test:temp": "npm run tape -- ./tests/customChains.spec.ts",
"test:node": "npm run tape -- ./tests/*.spec.ts",
"test:browser": "karma start karma.conf.js",
"docs:build": "typedoc --options typedoc.js"
Expand Down
56 changes: 32 additions & 24 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Chain as IChain,
GenesisBlock,
GenesisState,
GethGenesisState,
Hardfork as HardforkParams,
} from './types'

Expand Down Expand Up @@ -132,7 +133,7 @@ export interface CommonOpts extends BaseOpts {
* Initialize (in addition to the supported chains) with the selected
* custom chains
*
* Usage (directly with the respective chain intialization via the {@link CommonOpts.chain} option):
* Usage (directly with the respective chain initialization via the {@link CommonOpts.chain} option):
*
* Pattern 1 (without genesis state):
*
Expand All @@ -149,7 +150,7 @@ export interface CommonOpts extends BaseOpts {
* const common = new Common({ chain: 'myCustomChain1', customChains: [ [ myCustomChain1, chain1GenesisState ] ]})
* ```
*/
customChains?: IChain[] | [IChain, GenesisState][]
customChains?: IChain[] | [IChain, GenesisState | GethGenesisState][]
}

/**
Expand Down Expand Up @@ -185,7 +186,7 @@ export default class Common extends EventEmitter {
private _hardfork: string | Hardfork
private _supportedHardforks: Array<string | Hardfork> = []
private _eips: number[] = []
private _customChains: IChain[] | [IChain, GenesisState][]
private _customChains: IChain[] | [IChain, GenesisState | GethGenesisState][]

/**
* Creates a {@link Common} object for a custom chain, based on a standard one.
Expand Down Expand Up @@ -379,22 +380,33 @@ export default class Common extends EventEmitter {
* representation. Or, a Dictionary of chain parameters for a private network.
* @returns The dictionary with parameters set as chain
*/
setChain(chain: string | number | Chain | BN | object): any {
setChain(chain: string | number | Chain | BN | object): IChain {
if (typeof chain === 'number' || typeof chain === 'string' || BN.isBN(chain)) {
// Filter out genesis states if passed in to customChains
let plainCustomChains: IChain[]
if (
this._customChains &&
this._customChains.length > 0 &&
Array.isArray(this._customChains[0])
) {
plainCustomChains = (this._customChains as [IChain, GenesisState][]).map((e) => e[0])
if (this._customChains?.length && Array.isArray(this._customChains[0])) {
plainCustomChains = (this._customChains as [IChain, GenesisState | GethGenesisState][]).map(
([chain, state]) => {
if ('hash' && 'stateRoot' in state) {
return {
...chain,
genesis: {
...chain.genesis,
hash: state.hash,
stateRoot: state.stateRoot,
},
} as IChain
}

return chain
}
)
} else {
plainCustomChains = this._customChains as IChain[]
}
this._chainParams = Common._getChainParams(chain, plainCustomChains)
} else if (typeof chain === 'object') {
if (this._customChains.length > 0) {
if (this._customChains.length) {
throw new Error(
'Chain must be a string, number, or BN when initialized with customChains passed in'
)
Expand Down Expand Up @@ -1001,6 +1013,15 @@ export default class Common extends EventEmitter {
* all values are provided as hex-prefixed strings.
*/
genesisState(): GenesisState {
// Custom chains with genesis state provided
if (this._customChains?.length && Array.isArray(this._customChains[0])) {
for (const chainArrayWithGenesis of this._customChains as [IChain, GenesisState][]) {
if (chainArrayWithGenesis[0].name === this.chainName()) {
return chainArrayWithGenesis[1]
}
}
}

// Use require statements here in favor of import statements
// to load json files on demand
// (high memory usage by large mainnet.json genesis state file)
Expand All @@ -1019,19 +1040,6 @@ export default class Common extends EventEmitter {
return require('./genesisStates/sepolia.json')
}

// Custom chains with genesis state provided
if (
this._customChains &&
this._customChains.length > 0 &&
Array.isArray(this._customChains[0])
) {
for (const chainArrayWithGenesis of this._customChains as [IChain, GenesisState][]) {
if (chainArrayWithGenesis[0].name === this.chainName()) {
return chainArrayWithGenesis[1]
}
}
}

return {}
}

Expand Down
15 changes: 13 additions & 2 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,21 @@ export interface Chain {
}
}

export interface GenesisState {
[key: string]: string | [string, [[string, string]]] // balance | [balance, code, [[storageKey, storageValue]]]
export interface GethGenesisState {
json?: any
hash: string
stateRoot: string
}

export interface AccountState {
balance: string
nonce: string
code?: string
storage?: Record<string, string>
}

export type GenesisState = Record<string, string | AccountState>

export interface eipsType {
[key: number]: any
}
Expand Down
45 changes: 42 additions & 3 deletions packages/common/tests/customChains.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import Common, { Chain, ConsensusType, CustomChain, Hardfork } from '../src/'
import testnet from './data/testnet.json'
import testnet2 from './data/testnet2.json'
import testnet3 from './data/testnet3.json'
import { AccountState, Chain as IChain, GenesisState, GethGenesisState } from '../src/types'

import { Chain as IChain, GenesisState } from '../src/types'

tape('[Common]: Custom chains', function (t: tape.Test) {
tape.only('[Common]: Custom chains', function (t: tape.Test) {
t.test(
'chain -> object: should provide correct access to private network chain parameters',
function (st: tape.Test) {
Expand Down Expand Up @@ -210,4 +209,44 @@ tape('[Common]: Custom chains', function (t: tape.Test) {

st.end()
})

t.test('custom genesis state', function (st: tape.Test) {
const mockedCode = '0xcde'
const firstAddress = '0x0000000000000000000000000000000000000001'
const genesisState = {
'0x0000000000000000000000000000000000000000': '0x1',
[firstAddress]: {
balance: '0x1',
nonce: '0x',
storage: {},
code: mockedCode,
},
}
const customChainsWithGenesis: [IChain, GenesisState][] = [[testnet, genesisState]]
const c = new Common({
chain: 'testnet',
customChains: customChainsWithGenesis,
})

const expectedGenesisState = c.genesisState()[firstAddress] as AccountState

st.equal(c.genesisState(), genesisState)
st.equal(expectedGenesisState.code, genesisState[firstAddress].code)
st.end()
})

t.test('custom hash and state root sent in genesis state', function (st: tape.Test) {
const genesisState = {
stateRoot: 'cool-state-root',
hash: 'cool-hash',
}
const customChainsWithGenesis: [IChain, GethGenesisState][] = [[testnet, genesisState]]
const c = new Common({
chain: 'testnet',
customChains: customChainsWithGenesis,
})
st.equal(c.genesis().hash, genesisState.hash)
st.equal(c.genesis().stateRoot, genesisState.stateRoot)
st.end()
})
})