move exception handler deeper in the EVM

This commit is contained in:
andri lim 2019-04-04 10:50:25 +07:00
parent 07ac4620d9
commit 4c0ba876ef
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
4 changed files with 40 additions and 31 deletions

View File

@ -167,6 +167,24 @@ proc transferBalance(computation: BaseComputation, opCode: static[Op]) =
db.subBalance(computation.msg.sender, computation.msg.value)
db.addBalance(computation.msg.storageAddress, computation.msg.value)
template continuation*(comp: BaseComputation, body: untyped) =
var tmpNext = comp.nextProc
comp.nextProc = proc() =
body
tmpNext()
proc postExecuteVM(computation: BaseComputation) =
if computation.isSuccess and computation.msg.isCreate:
let fork = computation.getFork
let contractFailed = not computation.writeContract(fork)
if contractFailed and fork == FkHomestead:
computation.setError(&"writeContract failed, depth={computation.msg.depth}", true)
if computation.isSuccess:
computation.commit()
else:
computation.rollback()
proc executeOpcodes*(computation: BaseComputation) {.gcsafe.}
proc applyMessage*(computation: BaseComputation, opCode: static[Op]) =
@ -182,25 +200,9 @@ proc applyMessage*(computation: BaseComputation, opCode: static[Op]) =
if computation.gasMeter.gasRemaining < 0:
computation.commit()
return
let fork = computation.getFork
try:
if not computation.execPrecompiles(fork):
executeOpcodes(computation)
except:
let msg = getCurrentExceptionMsg()
computation.setError(&"applyMessage Error msg={msg}, depth={computation.msg.depth}", true)
if computation.isSuccess and computation.msg.isCreate:
let contractFailed = not computation.writeContract(fork)
if contractFailed and fork == FkHomestead:
computation.setError(&"writeContract failed, depth={computation.msg.depth}", true)
if computation.isSuccess:
computation.commit()
else:
computation.rollback()
executeOpcodes(computation)
postExecuteVM(computation)
proc addChildComputation*(computation: BaseComputation, child: BaseComputation) =
if child.isError:

View File

@ -231,14 +231,23 @@ proc opTableToCaseStmt(opTable: array[Op, NimNode], computation: NimNode): NimNo
# Wrap the case statement in while true + computed goto
result = quote do:
if `computation`.tracingEnabled:
`computation`.prepareTracer()
`computation`.instr = `computation`.code.next()
while true:
{.computedGoto.}
# TODO lots of macro magic here to unravel, with chronicles...
# `computation`.logger.log($`computation`.stack & "\n\n", fgGreen)
`result`
try:
let fork = `computation`.getFork
if `computation`.execPrecompiles(fork):
return
if `computation`.tracingEnabled:
`computation`.prepareTracer()
`computation`.instr = `computation`.code.next()
while true:
{.computedGoto.}
# TODO lots of macro magic here to unravel, with chronicles...
# `computation`.logger.log($`computation`.stack & "\n\n", fgGreen)
`result`
except:
let msg = getCurrentExceptionMsg()
let errorMsg = "Opcode Dispatch Error msg=" & msg & ", depth=" & $computation.msg.depth
`computation`.setError(errorMsg, true)
macro genFrontierDispatch(computation: BaseComputation): untyped =
result = opTableToCaseStmt(FrontierOpDispatch, computation)

View File

@ -67,6 +67,7 @@ type
dbsnapshot*: Snapshot
instr*: Op
opIndex*: int
nextProc*: proc()
Error* = ref object
info*: string

View File

@ -56,11 +56,8 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) =
createAddress = toAddress))
var computation = newBaseComputation(vmState, header.blockNumber, message)
try:
computation.executeOpcodes()
except VMError:
computation.error = Error(info: getCurrentExceptionMsg())
computation.executeOpcodes()
if not fixture{"post"}.isNil:
# Success checks
check(not computation.isError)