Merge branch 'jangko-fix_evm'

This commit is contained in:
Ștefan Talpalaru 2019-03-28 15:24:17 +01:00
commit 9d05c6bf4f
No known key found for this signature in database
GPG Key ID: CBF7934204F1B6F9
4 changed files with 38 additions and 64 deletions

View File

@ -7,7 +7,7 @@
import
chronicles, strformat, strutils, sequtils, macros, terminal, math, tables, options,
eth/[common, keys],
eth/[common, keys], eth/trie/db as triedb,
../constants, ../errors, ../validation, ../vm_state, ../vm_types,
./interpreter/[opcode_values, gas_meter, gas_costs, vm_forks],
./code_stream, ./memory, ./message, ./stack, ../db/[state_db, db_chain],
@ -93,24 +93,23 @@ proc prepareChildMessage*(
code,
childOptions)
type
ComputationSnapshot* = object
snapshot: Snapshot
computation: BaseComputation
proc snapshot*(comp: BaseComputation) =
comp.dbsnapshot.transaction = comp.vmState.chaindb.db.beginTransaction()
comp.dbsnapshot.intermediateRoot = comp.vmState.accountDb.rootHash
comp.vmState.blockHeader.stateRoot = comp.vmState.accountDb.rootHash
proc snapshot*(computation: BaseComputation): ComputationSnapshot =
result.snapshot = computation.vmState.snapshot()
result.computation = computation
proc revert*(comp: BaseComputation, burnsGas = false) =
comp.dbsnapshot.transaction.rollback()
comp.vmState.accountDb.rootHash = comp.dbsnapshot.intermediateRoot
comp.vmState.blockHeader.stateRoot = comp.dbsnapshot.intermediateRoot
comp.error = Error(info: getCurrentExceptionMsg(), burnsGas: burnsGas)
proc revert*(snapshot: var ComputationSnapshot, burnsGas: bool = false) =
snapshot.snapshot.revert()
snapshot.computation.error = Error(info: getCurrentExceptionMsg(), burnsGas: burnsGas)
proc commit*(comp: BaseComputation) =
comp.dbsnapshot.transaction.commit()
comp.vmState.accountDb.rootHash = comp.vmState.blockHeader.stateRoot
proc commit*(snapshot: var ComputationSnapshot) {.inline.} =
snapshot.snapshot.commit()
proc dispose*(snapshot: var ComputationSnapshot) {.inline.} =
snapshot.snapshot.dispose()
proc dispose*(comp: BaseComputation) {.inline.} =
comp.dbsnapshot.transaction.dispose()
proc getFork*(computation: BaseComputation): Fork =
result =
@ -165,16 +164,16 @@ proc transferBalance(computation: var BaseComputation, opCode: static[Op]): bool
proc executeOpcodes*(computation: var BaseComputation) {.gcsafe.}
proc applyMessage*(computation: var BaseComputation, opCode: static[Op]): bool =
var snapshot = computation.snapshot()
defer: snapshot.dispose()
computation.snapshot()
defer: computation.dispose()
when opCode in {CallCode, Call, Create}:
if not computation.transferBalance(opCode):
snapshot.revert()
computation.revert()
return
if computation.gasMeter.gasRemaining < 0:
snapshot.commit()
computation.commit()
return
try:
@ -197,9 +196,9 @@ proc applyMessage*(computation: var BaseComputation, opCode: static[Op]): bool =
result = not(contractFailed and fork == FkHomestead)
if result:
snapshot.commit()
computation.commit()
else:
snapshot.revert(true)
computation.revert(true)
proc addChildComputation(computation: var BaseComputation, child: BaseComputation) =
if child.isError:

View File

@ -186,7 +186,7 @@ let HomesteadOpDispatch {.compileTime.}: array[Op, NimNode] = genHomesteadJumpTa
proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNode =
let instr = genSym(nskVar)
let instr = quote do: `computation`.instr
result = nnkCaseStmt.newTree(instr)
# Add a branch for each (opcode, proc) pair
@ -199,28 +199,26 @@ proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNo
trace "op: Stop"
if not `computation`.code.atEnd() and `computation`.tracingEnabled:
# we only trace `REAL STOP` and ignore `FAKE STOP`
let lastOpIndex = `computation`.traceOpCodeStarted(`asOp`)
`computation`.traceOpCodeEnded(`asOp`, lastOpIndex)
`computation`.opIndex = `computation`.traceOpCodeStarted(`asOp`)
`computation`.traceOpCodeEnded(`asOp`, `computation`.opIndex)
break
else:
if BaseGasCosts[op].kind == GckFixed:
quote do:
var lastOpIndex: int
if `computation`.tracingEnabled:
lastOpIndex = `computation`.traceOpCodeStarted(`asOp`)
`computation`.opIndex = `computation`.traceOpCodeStarted(`asOp`)
`computation`.gasMeter.consumeGas(`computation`.gasCosts[`asOp`].cost, reason = $`asOp`)
`opImpl`(`computation`)
if `computation`.tracingEnabled:
`computation`.traceOpCodeEnded(`asOp`, lastOpIndex)
`computation`.traceOpCodeEnded(`asOp`, `computation`.opIndex)
`instr` = `computation`.code.next()
else:
quote do:
var lastOpIndex: int
if `computation`.tracingEnabled:
lastOpIndex = `computation`.traceOpCodeStarted(`asOp`)
`computation`.opIndex = `computation`.traceOpCodeStarted(`asOp`)
`opImpl`(`computation`)
if `computation`.tracingEnabled:
`computation`.traceOpCodeEnded(`asOp`, lastOpIndex)
`computation`.traceOpCodeEnded(`asOp`, `computation`.opIndex)
when `asOp` in {Return, Revert, SelfDestruct}:
break
else:
@ -235,7 +233,7 @@ proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNo
result = quote do:
if `computation`.tracingEnabled:
`computation`.prepareTracer()
var `instr` = `computation`.code.next()
`computation`.instr = `computation`.code.next()
while true:
{.computedGoto.}
# TODO lots of macro magic here to unravel, with chronicles...

View File

@ -132,33 +132,6 @@ template mutateStateDB*(vmState: BaseVMState, body: untyped) =
if finalStateRoot != initialStateRoot:
vmState.blockHeader.stateRoot = finalStateRoot
export DbTransaction, commit, rollback, dispose, safeDispose
type
Snapshot* = object
transaction: DbTransaction
intermediateRoot: Hash256
vmState: BaseVMState
proc snapshot*(vmState: BaseVMState): Snapshot =
# TODO: use AccountStateDB revert/commit after JournalDB implemented
result.transaction = vmState.chaindb.db.beginTransaction()
result.intermediateRoot = vmState.accountDb.rootHash
vmState.blockHeader.stateRoot = vmState.accountDb.rootHash
result.vmState = vmState
proc revert*(s: var Snapshot) =
s.transaction.rollback()
s.vmState.accountDb.rootHash = s.intermediateRoot
s.vmState.blockHeader.stateRoot = s.intermediateRoot
proc commit*(s: var Snapshot) =
s.transaction.commit()
s.vmState.accountDb.rootHash = s.vmState.blockHeader.stateRoot
proc dispose*(s: var Snapshot) {.inline.} =
s.transaction.dispose()
proc getTracingResult*(vmState: BaseVMState): JsonNode =
doAssert(vmState.tracingEnabled)
vmState.tracer.trace
@ -189,4 +162,3 @@ iterator tracedAccountsPairs*(vmState: BaseVMState): (int, EthAddress) =
proc removeTracedAccounts*(vmState: BaseVMState, accounts: varargs[EthAddress]) =
for acc in accounts:
vmState.tracer.accounts.excl acc

View File

@ -6,8 +6,8 @@
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
tables, eth/common, options,
./constants, json, sets,
tables, eth/common, eth/trie/db,
options, ./constants, json, sets,
./vm/[memory, stack, code_stream],
./vm/interpreter/[gas_costs, opcode_values, vm_forks], # TODO - will be hidden at a lower layer
./db/[db_chain, state_db]
@ -44,6 +44,10 @@ type
accounts*: HashSet[EthAddress]
storageKeys*: seq[HashSet[Uint256]]
Snapshot* = object
transaction*: DbTransaction
intermediateRoot*: Hash256
BaseComputation* = ref object of RootObj
# The execution computation
vmState*: BaseVMState
@ -56,12 +60,13 @@ type
rawOutput*: seq[byte]
returnData*: seq[byte]
error*: Error
shouldEraseReturnData*: bool
accountsToDelete*: Table[EthAddress, EthAddress]
opcodes*: Table[Op, proc(computation: var BaseComputation){.nimcall.}]
gasCosts*: GasCosts # TODO - will be hidden at a lower layer
forkOverride*: Option[Fork]
logEntries*: seq[Log]
dbsnapshot*: Snapshot
instr*: Op
opIndex*: int
Error* = ref object
info*: string