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.subBalance(computation.msg.sender, computation.msg.value)
db.addBalance(computation.msg.storageAddress, 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 executeOpcodes*(computation: BaseComputation) {.gcsafe.}
proc applyMessage*(computation: BaseComputation, opCode: static[Op]) = proc applyMessage*(computation: BaseComputation, opCode: static[Op]) =
@ -182,25 +200,9 @@ proc applyMessage*(computation: BaseComputation, opCode: static[Op]) =
if computation.gasMeter.gasRemaining < 0: if computation.gasMeter.gasRemaining < 0:
computation.commit() computation.commit()
return 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: executeOpcodes(computation)
let contractFailed = not computation.writeContract(fork) postExecuteVM(computation)
if contractFailed and fork == FkHomestead:
computation.setError(&"writeContract failed, depth={computation.msg.depth}", true)
if computation.isSuccess:
computation.commit()
else:
computation.rollback()
proc addChildComputation*(computation: BaseComputation, child: BaseComputation) = proc addChildComputation*(computation: BaseComputation, child: BaseComputation) =
if child.isError: 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 # Wrap the case statement in while true + computed goto
result = quote do: result = quote do:
if `computation`.tracingEnabled: try:
`computation`.prepareTracer() let fork = `computation`.getFork
`computation`.instr = `computation`.code.next() if `computation`.execPrecompiles(fork):
while true: return
{.computedGoto.}
# TODO lots of macro magic here to unravel, with chronicles... if `computation`.tracingEnabled:
# `computation`.logger.log($`computation`.stack & "\n\n", fgGreen) `computation`.prepareTracer()
`result` `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 = macro genFrontierDispatch(computation: BaseComputation): untyped =
result = opTableToCaseStmt(FrontierOpDispatch, computation) result = opTableToCaseStmt(FrontierOpDispatch, computation)

View File

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

View File

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