From 2a3c67b4be630c242ddc146c1cca4229e61758c6 Mon Sep 17 00:00:00 2001 From: jangko Date: Mon, 20 Mar 2023 18:51:09 +0700 Subject: [PATCH] refactor touched accounts, selfdestruct, and log simplify EVM and delegete those things to accounts cache. also no more manual state clearing, accounts cache will be responsible for both collecting touched account and perform state clearing. --- nimbus/core/executor/process_block.nim | 4 +- nimbus/core/executor/process_transaction.nim | 6 +- nimbus/core/tx_pool/tx_tasks/tx_packer.nim | 18 ++-- nimbus/core/validate.nim | 6 +- nimbus/db/accounts_cache.nim | 93 +++++++++++++++++--- nimbus/evm/computation.nim | 22 ++--- nimbus/evm/interpreter_dispatch.nim | 14 +-- nimbus/evm/state.nim | 16 +--- nimbus/evm/state_transactions.nim | 4 - nimbus/evm/types.nim | 6 -- nimbus/transaction/call_common.nim | 2 +- nimbus/transaction/host_services.nim | 18 +--- nimbus/transaction/host_types.nim | 3 - nimbus/utils/debug.nim | 5 +- nimbus/vm_computation.nim | 1 - nimbus/vm_internals.nim | 1 - nimbus/vm_state.nim | 1 - tests/macro_assembler.nim | 2 +- tests/test_generalstate_json.nim | 2 +- tests/test_helpers.nim | 5 +- tools/common/state_clearing.nim | 7 +- tools/evmstate/evmstate.nim | 2 +- tools/t8n/transition.nim | 3 +- 23 files changed, 125 insertions(+), 116 deletions(-) diff --git a/nimbus/core/executor/process_block.nim b/nimbus/core/executor/process_block.nim index f44034805..9594be2be 100644 --- a/nimbus/core/executor/process_block.nim +++ b/nimbus/core/executor/process_block.nim @@ -83,7 +83,6 @@ proc procBlkPreamble(vmState: BaseVMState; for withdrawal in body.withdrawals.get: vmState.stateDB.addBalance(withdrawal.address, withdrawal.amount.gwei) - vmState.stateDB.deleteAccountIfEmpty(withdrawal.address) else: if header.withdrawalsRoot.isSome: raise ValidationError.newException("Pre-Shanghai block header must not have withdrawalsRoot") @@ -111,7 +110,8 @@ proc procBlkEpilogue(vmState: BaseVMState; vmState.mutateStateDB: if vmState.generateWitness: db.collectWitnessData() - db.persist(ClearCache in vmState.flags) + let clearEmptyAccount = vmState.determineFork >= FkSpurious + db.persist(clearEmptyAccount, ClearCache in vmState.flags) let stateDb = vmState.stateDB if header.stateRoot != stateDb.rootHash: diff --git a/nimbus/core/executor/process_transaction.nim b/nimbus/core/executor/process_transaction.nim index f24eaf308..9be72bdcb 100644 --- a/nimbus/core/executor/process_transaction.nim +++ b/nimbus/core/executor/process_transaction.nim @@ -87,11 +87,11 @@ proc processTransactionImpl( vmState.cumulativeGasUsed += gasBurned result = ok(gasBurned) - vmState.clearSelfDestructsAndEmptyAccounts(fork, miner) - if vmState.generateWitness: vmState.stateDB.collectWitnessData() - vmState.stateDB.persist(clearCache = false) + vmState.stateDB.persist( + clearEmptyAccount = fork >= FkSpurious, + clearCache = false) # ------------------------------------------------------------------------------ # Public functions diff --git a/nimbus/core/tx_pool/tx_tasks/tx_packer.nim b/nimbus/core/tx_pool/tx_tasks/tx_packer.nim index 3b75b7353..0a77ccbb0 100644 --- a/nimbus/core/tx_pool/tx_tasks/tx_packer.nim +++ b/nimbus/core/tx_pool/tx_tasks/tx_packer.nim @@ -71,7 +71,10 @@ proc persist(pst: TxPackerStateRef) {.gcsafe,raises: [RlpError].} = ## Smart wrapper if not pst.cleanState: - pst.xp.chain.vmState.stateDB.persist(clearCache = false) + let fork = pst.xp.chain.nextFork + pst.xp.chain.vmState.stateDB.persist( + clearEmptyAccount = fork >= FkSpurious, + clearCache = false) pst.cleanState = true # ------------------------------------------------------------------------------ @@ -111,9 +114,6 @@ proc runTxCommit(pst: TxPackerStateRef; item: TxItemRef; gasBurned: GasInt) let reward = gasBurned.u256 * gasTip.uint64.u256 vmState.stateDB.addBalance(xp.chain.feeRecipient, reward) - # Update account database - vmState.clearSelfDestructsAndEmptyAccounts(xp.chain.nextFork, xp.chain.feeRecipient) - if vmState.generateWitness: vmState.stateDB.collectWitnessData() @@ -123,7 +123,7 @@ proc runTxCommit(pst: TxPackerStateRef; item: TxItemRef; gasBurned: GasInt) # that the account cache has been saved, the `persist()` call is # obligatory here. if xp.chain.nextFork < FkByzantium: - pst.persist + pst.persist() # Update receipts sequence if vmState.receipts.len <= inx: @@ -188,7 +188,9 @@ proc vmExecGrabItem(pst: TxPackerStateRef; item: TxItemRef): Result[bool,void] # Commit account state DB vmState.stateDB.commit(accTx) - vmState.stateDB.persist(clearCache = false) + vmState.stateDB.persist( + clearEmptyAccount = xp.chain.nextFork >= FkSpurious, + clearCache = false) # let midRoot = vmState.stateDB.rootHash -- notused # Finish book-keeping and move item to `packed` bucket @@ -215,7 +217,9 @@ proc vmExecCommit(pst: TxPackerStateRef) if vmState.generateWitness: db.collectWitnessData() # Finish up, then vmState.stateDB.rootHash may be accessed - db.persist(ClearCache in vmState.flags) + db.persist( + clearEmptyAccount = xp.chain.nextFork >= FkSpurious, + clearCache = ClearCache in vmState.flags) # Update flexi-array, set proper length let nItems = xp.txDB.byStatus.eq(txItemPacked).nItems diff --git a/nimbus/core/validate.nim b/nimbus/core/validate.nim index be9f19098..b00145a95 100644 --- a/nimbus/core/validate.nim +++ b/nimbus/core/validate.nim @@ -17,9 +17,13 @@ import ./pow/[difficulty, header], ./pow, chronicles, - nimcrypto/utils, stew/[objects, results] +# chronicles stuff +when loggingEnabled or enabledLogLevel >= NONE: + import + nimcrypto/utils + from stew/byteutils import nil diff --git a/nimbus/db/accounts_cache.nim b/nimbus/db/accounts_cache.nim index b6fbd0944..d7cb4a298 100644 --- a/nimbus/db/accounts_cache.nim +++ b/nimbus/db/accounts_cache.nim @@ -6,11 +6,15 @@ import ./distinct_tries, ./access_list as ac_access_list +const + debugAccountsCache = false + type AccountFlag = enum Alive IsNew Dirty + Touched CodeLoaded CodeChanged StorageChanged @@ -34,7 +38,7 @@ type savePoint: SavePoint witnessCache: Table[EthAddress, WitnessData] isDirty: bool - touched: HashSet[EthAddress] + ripemdSpecial: bool ReadOnlyStateDB* = distinct AccountsCache @@ -46,8 +50,12 @@ type SavePoint* = ref object parentSavepoint: SavePoint cache: Table[EthAddress, RefAccount] + selfDestruct: HashSet[EthAddress] + logEntries: seq[Log] accessList: ac_access_list.AccessList state: TransactionState + when debugAccountsCache: + depth: int const emptyAcc = newAccount() @@ -55,19 +63,35 @@ const resetFlags = { Dirty, IsNew, + Touched, CodeChanged, StorageChanged } -proc beginSavepoint*(ac: var AccountsCache): SavePoint {.gcsafe.} + ripemdAddr* = block: + proc initAddress(x: int): EthAddress {.compileTime.} = + result[19] = x.byte + initAddress(3) +when debugAccountsCache: + import + stew/byteutils + + proc inspectSavePoint(name: string, x: SavePoint) = + debugEcho "*** ", name, ": ", x.depth, " ***" + var sp = x + while sp != nil: + for address, acc in sp.cache: + debugEcho address.toHex, " ", acc.flags + sp = sp.parentSavepoint + +proc beginSavepoint*(ac: var AccountsCache): SavePoint {.gcsafe.} # FIXME-Adam: this is only necessary because of my sanity checks on the latest rootHash; # take this out once those are gone. proc rawTrie*(ac: AccountsCache): AccountsTrie = ac.trie proc rawDb*(ac: AccountsCache): TrieDatabaseRef = ac.trie.db - # The AccountsCache is modeled after TrieDatabase for it's transaction style proc init*(x: typedesc[AccountsCache], db: TrieDatabaseRef, root: KeccakHash, pruneTrie: bool = true): AccountsCache = @@ -99,6 +123,11 @@ proc beginSavepoint*(ac: var AccountsCache): SavePoint = result.parentSavepoint = ac.savePoint ac.savePoint = result + when debugAccountsCache: + if not result.parentSavePoint.isNil: + result.depth = result.parentSavePoint.depth + 1 + inspectSavePoint("snapshot", result) + proc rollback*(ac: var AccountsCache, sp: SavePoint) = # Transactions should be handled in a strictly nested fashion. # Any child transaction must be committed or rolled-back before @@ -107,6 +136,9 @@ proc rollback*(ac: var AccountsCache, sp: SavePoint) = ac.savePoint = sp.parentSavepoint sp.state = RolledBack + when debugAccountsCache: + inspectSavePoint("rollback", ac.savePoint) + proc commit*(ac: var AccountsCache, sp: SavePoint) = # Transactions should be handled in a strictly nested fashion. # Any child transaction must be committed or rolled-back before @@ -120,8 +152,13 @@ proc commit*(ac: var AccountsCache, sp: SavePoint) = sp.parentSavepoint.cache[k] = v ac.savePoint.accessList.merge(sp.accessList) + ac.savePoint.selfDestruct.incl sp.selfDestruct + ac.savePoint.logEntries.add sp.logEntries sp.state = Committed + when debugAccountsCache: + inspectSavePoint("commit", ac.savePoint) + proc dispose*(ac: var AccountsCache, sp: SavePoint) {.inline.} = if sp.state == Pending: ac.rollback(sp) @@ -397,7 +434,7 @@ proc addBalance*(ac: AccountsCache, address: EthAddress, delta: UInt256) {.inlin if delta == 0.u256: let acc = ac.getAccount(address) if acc.isEmpty: - ac.touched.incl address + ac.makeDirty(address).flags.incl Touched return ac.setBalance(address, ac.getBalance(address) + delta) @@ -445,8 +482,26 @@ proc deleteAccount*(ac: AccountsCache, address: EthAddress) = let acc = ac.getAccount(address) acc.kill() -proc deleteAccountIfEmpty*(ac: AccountsCache, address: EthAddress) = - # see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-158.md +proc selfDestruct*(ac: AccountsCache, address: EthAddress) = + ac.savePoint.selfDestruct.incl address + +proc selfDestructLen*(ac: AccountsCache): int = + ac.savePoint.selfDestruct.len + +proc addLogEntry*(ac: AccountsCache, log: Log) = + ac.savePoint.logEntries.add log + +proc logEntries*(ac: AccountsCache): seq[Log] = + ac.savePoint.logEntries + +proc getAndClearLogEntries*(ac: AccountsCache): seq[Log] = + result = ac.savePoint.logEntries + ac.savePoint.logEntries.setLen(0) + +proc ripemdSpecial*(ac: AccountsCache) = + ac.ripemdSpecial = true + +proc deleteEmptyAccount(ac: AccountsCache, address: EthAddress) = let acc = ac.getAccount(address, false) if acc.isNil: return @@ -454,14 +509,32 @@ proc deleteAccountIfEmpty*(ac: AccountsCache, address: EthAddress) = return if not acc.exists: return - if address in ac.touched or Dirty in acc.flags: - ac.deleteAccount(address) + acc.kill() -proc persist*(ac: AccountsCache, clearCache: bool = true) = +proc clearEmptyAccounts(ac: AccountsCache) = + for address, acc in ac.savePoint.cache: + if Touched in acc.flags and + acc.isEmpty and acc.exists: + acc.kill() + + # https://github.com/ethereum/EIPs/issues/716 + if ac.ripemdSpecial: + ac.deleteEmptyAccount(ripemdAddr) + ac.ripemdSpecial = false + +proc persist*(ac: AccountsCache, + clearEmptyAccount: bool = false, + clearCache: bool = true) = # make sure all savepoint already committed doAssert(ac.savePoint.parentSavepoint.isNil) var cleanAccounts = initHashSet[EthAddress]() + if clearEmptyAccount: + ac.clearEmptyAccounts() + + for address in ac.savePoint.selfDestruct: + ac.deleteAccount(address) + for address, acc in ac.savePoint.cache: case acc.persistMode() of Update: @@ -487,7 +560,7 @@ proc persist*(ac: AccountsCache, clearCache: bool = true) = for x in cleanAccounts: ac.savePoint.cache.del x - ac.touched.clear() + ac.savePoint.selfDestruct.clear() # EIP2929 ac.savePoint.accessList.clear() diff --git a/nimbus/evm/computation.nim b/nimbus/evm/computation.nim index ea718de35..5b3e948b1 100644 --- a/nimbus/evm/computation.nim +++ b/nimbus/evm/computation.nim @@ -195,8 +195,6 @@ proc newComputation*(vmState: BaseVMState, message: Message, result.stack = newStack() result.returnStack = @[] result.gasMeter.init(message.gas) - result.touchedAccounts = initHashSet[EthAddress]() - result.selfDestructs = initHashSet[EthAddress]() if result.msg.isCreate(): result.msg.contractAddress = result.generateContractAddress(salt) @@ -214,8 +212,6 @@ proc newComputation*(vmState: BaseVMState, message: Message, code: seq[byte]): C result.stack = newStack() result.returnStack = @[] result.gasMeter.init(message.gas) - result.touchedAccounts = initHashSet[EthAddress]() - result.selfDestructs = initHashSet[EthAddress]() result.code = newCodeStream(code) template gasCosts*(c: Computation): untyped = @@ -237,9 +233,6 @@ template isError*(c: Computation): bool = func shouldBurnGas*(c: Computation): bool = c.isError and c.error.burnsGas -proc isSelfDestructed*(c: Computation, address: EthAddress): bool = - result = address in c.selfDestructs - proc snapshot*(c: Computation) = c.savePoint = c.vmState.stateDB.beginSavepoint() @@ -327,10 +320,7 @@ template asyncChainTo*(c: Computation, asyncOperation: Future[void], after: unty after proc merge*(c, child: Computation) = - c.logEntries.add child.logEntries c.gasMeter.refundGas(child.gasMeter.gasRefunded) - c.selfDestructs.incl child.selfDestructs - c.touchedAccounts.incl child.touchedAccounts proc execSelfDestruct*(c: Computation, beneficiary: EthAddress) {.gcsafe, raises: [CatchableError].} = @@ -345,17 +335,16 @@ proc execSelfDestruct*(c: Computation, beneficiary: EthAddress) # contract named itself as the beneficiary. db.setBalance(c.msg.contractAddress, 0.u256) + # Register the account to be deleted + db.selfDestruct(c.msg.contractAddress) + trace "SELFDESTRUCT", contractAddress = c.msg.contractAddress.toHex, localBalance = localBalance.toString, beneficiary = beneficiary.toHex - c.touchedAccounts.incl beneficiary - # Register the account to be deleted - c.selfDestructs.incl(c.msg.contractAddress) - proc addLogEntry*(c: Computation, log: Log) = - c.logEntries.add(log) + c.vmState.stateDB.addLogEntry(log) proc getGasRefund*(c: Computation): GasInt = if c.isSuccess: @@ -363,7 +352,8 @@ proc getGasRefund*(c: Computation): GasInt = proc refundSelfDestruct*(c: Computation) = let cost = gasFees[c.fork][RefundSelfDestruct] - c.gasMeter.refundGas(cost * c.selfDestructs.len) + let num = c.vmState.stateDB.selfDestructLen + c.gasMeter.refundGas(cost * num) proc tracingEnabled*(c: Computation): bool = TracerFlags.EnableTracing in c.vmState.tracer.flags diff --git a/nimbus/evm/interpreter_dispatch.nim b/nimbus/evm/interpreter_dispatch.nim index f5f0086d3..d5db76a3c 100644 --- a/nimbus/evm/interpreter_dispatch.nim +++ b/nimbus/evm/interpreter_dispatch.nim @@ -14,7 +14,7 @@ const lowMemoryCompileTime {.used.} = lowmem > 0 import - std/[macros, sets, strformat], + std/[macros, strformat], pkg/[chronicles, chronos, stew/byteutils], ".."/[constants, utils/utils, db/accounts_cache], "."/[code_stream, computation], @@ -26,12 +26,6 @@ import logScope: topics = "vm opcode" -const - ripemdAddr = block: - proc initAddress(x: int): EthAddress {.compileTime.} = - result[19] = x.byte - initAddress(3) - # ------------------------------------------------------------------------------ # Private functions # ------------------------------------------------------------------------------ @@ -105,7 +99,6 @@ proc selectVM(c: Computation, fork: EVMFork, shouldPrepareTracer: bool) genLowMemDispatcher(fork, c.instr, desc) - proc beforeExecCall(c: Computation) = c.snapshot() if c.msg.kind == evmcCall: @@ -121,15 +114,13 @@ proc afterExecCall(c: Computation) = if c.isError or c.fork >= FkByzantium: if c.msg.contractAddress == ripemdAddr: # Special case to account for geth+parity bug - c.vmState.touchedAccounts.incl c.msg.contractAddress + c.vmState.stateDB.ripemdSpecial() if c.isSuccess: c.commit() - c.touchedAccounts.incl c.msg.contractAddress else: c.rollback() - proc beforeExecCreate(c: Computation): bool {.gcsafe, raises: [ValueError].} = c.vmState.mutateStateDB: @@ -179,7 +170,6 @@ proc afterExecCreate(c: Computation) else: c.rollback() - proc beforeExec(c: Computation): bool {.gcsafe, raises: [ValueError].} = if not c.msg.isCreate: diff --git a/nimbus/evm/state.nim b/nimbus/evm/state.nim index ac54b3b5a..f2a6b6258 100644 --- a/nimbus/evm/state.nim +++ b/nimbus/evm/state.nim @@ -43,9 +43,7 @@ proc init( self.blockDifficulty = difficulty self.com = com self.tracer = tracer - self.logEntries = @[] self.stateDB = ac - self.touchedAccounts = initHashSet[EthAddress]() self.minerAddress = miner self.asyncFactory = AsyncOperationFactory(maybeDataSource: none[AsyncDataSource]()) @@ -326,8 +324,7 @@ proc getTracingResult*(vmState: BaseVMState): JsonNode {.inline.} = vmState.tracer.trace proc getAndClearLogEntries*(vmState: BaseVMState): seq[Log] = - shallowCopy(result, vmState.logEntries) - vmState.logEntries = @[] + vmState.stateDB.getAndClearLogEntries() proc enableTracing*(vmState: BaseVMState) = vmState.tracer.flags.incl EnableTracing @@ -390,14 +387,3 @@ func forkDeterminationInfoForVMState*(vmState: BaseVMState): ForkDeterminationIn func determineFork*(vmState: BaseVMState): EVMFork = vmState.com.toEVMFork(vmState.forkDeterminationInfoForVMState) - -proc clearSelfDestructsAndEmptyAccounts*(vmState: BaseVMState, fork: EVMFork, miner: EthAddress): void = - vmState.mutateStateDB: - for deletedAccount in vmState.selfDestructs: - db.deleteAccount(deletedAccount) - - if fork >= FkSpurious: - vmState.touchedAccounts.incl(miner) - # EIP158/161 state clearing - for account in vmState.touchedAccounts: - db.deleteAccountIfEmpty(account) diff --git a/nimbus/evm/state_transactions.nim b/nimbus/evm/state_transactions.nim index 1aa5084e6..feb49384a 100644 --- a/nimbus/evm/state_transactions.nim +++ b/nimbus/evm/state_transactions.nim @@ -52,10 +52,6 @@ proc postExecComputation(c: Computation) = if c.fork < FkLondon: # EIP-3529: Reduction in refunds c.refundSelfDestruct() - shallowCopy(c.vmState.selfDestructs, c.selfDestructs) - shallowCopy(c.vmState.logEntries, c.logEntries) - c.vmState.touchedAccounts.incl c.touchedAccounts - c.vmState.status = c.isSuccess proc execComputation*(c: Computation) diff --git a/nimbus/evm/types.nim b/nimbus/evm/types.nim index 45bbceb5a..3e764fae1 100644 --- a/nimbus/evm/types.nim +++ b/nimbus/evm/types.nim @@ -46,12 +46,9 @@ type blockDifficulty*: UInt256 flags* : set[VMFlag] tracer* : TransactionTracer - logEntries* : seq[Log] receipts* : seq[Receipt] stateDB* : AccountsCache cumulativeGasUsed*: GasInt - touchedAccounts*: HashSet[EthAddress] - selfDestructs* : HashSet[EthAddress] txOrigin* : EthAddress txGasPrice* : GasInt gasCosts* : GasCosts @@ -89,9 +86,6 @@ type output*: seq[byte] returnData*: seq[byte] error*: Error - touchedAccounts*: HashSet[EthAddress] - selfDestructs*: HashSet[EthAddress] - logEntries*: seq[Log] savePoint*: SavePoint instr*: Op opIndex*: int diff --git a/nimbus/transaction/call_common.nim b/nimbus/transaction/call_common.nim index 93fecd9a7..a886d19d2 100644 --- a/nimbus/transaction/call_common.nim +++ b/nimbus/transaction/call_common.nim @@ -264,7 +264,7 @@ proc finishRunningComputation(host: TransactionHost, call: CallParams): CallResu shallowCopy(result.output, c.output) result.contractAddress = if call.isCreate: c.msg.contractAddress else: default(HostAddress) - shallowCopy(result.logEntries, c.logEntries) + result.logEntries = host.vmState.stateDB.logEntries() result.stack = c.stack result.memory = c.memory diff --git a/nimbus/transaction/host_services.nim b/nimbus/transaction/host_services.nim index 815d9cd7f..eba59d721 100644 --- a/nimbus/transaction/host_services.nim +++ b/nimbus/transaction/host_services.nim @@ -220,15 +220,7 @@ proc selfDestruct(host: TransactionHost, address, beneficiary: HostAddress) {.sh # This must come after sending to the beneficiary in case the # contract named itself as the beneficiary. db.setBalance(address, 0.u256) - - # TODO: Calling via `computation` is necessary to make some tests pass. - # Here's one that passes only with this: - # tests/fixtures/eth_tests/GeneralStateTests/stRandom2/randomStatetest487.json - # We can't keep using `computation` though. - host.computation.touchedAccounts.incl(beneficiary) - host.computation.selfDestructs.incl(address) - #host.touchedAccounts.incl(beneficiary) - #host.selfDestructs.incl(address) + db.selfDestruct(address) template call(host: TransactionHost, msg: EvmcMessage): EvmcResult = # `call` is special. The C stack usage must be kept small for deeply nested @@ -266,13 +258,7 @@ proc emitLog(host: TransactionHost, address: HostAddress, copyMem(log.data[0].addr, data, data_size.int) log.address = address - - # TODO: Calling via `computation` is necessary to makes some tests pass. - # Here's one that passes only with this: - # tests/fixtures/eth_tests/GeneralStateTests/stRandom2/randomStatetest583.json - # We can't keep using `computation` though. - host.computation.logEntries.add(log) - #host.logEntries.add(log) + host.vmState.stateDB.addlogEntry(log) proc accessAccount(host: TransactionHost, address: HostAddress): EvmcAccessStatus {.show.} = host.vmState.mutateStateDB: diff --git a/nimbus/transaction/host_types.nim b/nimbus/transaction/host_types.nim index 558f130ac..83723b3ac 100644 --- a/nimbus/transaction/host_types.nim +++ b/nimbus/transaction/host_types.nim @@ -59,9 +59,6 @@ type code*: seq[byte] cachedTxContext*: bool txContext*: EvmcTxContext - logEntries*: seq[Log] - touchedAccounts*: HashSet[EthAddress] - selfDestructs*: HashSet[EthAddress] depth*: int saveComputation*: seq[Computation] hostInterface*: ptr evmc_host_interface diff --git a/nimbus/utils/debug.nim b/nimbus/utils/debug.nim index 78f887279..8db19764c 100644 --- a/nimbus/utils/debug.nim +++ b/nimbus/utils/debug.nim @@ -9,7 +9,7 @@ # according to those terms. import - std/[options, times, json, strutils, sets], + std/[options, times, json, strutils], ../common/common, stew/byteutils, ../vm_state, @@ -98,12 +98,9 @@ proc debug*(vms: BaseVMState): string = result.add "prevRandao : " & $vms.prevRandao & "\n" result.add "blockDifficulty : " & $vms.blockDifficulty & "\n" result.add "flags : " & $vms.flags & "\n" - result.add "logEntries.len : " & $vms.logEntries.len & "\n" result.add "receipts.len : " & $vms.receipts.len & "\n" result.add "stateDB.root : " & $vms.stateDB.rootHash & "\n" result.add "cumulativeGasUsed: " & $vms.cumulativeGasUsed & "\n" - result.add "touchedAccs.len : " & $vms.touchedAccounts.len & "\n" - result.add "selfDestructs.len: " & $vms.selfDestructs.len & "\n" result.add "txOrigin : " & $vms.txOrigin & "\n" result.add "txGasPrice : " & $vms.txGasPrice & "\n" result.add "fork : " & $vms.fork & "\n" diff --git a/nimbus/vm_computation.nim b/nimbus/vm_computation.nim index 2dd15225e..f030d9108 100644 --- a/nimbus/vm_computation.nim +++ b/nimbus/vm_computation.nim @@ -44,7 +44,6 @@ export vmc.isError, vmc.isOriginComputation, vmc.isSuccess, - vmc.isSelfDestructed, vmc.merge, vmc.newComputation, vmc.prepareTracer, diff --git a/nimbus/vm_internals.nim b/nimbus/vm_internals.nim index e1f85b2c9..2e3191d15 100644 --- a/nimbus/vm_internals.nim +++ b/nimbus/vm_internals.nim @@ -94,7 +94,6 @@ export bChp.isError, bChp.isOriginComputation, bChp.isSuccess, - bChp.isSelfDestructed, bChp.merge, bChp.newComputation, bChp.prepareTracer, diff --git a/nimbus/vm_state.nim b/nimbus/vm_state.nim index 20fb5c6d2..b88014db4 100644 --- a/nimbus/vm_state.nim +++ b/nimbus/vm_state.nim @@ -18,7 +18,6 @@ export vms.`$`, vms.blockNumber, vms.buildWitness, - vms.clearSelfDestructsAndEmptyAccounts, vms.coinbase, vms.determineFork, vms.difficulty, diff --git a/tests/macro_assembler.nim b/tests/macro_assembler.nim index 9fc391f35..95b558e9f 100644 --- a/tests/macro_assembler.nim +++ b/tests/macro_assembler.nim @@ -350,7 +350,7 @@ proc verifyAsmResult(vmState: BaseVMState, com: CommonRef, boa: Assembler, asmRe error "storage has different value", key=key, expected=val, actual=value return false - let logs = vmState.logEntries + let logs = vmState.getAndClearLogEntries() if logs.len != boa.logs.len: error "different logs len", expected=boa.logs.len, actual=logs.len return false diff --git a/tests/test_generalstate_json.nim b/tests/test_generalstate_json.nim index 3e685cddb..2e6136fa6 100644 --- a/tests/test_generalstate_json.nim +++ b/tests/test_generalstate_json.nim @@ -87,7 +87,7 @@ proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) = let obtainedHash = vmState.readOnlyStateDB.rootHash check obtainedHash == tester.expectedHash let logEntries = vmState.getAndClearLogEntries() - let actualLogsHash = hashLogEntries(logEntries) + let actualLogsHash = rlpHash(logEntries) check(tester.expectedLogs == actualLogsHash) if tester.debugMode: let success = tester.expectedLogs == actualLogsHash and obtainedHash == tester.expectedHash diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim index 075e4334c..89ab8f338 100644 --- a/tests/test_helpers.nim +++ b/tests/test_helpers.nim @@ -7,7 +7,7 @@ import std/[os, macros, json, strformat, strutils, tables], - stew/byteutils, net, eth/[keys, rlp, p2p], unittest2, + stew/byteutils, net, eth/[keys, p2p], unittest2, testutils/markdown_reports, ../nimbus/[constants, config, transaction, errors], ../nimbus/db/accounts_cache, @@ -138,9 +138,6 @@ proc verifyStateDB*(wantedState: JsonNode, stateDB: ReadOnlyStateDB) = if wantedNonce != actualNonce: raise newException(ValidationError, &"{ac} nonceDiff {wantedNonce.toHex} != {actualNonce.toHex}") -proc hashLogEntries*(logs: seq[Log]): Hash256 = - keccakHash(rlp.encode(logs)) - proc setupEthNode*( conf: NimbusConf, ctx: EthContext, capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = diff --git a/tools/common/state_clearing.nim b/tools/common/state_clearing.nim index 4c3ae2ea6..2d0259f95 100644 --- a/tools/common/state_clearing.nim +++ b/tools/common/state_clearing.nim @@ -31,9 +31,6 @@ proc coinbaseStateClearing*(vmState: BaseVMState, if touched: db.addBalance(miner, 0.u256) - if fork >= FkSpurious: - db.deleteAccountIfEmpty(miner) - # db.persist is an important step when using accounts_cache # it will affect the account storage's location # during the next call to `getComittedStorage` @@ -41,4 +38,6 @@ proc coinbaseStateClearing*(vmState: BaseVMState, # do not clear cache, we need the cache when constructing # post state - db.persist(clearCache = false) + db.persist( + clearEmptyAccount = fork >= FkSpurious, + clearCache = false) diff --git a/tools/evmstate/evmstate.nim b/tools/evmstate/evmstate.nim index 3ace28d7e..2ab9390c9 100644 --- a/tools/evmstate/evmstate.nim +++ b/tools/evmstate/evmstate.nim @@ -215,7 +215,7 @@ proc runExecution(ctx: var StateContext, conf: StateConf, pre: JsonNode): StateR vmState.mutateStateDB: setupStateDB(pre, db) - db.persist() # settle accounts storage + db.persist(clearEmptyAccount = false) # settle accounts storage defer: ctx.verifyResult(vmState) diff --git a/tools/t8n/transition.nim b/tools/t8n/transition.nim index 8c7424161..132b36e43 100644 --- a/tools/t8n/transition.nim +++ b/tools/t8n/transition.nim @@ -220,7 +220,6 @@ proc exec(ctx: var TransContext, vmState.mutateStateDB: db.addBalance(ctx.env.currentCoinbase, mainReward) - db.persist(clearCache = false) let miner = ctx.env.currentCoinbase let fork = vmState.com.toEVMFork @@ -411,7 +410,7 @@ proc transitionAction*(ctx: var TransContext, conf: T8NConf) = vmState.mutateStateDB: db.setupAlloc(ctx.alloc) - db.persist(clearCache = false) + db.persist(clearEmptyAccount = false, clearCache = false) let res = exec(ctx, vmState, conf.stateReward, header)