diff --git a/nimbus/p2p/executor.nim b/nimbus/p2p/executor.nim index e1d0ab8c0..8d0859e76 100644 --- a/nimbus/p2p/executor.nim +++ b/nimbus/p2p/executor.nim @@ -5,7 +5,7 @@ import options, sets, ../vm_state, ../vm_types, ../vm_state_transactions, ../vm/[computation, message], ../vm/interpreter/vm_forks, - ./dao + ./dao, ../config proc processTransaction*(tx: Transaction, sender: EthAddress, vmState: BaseVMState, fork: Fork): GasInt = ## Process the transaction, write the results to db. @@ -82,16 +82,13 @@ const eth2 = 2.eth blockRewards*: array[Fork, Uint256] = [ eth5, # FkFrontier - eth5, # FkThawing eth5, # FkHomestead - eth5, # FkDao eth5, # FkTangerine eth5, # FkSpurious eth3, # FkByzantium eth2, # FkConstantinople eth2, # FkPetersburg - eth2, # FkIstanbul - eth2 # FkMuirGlacier + eth2 # FkIstanbul ] proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, vmState: BaseVMState): ValidationResult = @@ -106,7 +103,7 @@ proc processBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, v debug "Mismatched txRoot", blockNumber=header.blockNumber return ValidationResult.Error - let fork = vmState.blockNumber.toFork + let fork = chainDB.config.toFork(vmState.blockNumber) if header.txRoot != BLANK_ROOT_HASH: if body.transactions.len == 0: diff --git a/nimbus/rpc/p2p.nim b/nimbus/rpc/p2p.nim index b5b9b3e7e..f258d733e 100644 --- a/nimbus/rpc/p2p.nim +++ b/nimbus/rpc/p2p.nim @@ -37,6 +37,8 @@ template balance(addressDb: ReadOnlyStateDb, address: EthAddress): GasInt = proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress, gasPrice: GasInt, tolerance = 1): GasInt = proc dummyComputation(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress): Computation = # Note that vmState may be altered + var chainDB = vmState.chainDB + let fork = chainDB.config.toFork(vmState.blockNumber) setupComputation( vmState, transaction, @@ -52,7 +54,8 @@ proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: value: value ) var - fork = vmState.blockNumber.toFork + chainDB = vmState.chainDB + fork = chainDB.config.toFork(vmState.blockNumber) hiGas = vmState.gasLimit loGas = transaction.intrinsicGas(fork) gasPrice = transaction.gasPrice # TODO: Or zero? diff --git a/nimbus/tracer.nim b/nimbus/tracer.nim index 1ba2247d9..590544d21 100644 --- a/nimbus/tracer.nim +++ b/nimbus/tracer.nim @@ -3,7 +3,7 @@ import constants, vm_state, vm_types, transaction, p2p/executor, eth/trie/db, nimcrypto, strutils, stew/ranges, chronicles, rpc/hexstrings, launcher, - vm/interpreter/vm_forks + vm/interpreter/vm_forks, ./config proc getParentHeader(self: BaseChainDB, header: BlockHeader): BlockHeader = self.getBlockHeader(header.parentHash) @@ -66,14 +66,14 @@ const uncleName = "uncle" internalTxName = "internalTx" -proc traceTransaction*(db: BaseChainDB, header: BlockHeader, +proc traceTransaction*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, txIndex: int, tracerFlags: set[TracerFlags] = {}): JsonNode = let - parent = db.getParentHeader(header) + parent = chainDB.getParentHeader(header) # we add a memory layer between backend/lower layer db # and capture state db snapshot during transaction execution memoryDB = newMemoryDB() - captureDB = newCaptureDB(db.db, memoryDB) + captureDB = newCaptureDB(chainDB.db, memoryDB) captureTrieDB = trieDB captureDB captureChainDB = newBaseChainDB(captureTrieDB, false) # prune or not prune? vmState = newBaseVMState(parent.stateRoot, header, captureChainDB, tracerFlags + {EnableAccount}) @@ -91,7 +91,7 @@ proc traceTransaction*(db: BaseChainDB, header: BlockHeader, stateDiff = %{"before": before, "after": after} beforeRoot: Hash256 - let fork = header.blockNumber.toFork + let fork = chainDB.config.toFork(header.blockNumber) for idx, tx in body.transactions: let sender = tx.getSender @@ -116,7 +116,7 @@ proc traceTransaction*(db: BaseChainDB, header: BlockHeader, break # internal transactions: - var stateBefore = newAccountStateDB(captureTrieDB, beforeRoot, db.pruneTrie) + var stateBefore = newAccountStateDB(captureTrieDB, beforeRoot, chainDB.pruneTrie) for idx, acc in tracedAccountsPairs(vmState): before.captureAccount(stateBefore, acc, internalTxName & $idx) @@ -189,11 +189,11 @@ proc dumpBlockState*(db: BaseChainDB, header: BlockHeader, body: BlockBody, dump if dumpState: result.dumpMemoryDB(memoryDB) -proc traceBlock*(db: BaseChainDB, header: BlockHeader, body: BlockBody, tracerFlags: set[TracerFlags] = {}): JsonNode = +proc traceBlock*(chainDB: BaseChainDB, header: BlockHeader, body: BlockBody, tracerFlags: set[TracerFlags] = {}): JsonNode = let - parent = db.getParentHeader(header) + parent = chainDB.getParentHeader(header) memoryDB = newMemoryDB() - captureDB = newCaptureDB(db.db, memoryDB) + captureDB = newCaptureDB(chainDB.db, memoryDB) captureTrieDB = trieDB captureDB captureChainDB = newBaseChainDB(captureTrieDB, false) vmState = newBaseVMState(parent.stateRoot, header, captureChainDB, tracerFlags + {EnableTracing}) @@ -203,7 +203,7 @@ proc traceBlock*(db: BaseChainDB, header: BlockHeader, body: BlockBody, tracerFl doAssert(body.transactions.len != 0) var gasUsed = GasInt(0) - let fork = header.blockNumber.toFork + let fork = chainDB.config.toFork(header.blockNumber) for tx in body.transactions: let sender = tx.getSender diff --git a/nimbus/utils/difficulty.nim b/nimbus/utils/difficulty.nim index 0c2e01ed1..198c369f6 100644 --- a/nimbus/utils/difficulty.nim +++ b/nimbus/utils/difficulty.nim @@ -1,7 +1,8 @@ import times, eth/common, stint, - ../constants, ../vm/interpreter/vm_forks + ../constants, ../vm/interpreter/vm_forks, + ../config const ExpDiffPeriod = 100000.u256 @@ -143,28 +144,15 @@ template calcDifficultyConstantinople*(timeStamp: EthTime, parent: BlockHeader): template calcDifficultyGlacierMuir*(timeStamp: EthTime, parent: BlockHeader): DifficultyInt = makeDifficultyCalculator(9_000_000, timeStamp, parent) -func calcDifficulty*(timeStamp: EthTime, parent: BlockHeader): DifficultyInt = +func calcDifficulty*(c: ChainConfig, timeStamp: EthTime, parent: BlockHeader): DifficultyInt = let next = parent.blockNumber + bigOne - if next >= forkBlocks[FkMuirGlacier]: + if next >= c.muirGlacierBlock: result = calcDifficultyGlacierMuir(timeStamp, parent) - elif next >= forkBlocks[FkConstantinople]: + elif next >= c.constantinopleBlock: result = calcDifficultyConstantinople(timeStamp, parent) - elif next >= forkBlocks[FkByzantium]: + elif next >= c.byzantiumBlock: result = calcDifficultyByzantium(timeStamp, parent) - elif next >= forkBlocks[FkHomestead]: + elif next >= c.homesteadBlock: result = calcDifficultyHomestead(timeStamp, parent) else: result = calcDifficultyFrontier(timeStamp, parent) - -func calcDifficulty*(timeStamp: EthTime, parent: BlockHeader, fork: Fork): DifficultyInt = - case fork - of FkMuirGlacier: - result = calcDifficultyGlacierMuir(timeStamp, parent) - of FkConstantinople..FkPetersburg: - result = calcDifficultyConstantinople(timeStamp, parent) - of FkByzantium: - result = calcDifficultyByzantium(timeStamp, parent) - of FkHomestead..FkSpurious: - result = calcDifficultyHomestead(timeStamp, parent) - else: - result = calcDifficultyFrontier(timeStamp, parent) \ No newline at end of file diff --git a/nimbus/utils/header.nim b/nimbus/utils/header.nim index 4d82ccd6d..be157d4df 100644 --- a/nimbus/utils/header.nim +++ b/nimbus/utils/header.nim @@ -9,7 +9,8 @@ import strformat, times, options, eth/[common, rlp], - ./difficulty, ../vm/interpreter/vm_forks, ../constants + ./difficulty, ../vm/interpreter/vm_forks, ../constants, + ../config export BlockHeader @@ -66,8 +67,8 @@ proc computeGasLimit*(parent: BlockHeader, gasLimitFloor: GasInt): GasInt = else: return gasLimit -proc generateHeaderFromParentHeader*(parent: BlockHeader, - coinbase: EthAddress, fork: Fork, timestamp: Option[EthTime], +proc generateHeaderFromParentHeader*(config: ChainConfig, parent: BlockHeader, + coinbase: EthAddress, timestamp: Option[EthTime], gasLimit: Option[GasInt], extraData: Blob): BlockHeader = var lcTimestamp: EthTime @@ -82,7 +83,7 @@ proc generateHeaderFromParentHeader*(parent: BlockHeader, result = BlockHeader( timestamp: lcTimestamp, blockNumber: (parent.blockNumber + 1), - difficulty: calcDifficulty(lcTimestamp, parent, fork), + difficulty: config.calcDifficulty(lcTimestamp, parent), gasLimit: if gasLimit.isSome: gasLimit.get() else: computeGasLimit(parent, gasLimitFloor = GENESIS_GAS_LIMIT), stateRoot: parent.stateRoot, coinbase: coinbase, diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index d57a38257..ce54b7d28 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -715,16 +715,13 @@ const gasFees*: array[Fork, GasFeeSchedule] = [ FkFrontier: BaseGasFees, - FkThawing: BaseGasFees, FkHomestead: HomesteadGasFees, - FkDao: HomesteadGasFees, FkTangerine: TangerineGasFees, FkSpurious: SpuriousGasFees, FkByzantium: SpuriousGasFees, FkConstantinople: SpuriousGasFees, FkPetersburg: SpuriousGasFees, - FkIstanbul: IstanbulGasFees, - FkMuirGlacier: IstanbulGasFees + FkIstanbul: IstanbulGasFees ] diff --git a/nimbus/vm/interpreter/vm_forks.nim b/nimbus/vm/interpreter/vm_forks.nim index 236de1958..1901bc1e9 100644 --- a/nimbus/vm/interpreter/vm_forks.nim +++ b/nimbus/vm/interpreter/vm_forks.nim @@ -10,63 +10,21 @@ import stint, eth/common/eth_types type Fork* = enum FkFrontier, - FkThawing, FkHomestead, - FkDao, FkTangerine, FkSpurious, FkByzantium, FkConstantinople, FkPetersburg, - FkIstanbul, - FkMuirGlacier - -const - forkBlocks*: array[Fork, BlockNumber] = [ - FkFrontier: 1.toBlockNumber, # 30/07/2015 19:26:28 - FkThawing: 200_000.toBlockNumber, # 08/09/2015 01:33:09 - FkHomestead: 1_150_000.toBlockNumber, # 14/03/2016 20:49:53 - FkDao: 1_920_000.toBlockNumber, # 20/07/2016 17:20:40 - FkTangerine: 2_463_000.toBlockNumber, # 18/10/2016 17:19:31 - FkSpurious: 2_675_000.toBlockNumber, # 22/11/2016 18:15:44 - FkByzantium: 4_370_000.toBlockNumber, # 16/10/2017 09:22:11 - FkConstantinople: 7_280_000.toBlockNumber, # Never Occured in MainNet - FkPetersburg: 7_280_000.toBlockNumber, # 28/02/2019 07:52:04 - FkIstanbul: 9_069_000.toBlockNumber, # 08/12/2019 12:25:09 - FkMuirGlacier: 9_200_000.toBlockNumber # 02/01/2020 08:30:49 - ] - -proc toFork*(blockNumber: BlockNumber): Fork = - - # TODO: uint256 comparison is probably quite expensive - # hence binary search is probably worth it earlier than - # linear search - - # TODO: all toFork usage currently incurs comparison to get the fork and then another comparison to - # go to the ultimate needed result. - - # Genesis block 0 also uses the Frontier code path - if blockNumber < forkBlocks[FkThawing]: FkFrontier - elif blockNumber < forkBlocks[FkHomestead]: FkThawing - elif blockNumber < forkBlocks[FkDao]: FkHomestead - elif blockNumber < forkBlocks[FkTangerine]: FkDao - elif blockNumber < forkBlocks[FkSpurious]: FkTangerine - elif blockNumber < forkBlocks[FkByzantium]: FkSpurious - elif blockNumber < forkBlocks[FkConstantinople]: FkByzantium - elif blockNumber < forkBlocks[FkIstanbul]: FkPetersburg - elif blockNumber < forkBlocks[FkMuirGlacier]: FkIstanbul - else: FkMuirGlacier + FkIstanbul proc `$`*(fork: Fork): string = case fork of FkFrontier: result = "Frontier" - of FkThawing: result = "Thawing" of FkHomestead: result = "Homestead" - of FkDao: result = "Dao" of FkTangerine: result = "Tangerine Whistle" of FkSpurious: result = "Spurious Dragon" of FkByzantium: result = "Byzantium" of FkConstantinople: result = "Constantinople" of FkPetersburg: result = "Petersburg" of FkIstanbul: result = "Istanbul" - of FkMuirGlacier: result = "Glacier Muir" diff --git a/nimbus/vm/interpreter_dispatch.nim b/nimbus/vm/interpreter_dispatch.nim index e034c9847..316791b0d 100644 --- a/nimbus/vm/interpreter_dispatch.nim +++ b/nimbus/vm/interpreter_dispatch.nim @@ -336,9 +336,9 @@ proc istanbulVM(c: Computation) {.gcsafe.} = proc selectVM(c: Computation, fork: Fork) {.gcsafe.} = # TODO: Optimise getting fork and updating opCodeExec only when necessary case fork - of FkFrontier..FkThawing: + of FkFrontier: c.frontierVM() - of FkHomestead..FkDao: + of FkHomestead: c.homesteadVM() of FkTangerine: c.tangerineVM() diff --git a/nimbus/vm_state.nim b/nimbus/vm_state.nim index 0a0cd1a4f..f75723c26 100644 --- a/nimbus/vm_state.nim +++ b/nimbus/vm_state.nim @@ -10,7 +10,8 @@ import eth/common, vm/interpreter/[vm_forks, gas_costs], ./constants, ./db/[db_chain, state_db], - ./utils, json, vm_types, vm/transaction_tracer + ./utils, json, vm_types, vm/transaction_tracer, + ./config proc newAccessLogs*: AccessLogs = AccessLogs(reads: initTable[string, string](), writes: initTable[string, string]()) @@ -52,7 +53,7 @@ proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt, if forkOverride.isSome: forkOverride.get else: - vmState.blockHeader.blockNumber.toFork + vmState.chainDB.config.toFork(vmState.blockHeader.blockNumber) vmState.gasCosts = vmState.fork.forkToSchedule method blockhash*(vmState: BaseVMState): Hash256 {.base, gcsafe.} = diff --git a/tests/macro_assembler.nim b/tests/macro_assembler.nim index f362f8273..7a71a2478 100644 --- a/tests/macro_assembler.nim +++ b/tests/macro_assembler.nim @@ -2,7 +2,7 @@ import macrocache, strutils, unittest2, stew/byteutils, chronicles, stew/ranges, eth/common, ../nimbus/vm/interpreter/opcode_values, - stew/shims/macros + stew/shims/macros, ../nimbus/config import options, json, os, eth/trie/[db, hexary], @@ -201,7 +201,7 @@ proc initComputation(vmState: BaseVMState, tx: Transaction, sender: EthAddress, if forkOverride.isSome: forkOverride.get else: - vmState.blockNumber.toFork + vmState.chainDB.config.toFork(vmState.blockNumber) let gasUsed = 0 #tx.payload.intrinsicGas.GasInt + gasFees[fork][GasTXCreate] @@ -225,7 +225,7 @@ proc initComputation(vmState: BaseVMState, tx: Transaction, sender: EthAddress, vmState.mutateStateDb: db.setCode(contractAddress, tx.payload.toRange) - + newComputation(vmState, msg) proc initDatabase*(): (Uint256, BaseChainDB) = diff --git a/tests/test_blockchain_json.nim b/tests/test_blockchain_json.nim index 3c896a1f8..08f245526 100644 --- a/tests/test_blockchain_json.nim +++ b/tests/test_blockchain_json.nim @@ -509,9 +509,9 @@ proc importBlock(tester: var Tester, chainDB: BaseChainDB, preminedBlock: PlainBlock, fork: Fork, checkSeal, validation = true): PlainBlock = let parentHeader = chainDB.getBlockHeader(preminedBlock.header.parentHash) - let baseHeaderForImport = generateHeaderFromParentHeader(parentHeader, - preminedBlock.header.coinbase, - fork, + let baseHeaderForImport = generateHeaderFromParentHeader(chainDB.config, + parentHeader, + preminedBlock.header.coinbase, some(preminedBlock.header.timestamp), some(preminedBlock.header.gasLimit), @[] diff --git a/tests/test_difficulty.nim b/tests/test_difficulty.nim index 16f6c29a7..93d6dc615 100644 --- a/tests/test_difficulty.nim +++ b/tests/test_difficulty.nim @@ -1,7 +1,8 @@ import unittest2, strutils, tables, os, json, ../nimbus/utils/difficulty, stint, times, eth/common, test_helpers, stew/byteutils, - ../nimbus/constants, ../nimbus/vm/interpreter/vm_forks + ../nimbus/constants, ../nimbus/vm/interpreter/vm_forks, + ../nimbus/config type Tester = object @@ -59,10 +60,11 @@ template runTests(name: string, hex: bool, calculator: typed) = let diff = calculator(times.fromUnix(t.currentTimeStamp), p) check diff == t.currentDifficulty -func calcDifficultyMainNetWork(timeStamp: EthTime, parent: BlockHeader): DifficultyInt = - calcDifficulty(timeStamp, parent, parent.blockNumber.toFork) - proc difficultyMain*() = + let mainnetConfig = publicChainConfig(MainNet) + func calcDifficultyMainNetWork(timeStamp: EthTime, parent: BlockHeader): DifficultyInt = + mainnetConfig.calcDifficulty(timeStamp, parent) + suite "DifficultyTest": runTests("EIP2384_random_to20M", true, calcDifficultyGlacierMuir) runTests("EIP2384_random", true, calcDifficultyGlacierMuir) @@ -72,7 +74,7 @@ proc difficultyMain*() = runTests("Homestead", true, calcDifficultyHomestead) runTests("MainNetwork", true, calcDifficultyMainNetwork) runTests("Frontier", true, calcDifficultyFrontier) - runTests("", false, calcDifficulty) + runTests("", false, calcDifficultyMainNetWork) when isMainModule: difficultyMain()