@ethereumjs/common
Version:
Resources common to all Ethereum implementations
176 lines (165 loc) • 4.62 kB
text/typescript
import { type PrefixedHexString, addHexPrefix, bigIntToHex, isHexString } from '@ethereumjs/util'
/**
* Interface for Geth Genesis Config
*/
export interface GethGenesisConfig {
chainId: number
depositContractAddress?: string
homesteadBlock?: number
daoForkBlock?: number
daoForkSupport?: boolean
eip150Block?: number
eip150Hash?: string
eip155Block?: number
eip158Block?: number
byzantiumBlock?: number
constantinopleBlock?: number
petersburgBlock?: number
istanbulBlock?: number
muirGlacierBlock?: number
berlinBlock?: number
londonBlock?: number
mergeForkBlock?: number
cancunBlock?: number
arrowGlacierBlock?: number
grayGlacierBlock?: number
mergeNetsplitBlock?: number
shanghaiTime?: number
cancunTime?: number
pragueTime?: number
terminalTotalDifficulty?: number
terminalTotalDifficultyPassed?: boolean
ethash?: {}
clique?: {
period?: number
epoch?: number
blockperiodseconds?: number
epochlength?: number
}
trustedCheckpoint?: {
sectionIndex: number
sectionHead: string
chtRoot: string
bloomRoot: string
}
trustedCheckpointOracle?: {
address: string
signers: string[]
threshold: number
}
blobSchedule?: GethGenesisBlobSchedule
proofInBlocks?: boolean
}
/**
* Interface for account allocation in Geth Genesis
*/
export interface GethGenesisAlloc {
[address: string]: {
balance: string
code?: string
storage?: { [key: string]: string }
nonce?: string
}
}
/**
* Interface for blob schedule in Geth Genesis (EIP-7840)
*/
export interface GethGenesisBlobSchedule {
[fork: string]: {
target?: number
max?: number
baseFeeUpdateFraction?: number
}
}
/**
* Interface for Geth Genesis object
*/
export interface GethGenesis {
config: GethGenesisConfig
name?: string
excessBlobGas?: string
requestsHash?: string
nonce: string
timestamp: string
extraData?: string
gasLimit: PrefixedHexString
difficulty?: PrefixedHexString
mixHash?: PrefixedHexString
coinbase?: PrefixedHexString
alloc: GethGenesisAlloc
number?: PrefixedHexString
gasUsed?: PrefixedHexString
parentHash?: PrefixedHexString
baseFeePerGas?: PrefixedHexString | number | null
}
/**
* Type for the options passed to createCommonFromGethGenesis
*/
export interface CreateCommonFromGethGenesisOpts {
chain?: string
genesisHash?: string
mergeForkIdPostMerge?: boolean
}
export type StoragePair = [key: PrefixedHexString, value: PrefixedHexString]
export type AccountState = [
balance: PrefixedHexString,
code?: PrefixedHexString,
storage?: Array<StoragePair>,
nonce?: PrefixedHexString,
]
/**
* If you are using a custom chain {@link Common}, pass the genesis state.
*
* Pattern 1 (with genesis state see {@link GenesisState} for format):
*
* ```javascript
* {
* '0x0...01': '0x100', // For EoA
* }
* ```
*
* Pattern 2 (with complex genesis state, containing contract accounts and storage).
* Note that in {@link AccountState} there are two
* accepted types. This allows to easily insert accounts in the genesis state:
*
* A complex genesis state with Contract and EoA states would have the following format:
*
* ```javascript
* {
* '0x0...01': '0x100', // For EoA
* '0x0...02': ['0x1', '0xRUNTIME_BYTECODE', [[storageKey1, storageValue1], [storageKey2, storageValue2]]] // For contracts
* }
* ```
*/
export interface GenesisState {
[key: PrefixedHexString]: PrefixedHexString | AccountState
}
/**
* Parses the geth genesis state into Blockchain {@link GenesisState}
* @param gethGenesis GethGenesis object
* @returns Parsed {@link GenesisState}
*/
export function parseGethGenesisState(gethGenesis: GethGenesis): GenesisState {
const state: GenesisState = {}
for (const address of Object.keys(gethGenesis.alloc)) {
const {
balance: rawBalance,
code: rawCode,
nonce: rawNonce,
storage: rawStorage,
} = gethGenesis.alloc[address]
// create a map with lowercase for easy lookups
const prefixedAddress = addHexPrefix(address.toLowerCase())
const balance = isHexString(rawBalance) ? rawBalance : bigIntToHex(BigInt(rawBalance))
const code = rawCode !== undefined ? addHexPrefix(rawCode) : undefined
const storage =
rawStorage !== undefined
? (Object.entries(rawStorage).map((storagePair) =>
storagePair.map(addHexPrefix),
) as StoragePair[])
: undefined
const nonce = rawNonce !== undefined ? addHexPrefix(rawNonce) : undefined
state[prefixedAddress] = [balance, code, storage, nonce]
}
return state
}