move exception handler deeper in the EVM
This commit is contained in:
parent
07ac4620d9
commit
4c0ba876ef
|
@ -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]) =
|
||||||
|
@ -183,24 +201,8 @@ proc applyMessage*(computation: BaseComputation, opCode: static[Op]) =
|
||||||
computation.commit()
|
computation.commit()
|
||||||
return
|
return
|
||||||
|
|
||||||
let fork = computation.getFork
|
executeOpcodes(computation)
|
||||||
|
postExecuteVM(computation)
|
||||||
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()
|
|
||||||
|
|
||||||
proc addChildComputation*(computation: BaseComputation, child: BaseComputation) =
|
proc addChildComputation*(computation: BaseComputation, child: BaseComputation) =
|
||||||
if child.isError:
|
if child.isError:
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -56,10 +56,7 @@ 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
|
||||||
|
|
Loading…
Reference in New Issue