diff --git a/nimbus/chain_config.nim b/nimbus/chain_config.nim new file mode 100644 index 000000000..f65d13e13 --- /dev/null +++ b/nimbus/chain_config.nim @@ -0,0 +1,195 @@ +# Nimbus +# Copyright (c) 2021 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) +# * MIT license ([LICENSE-MIT](LICENSE-MIT)) +# at your option. +# This file may not be copied, modified, or distributed except according to +# those terms. + +import + std/[tables, strutils, options, times], + eth/[common, rlp], stint, stew/[byteutils], + nimcrypto/hash, + json_serialization, chronicles, + json_serialization/std/options as jsoptions, + json_serialization/std/tables as jstable, + json_serialization/lexer + +type + # beware that although in some cases + # chainId have identical value to networkId + # they are separate entity + ChainId* = distinct uint + + ChainOptions = object + chainId : ChainId + homesteadBlock : Option[BlockNumber] + daoForkBlock : Option[BlockNumber] + daoForkSupport : bool + eip150Block : Option[BlockNumber] + eip150Hash : Hash256 + eip155Block : Option[BlockNumber] + eip158Block : Option[BlockNumber] + byzantiumBlock : Option[BlockNumber] + constantinopleBlock: Option[BlockNumber] + petersburgBlock : Option[BlockNumber] + istanbulBlock : Option[BlockNumber] + muirGlacierBlock : Option[BlockNumber] + berlinBlock : Option[BlockNumber] + + ChainConfig* = object + chainId* : ChainId + homesteadBlock* : BlockNumber + daoForkBlock* : BlockNumber + daoForkSupport* : bool + + # EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) + eip150Block* : BlockNumber + eip150Hash* : Hash256 + + eip155Block* : BlockNumber + eip158Block* : BlockNumber + + byzantiumBlock* : BlockNumber + constantinopleBlock*: BlockNumber + petersburgBlock* : BlockNumber + istanbulBlock* : BlockNumber + muirGlacierBlock* : BlockNumber + berlinBlock* : BlockNumber + + Genesis* = object + nonce* : BlockNonce + timestamp* : EthTime + extraData* : seq[byte] + gasLimit* : GasInt + difficulty* : DifficultyInt + mixHash* : Hash256 + coinbase* : EthAddress + alloc* : GenesisAlloc + + GenesisAlloc* = Table[EthAddress, GenesisAccount] + GenesisAccount* = object + code* : seq[byte] + storage*: Table[UInt256, UInt256] + balance*: UInt256 + nonce* : AccountNonce + + CustomGenesis* = object + config* : ChainConfig + genesis*: Genesis + + AddressBalance = object + address {.rlpCustomSerialization.}: EthAddress + account {.rlpCustomSerialization.}: GenesisAccount + + CustomChain = object + config : ChainOptions + genesis: Genesis + +proc read(rlp: var Rlp, x: var AddressBalance, _: type EthAddress): EthAddress {.inline.} = + let val = rlp.read(UInt256).toByteArrayBE() + result[0 .. ^1] = val.toOpenArray(12, val.high) + +proc read(rlp: var Rlp, x: var AddressBalance, _: type GenesisAccount): GenesisAccount {.inline.} = + GenesisAccount(balance: rlp.read(UInt256)) + +func decodePrealloc*(data: seq[byte]): GenesisAlloc = + for tup in rlp.decode(data, seq[AddressBalance]): + result[tup.address] = tup.account + +proc readValue(reader: var JsonReader, value: var BlockNumber) = + let tok = reader.lexer.tok + if tok == tkInt: + value = toBlockNumber(reader.lexer.absintVal) + reader.lexer.next() + elif tok == tkString: + value = UInt256.fromHex(reader.lexer.strVal) + reader.lexer.next() + else: + reader.raiseUnexpectedValue("expect int or hex string") + +proc readValue(reader: var JsonReader, value: var ChainId) = + value = reader.readValue(int).ChainId + +proc readValue(reader: var JsonReader, value: var Hash256) = + value = Hash256.fromHex(reader.readValue(string)) + +proc readValue(reader: var JsonReader, value: var BlockNonce) = + value = fromHex[uint64](reader.readValue(string)).toBlockNonce + +proc readValue(reader: var JsonReader, value: var EthTime) = + value = fromHex[int64](reader.readValue(string)).fromUnix + +proc readValue(reader: var JsonReader, value: var seq[byte]) = + value = hexToSeqByte(reader.readValue(string)) + +proc readValue(reader: var JsonReader, value: var GasInt) = + value = fromHex[GasInt](reader.readValue(string)) + +proc readValue(reader: var JsonReader, value: var EthAddress) = + value = parseAddress(reader.readValue(string)) + +proc readValue(reader: var JsonReader, value: var AccountNonce) = + value = fromHex[uint64](reader.readValue(string)) + +template to(a: string, b: type EthAddress): EthAddress = + # json_serialization decode table stuff + parseAddress(a) + +template to(a: string, b: type UInt256): UInt256 = + # json_serialization decode table stuff + UInt256.fromHex(a) + +proc loadCustomGenesis*(fileName: string, cg: var CustomGenesis): bool = + var cc: CustomChain + try: + cc = Json.loadFile(fileName, CustomChain, allowUnknownFields = true) + except IOError as e: + error "Genesis config file error", fileName, msg=e.msg + return false + except JsonReaderError as e: + error "Invalid genesis config file format", fileName, msg=e.formatMsg("") + return false + except: + var msg = getCurrentExceptionMsg() + error "Error loading genesis block config file", fileName, msg + return false + + cg.genesis = cc.genesis + cg.config.chainId = cc.config.chainId + cg.config.daoForkSupport = cc.config.daoForkSupport + cg.config.eip150Hash = cc.config.eip150Hash + + template validateFork(forkName: untyped, nextBlock: BlockNumber) = + let fork = astToStr(forkName) + if cc.config.forkName.isSome: + cg.config.forkName = cc.config.forkName.get() + else: + cg.config.forkName = nextBlock + if cg.config.forkName > nextBlock: + error "Forks can't be assigned out of order", fork=fork + return false + + validateFork(berlinBlock, high(BlockNumber).toBlockNumber) + validateFork(muirGlacierBlock, cg.config.berlinBlock) + validateFork(istanbulBlock, cg.config.muirGlacierBlock) + validateFork(petersburgBlock, cg.config.istanbulBlock) + validateFork(constantinopleBlock, cg.config.petersburgBlock) + validateFork(byzantiumBlock, cg.config.constantinopleBlock) + validateFork(eip158Block, cg.config.byzantiumBlock) + validateFork(eip155Block, cg.config.eip158Block) + validateFork(eip150Block, cg.config.eip155Block) + validateFork(daoForkBlock, cg.config.eip150Block) + validateFork(homesteadBlock, cg.config.daoForkBlock) + + return true + +proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool = + try: + ga = Json.decode(data, GenesisAlloc, allowUnknownFields = true) + except JsonReaderError as e: + error "Invalid genesis config file format", msg=e.formatMsg("") + return false + + return true diff --git a/nimbus/config.nim b/nimbus/config.nim index e1b83970e..13fce062c 100644 --- a/nimbus/config.nim +++ b/nimbus/config.nim @@ -11,8 +11,9 @@ import parseopt, strutils, macros, os, times, json, tables, stew/[byteutils], chronos, eth/[keys, common, p2p, net/nat], chronicles, nimcrypto/hash, eth/p2p/bootnodes, eth/p2p/rlpx_protocols/whisper_protocol, - ./db/select_backend, eth/keys, - ./vm_types2 + ./db/select_backend, eth/keys, ./chain_config + +from ./vm_types2 import Fork const NimbusName* = "Nimbus" @@ -130,31 +131,6 @@ type keystore*: JsonNode unlocked*: bool - # beware that although in some cases - # chainId have identical value to networkId - # they are separate entity - ChainId* = distinct uint - - ChainConfig* = object - chainId*: ChainId - homesteadBlock*: BlockNumber - daoForkBlock*: BlockNumber - daoForkSupport*: bool - - # EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) - eip150Block*: BlockNumber - eip150Hash*: Hash256 - - eip155Block*: BlockNumber - eip158Block*: BlockNumber - - byzantiumBlock*: BlockNumber - constantinopleBlock*: BlockNumber - petersburgBlock*: BlockNumber - istanbulBlock*: BlockNumber - muirGlacierBlock*: BlockNumber - berlinBlock*: BlockNumber - NimbusConfiguration* = ref object ## Main Nimbus configuration object dataDir*: string @@ -165,37 +141,13 @@ type net*: NetConfiguration ## Network configuration debug*: DebugConfiguration ## Debug configuration shh*: WhisperConfig ## Whisper configuration - customGenesis*: CustomGenesisConfig ## Custom Genesis Configuration + customGenesis*: CustomGenesis ## Custom Genesis Configuration # You should only create one instance of the RNG per application / library # Ref is used so that it can be shared between components rng*: ref BrHmacDrbgContext accounts*: Table[EthAddress, NimbusAccount] importFile*: string - CustomGenesisConfig* = object - chainId*: ChainId - homesteadBlock*: BlockNumber - daoForkBlock*: BlockNumber - daoForkSupport*: bool - eip150Block*: BlockNumber - eip150Hash*: Hash256 - eip155Block*: BlockNumber - eip158Block*: BlockNumber - byzantiumBlock*: BlockNumber - constantinopleBlock*: BlockNumber - petersburgBlock*: BlockNumber - istanbulBlock*: BlockNumber - muirGlacierBlock*: BlockNumber - berlinBlock*: BlockNumber - nonce*: BlockNonce - extraData*: seq[byte] - gasLimit*: int64 - difficulty*: UInt256 - prealloc*: JsonNode - mixHash*: Hash256 - coinBase*: EthAddress - timestamp*: EthTime - const defaultRpcApi = {RpcFlags.Eth, RpcFlags.Shh} defaultProtocols = {ProtocolFlags.Eth, ProtocolFlags.Shh} @@ -220,26 +172,6 @@ proc toFork*(c: ChainConfig, number: BlockNumber): Fork = elif number >= c.homesteadBlock: FkHomestead else: FkFrontier -proc privateChainConfig*(): ChainConfig = - let config = getConfiguration() - result = ChainConfig( - chainId: config.customGenesis.chainId, - homesteadBlock: config.customGenesis.homesteadBlock, - daoForkSupport: config.customGenesis.daoForkSupport, - daoForkBlock: config.customGenesis.daoForkBlock, - eip150Block: config.customGenesis.eip150Block, - eip150Hash: config.customGenesis.eip150Hash, - eip155Block: config.customGenesis.eip155Block, - eip158Block: config.customGenesis.eip158Block, - byzantiumBlock: config.customGenesis.byzantiumBlock, - constantinopleBlock: config.customGenesis.constantinopleBlock, - petersburgBlock: config.customGenesis.petersburgBlock, - istanbulBlock: config.customGenesis.istanbulBlock, - muirGlacierBlock: config.customGenesis.muirGlacierBlock, - berlinBlock: config.customGenesis.berlinBlock - ) - trace "Custom genesis block configuration loaded", configuration=result - proc publicChainConfig*(id: PublicNetwork): ChainConfig = # For some public networks, NetworkId and ChainId value are identical # but that is not always the case @@ -311,155 +243,14 @@ proc publicChainConfig*(id: PublicNetwork): ChainConfig = berlinBlock: 4_460_644.toBlockNumber ) of CustomNet: - privateChainConfig() + let conf = getConfiguration() + trace "Custom genesis block configuration loaded", conf=conf.customGenesis.config + conf.customGenesis.config else: error "No chain config for public network", networkId = id doAssert(false, "No chain config for " & $id) ChainConfig() -proc processCustomGenesisConfig(customGenesis: JsonNode): ConfigStatus = - ## Parses Custom Genesis Block config options when customnetwork option provided - - template checkForFork(chain, currentFork, previousFork: untyped, optional = false) = - # Template to load fork blocks and validate order - let currentForkName = currentFork.astToStr() - if chain.hasKey(currentForkName) and not optional: - if chain[currentForkName].kind == JInt: - currentFork = chain[currentForkName].getInt().toBlockNumber - if currentFork < previousFork: - error "Forks can't be assigned out of order" - quit(1) - else: - error "Invalid block value provided for", currentForkName, invalidValue=currentFork - quit(1) - - proc parseConfig(T: type, c: JsonNode, field: string): T = - when T is string: - c[field].getStr() - elif T is Uint256: - hexToUint[256](c[field].getStr()) - elif T is bool: - c[field].getBool() - elif T is Hash256: - MDigest[256].fromHex(c[field].getStr()) - elif T is uint: - c[field].getInt().uint - elif T is Blocknonce: - (parseHexInt(c[field].getStr()).uint64).toBlockNonce - elif T is EthTime: - fromHex[int64](c[field].getStr()).fromUnix - elif T is EthAddress: - parseAddress(c[field].getStr()) - elif T is seq[byte]: - hexToSeqByte(c[field].getStr()) - elif T is int64: - fromHex[int64](c[field].getStr()) - elif T is ChainId: - c[field].getInt().T - - template validateConfigValue(chainDetails, field, jtype, T: untyped, checkError: static[bool] = true) = - let fieldName = field.astToStr() - if chainDetails.hasKey(fieldName): - if chainDetails[fieldName].kind == jtype: - field = parseConfig(T, chainDetails, fieldName) - else: - error "Invalid value provided for ", fieldName - quit(1) - else: - when checkError: - error "No value found in genesis block for", fieldName - quit(1) - - let config = getConfiguration() - result = Success - var - chainId = 1.ChainId - homesteadBlock, daoForkblock, eip150Block, eip155Block, eip158Block, byzantiumBlock, constantinopleBlock = high(BlockNumber).toBlockNumber - petersburgBlock, istanbulBlock, muirGlacierBlock, berlinBlock = high(BlockNumber).toBlockNumber - eip150Hash, mixHash : MDigest[256] - daoForkSupport = false - nonce = 66.toBlockNonce - extraData = hexToSeqByte("0x") - gasLimit = 16777216.int64 - difficulty = 1048576.u256 - alloc = parseJson("{}") - timestamp : EthTime - coinbase : EthAddress - - - if customGenesis.hasKey("config"): - # Validate all fork blocks for custom genesis - let forkDetails = customGenesis["config"] - validateConfigValue(forkDetails, chainId, JInt, ChainId, checkError=false) - checkForFork(forkDetails, homesteadBlock, 0.toBlockNumber) - validateConfigValue(forkDetails, daoForkSupport, JBool, bool, checkError=false) - if daoForkSupport == true: - checkForFork(forkDetails, daoForkBlock, 0.toBlockNumber) - - checkForFork(forkDetails, eip150Block, homesteadBlock) - validateConfigValue(forkDetails, eip150Hash, JString, Hash256, checkError = false) - checkForFork(forkDetails, eip155Block, eip150Block) - checkForFork(forkDetails, eip158Block, eip155Block) - checkForFork(forkDetails, byzantiumBlock, eip158Block) - checkForFork(forkDetails, constantinopleBlock, byzantiumBlock) - checkForFork(forkDetails, petersburgBlock, constantinopleBlock) - checkForFork(forkDetails, istanbulBlock, petersburgBlock) - checkForFork(forkDetails, muirGlacierBlock, istanbulBlock, optional = true) - checkForFork(forkDetails, istanbulBlock, berlinBlock) - - validateConfigValue(customGenesis, nonce, JString, BlockNonce, checkError = false) - validateConfigValue(customGenesis, extraData, JSTring, seq[byte], checkError = false) - validateConfigValue(customGenesis, gasLimit, JString, int64, checkError = false) - validateConfigValue(customGenesis, difficulty, JString, UInt256) - if customGenesis.hasKey("alloc"): - alloc = customGenesis["alloc"] - - validateConfigValue(customGenesis, mixHash, JString, Hash256, checkError = false) - validateConfigValue(customGenesis, coinbase, JString, EthAddress, checkError = false) - validateConfigValue(customGenesis, timestamp, JString, EthTime, checkError = false) - - config.customGenesis = CustomGenesisConfig( - chainId: chainId, - homesteadBlock: homesteadBlock, - eip150Block: eip150Block, - eip150Hash: eip150Hash, - eip155Block: eip155Block, - eip158Block: eip158Block, - daoForkSupport: daoForkSupport, - byzantiumBlock: byzantiumBlock, - constantinopleBlock: constantinopleBlock, - petersburgBlock: petersburgBlock, - istanbulBlock: istanbulBlock, - muirGlacierBlock: muirGlacierBlock, - berlinBlock: berlinBlock, - nonce: nonce, - extraData: extraData, - gasLimit: gasLimit, - difficulty: difficulty, - prealloc: alloc, - mixHash: mixHash, - coinbase: coinbase, - timestamp: timestamp - ) - -proc customGenesis(key, value: string): ConfigStatus = - if value == "": - error "No genesis block config provided for custom network", network=key - result = ErrorParseOption - else: - try: - result = processCustomGenesisConfig(parseFile(value)) - except IOError: - error "Genesis block config file not found", invalidFileName=value - result = ErrorParseOption - except JsonParsingError: - error "Invalid genesis block config file format", invalidFileName=value - result = ErrorIncorrectOption - except: - var msg = getCurrentExceptionMsg() - error "Error loading genesis block config file", invalidFileName=msg - result = Error - proc processList(v: string, o: var seq[string]) = ## Process comma-separated list of strings. if len(v) > 0: @@ -687,7 +478,8 @@ proc processNetArguments(key, value: string): ConfigStatus = elif skey == "kovan": config.net.setNetwork(KovanNet) elif skey == "customnetwork": - result = customGenesis(key, value) + if not loadCustomGenesis(value, config.customGenesis): + result = Error config.net.networkId = NetworkId(CustomNet) elif skey == "networkid": var res = 0 diff --git a/nimbus/db/db_chain.nim b/nimbus/db/db_chain.nim index 9dba3edd0..9019b1d4a 100644 --- a/nimbus/db/db_chain.nim +++ b/nimbus/db/db_chain.nim @@ -10,7 +10,7 @@ import stew/[byteutils], eth/trie/[hexary, db], eth/[common, rlp], chronicles, ../errors, ../constants, ./storage_types, - ../utils, ../config + ../utils, ../config, ../chain_config type BaseChainDB* = ref object diff --git a/nimbus/genesis.nim b/nimbus/genesis.nim index 4edf5f0f0..1922e9e62 100644 --- a/nimbus/genesis.nim +++ b/nimbus/genesis.nim @@ -1,62 +1,10 @@ import - tables, json, times, strutils, - eth/[common, rlp, trie], stint, stew/[byteutils], + std/[json, strutils, times, tables], + eth/[common, rlp, trie], stew/[byteutils], chronicles, eth/trie/db, - db/[db_chain, state_db], genesis_alloc, config, constants - -type - Genesis* = object - config*: ChainConfig - nonce*: BlockNonce - timestamp*: EthTime - extraData*: seq[byte] - gasLimit*: GasInt - difficulty*: DifficultyInt - mixhash*: Hash256 - coinbase*: EthAddress - alloc*: GenesisAlloc - - GenesisAlloc = TableRef[EthAddress, GenesisAccount] - GenesisAccount = object - code*: seq[byte] - storage*: Table[UInt256, UInt256] - balance*: UInt256 - nonce*: AccountNonce - -func toAddress(n: UInt256): EthAddress = - let a = n.toByteArrayBE() - result[0 .. ^1] = a.toOpenArray(12, a.high) - -func decodePrealloc(data: seq[byte]): GenesisAlloc = - result = newTable[EthAddress, GenesisAccount]() - for tup in rlp.decode(data, seq[(UInt256, UInt256)]): - result[toAddress(tup[0])] = GenesisAccount(balance: tup[1]) - -proc customNetPrealloc(genesisBlock: JsonNode): GenesisAlloc = - result = newTable[EthAddress, GenesisAccount]() - for address, account in genesisBlock.pairs(): - let nonce = if "nonce" in account: - parseHexInt(account["nonce"].getStr).AccountNonce - else: - AccountNonce(0) - - let code = if "code" in account: - hexToSeqByte(account["code"].getStr) - else: - @[] - - var acc = GenesisAccount( - balance: fromHex(UInt256, account["balance"].getStr), - code: code, - nonce: nonce - ) - - if "storage" in account: - let storage = account["storage"] - for k, v in storage: - acc.storage[fromHex(UInt256, k)] = fromHex(UInt256, v.getStr) - - result[parseAddress(address)] = acc + ./db/[db_chain, state_db], + ./genesis_alloc, ./config, ./constants, + ./chain_config proc defaultGenesisBlockForNetwork*(id: PublicNetwork): Genesis = result = case id @@ -95,28 +43,13 @@ proc defaultGenesisBlockForNetwork*(id: PublicNetwork): Genesis = alloc: decodePrealloc(goerliAllocData) ) of CustomNet: - let genesis = getConfiguration().customGenesis - var alloc = new GenesisAlloc - assert(genesis.prealloc.isNil.not, "genesis prealloc should not nil") - if genesis.prealloc != parseJson("{}"): - alloc = customNetPrealloc(genesis.prealloc) - Genesis( - nonce: genesis.nonce, - extraData: genesis.extraData, - gasLimit: genesis.gasLimit, - difficulty: genesis.difficulty, - alloc: alloc, - timestamp: genesis.timestamp, - mixhash: genesis.mixHash, - coinbase: genesis.coinbase - ) - + let customGenesis = getConfiguration().customGenesis + customGenesis.genesis else: # TODO: Fill out the rest error "No default genesis for network", id doAssert(false, "No default genesis for " & $id) Genesis() - result.config = publicChainConfig(id) proc toBlock*(g: Genesis, db: BaseChainDB = nil): BlockHeader = let (tdb, pruneTrie) = if db.isNil: (newMemoryDB(), true) @@ -130,8 +63,6 @@ proc toBlock*(g: Genesis, db: BaseChainDB = nil): BlockHeader = for k, v in account.storage: sdb.setStorage(address, k, v) - var root = sdb.rootHash - result = BlockHeader( nonce: g.nonce, timestamp: g.timestamp, @@ -140,7 +71,7 @@ proc toBlock*(g: Genesis, db: BaseChainDB = nil): BlockHeader = difficulty: g.difficulty, mixDigest: g.mixhash, coinbase: g.coinbase, - stateRoot: root, + stateRoot: sdb.rootHash, parentHash: GENESIS_PARENT_HASH, txRoot: BLANK_ROOT_HASH, receiptRoot: BLANK_ROOT_HASH, @@ -161,7 +92,4 @@ proc commit*(g: Genesis, db: BaseChainDB) = proc initializeEmptyDb*(db: BaseChainDB) = trace "Writing genesis to DB" let networkId = getConfiguration().net.networkId.toPublicNetwork() -# if networkId == CustomNet: -# raise newException(Exception, "Custom genesis not implemented") -# else: defaultGenesisBlockForNetwork(networkId).commit(db) diff --git a/nimbus/p2p/chain.nim b/nimbus/p2p/chain.nim index b8978451e..4d06e3e17 100644 --- a/nimbus/p2p/chain.nim +++ b/nimbus/p2p/chain.nim @@ -1,6 +1,6 @@ import ../db/db_chain, eth/common, chronicles, ../vm_state, ../vm_types, ../vm_computation, ../vm_message, ../vm_types2, stint, nimcrypto, - ../utils, eth/trie/db, ./executor, ../config, ../genesis, ../utils, + ../utils, eth/trie/db, ./executor, ../chain_config, ../genesis, ../utils, stew/endians2 when not defined(release): diff --git a/nimbus/rpc/rpc_utils.nim b/nimbus/rpc/rpc_utils.nim index 15c59a470..2d2a77225 100644 --- a/nimbus/rpc/rpc_utils.nim +++ b/nimbus/rpc/rpc_utils.nim @@ -9,7 +9,7 @@ import hexstrings, eth/[common, rlp, keys, trie/db], stew/byteutils, nimcrypto, ../db/[db_chain, accounts_cache], strutils, algorithm, options, times, json, - ../constants, stint, hexstrings, rpc_types, ../config, + ../constants, stint, hexstrings, rpc_types, ../chain_config, ../vm_state_transactions, ../vm_state, ../vm_types, ../vm_types2, ../vm_computation, ../p2p/executor, ../utils, ../transaction, ../transaction/call_evm diff --git a/nimbus/utils/difficulty.nim b/nimbus/utils/difficulty.nim index 1c8624df7..f27313220 100644 --- a/nimbus/utils/difficulty.nim +++ b/nimbus/utils/difficulty.nim @@ -1,6 +1,6 @@ import times, eth/common, stint, - ../constants, ../config + ../constants, ../chain_config const ExpDiffPeriod = 100000.u256 diff --git a/nimbus/utils/header.nim b/nimbus/utils/header.nim index 45ca23976..b4095ae1f 100644 --- a/nimbus/utils/header.nim +++ b/nimbus/utils/header.nim @@ -10,7 +10,7 @@ import strformat, times, options, eth/[common, rlp], ./difficulty, ../constants, - ../config + ../chain_config export BlockHeader diff --git a/tests/customgenesis/berlin2000.json b/tests/customgenesis/berlin2000.json new file mode 100644 index 000000000..28d6b7fe5 --- /dev/null +++ b/tests/customgenesis/berlin2000.json @@ -0,0 +1,56 @@ +{ + "config": { + "chainId": 1, + "homesteadBlock": 0, + "daoForkSupport": true, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 2000 + }, + "genesis": { + "nonce": "0x0", + "timestamp": "0x0", + "extraData": "0x00", + "gasLimit": "0x5f5e100", + "difficulty": "0x20000", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "alloc": { + "0000000000000000000000000000000000000100": { + "code": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0160005500", + "balance": "0xba1a9ce0ba1a9ce" + }, + "0000000000000000000000000000000000000101": { + "code": "0x60047fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0160005500", + "balance": "0xba1a9ce0ba1a9ce" + }, + "0000000000000000000000000000000000000102": { + "code": "0x60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0160005500", + "balance": "0xba1a9ce0ba1a9ce" + }, + "0000000000000000000000000000000000000103": { + "code": "0x600060000160005500", + "balance": "0xba1a9ce0ba1a9ce" + }, + "0000000000000000000000000000000000000104": { + "code": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60010160005500", + "balance": "0xba1a9ce0ba1a9ce" + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0xba1a9ce0ba1a9ce" + }, + "cccccccccccccccccccccccccccccccccccccccc": { + "code": "0x600060006000600060006004356101000162fffffff100", + "balance": "0xba1a9ce0ba1a9ce" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } +} diff --git a/tests/customgenesis/chainid7.json b/tests/customgenesis/chainid7.json new file mode 100644 index 000000000..5aafa9027 --- /dev/null +++ b/tests/customgenesis/chainid7.json @@ -0,0 +1,45 @@ +{ + "config": { + "chainId": 7, + "homesteadBlock": 0, + "eip150Block": 0, + "eip158Block": 0 + }, + "genesis": { + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x20000", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000658bdf435d810c91414ec09147daa6db624063790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x2fefd8", + "nonce": "0x0000000000000000", + "timestamp": "0x1234", + "alloc": { + "cf49fda3be353c69b41ed96333cd24302da4556f": { + "balance": "0x123450000000000000000" + }, + "0161e041aad467a890839d5b08b138c1e6373072": { + "balance": "0x123450000000000000000" + }, + "87da6a8c6e9eff15d703fc2773e32f6af8dbe301": { + "balance": "0x123450000000000000000" + }, + "b97de4b8c857e4f6bc354f226dc3249aaee49209": { + "balance": "0x123450000000000000000" + }, + "c5065c9eeebe6df2c2284d046bfc906501846c51": { + "balance": "0x123450000000000000000" + }, + "0000000000000000000000000000000000000314": { + "balance": "0x0", + "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063a223e05d1461006a578063abd1a0cf1461008d578063abfced1d146100d4578063e05c914a14610110578063e6768b451461014c575b610000565b346100005761007761019d565b6040518082815260200191505060405180910390f35b34610000576100be600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101a3565b6040518082815260200191505060405180910390f35b346100005761010e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506101ed565b005b346100005761014a600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610236565b005b346100005761017960048080359060200190919080359060200190919080359060200190919050506103c4565b60405180848152602001838152602001828152602001935050505060405180910390f35b60005481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490505b919050565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b7f6031a8d62d7c95988fa262657cd92107d90ed96e08d8f867d32f26edfe85502260405180905060405180910390a17f47e2689743f14e97f7dcfa5eec10ba1dff02f83b3d1d4b9c07b206cbbda66450826040518082815260200191505060405180910390a1817fa48a6b249a5084126c3da369fbc9b16827ead8cb5cdc094b717d3f1dcd995e2960405180905060405180910390a27f7890603b316f3509577afd111710f9ebeefa15e12f72347d9dffd0d65ae3bade81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a18073ffffffffffffffffffffffffffffffffffffffff167f7efef9ea3f60ddc038e50cccec621f86a0195894dc0520482abf8b5c6b659e4160405180905060405180910390a28181604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a05b5050565b6000600060008585859250925092505b935093509390505600a165627a7a72305820aaf842d0d0c35c45622c5263cbb54813d2974d3999c8c38551d7c613ea2bc1170029", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x1234", + "0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9": "0x01" + } + }, + "0000000000000000000000000000000000000315": { + "balance": "0x9999999999999999999999999999999", + "code": "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef2769ca1461003e575b610000565b3461000057610078600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061007a565b005b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015610106578173ffffffffffffffffffffffffffffffffffffffff167f30a3c50752f2552dcc2b93f5b96866280816a986c0c0408cb6778b9fa198288f826040518082815260200191505060405180910390a25b5b50505600a165627a7a72305820637991fabcc8abad4294bf2bb615db78fbec4edff1635a2647d3894e2daf6a610029" + } + } + } +} \ No newline at end of file diff --git a/tests/customgenesis/noconfig.json b/tests/customgenesis/noconfig.json new file mode 100644 index 000000000..3e67a4294 --- /dev/null +++ b/tests/customgenesis/noconfig.json @@ -0,0 +1,17 @@ +{ + "genesis": { + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "0x020000", + "extraData" : "0x42", + "gasLimit" : "0x2fefd8", + "mixHash" : "0x2c85bcbce56429100b2108254bb56906257582aeafcbd682bc9af67a9f5aee46", + "nonce" : "0x78cc16f7b4f65485", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp" : "0x54c98c81", + "alloc" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance" : "0x09184e72a000" + } + } + } +} \ No newline at end of file diff --git a/tests/test_blockchain_json.nim b/tests/test_blockchain_json.nim index eb2ac8446..c48246421 100644 --- a/tests/test_blockchain_json.nim +++ b/tests/test_blockchain_json.nim @@ -16,7 +16,7 @@ import ../nimbus/db/[db_chain, accounts_cache], ../nimbus/utils/header, ../nimbus/p2p/[executor, dao], - ../nimbus/config, + ../nimbus/[config, chain_config], ../stateless/[tree_from_witness, witness_types] type diff --git a/tests/test_genesis.nim b/tests/test_genesis.nim index b345a331e..9b4af34f8 100644 --- a/tests/test_genesis.nim +++ b/tests/test_genesis.nim @@ -1,6 +1,11 @@ -import unittest2, ../nimbus/[genesis, config], eth/common, nimcrypto/hash +import + std/[os], + unittest2, eth/common, nimcrypto/hash, + ../nimbus/[genesis, config, chain_config] -proc genesisMain*() = +const dataFolder = "tests" / "customgenesis" + +proc genesisTest() = suite "Genesis": test "Correct mainnet hash": let g = defaultGenesisBlockForNetwork(MainNet) @@ -22,5 +27,17 @@ proc genesisMain*() = let b = g.toBlock check(b.blockHash == "bf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a".toDigest) +proc customGenesisTest() = + suite "Custom Genesis": + test "loadCustomGenesis": + var cga, cgb, cgc: CustomGenesis + check loadCustomGenesis(dataFolder / "berlin2000.json", cga) + check loadCustomGenesis(dataFolder / "chainid7.json", cgb) + check loadCustomGenesis(dataFolder / "noconfig.json", cgc) + +proc genesisMain*() = + genesisTest() + customGenesisTest() + when isMainModule: genesisMain() diff --git a/tests/test_graphql.nim b/tests/test_graphql.nim index ef36dc2ec..6ea792ef8 100644 --- a/tests/test_graphql.nim +++ b/tests/test_graphql.nim @@ -13,7 +13,7 @@ import eth/[p2p, common, trie/db, rlp, trie], eth/p2p/rlpx_protocols/eth_protocol, graphql, ../nimbus/graphql/ethapi, graphql/test_common, - ../nimbus/[genesis, config], ../nimbus/db/[db_chain, state_db], + ../nimbus/[genesis, config, chain_config], ../nimbus/db/[db_chain, state_db], ../nimbus/p2p/chain, ../premix/parser, ./test_helpers type @@ -37,17 +37,19 @@ proc setupChain(chainDB: BaseChainDB) = jn = v break - let genesisBlock = jn.toBlock("genesisRLP") + let genesis = jn.toBlock("genesisRLP") let conf = getConfiguration() - conf.customGenesis.nonce = genesisBlock.header.nonce - conf.customGenesis.extraData = genesisBlock.header.extraData - conf.customGenesis.gasLimit = genesisBlock.header.gasLimit - conf.customGenesis.difficulty = genesisBlock.header.difficulty - conf.customGenesis.mixHash = genesisBlock.header.mixDigest - conf.customGenesis.coinBase = genesisBlock.header.coinbase - conf.customGenesis.timestamp = genesisBlock.header.timestamp - conf.customGenesis.prealloc = jn["pre"] + conf.customGenesis.genesis.nonce = genesis.header.nonce + conf.customGenesis.genesis.extraData = genesis.header.extraData + conf.customGenesis.genesis.gasLimit = genesis.header.gasLimit + conf.customGenesis.genesis.difficulty = genesis.header.difficulty + conf.customGenesis.genesis.mixHash = genesis.header.mixDigest + conf.customGenesis.genesis.coinBase = genesis.header.coinbase + conf.customGenesis.genesis.timestamp = genesis.header.timestamp + if not parseGenesisAlloc($(jn["pre"]), conf.customGenesis.genesis.alloc): + quit(QuitFailure) + chainDB.initializeEmptyDb() let blocks = jn["blocks"] @@ -68,7 +70,7 @@ proc setupChain(chainDB: BaseChainDB) = proc graphqlMain*() = let conf = getConfiguration() conf.net.networkId = NetworkId(CustomNet) - conf.customGenesis = CustomGenesisConfig( + conf.customGenesis.config = ChainConfig( chainId : MainNet.ChainId, byzantiumBlock : 0.toBlockNumber, constantinopleBlock : 0.toBlockNumber,