EVM cosmetic changes, one less indirect access of VmCpt (#2503)
This commit is contained in:
parent
5ac362fe6f
commit
fb196849ee
|
@ -36,42 +36,42 @@ export
|
||||||
# Helpers
|
# Helpers
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
template handleStopDirective(k: var VmCtx) =
|
template handleStopDirective(cpt: VmCpt) =
|
||||||
#trace "op: Stop"
|
#trace "op: Stop"
|
||||||
if not k.cpt.code.atEnd() and k.cpt.tracingEnabled:
|
if not cpt.code.atEnd() and cpt.tracingEnabled:
|
||||||
# we only trace `REAL STOP` and ignore `FAKE STOP`
|
# we only trace `REAL STOP` and ignore `FAKE STOP`
|
||||||
k.cpt.opIndex = k.cpt.traceOpCodeStarted(Stop)
|
cpt.opIndex = cpt.traceOpCodeStarted(Stop)
|
||||||
k.cpt.traceOpCodeEnded(Stop, k.cpt.opIndex)
|
cpt.traceOpCodeEnded(Stop, cpt.opIndex)
|
||||||
|
|
||||||
|
|
||||||
template handleFixedGasCostsDirective(fork: EVMFork; op: Op; k: var VmCtx) =
|
template handleFixedGasCostsDirective(fork: EVMFork; op: Op; cpt: VmCpt) =
|
||||||
if k.cpt.tracingEnabled:
|
if cpt.tracingEnabled:
|
||||||
k.cpt.opIndex = k.cpt.traceOpCodeStarted(op)
|
cpt.opIndex = cpt.traceOpCodeStarted(op)
|
||||||
|
|
||||||
? k.cpt.opcodeGasCost(op, k.cpt.gasCosts[op].cost, reason = $op)
|
? cpt.opcodeGasCost(op, cpt.gasCosts[op].cost, reason = $op)
|
||||||
? vmOpHandlers[fork][op].run(k)
|
? vmOpHandlers[fork][op].run(cpt)
|
||||||
|
|
||||||
# If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes.
|
# If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes.
|
||||||
if k.cpt.tracingEnabled and k.cpt.continuation.isNil:
|
if cpt.tracingEnabled and cpt.continuation.isNil:
|
||||||
k.cpt.traceOpCodeEnded(op, k.cpt.opIndex)
|
cpt.traceOpCodeEnded(op, cpt.opIndex)
|
||||||
|
|
||||||
|
|
||||||
template handleOtherDirective(fork: EVMFork; op: Op; k: var VmCtx) =
|
template handleOtherDirective(fork: EVMFork; op: Op; cpt: VmCpt) =
|
||||||
if k.cpt.tracingEnabled:
|
if cpt.tracingEnabled:
|
||||||
k.cpt.opIndex = k.cpt.traceOpCodeStarted(op)
|
cpt.opIndex = cpt.traceOpCodeStarted(op)
|
||||||
|
|
||||||
? vmOpHandlers[fork][op].run(k)
|
? vmOpHandlers[fork][op].run(cpt)
|
||||||
|
|
||||||
# If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes.
|
# If continuation is not nil, traceOpCodeEnded will be called in executeOpcodes.
|
||||||
if k.cpt.tracingEnabled and k.cpt.continuation.isNil:
|
if cpt.tracingEnabled and cpt.continuation.isNil:
|
||||||
k.cpt.traceOpCodeEnded(op, k.cpt.opIndex)
|
cpt.traceOpCodeEnded(op, cpt.opIndex)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private, big nasty doubly nested case matrix generator
|
# Private, big nasty doubly nested case matrix generator
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# reminiscent of Mamy's opTableToCaseStmt() from original VM
|
# reminiscent of Mamy's opTableToCaseStmt() from original VM
|
||||||
proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
|
proc toCaseStmt(forkArg, opArg, cpt: NimNode): NimNode =
|
||||||
|
|
||||||
# Outer case/switch => Op
|
# Outer case/switch => Op
|
||||||
let branchOnOp = quote do: `opArg`
|
let branchOnOp = quote do: `opArg`
|
||||||
|
@ -89,13 +89,13 @@ proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
|
||||||
let branchStmt = block:
|
let branchStmt = block:
|
||||||
if op == Stop:
|
if op == Stop:
|
||||||
quote do:
|
quote do:
|
||||||
handleStopDirective(`k`)
|
handleStopDirective(`cpt`)
|
||||||
elif gcTable[op] == GckFixed:
|
elif gcTable[op] == GckFixed:
|
||||||
quote do:
|
quote do:
|
||||||
handleFixedGasCostsDirective(`asFork`,`asOp`,`k`)
|
handleFixedGasCostsDirective(`asFork`,`asOp`,`cpt`)
|
||||||
else:
|
else:
|
||||||
quote do:
|
quote do:
|
||||||
handleOtherDirective(`asFork`,`asOp`,`k`)
|
handleOtherDirective(`asFork`,`asOp`,`cpt`)
|
||||||
|
|
||||||
forkCaseSubExpr.add nnkOfBranch.newTree(asFork, branchStmt)
|
forkCaseSubExpr.add nnkOfBranch.newTree(asFork, branchStmt)
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
|
||||||
# break no matter what).
|
# break no matter what).
|
||||||
quote do:
|
quote do:
|
||||||
`forkCaseSubExpr`
|
`forkCaseSubExpr`
|
||||||
if not `k`.cpt.continuation.isNil:
|
if not `cpt`.continuation.isNil:
|
||||||
break
|
break
|
||||||
|
|
||||||
result.add nnkOfBranch.newTree(asOp, branchStmt)
|
result.add nnkOfBranch.newTree(asOp, branchStmt)
|
||||||
|
@ -124,26 +124,26 @@ proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
|
||||||
# Public macros/functions
|
# Public macros/functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
macro genOptimisedDispatcher*(fork: EVMFork; op: Op; k: VmCtx): untyped =
|
macro genOptimisedDispatcher*(fork: EVMFork; op: Op; cpt: VmCpt): untyped =
|
||||||
result = fork.toCaseStmt(op, k)
|
result = fork.toCaseStmt(op, cpt)
|
||||||
|
|
||||||
|
|
||||||
template genLowMemDispatcher*(fork: EVMFork; op: Op; k: VmCtx) =
|
template genLowMemDispatcher*(fork: EVMFork; op: Op; cpt: VmCpt) =
|
||||||
if op == Stop:
|
if op == Stop:
|
||||||
handleStopDirective(k)
|
handleStopDirective(cpt)
|
||||||
break
|
break
|
||||||
|
|
||||||
if BaseGasCosts[op].kind == GckFixed:
|
if BaseGasCosts[op].kind == GckFixed:
|
||||||
handleFixedGasCostsDirective(fork, op, k)
|
handleFixedGasCostsDirective(fork, op, cpt)
|
||||||
else:
|
else:
|
||||||
handleOtherDirective(fork, op, k)
|
handleOtherDirective(fork, op, cpt)
|
||||||
|
|
||||||
case c.instr
|
case cpt.instr
|
||||||
of Return, Revert, SelfDestruct:
|
of Return, Revert, SelfDestruct:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# FIXME-manyOpcodesNowRequireContinuations
|
# FIXME-manyOpcodesNowRequireContinuations
|
||||||
if not k.cpt.continuation.isNil:
|
if not cpt.continuation.isNil:
|
||||||
break
|
break
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -154,10 +154,9 @@ when isMainModule and isChatty:
|
||||||
|
|
||||||
import ../types
|
import ../types
|
||||||
|
|
||||||
proc optimised(c: Computation, fork: EVMFork): EvmResultVoid {.compileTime.} =
|
proc optimised(cpt: VmCpt, fork: EVMFork): EvmResultVoid {.compileTime.} =
|
||||||
var desc: VmCtx
|
|
||||||
while true:
|
while true:
|
||||||
genOptimisedDispatcher(fork, desc.cpt.instr, desc)
|
genOptimisedDispatcher(fork, cpt.instr, desc)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -122,9 +122,9 @@ const
|
||||||
|
|
||||||
when isMainModule and isChatty:
|
when isMainModule and isChatty:
|
||||||
|
|
||||||
proc opHandlersRun(fork: EVMFork; op: Op; d: var VmCtx) {.used.} =
|
proc opHandlersRun(fork: EVMFork; op: Op; cpt: VmCpt) {.used.} =
|
||||||
## Given a particular `fork` and an `op`-code, run the associated handler
|
## Given a particular `fork` and an `op`-code, run the associated handler
|
||||||
vmOpHandlers[fork][op].run(d)
|
vmOpHandlers[fork][op].run(cpt)
|
||||||
|
|
||||||
proc opHandlersName(fork: EVMFork; op: Op): string {.used.} =
|
proc opHandlersName(fork: EVMFork; op: Op): string {.used.} =
|
||||||
## Get name (or ID) of op handler
|
## Get name (or ID) of op handler
|
||||||
|
|
|
@ -37,19 +37,19 @@ func slt(x, y: UInt256): bool =
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc addOp (k: var VmCtx): EvmResultVoid =
|
proc addOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x01, Addition
|
## 0x01, Addition
|
||||||
k.cpt.stack.binaryOp(`+`)
|
cpt.stack.binaryOp(`+`)
|
||||||
|
|
||||||
proc mulOp(k: var VmCtx): EvmResultVoid =
|
proc mulOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x02, Multiplication
|
## 0x02, Multiplication
|
||||||
k.cpt.stack.binaryOp(`*`)
|
cpt.stack.binaryOp(`*`)
|
||||||
|
|
||||||
proc subOp(k: var VmCtx): EvmResultVoid =
|
proc subOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x03, Substraction
|
## 0x03, Substraction
|
||||||
k.cpt.stack.binaryOp(`-`)
|
cpt.stack.binaryOp(`-`)
|
||||||
|
|
||||||
proc divideOp(k: var VmCtx): EvmResultVoid =
|
proc divideOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x04, Division
|
## 0x04, Division
|
||||||
template div256(top, lhs, rhs) =
|
template div256(top, lhs, rhs) =
|
||||||
if rhs.isZero:
|
if rhs.isZero:
|
||||||
|
@ -58,9 +58,9 @@ proc divideOp(k: var VmCtx): EvmResultVoid =
|
||||||
else:
|
else:
|
||||||
top = lhs div rhs
|
top = lhs div rhs
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(div256)
|
cpt.stack.binaryWithTop(div256)
|
||||||
|
|
||||||
proc sdivOp(k: var VmCtx): EvmResultVoid =
|
proc sdivOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x05, Signed division
|
## 0x05, Signed division
|
||||||
template sdiv256(top, lhs, rhs) =
|
template sdiv256(top, lhs, rhs) =
|
||||||
if rhs.isZero.not:
|
if rhs.isZero.not:
|
||||||
|
@ -70,9 +70,9 @@ proc sdivOp(k: var VmCtx): EvmResultVoid =
|
||||||
top = lhs div rhs
|
top = lhs div rhs
|
||||||
setSign(top, signA xor signB)
|
setSign(top, signA xor signB)
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(sdiv256)
|
cpt.stack.binaryWithTop(sdiv256)
|
||||||
|
|
||||||
proc moduloOp(k: var VmCtx): EvmResultVoid =
|
proc moduloOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x06, Modulo
|
## 0x06, Modulo
|
||||||
template mod256(top, lhs, rhs) =
|
template mod256(top, lhs, rhs) =
|
||||||
if rhs.isZero:
|
if rhs.isZero:
|
||||||
|
@ -80,9 +80,9 @@ proc moduloOp(k: var VmCtx): EvmResultVoid =
|
||||||
else:
|
else:
|
||||||
top = lhs mod rhs
|
top = lhs mod rhs
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(mod256)
|
cpt.stack.binaryWithTop(mod256)
|
||||||
|
|
||||||
proc smodOp(k: var VmCtx): EvmResultVoid =
|
proc smodOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x07, Signed modulo
|
## 0x07, Signed modulo
|
||||||
template smod256(top, lhs, rhs) =
|
template smod256(top, lhs, rhs) =
|
||||||
if rhs.isZero.not:
|
if rhs.isZero.not:
|
||||||
|
@ -92,47 +92,47 @@ proc smodOp(k: var VmCtx): EvmResultVoid =
|
||||||
top = lhs mod rhs
|
top = lhs mod rhs
|
||||||
setSign(top, sign)
|
setSign(top, sign)
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(smod256)
|
cpt.stack.binaryWithTop(smod256)
|
||||||
|
|
||||||
proc addmodOp(k: var VmCtx): EvmResultVoid =
|
proc addmodOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x08, Modulo addition
|
## 0x08, Modulo addition
|
||||||
## Intermediate computations do not roll over at 2^256
|
## Intermediate computations do not roll over at 2^256
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
let
|
let
|
||||||
lhs = k.cpt.stack.lsPeekInt(^1)
|
lhs = cpt.stack.lsPeekInt(^1)
|
||||||
rhs = k.cpt.stack.lsPeekInt(^2)
|
rhs = cpt.stack.lsPeekInt(^2)
|
||||||
modulus = k.cpt.stack.lsPeekInt(^3)
|
modulus = cpt.stack.lsPeekInt(^3)
|
||||||
value = if modulus.isZero:
|
value = if modulus.isZero:
|
||||||
zero(UInt256)
|
zero(UInt256)
|
||||||
else:
|
else:
|
||||||
addmod(lhs, rhs, modulus)
|
addmod(lhs, rhs, modulus)
|
||||||
|
|
||||||
k.cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
k.cpt.stack.lsTop value
|
cpt.stack.lsTop value
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc mulmodOp(k: var VmCtx): EvmResultVoid =
|
proc mulmodOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x09, Modulo multiplication
|
## 0x09, Modulo multiplication
|
||||||
## Intermediate computations do not roll over at 2^256
|
## Intermediate computations do not roll over at 2^256
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
let
|
let
|
||||||
lhs = k.cpt.stack.lsPeekInt(^1)
|
lhs = cpt.stack.lsPeekInt(^1)
|
||||||
rhs = k.cpt.stack.lsPeekInt(^2)
|
rhs = cpt.stack.lsPeekInt(^2)
|
||||||
modulus = k.cpt.stack.lsPeekInt(^3)
|
modulus = cpt.stack.lsPeekInt(^3)
|
||||||
value = if modulus.isZero:
|
value = if modulus.isZero:
|
||||||
zero(UInt256)
|
zero(UInt256)
|
||||||
else:
|
else:
|
||||||
mulmod(lhs, rhs, modulus)
|
mulmod(lhs, rhs, modulus)
|
||||||
|
|
||||||
k.cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
k.cpt.stack.lsTop value
|
cpt.stack.lsTop value
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc expOp(k: var VmCtx): EvmResultVoid =
|
proc expOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x0A, Exponentiation
|
## 0x0A, Exponentiation
|
||||||
template exp256(top, base, exponent) =
|
template exp256(top, base, exponent) =
|
||||||
? k.cpt.opcodeGasCost(Exp,
|
? cpt.opcodeGasCost(Exp,
|
||||||
k.cpt.gasCosts[Exp].d_handler(exponent),
|
cpt.gasCosts[Exp].d_handler(exponent),
|
||||||
reason = "EXP: exponent bytes")
|
reason = "EXP: exponent bytes")
|
||||||
|
|
||||||
if not base.isZero:
|
if not base.isZero:
|
||||||
|
@ -145,9 +145,9 @@ proc expOp(k: var VmCtx): EvmResultVoid =
|
||||||
else:
|
else:
|
||||||
top = zero(UInt256)
|
top = zero(UInt256)
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(exp256)
|
cpt.stack.binaryWithTop(exp256)
|
||||||
|
|
||||||
proc signExtendOp(k: var VmCtx): EvmResultVoid =
|
proc signExtendOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x0B, Sign extend
|
## 0x0B, Sign extend
|
||||||
## Extend length of two’s complement signed integer.
|
## Extend length of two’s complement signed integer.
|
||||||
template se256(top, bits, value) =
|
template se256(top, bits, value) =
|
||||||
|
@ -164,62 +164,62 @@ proc signExtendOp(k: var VmCtx): EvmResultVoid =
|
||||||
else:
|
else:
|
||||||
top = value
|
top = value
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(se256)
|
cpt.stack.binaryWithTop(se256)
|
||||||
|
|
||||||
proc ltOp(k: var VmCtx): EvmResultVoid =
|
proc ltOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x10, Less-than comparison
|
## 0x10, Less-than comparison
|
||||||
template lt256(lhs, rhs): auto =
|
template lt256(lhs, rhs): auto =
|
||||||
(lhs < rhs).uint.u256
|
(lhs < rhs).uint.u256
|
||||||
k.cpt.stack.binaryOp(lt256)
|
cpt.stack.binaryOp(lt256)
|
||||||
|
|
||||||
proc gtOp(k: var VmCtx): EvmResultVoid =
|
proc gtOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x11, Greater-than comparison
|
## 0x11, Greater-than comparison
|
||||||
template gt256(lhs, rhs): auto =
|
template gt256(lhs, rhs): auto =
|
||||||
(lhs > rhs).uint.u256
|
(lhs > rhs).uint.u256
|
||||||
k.cpt.stack.binaryOp(gt256)
|
cpt.stack.binaryOp(gt256)
|
||||||
|
|
||||||
proc sltOp(k: var VmCtx): EvmResultVoid =
|
proc sltOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x12, Signed less-than comparison
|
## 0x12, Signed less-than comparison
|
||||||
template slt256(lhs, rhs): auto =
|
template slt256(lhs, rhs): auto =
|
||||||
slt(lhs, rhs).uint.u256
|
slt(lhs, rhs).uint.u256
|
||||||
k.cpt.stack.binaryOp(slt256)
|
cpt.stack.binaryOp(slt256)
|
||||||
|
|
||||||
proc sgtOp(k: var VmCtx): EvmResultVoid =
|
proc sgtOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x13, Signed greater-than comparison
|
## 0x13, Signed greater-than comparison
|
||||||
# Arguments are swapped and SLT is used.
|
# Arguments are swapped and SLT is used.
|
||||||
template sgt256(lhs, rhs): auto =
|
template sgt256(lhs, rhs): auto =
|
||||||
slt(rhs, lhs).uint.u256
|
slt(rhs, lhs).uint.u256
|
||||||
k.cpt.stack.binaryOp(sgt256)
|
cpt.stack.binaryOp(sgt256)
|
||||||
|
|
||||||
proc eqOp(k: var VmCtx): EvmResultVoid =
|
proc eqOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x14, Equality comparison
|
## 0x14, Equality comparison
|
||||||
template eq256(lhs, rhs): auto =
|
template eq256(lhs, rhs): auto =
|
||||||
(lhs == rhs).uint.u256
|
(lhs == rhs).uint.u256
|
||||||
k.cpt.stack.binaryOp(eq256)
|
cpt.stack.binaryOp(eq256)
|
||||||
|
|
||||||
proc isZeroOp(k: var VmCtx): EvmResultVoid =
|
proc isZeroOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x15, Check if zero
|
## 0x15, Check if zero
|
||||||
template zero256(value): auto =
|
template zero256(value): auto =
|
||||||
value.isZero.uint.u256
|
value.isZero.uint.u256
|
||||||
k.cpt.stack.unaryOp(zero256)
|
cpt.stack.unaryOp(zero256)
|
||||||
|
|
||||||
proc andOp(k: var VmCtx): EvmResultVoid =
|
proc andOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x16, Bitwise AND
|
## 0x16, Bitwise AND
|
||||||
k.cpt.stack.binaryOp(`and`)
|
cpt.stack.binaryOp(`and`)
|
||||||
|
|
||||||
proc orOp(k: var VmCtx): EvmResultVoid =
|
proc orOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x17, Bitwise OR
|
## 0x17, Bitwise OR
|
||||||
k.cpt.stack.binaryOp(`or`)
|
cpt.stack.binaryOp(`or`)
|
||||||
|
|
||||||
proc xorOp(k: var VmCtx): EvmResultVoid =
|
proc xorOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x18, Bitwise XOR
|
## 0x18, Bitwise XOR
|
||||||
k.cpt.stack.binaryOp(`xor`)
|
cpt.stack.binaryOp(`xor`)
|
||||||
|
|
||||||
proc notOp(k: var VmCtx): EvmResultVoid =
|
proc notOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x19, Check if zero
|
## 0x19, Check if zero
|
||||||
k.cpt.stack.unaryOp(`not`)
|
cpt.stack.unaryOp(`not`)
|
||||||
|
|
||||||
proc byteOp(k: var VmCtx): EvmResultVoid =
|
proc byteOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x20, Retrieve single byte from word.
|
## 0x20, Retrieve single byte from word.
|
||||||
template byte256(top, position, value) =
|
template byte256(top, position, value) =
|
||||||
if position >= 32.u256:
|
if position >= 32.u256:
|
||||||
|
@ -231,11 +231,11 @@ proc byteOp(k: var VmCtx): EvmResultVoid =
|
||||||
else:
|
else:
|
||||||
top = cast[array[32, byte]](value)[31 - pos].u256
|
top = cast[array[32, byte]](value)[31 - pos].u256
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(byte256)
|
cpt.stack.binaryWithTop(byte256)
|
||||||
|
|
||||||
# Constantinople's new opcodes
|
# Constantinople's new opcodes
|
||||||
|
|
||||||
proc shlOp(k: var VmCtx): EvmResultVoid =
|
proc shlOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x1b, Shift left
|
## 0x1b, Shift left
|
||||||
template shl256(top, lhs, num) =
|
template shl256(top, lhs, num) =
|
||||||
let shiftLen = lhs.safeInt
|
let shiftLen = lhs.safeInt
|
||||||
|
@ -244,9 +244,9 @@ proc shlOp(k: var VmCtx): EvmResultVoid =
|
||||||
else:
|
else:
|
||||||
top = num shl shiftLen
|
top = num shl shiftLen
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(shl256)
|
cpt.stack.binaryWithTop(shl256)
|
||||||
|
|
||||||
proc shrOp(k: var VmCtx): EvmResultVoid =
|
proc shrOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x1c, Shift right logical
|
## 0x1c, Shift right logical
|
||||||
template shr256(top, lhs, num) =
|
template shr256(top, lhs, num) =
|
||||||
let shiftLen = lhs.safeInt
|
let shiftLen = lhs.safeInt
|
||||||
|
@ -256,9 +256,9 @@ proc shrOp(k: var VmCtx): EvmResultVoid =
|
||||||
# uint version of `shr`
|
# uint version of `shr`
|
||||||
top = num shr shiftLen
|
top = num shr shiftLen
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(shr256)
|
cpt.stack.binaryWithTop(shr256)
|
||||||
|
|
||||||
proc sarOp(k: var VmCtx): EvmResultVoid =
|
proc sarOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x1d, Shift right arithmetic
|
## 0x1d, Shift right arithmetic
|
||||||
template sar256(top, lhs, num256) =
|
template sar256(top, lhs, num256) =
|
||||||
let
|
let
|
||||||
|
@ -275,7 +275,7 @@ proc sarOp(k: var VmCtx): EvmResultVoid =
|
||||||
# into uint256
|
# into uint256
|
||||||
top = cast[UInt256](num shr shiftLen)
|
top = cast[UInt256](num shr shiftLen)
|
||||||
|
|
||||||
k.cpt.stack.binaryWithTop(sar256)
|
cpt.stack.binaryWithTop(sar256)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public, op exec table entries
|
# Public, op exec table entries
|
||||||
|
|
|
@ -30,66 +30,65 @@ when not defined(evmc_enabled):
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc blockhashOp (k: var VmCtx): EvmResultVoid =
|
proc blockhashOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x40, Get the hash of one of the 256 most recent complete blocks.
|
## 0x40, Get the hash of one of the 256 most recent complete blocks.
|
||||||
template block256(top, number, conv) =
|
template block256(top, number, conv) =
|
||||||
if number > high(BlockNumber).u256:
|
if number > high(BlockNumber).u256:
|
||||||
top = zero(UInt256)
|
top = zero(UInt256)
|
||||||
else:
|
else:
|
||||||
conv(k.cpt.getBlockHash(number.truncate(BlockNumber)), top)
|
conv(cpt.getBlockHash(number.truncate(BlockNumber)), top)
|
||||||
|
|
||||||
k.cpt.stack.unaryWithTop(block256)
|
cpt.stack.unaryWithTop(block256)
|
||||||
|
|
||||||
proc coinBaseOp (k: var VmCtx): EvmResultVoid =
|
proc coinBaseOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x41, Get the block's beneficiary address.
|
## 0x41, Get the block's beneficiary address.
|
||||||
k.cpt.stack.push k.cpt.getCoinbase
|
cpt.stack.push cpt.getCoinbase
|
||||||
|
|
||||||
proc timestampOp (k: var VmCtx): EvmResultVoid =
|
proc timestampOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x42, Get the block's timestamp.
|
## 0x42, Get the block's timestamp.
|
||||||
k.cpt.stack.push k.cpt.getTimestamp
|
cpt.stack.push cpt.getTimestamp
|
||||||
|
|
||||||
proc blocknumberOp (k: var VmCtx): EvmResultVoid =
|
proc blocknumberOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x43, Get the block's number.
|
## 0x43, Get the block's number.
|
||||||
k.cpt.stack.push k.cpt.getBlockNumber
|
cpt.stack.push cpt.getBlockNumber
|
||||||
|
|
||||||
proc difficultyOp (k: var VmCtx): EvmResultVoid =
|
proc difficultyOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x44, Get the block's difficulty
|
## 0x44, Get the block's difficulty
|
||||||
k.cpt.stack.push k.cpt.getDifficulty
|
cpt.stack.push cpt.getDifficulty
|
||||||
|
|
||||||
proc gasLimitOp (k: var VmCtx): EvmResultVoid =
|
proc gasLimitOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x45, Get the block's gas limit
|
## 0x45, Get the block's gas limit
|
||||||
k.cpt.stack.push k.cpt.getGasLimit
|
cpt.stack.push cpt.getGasLimit
|
||||||
|
|
||||||
proc chainIdOp (k: var VmCtx): EvmResultVoid =
|
proc chainIdOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x46, Get current chain’s EIP-155 unique identifier.
|
## 0x46, Get current chain’s EIP-155 unique identifier.
|
||||||
k.cpt.stack.push k.cpt.getChainId
|
cpt.stack.push cpt.getChainId
|
||||||
|
|
||||||
proc selfBalanceOp (k: var VmCtx): EvmResultVoid =
|
proc selfBalanceOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x47, Get current contract's balance.
|
## 0x47, Get current contract's balance.
|
||||||
let cpt = k.cpt
|
|
||||||
cpt.stack.push cpt.getBalance(cpt.msg.contractAddress)
|
cpt.stack.push cpt.getBalance(cpt.msg.contractAddress)
|
||||||
|
|
||||||
proc baseFeeOp (k: var VmCtx): EvmResultVoid =
|
proc baseFeeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x48, Get the block's base fee.
|
## 0x48, Get the block's base fee.
|
||||||
k.cpt.stack.push k.cpt.getBaseFee
|
cpt.stack.push cpt.getBaseFee
|
||||||
|
|
||||||
proc blobHashOp (k: var VmCtx): EvmResultVoid =
|
proc blobHashOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x49, Get current transaction's EIP-4844 versioned hash.
|
## 0x49, Get current transaction's EIP-4844 versioned hash.
|
||||||
template blob256(top, number, conv) =
|
template blob256(top, number, conv) =
|
||||||
let
|
let
|
||||||
index = number.safeInt
|
index = number.safeInt
|
||||||
len = k.cpt.getVersionedHashesLen
|
len = cpt.getVersionedHashesLen
|
||||||
|
|
||||||
if index < len:
|
if index < len:
|
||||||
conv(k.cpt.getVersionedHash(index), top)
|
conv(cpt.getVersionedHash(index), top)
|
||||||
else:
|
else:
|
||||||
top = zero(UInt256)
|
top = zero(UInt256)
|
||||||
|
|
||||||
k.cpt.stack.unaryWithTop(blob256)
|
cpt.stack.unaryWithTop(blob256)
|
||||||
|
|
||||||
proc blobBaseFeeOp (k: var VmCtx): EvmResultVoid =
|
proc blobBaseFeeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x4a, Get the block's base fee.
|
## 0x4a, Get the block's base fee.
|
||||||
k.cpt.stack.push k.cpt.getBlobBaseFee
|
cpt.stack.push cpt.getBlobBaseFee
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -213,14 +213,12 @@ else:
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc callOp(k: var VmCtx): EvmResultVoid =
|
proc callOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xf1, Message-Call into an account
|
## 0xf1, Message-Call into an account
|
||||||
let cpt = k.cpt
|
|
||||||
|
|
||||||
if EVMC_STATIC in cpt.msg.flags:
|
if EVMC_STATIC in cpt.msg.flags:
|
||||||
let val = ? cpt.stack[^3, UInt256]
|
let val = ? cpt.stack[^3, UInt256]
|
||||||
if val > 0.u256:
|
if val > 0.u256:
|
||||||
return err(opErr(StaticContext))
|
return err(opErr(StaticContext))
|
||||||
|
|
||||||
let
|
let
|
||||||
p = ? cpt.callParams
|
p = ? cpt.callParams
|
||||||
|
@ -292,10 +290,9 @@ proc callOp(k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
proc callCodeOp(k: var VmCtx): EvmResultVoid =
|
proc callCodeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xf2, Message-call into this account with an alternative account's code.
|
## 0xf2, Message-call into this account with an alternative account's code.
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
p = ? cpt.callCodeParams
|
p = ? cpt.callCodeParams
|
||||||
(gasCost, childGasLimit) = ? cpt.gasCosts[CallCode].c_handler(
|
(gasCost, childGasLimit) = ? cpt.gasCosts[CallCode].c_handler(
|
||||||
p.value,
|
p.value,
|
||||||
|
@ -365,11 +362,10 @@ proc callCodeOp(k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
proc delegateCallOp(k: var VmCtx): EvmResultVoid =
|
proc delegateCallOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xf4, Message-call into this account with an alternative account's
|
## 0xf4, Message-call into this account with an alternative account's
|
||||||
## code, but persisting the current values for sender and value.
|
## code, but persisting the current values for sender and value.
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
p = ? cpt.delegateCallParams
|
p = ? cpt.delegateCallParams
|
||||||
(gasCost, childGasLimit) = ? cpt.gasCosts[DelegateCall].c_handler(
|
(gasCost, childGasLimit) = ? cpt.gasCosts[DelegateCall].c_handler(
|
||||||
p.value,
|
p.value,
|
||||||
|
@ -433,11 +429,10 @@ proc delegateCallOp(k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
proc staticCallOp(k: var VmCtx): EvmResultVoid =
|
proc staticCallOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xfa, Static message-call into an account.
|
## 0xfa, Static message-call into an account.
|
||||||
|
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
p = ? cpt.staticCallParams
|
p = ? cpt.staticCallParams
|
||||||
(gasCost, childGasLimit) = ? cpt.gasCosts[StaticCall].c_handler(
|
(gasCost, childGasLimit) = ? cpt.gasCosts[StaticCall].c_handler(
|
||||||
p.value,
|
p.value,
|
||||||
|
|
|
@ -87,13 +87,12 @@ else:
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
proc createOp(k: var VmCtx): EvmResultVoid =
|
proc createOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xf0, Create a new account with associated code
|
## 0xf0, Create a new account with associated code
|
||||||
? checkInStaticContext(k.cpt)
|
? cpt.checkInStaticContext()
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
|
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
endowment = cpt.stack.lsPeekInt(^1)
|
endowment = cpt.stack.lsPeekInt(^1)
|
||||||
memPos = cpt.stack.lsPeekSafeInt(^2)
|
memPos = cpt.stack.lsPeekSafeInt(^2)
|
||||||
memLen = cpt.stack.lsPeekSafeInt(^3)
|
memLen = cpt.stack.lsPeekSafeInt(^3)
|
||||||
|
@ -167,13 +166,12 @@ proc createOp(k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
proc create2Op(k: var VmCtx): EvmResultVoid =
|
proc create2Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xf5, Behaves identically to CREATE, except using keccak256
|
## 0xf5, Behaves identically to CREATE, except using keccak256
|
||||||
? checkInStaticContext(k.cpt)
|
? cpt.checkInStaticContext()
|
||||||
? k.cpt.stack.lsCheck(4)
|
? cpt.stack.lsCheck(4)
|
||||||
|
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
endowment = cpt.stack.lsPeekInt(^1)
|
endowment = cpt.stack.lsPeekInt(^1)
|
||||||
memPos = cpt.stack.lsPeekSafeInt(^2)
|
memPos = cpt.stack.lsPeekSafeInt(^2)
|
||||||
memLen = cpt.stack.lsPeekSafeInt(^3)
|
memLen = cpt.stack.lsPeekSafeInt(^3)
|
||||||
|
|
|
@ -21,12 +21,11 @@ import
|
||||||
../op_codes
|
../op_codes
|
||||||
|
|
||||||
type
|
type
|
||||||
VmCtx* = tuple
|
VmCpt* = Computation ## computation text
|
||||||
cpt: Computation ## computation text
|
|
||||||
|
|
||||||
VmOpFn* = ## general op handler, return codes are passed
|
VmOpFn* = ## general op handler, return codes are passed
|
||||||
## back via argument descriptor ``k``
|
## back via argument descriptor ``cpt``
|
||||||
proc(k: var VmCtx): EvmResultVoid {.nimcall, gcsafe, raises:[].}
|
proc(cpt: VmCpt): EvmResultVoid {.nimcall, gcsafe, raises:[].}
|
||||||
|
|
||||||
VmOpExec* = tuple ## op code handler entry
|
VmOpExec* = tuple ## op code handler entry
|
||||||
opCode: Op ## index back-reference
|
opCode: Op ## index back-reference
|
||||||
|
@ -41,7 +40,7 @@ type
|
||||||
|
|
||||||
const
|
const
|
||||||
VmOpIgnore*: VmOpFn = ## No operation, placeholder function
|
VmOpIgnore*: VmOpFn = ## No operation, placeholder function
|
||||||
proc(k: var VmCtx): EvmResultVoid = ok()
|
proc(cpt: VmCpt): EvmResultVoid = ok()
|
||||||
|
|
||||||
# similar to: toSeq(Fork).mapIt({it}).foldl(a+b)
|
# similar to: toSeq(Fork).mapIt({it}).foldl(a+b)
|
||||||
VmOpAllForks* =
|
VmOpAllForks* =
|
||||||
|
|
|
@ -41,8 +41,8 @@ proc fnInfo(n: int): string {.compileTime.} =
|
||||||
"Duplicate " & blurb & " item in the stack"
|
"Duplicate " & blurb & " item in the stack"
|
||||||
|
|
||||||
|
|
||||||
template dupImpl(k: var VmCtx; n: int): EvmResultVoid =
|
template dupImpl(cpt: VmCpt; n: int): EvmResultVoid =
|
||||||
k.cpt.stack.dup(n)
|
cpt.stack.dup(n)
|
||||||
|
|
||||||
const
|
const
|
||||||
inxRange = toSeq(1 .. 16)
|
inxRange = toSeq(1 .. 16)
|
||||||
|
|
|
@ -35,71 +35,70 @@ when not defined(evmc_enabled):
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc addressOp (k: var VmCtx): EvmResultVoid =
|
proc addressOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x30, Get address of currently executing account.
|
## 0x30, Get address of currently executing account.
|
||||||
k.cpt.stack.push k.cpt.msg.contractAddress
|
cpt.stack.push cpt.msg.contractAddress
|
||||||
|
|
||||||
# ------------------
|
# ------------------
|
||||||
|
|
||||||
proc balanceOp (k: var VmCtx): EvmResultVoid =
|
proc balanceOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x31, Get balance of the given account.
|
## 0x31, Get balance of the given account.
|
||||||
template balance256(address): auto =
|
template balance256(address): auto =
|
||||||
k.cpt.getBalance(address)
|
cpt.getBalance(address)
|
||||||
k.cpt.stack.unaryAddress(balance256)
|
cpt.stack.unaryAddress(balance256)
|
||||||
|
|
||||||
proc balanceEIP2929Op (k: var VmCtx): EvmResultVoid =
|
proc balanceEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x31, EIP292: Get balance of the given account for Berlin and later
|
## 0x31, EIP292: Get balance of the given account for Berlin and later
|
||||||
template balanceEIP2929(address): auto =
|
template balanceEIP2929(address): auto =
|
||||||
let gasCost = k.cpt.gasEip2929AccountCheck(address)
|
let gasCost = cpt.gasEip2929AccountCheck(address)
|
||||||
? k.cpt.opcodeGasCost(Balance, gasCost, reason = "Balance EIP2929")
|
? cpt.opcodeGasCost(Balance, gasCost, reason = "Balance EIP2929")
|
||||||
k.cpt.getBalance(address)
|
cpt.getBalance(address)
|
||||||
k.cpt.stack.unaryAddress(balanceEIP2929)
|
cpt.stack.unaryAddress(balanceEIP2929)
|
||||||
|
|
||||||
# ------------------
|
# ------------------
|
||||||
|
|
||||||
proc originOp (k: var VmCtx): EvmResultVoid =
|
proc originOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x32, Get execution origination address.
|
## 0x32, Get execution origination address.
|
||||||
k.cpt.stack.push k.cpt.getOrigin()
|
cpt.stack.push cpt.getOrigin()
|
||||||
|
|
||||||
proc callerOp (k: var VmCtx): EvmResultVoid =
|
proc callerOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x33, Get caller address.
|
## 0x33, Get caller address.
|
||||||
k.cpt.stack.push k.cpt.msg.sender
|
cpt.stack.push cpt.msg.sender
|
||||||
|
|
||||||
proc callValueOp (k: var VmCtx): EvmResultVoid =
|
proc callValueOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x34, Get deposited value by the instruction/transaction
|
## 0x34, Get deposited value by the instruction/transaction
|
||||||
## responsible for this execution
|
## responsible for this execution
|
||||||
k.cpt.stack.push k.cpt.msg.value
|
cpt.stack.push cpt.msg.value
|
||||||
|
|
||||||
proc callDataLoadOp (k: var VmCtx): EvmResultVoid =
|
proc callDataLoadOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x35, Get input data of current environment
|
## 0x35, Get input data of current environment
|
||||||
? k.cpt.stack.lsCheck(1)
|
? cpt.stack.lsCheck(1)
|
||||||
let start = k.cpt.stack.lsPeekMemRef(^1)
|
let start = cpt.stack.lsPeekMemRef(^1)
|
||||||
|
|
||||||
if start >= k.cpt.msg.data.len:
|
if start >= cpt.msg.data.len:
|
||||||
k.cpt.stack.lsTop 0
|
cpt.stack.lsTop 0
|
||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
# If the data does not take 32 bytes, pad with zeros
|
# If the data does not take 32 bytes, pad with zeros
|
||||||
let
|
let
|
||||||
endRange = min(k.cpt.msg.data.len - 1, start + 31)
|
endRange = min(cpt.msg.data.len - 1, start + 31)
|
||||||
presentBytes = endRange - start
|
presentBytes = endRange - start
|
||||||
|
|
||||||
# We rely on value being initialized with 0 by default
|
# We rely on value being initialized with 0 by default
|
||||||
var value: array[32, byte]
|
var value: array[32, byte]
|
||||||
assign(value.toOpenArray(0, presentBytes), k.cpt.msg.data.toOpenArray(start, endRange))
|
assign(value.toOpenArray(0, presentBytes), cpt.msg.data.toOpenArray(start, endRange))
|
||||||
k.cpt.stack.lsTop value
|
cpt.stack.lsTop value
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc callDataSizeOp (k: var VmCtx): EvmResultVoid =
|
proc callDataSizeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x36, Get size of input data in current environment.
|
## 0x36, Get size of input data in current environment.
|
||||||
k.cpt.stack.push k.cpt.msg.data.len.u256
|
cpt.stack.push cpt.msg.data.len.u256
|
||||||
|
|
||||||
|
|
||||||
proc callDataCopyOp (k: var VmCtx): EvmResultVoid =
|
proc callDataCopyOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x37, Copy input data in current environment to memory.
|
## 0x37, Copy input data in current environment to memory.
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
memPos = cpt.stack.lsPeekMemRef(^1)
|
memPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
copyPos = cpt.stack.lsPeekMemRef(^2)
|
copyPos = cpt.stack.lsPeekMemRef(^2)
|
||||||
len = cpt.stack.lsPeekMemRef(^3)
|
len = cpt.stack.lsPeekMemRef(^3)
|
||||||
|
@ -113,17 +112,15 @@ proc callDataCopyOp (k: var VmCtx): EvmResultVoid =
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
||||||
proc codeSizeOp (k: var VmCtx): EvmResultVoid =
|
proc codeSizeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x38, Get size of code running in current environment.
|
## 0x38, Get size of code running in current environment.
|
||||||
let cpt = k.cpt
|
|
||||||
cpt.stack.push cpt.code.len
|
cpt.stack.push cpt.code.len
|
||||||
|
|
||||||
|
|
||||||
proc codeCopyOp (k: var VmCtx): EvmResultVoid =
|
proc codeCopyOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x39, Copy code running in current environment to memory.
|
## 0x39, Copy code running in current environment to memory.
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
memPos = cpt.stack.lsPeekMemRef(^1)
|
memPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
copyPos = cpt.stack.lsPeekMemRef(^2)
|
copyPos = cpt.stack.lsPeekMemRef(^2)
|
||||||
len = cpt.stack.lsPeekMemRef(^3)
|
len = cpt.stack.lsPeekMemRef(^3)
|
||||||
|
@ -136,34 +133,33 @@ proc codeCopyOp (k: var VmCtx): EvmResultVoid =
|
||||||
cpt.memory.writePadded(cpt.code.bytes, memPos, copyPos, len)
|
cpt.memory.writePadded(cpt.code.bytes, memPos, copyPos, len)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc gasPriceOp (k: var VmCtx): EvmResultVoid =
|
proc gasPriceOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3A, Get price of gas in current environment.
|
## 0x3A, Get price of gas in current environment.
|
||||||
k.cpt.stack.push k.cpt.getGasPrice()
|
cpt.stack.push cpt.getGasPrice()
|
||||||
|
|
||||||
# -----------
|
# -----------
|
||||||
|
|
||||||
proc extCodeSizeOp (k: var VmCtx): EvmResultVoid =
|
proc extCodeSizeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3b, Get size of an account's code
|
## 0x3b, Get size of an account's code
|
||||||
template ecs256(address): auto =
|
template ecs256(address): auto =
|
||||||
k.cpt.getCodeSize(address)
|
cpt.getCodeSize(address)
|
||||||
k.cpt.stack.unaryAddress(ecs256)
|
cpt.stack.unaryAddress(ecs256)
|
||||||
|
|
||||||
proc extCodeSizeEIP2929Op (k: var VmCtx): EvmResultVoid =
|
proc extCodeSizeEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3b, Get size of an account's code
|
## 0x3b, Get size of an account's code
|
||||||
template ecsEIP2929(address): auto =
|
template ecsEIP2929(address): auto =
|
||||||
let gasCost = k.cpt.gasEip2929AccountCheck(address)
|
let gasCost = cpt.gasEip2929AccountCheck(address)
|
||||||
? k.cpt.opcodeGasCost(ExtCodeSize, gasCost, reason = "ExtCodeSize EIP2929")
|
? cpt.opcodeGasCost(ExtCodeSize, gasCost, reason = "ExtCodeSize EIP2929")
|
||||||
k.cpt.getCodeSize(address)
|
cpt.getCodeSize(address)
|
||||||
|
|
||||||
k.cpt.stack.unaryAddress(ecsEIP2929)
|
cpt.stack.unaryAddress(ecsEIP2929)
|
||||||
|
|
||||||
# -----------
|
# -----------
|
||||||
|
|
||||||
proc extCodeCopyOp (k: var VmCtx): EvmResultVoid =
|
proc extCodeCopyOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3c, Copy an account's code to memory.
|
## 0x3c, Copy an account's code to memory.
|
||||||
? k.cpt.stack.lsCheck(4)
|
? cpt.stack.lsCheck(4)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
address = cpt.stack.lsPeekAddress(^1)
|
address = cpt.stack.lsPeekAddress(^1)
|
||||||
memPos = cpt.stack.lsPeekMemRef(^2)
|
memPos = cpt.stack.lsPeekMemRef(^2)
|
||||||
codePos = cpt.stack.lsPeekMemRef(^3)
|
codePos = cpt.stack.lsPeekMemRef(^3)
|
||||||
|
@ -179,11 +175,10 @@ proc extCodeCopyOp (k: var VmCtx): EvmResultVoid =
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
||||||
proc extCodeCopyEIP2929Op (k: var VmCtx): EvmResultVoid =
|
proc extCodeCopyEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3c, Copy an account's code to memory.
|
## 0x3c, Copy an account's code to memory.
|
||||||
? k.cpt.stack.lsCheck(4)
|
? cpt.stack.lsCheck(4)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
address = cpt.stack.lsPeekAddress(^1)
|
address = cpt.stack.lsPeekAddress(^1)
|
||||||
memPos = cpt.stack.lsPeekMemRef(^2)
|
memPos = cpt.stack.lsPeekMemRef(^2)
|
||||||
codePos = cpt.stack.lsPeekMemRef(^3)
|
codePos = cpt.stack.lsPeekMemRef(^3)
|
||||||
|
@ -200,17 +195,16 @@ proc extCodeCopyEIP2929Op (k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# -----------
|
# -----------
|
||||||
|
|
||||||
proc returnDataSizeOp (k: var VmCtx): EvmResultVoid =
|
proc returnDataSizeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3d, Get size of output data from the previous call from the
|
## 0x3d, Get size of output data from the previous call from the
|
||||||
## current environment.
|
## current environment.
|
||||||
k.cpt.stack.push k.cpt.returnData.len
|
cpt.stack.push cpt.returnData.len
|
||||||
|
|
||||||
|
|
||||||
proc returnDataCopyOp (k: var VmCtx): EvmResultVoid =
|
proc returnDataCopyOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3e, Copy output data from the previous call to memory.
|
## 0x3e, Copy output data from the previous call to memory.
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
memPos = cpt.stack.lsPeekMemRef(^1)
|
memPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
copyPos = cpt.stack.lsPeekMemRef(^2)
|
copyPos = cpt.stack.lsPeekMemRef(^2)
|
||||||
len = cpt.stack.lsPeekMemRef(^3)
|
len = cpt.stack.lsPeekMemRef(^3)
|
||||||
|
@ -227,19 +221,19 @@ proc returnDataCopyOp (k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# ---------------
|
# ---------------
|
||||||
|
|
||||||
proc extCodeHashOp (k: var VmCtx): EvmResultVoid =
|
proc extCodeHashOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3f, Returns the keccak256 hash of a contract’s code
|
## 0x3f, Returns the keccak256 hash of a contract’s code
|
||||||
template ech256(address): auto =
|
template ech256(address): auto =
|
||||||
k.cpt.getCodeHash(address)
|
cpt.getCodeHash(address)
|
||||||
k.cpt.stack.unaryAddress(ech256)
|
cpt.stack.unaryAddress(ech256)
|
||||||
|
|
||||||
proc extCodeHashEIP2929Op (k: var VmCtx): EvmResultVoid =
|
proc extCodeHashEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x3f, EIP2929: Returns the keccak256 hash of a contract’s code
|
## 0x3f, EIP2929: Returns the keccak256 hash of a contract’s code
|
||||||
template echEIP2929(address): auto =
|
template echEIP2929(address): auto =
|
||||||
let gasCost = k.cpt.gasEip2929AccountCheck(address)
|
let gasCost = cpt.gasEip2929AccountCheck(address)
|
||||||
? k.cpt.opcodeGasCost(ExtCodeHash, gasCost, reason = "ExtCodeHash EIP2929")
|
? cpt.opcodeGasCost(ExtCodeHash, gasCost, reason = "ExtCodeHash EIP2929")
|
||||||
k.cpt.getCodeHash(address)
|
cpt.getCodeHash(address)
|
||||||
k.cpt.stack.unaryAddress(echEIP2929)
|
cpt.stack.unaryAddress(echEIP2929)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public, op exec table entries
|
# Public, op exec table entries
|
||||||
|
|
|
@ -19,7 +19,6 @@ import
|
||||||
|
|
||||||
type
|
type
|
||||||
OphNumToTextFn* = proc(n: int): string
|
OphNumToTextFn* = proc(n: int): string
|
||||||
# OpHanldlerImplFn* = proc(k: var VmCtx; n: static int): EvmResultVoid
|
|
||||||
|
|
||||||
const
|
const
|
||||||
recForkSet = "VmOpAllForks"
|
recForkSet = "VmOpAllForks"
|
||||||
|
@ -48,9 +47,9 @@ macro genOphHandlers*(runHandler: static[OphNumToTextFn];
|
||||||
body: untyped): untyped =
|
body: untyped): untyped =
|
||||||
## Generate the equivalent of
|
## Generate the equivalent of
|
||||||
## ::
|
## ::
|
||||||
## const <runHandler>: VmOpFn = proc (k: var VmCtx) =
|
## const <runHandler>: VmOpFn = proc(cpt: VmCpt) =
|
||||||
## ## <itemInfo(n)>,
|
## ## <itemInfo(n)>,
|
||||||
## <body(k,n)>
|
## <body(cpt,n)>
|
||||||
##
|
##
|
||||||
## for all `n` in `inxList`
|
## for all `n` in `inxList`
|
||||||
##
|
##
|
||||||
|
@ -61,12 +60,11 @@ macro genOphHandlers*(runHandler: static[OphNumToTextFn];
|
||||||
fnName = ident(n.runHandler)
|
fnName = ident(n.runHandler)
|
||||||
comment = newCommentStmtNode(n.itemInfo)
|
comment = newCommentStmtNode(n.itemInfo)
|
||||||
|
|
||||||
# => push##Op: VmOpFn = proc (k: var VmCtx) = ...
|
# => push##Op: VmOpFn = proc(cpt: VmCpt) = ...
|
||||||
result.add quote do:
|
result.add quote do:
|
||||||
proc `fnName`(k: var VmCtx): EvmResultVoid =
|
proc `fnName`(cpt: VmCpt): EvmResultVoid =
|
||||||
`comment`
|
`comment`
|
||||||
`body`(k,`n`)
|
`body`(cpt,`n`)
|
||||||
# echo ">>>", result.repr
|
|
||||||
|
|
||||||
|
|
||||||
macro genOphList*(runHandler: static[OphNumToTextFn];
|
macro genOphList*(runHandler: static[OphNumToTextFn];
|
||||||
|
@ -83,9 +81,7 @@ macro genOphList*(runHandler: static[OphNumToTextFn];
|
||||||
## (opCode: <opCode(n)>,
|
## (opCode: <opCode(n)>,
|
||||||
## forks: VmOpAllForks,
|
## forks: VmOpAllForks,
|
||||||
## info: <handlerInfo(n)>,
|
## info: <handlerInfo(n)>,
|
||||||
## exec: (prep: VmOpIgnore,
|
## exec: <runHandler(n)>)
|
||||||
## run: <runHandler(n)>,
|
|
||||||
## post: VmOpIgnore))
|
|
||||||
##
|
##
|
||||||
## for all `n` in `inxList`
|
## for all `n` in `inxList`
|
||||||
##
|
##
|
||||||
|
@ -113,7 +109,6 @@ macro genOphList*(runHandler: static[OphNumToTextFn];
|
||||||
newIdentNode("VmOpExec")),
|
newIdentNode("VmOpExec")),
|
||||||
nnkPrefix.newTree(
|
nnkPrefix.newTree(
|
||||||
newIdentNode("@"), records))))
|
newIdentNode("@"), records))))
|
||||||
# echo ">>> ", result.repr
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
|
|
|
@ -29,11 +29,10 @@ import
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc sha3Op(k: var VmCtx): EvmResultVoid =
|
proc sha3Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x20, Compute Keccak-256 hash.
|
## 0x20, Compute Keccak-256 hash.
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
pos = cpt.stack.lsPeekSafeInt(^1)
|
pos = cpt.stack.lsPeekSafeInt(^1)
|
||||||
len = cpt.stack.lsPeekSafeInt(^2)
|
len = cpt.stack.lsPeekSafeInt(^2)
|
||||||
cpt.stack.lsShrink(1)
|
cpt.stack.lsShrink(1)
|
||||||
|
@ -51,7 +50,7 @@ proc sha3Op(k: var VmCtx): EvmResultVoid =
|
||||||
if endRange == -1 or pos >= cpt.memory.len:
|
if endRange == -1 or pos >= cpt.memory.len:
|
||||||
cpt.stack.lsTop(EMPTY_SHA3)
|
cpt.stack.lsTop(EMPTY_SHA3)
|
||||||
else:
|
else:
|
||||||
cpt.stack.lsTop keccakHash k.cpt.memory.bytes.toOpenArray(pos, endRange)
|
cpt.stack.lsTop keccakHash cpt.memory.bytes.toOpenArray(pos, endRange)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -98,8 +98,8 @@ const
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc wrapperFn(k: var VmCtx; n: static int): EvmResultVoid =
|
proc wrapperFn(cpt: VmCpt; n: static int): EvmResultVoid =
|
||||||
logImpl(k.cpt, logOpArg[n], n)
|
cpt.logImpl(logOpArg[n], n)
|
||||||
|
|
||||||
genOphHandlers fnName, fnInfo, inxRange, wrapperFn
|
genOphHandlers fnName, fnInfo, inxRange, wrapperFn
|
||||||
|
|
||||||
|
|
|
@ -120,19 +120,17 @@ func jumpImpl(c: Computation; jumpTarget: UInt256): EvmResultVoid =
|
||||||
# Private, op handlers implementation
|
# Private, op handlers implementation
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc popOp(k: var VmCtx): EvmResultVoid =
|
proc popOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x50, Remove item from stack.
|
## 0x50, Remove item from stack.
|
||||||
k.cpt.stack.popInt.isOkOr:
|
cpt.stack.popInt.isOkOr:
|
||||||
return err(error)
|
return err(error)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc mloadOp (k: var VmCtx): EvmResultVoid =
|
proc mloadOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x51, Load word from memory
|
## 0x51, Load word from memory
|
||||||
|
|
||||||
? k.cpt.stack.lsCheck(1)
|
? cpt.stack.lsCheck(1)
|
||||||
let
|
let memPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
cpt = k.cpt
|
|
||||||
memPos = cpt.stack.lsPeekMemRef(^1)
|
|
||||||
|
|
||||||
? cpt.opcodeGasCost(Mload,
|
? cpt.opcodeGasCost(Mload,
|
||||||
cpt.gasCosts[Mload].m_handler(cpt.memory.len, memPos, 32),
|
cpt.gasCosts[Mload].m_handler(cpt.memory.len, memPos, 32),
|
||||||
|
@ -143,11 +141,10 @@ proc mloadOp (k: var VmCtx): EvmResultVoid =
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
||||||
proc mstoreOp (k: var VmCtx): EvmResultVoid =
|
proc mstoreOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x52, Save word to memory
|
## 0x52, Save word to memory
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
memPos = cpt.stack.lsPeekMemRef(^1)
|
memPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
value = cpt.stack.lsPeekInt(^2)
|
value = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -160,11 +157,10 @@ proc mstoreOp (k: var VmCtx): EvmResultVoid =
|
||||||
cpt.memory.write(memPos, value.toBytesBE)
|
cpt.memory.write(memPos, value.toBytesBE)
|
||||||
|
|
||||||
|
|
||||||
proc mstore8Op (k: var VmCtx): EvmResultVoid =
|
proc mstore8Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x53, Save byte to memory
|
## 0x53, Save byte to memory
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
memPos = cpt.stack.lsPeekMemRef(^1)
|
memPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
value = cpt.stack.lsPeekInt(^2)
|
value = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -179,27 +175,26 @@ proc mstore8Op (k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# -------
|
# -------
|
||||||
|
|
||||||
proc sloadOp (k: var VmCtx): EvmResultVoid =
|
proc sloadOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x54, Load word from storage.
|
## 0x54, Load word from storage.
|
||||||
template sload256(top, slot, conv) =
|
template sload256(top, slot, conv) =
|
||||||
top = k.cpt.getStorage(slot)
|
top = cpt.getStorage(slot)
|
||||||
k.cpt.stack.unaryWithTop(sload256)
|
cpt.stack.unaryWithTop(sload256)
|
||||||
|
|
||||||
proc sloadEIP2929Op (k: var VmCtx): EvmResultVoid =
|
proc sloadEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x54, EIP2929: Load word from storage for Berlin and later
|
## 0x54, EIP2929: Load word from storage for Berlin and later
|
||||||
template sloadEIP2929(top, slot, conv) =
|
template sloadEIP2929(top, slot, conv) =
|
||||||
let gasCost = k.cpt.gasEip2929AccountCheck(k.cpt.msg.contractAddress, slot)
|
let gasCost = cpt.gasEip2929AccountCheck(cpt.msg.contractAddress, slot)
|
||||||
? k.cpt.opcodeGasCost(Sload, gasCost, reason = "sloadEIP2929")
|
? cpt.opcodeGasCost(Sload, gasCost, reason = "sloadEIP2929")
|
||||||
top = k.cpt.getStorage(slot)
|
top = cpt.getStorage(slot)
|
||||||
k.cpt.stack.unaryWithTop(sloadEIP2929)
|
cpt.stack.unaryWithTop(sloadEIP2929)
|
||||||
|
|
||||||
# -------
|
# -------
|
||||||
|
|
||||||
proc sstoreOp (k: var VmCtx): EvmResultVoid =
|
proc sstoreOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x55, Save word to storage.
|
## 0x55, Save word to storage.
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
slot = cpt.stack.lsPeekInt(^1)
|
slot = cpt.stack.lsPeekInt(^1)
|
||||||
newValue = cpt.stack.lsPeekInt(^2)
|
newValue = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -208,11 +203,10 @@ proc sstoreOp (k: var VmCtx): EvmResultVoid =
|
||||||
sstoreEvmcOrSstore(cpt, slot, newValue)
|
sstoreEvmcOrSstore(cpt, slot, newValue)
|
||||||
|
|
||||||
|
|
||||||
proc sstoreEIP1283Op (k: var VmCtx): EvmResultVoid =
|
proc sstoreEIP1283Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x55, EIP1283: sstore for Constantinople and later
|
## 0x55, EIP1283: sstore for Constantinople and later
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
slot = cpt.stack.lsPeekInt(^1)
|
slot = cpt.stack.lsPeekInt(^1)
|
||||||
newValue = cpt.stack.lsPeekInt(^2)
|
newValue = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -221,11 +215,10 @@ proc sstoreEIP1283Op (k: var VmCtx): EvmResultVoid =
|
||||||
sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
|
sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
|
||||||
|
|
||||||
|
|
||||||
proc sstoreEIP2200Op (k: var VmCtx): EvmResultVoid =
|
proc sstoreEIP2200Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x55, EIP2200: sstore for Istanbul and later
|
## 0x55, EIP2200: sstore for Istanbul and later
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
slot = cpt.stack.lsPeekInt(^1)
|
slot = cpt.stack.lsPeekInt(^1)
|
||||||
newValue = cpt.stack.lsPeekInt(^2)
|
newValue = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -239,11 +232,10 @@ proc sstoreEIP2200Op (k: var VmCtx): EvmResultVoid =
|
||||||
sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
|
sstoreEvmcOrNetGasMetering(cpt, slot, newValue)
|
||||||
|
|
||||||
|
|
||||||
proc sstoreEIP2929Op (k: var VmCtx): EvmResultVoid =
|
proc sstoreEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x55, EIP2929: sstore for Berlin and later
|
## 0x55, EIP2929: sstore for Berlin and later
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
slot = cpt.stack.lsPeekInt(^1)
|
slot = cpt.stack.lsPeekInt(^1)
|
||||||
newValue = cpt.stack.lsPeekInt(^2)
|
newValue = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -270,60 +262,58 @@ proc sstoreEIP2929Op (k: var VmCtx): EvmResultVoid =
|
||||||
|
|
||||||
# -------
|
# -------
|
||||||
|
|
||||||
proc jumpOp (k: var VmCtx): EvmResultVoid =
|
proc jumpOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x56, Alter the program counter
|
## 0x56, Alter the program counter
|
||||||
let jumpTarget = ? k.cpt.stack.popInt()
|
let jumpTarget = ? cpt.stack.popInt()
|
||||||
jumpImpl(k.cpt, jumpTarget)
|
cpt.jumpImpl(jumpTarget)
|
||||||
|
|
||||||
|
|
||||||
proc jumpIOp (k: var VmCtx): EvmResultVoid =
|
proc jumpIOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x57, Conditionally alter the program counter.
|
## 0x57, Conditionally alter the program counter.
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
jumpTarget = k.cpt.stack.lsPeekInt(^1)
|
jumpTarget = cpt.stack.lsPeekInt(^1)
|
||||||
testedValue = k.cpt.stack.lsPeekInt(^2)
|
testedValue = cpt.stack.lsPeekInt(^2)
|
||||||
k.cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
|
||||||
if testedValue.isZero:
|
if testedValue.isZero:
|
||||||
return ok()
|
return ok()
|
||||||
jumpImpl(k.cpt, jumpTarget)
|
cpt.jumpImpl(jumpTarget)
|
||||||
|
|
||||||
proc pcOp (k: var VmCtx): EvmResultVoid =
|
proc pcOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x58, Get the value of the program counter prior to the increment
|
## 0x58, Get the value of the program counter prior to the increment
|
||||||
## corresponding to this instruction.
|
## corresponding to this instruction.
|
||||||
k.cpt.stack.push max(k.cpt.code.pc - 1, 0)
|
cpt.stack.push max(cpt.code.pc - 1, 0)
|
||||||
|
|
||||||
proc msizeOp (k: var VmCtx): EvmResultVoid =
|
proc msizeOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x59, Get the size of active memory in bytes.
|
## 0x59, Get the size of active memory in bytes.
|
||||||
k.cpt.stack.push k.cpt.memory.len
|
cpt.stack.push cpt.memory.len
|
||||||
|
|
||||||
proc gasOp (k: var VmCtx): EvmResultVoid =
|
proc gasOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x5a, Get the amount of available gas, including the corresponding
|
## 0x5a, Get the amount of available gas, including the corresponding
|
||||||
## reduction for the cost of this instruction.
|
## reduction for the cost of this instruction.
|
||||||
k.cpt.stack.push k.cpt.gasMeter.gasRemaining
|
cpt.stack.push cpt.gasMeter.gasRemaining
|
||||||
|
|
||||||
proc jumpDestOp (k: var VmCtx): EvmResultVoid =
|
proc jumpDestOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x5b, Mark a valid destination for jumps. This operation has no effect
|
## 0x5b, Mark a valid destination for jumps. This operation has no effect
|
||||||
## on machine state during execution.
|
## on machine state during execution.
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc tloadOp (k: var VmCtx): EvmResultVoid =
|
proc tloadOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x5c, Load word from transient storage.
|
## 0x5c, Load word from transient storage.
|
||||||
? k.cpt.stack.lsCheck(1)
|
? cpt.stack.lsCheck(1)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
slot = cpt.stack.lsPeekInt(^1)
|
slot = cpt.stack.lsPeekInt(^1)
|
||||||
val = cpt.getTransientStorage(slot)
|
val = cpt.getTransientStorage(slot)
|
||||||
cpt.stack.lsTop val
|
cpt.stack.lsTop val
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc tstoreOp (k: var VmCtx): EvmResultVoid =
|
proc tstoreOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x5d, Save word to transient storage.
|
## 0x5d, Save word to transient storage.
|
||||||
? checkInStaticContext(k.cpt)
|
? cpt.checkInStaticContext()
|
||||||
|
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
slot = cpt.stack.lsPeekInt(^1)
|
slot = cpt.stack.lsPeekInt(^1)
|
||||||
val = cpt.stack.lsPeekInt(^2)
|
val = cpt.stack.lsPeekInt(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -331,11 +321,10 @@ proc tstoreOp (k: var VmCtx): EvmResultVoid =
|
||||||
cpt.setTransientStorage(slot, val)
|
cpt.setTransientStorage(slot, val)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc mCopyOp (k: var VmCtx): EvmResultVoid =
|
proc mCopyOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x5e, Copy memory
|
## 0x5e, Copy memory
|
||||||
? k.cpt.stack.lsCheck(3)
|
? cpt.stack.lsCheck(3)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
dstPos = cpt.stack.lsPeekMemRef(^1)
|
dstPos = cpt.stack.lsPeekMemRef(^1)
|
||||||
srcPos = cpt.stack.lsPeekMemRef(^2)
|
srcPos = cpt.stack.lsPeekMemRef(^2)
|
||||||
len = cpt.stack.lsPeekMemRef(^3)
|
len = cpt.stack.lsPeekMemRef(^3)
|
||||||
|
|
|
@ -40,8 +40,8 @@ proc fnInfo(n: int): string {.compileTime.} =
|
||||||
"Push " & blurb & " on the stack"
|
"Push " & blurb & " on the stack"
|
||||||
|
|
||||||
|
|
||||||
template pushImpl(k: var VmCtx; n: static int): EvmResultVoid =
|
template pushImpl(cpt: VmCpt; n: static int): EvmResultVoid =
|
||||||
k.cpt.stack.push k.cpt.code.readVmWord(n)
|
cpt.stack.push cpt.code.readVmWord(n)
|
||||||
|
|
||||||
const
|
const
|
||||||
inxRange = toSeq(1 .. 32)
|
inxRange = toSeq(1 .. 32)
|
||||||
|
@ -65,9 +65,9 @@ genOphList fnName, fnInfo, inxRange, "VmOpExecPush", opName
|
||||||
# about which opcodes are for which forks, but that seems uglier than
|
# about which opcodes are for which forks, but that seems uglier than
|
||||||
# just adding Push0 here as a special case.)
|
# just adding Push0 here as a special case.)
|
||||||
|
|
||||||
proc push0Op(k: var VmCtx): EvmResultVoid =
|
proc push0Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0x5f, push 0 onto the stack
|
## 0x5f, push 0 onto the stack
|
||||||
k.cpt.stack.push(0)
|
cpt.stack.push(0)
|
||||||
|
|
||||||
const
|
const
|
||||||
VmOpExecPushZero*: seq[VmOpExec] = @[
|
VmOpExecPushZero*: seq[VmOpExec] = @[
|
||||||
|
|
|
@ -41,8 +41,8 @@ proc fnInfo(n: int): string {.compileTime.} =
|
||||||
"Exchange first and " & blurb & " stack items"
|
"Exchange first and " & blurb & " stack items"
|
||||||
|
|
||||||
|
|
||||||
template swapImpl(k: var VmCtx; n: static int): EvmResultVoid =
|
template swapImpl(cpt: VmCpt; n: static int): EvmResultVoid =
|
||||||
k.cpt.stack.swap(n)
|
cpt.stack.swap(n)
|
||||||
|
|
||||||
const
|
const
|
||||||
inxRange = toSeq(1 .. 16)
|
inxRange = toSeq(1 .. 16)
|
||||||
|
|
|
@ -37,11 +37,10 @@ when not defined(evmc_enabled):
|
||||||
# Private
|
# Private
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc returnOp(k: var VmCtx): EvmResultVoid =
|
proc returnOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xf3, Halt execution returning output data.
|
## 0xf3, Halt execution returning output data.
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
pos = cpt.stack.lsPeekMemRef(^1)
|
pos = cpt.stack.lsPeekMemRef(^1)
|
||||||
len = cpt.stack.lsPeekMemRef(^2)
|
len = cpt.stack.lsPeekMemRef(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -55,12 +54,11 @@ proc returnOp(k: var VmCtx): EvmResultVoid =
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
||||||
proc revertOp(k: var VmCtx): EvmResultVoid =
|
proc revertOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xfd, Halt execution reverting state changes but returning data
|
## 0xfd, Halt execution reverting state changes but returning data
|
||||||
## and remaining gas.
|
## and remaining gas.
|
||||||
? k.cpt.stack.lsCheck(2)
|
? cpt.stack.lsCheck(2)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
pos = cpt.stack.lsPeekMemRef(^1)
|
pos = cpt.stack.lsPeekMemRef(^1)
|
||||||
len = cpt.stack.lsPeekMemRef(^2)
|
len = cpt.stack.lsPeekMemRef(^2)
|
||||||
cpt.stack.lsShrink(2)
|
cpt.stack.lsShrink(2)
|
||||||
|
@ -75,29 +73,24 @@ proc revertOp(k: var VmCtx): EvmResultVoid =
|
||||||
cpt.setError(EVMC_REVERT, "REVERT opcode executed", false)
|
cpt.setError(EVMC_REVERT, "REVERT opcode executed", false)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc invalidOp(k: var VmCtx): EvmResultVoid =
|
proc invalidOp(cpt: VmCpt): EvmResultVoid =
|
||||||
err(opErr(InvalidInstruction))
|
err(opErr(InvalidInstruction))
|
||||||
|
|
||||||
# -----------
|
# -----------
|
||||||
|
|
||||||
proc selfDestructOp(k: var VmCtx): EvmResultVoid =
|
proc selfDestructOp(cpt: VmCpt): EvmResultVoid =
|
||||||
## 0xff, Halt execution and register account for later deletion.
|
## 0xff, Halt execution and register account for later deletion.
|
||||||
let
|
let beneficiary = ? cpt.stack.popAddress()
|
||||||
cpt = k.cpt
|
|
||||||
beneficiary = ? cpt.stack.popAddress()
|
|
||||||
|
|
||||||
when defined(evmc_enabled):
|
when defined(evmc_enabled):
|
||||||
block:
|
cpt.selfDestruct(beneficiary)
|
||||||
cpt.selfDestruct(beneficiary)
|
|
||||||
else:
|
else:
|
||||||
block:
|
cpt.selfDestruct(beneficiary)
|
||||||
cpt.selfDestruct(beneficiary)
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc selfDestructEIP150Op(k: var VmCtx): EvmResultVoid =
|
proc selfDestructEIP150Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## selfDestructEip150 (auto generated comment)
|
## selfDestructEip150 (auto generated comment)
|
||||||
let
|
let
|
||||||
cpt = k.cpt
|
|
||||||
beneficiary = ? cpt.stack.popAddress()
|
beneficiary = ? cpt.stack.popAddress()
|
||||||
condition = not cpt.accountExists(beneficiary)
|
condition = not cpt.accountExists(beneficiary)
|
||||||
gasCost = cpt.gasCosts[SelfDestruct].sc_handler(condition)
|
gasCost = cpt.gasCosts[SelfDestruct].sc_handler(condition)
|
||||||
|
@ -107,27 +100,25 @@ proc selfDestructEIP150Op(k: var VmCtx): EvmResultVoid =
|
||||||
cpt.selfDestruct(beneficiary)
|
cpt.selfDestruct(beneficiary)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc selfDestructEIP161Op(k: var VmCtx): EvmResultVoid =
|
proc selfDestructEIP161Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## selfDestructEip161 (auto generated comment)
|
## selfDestructEip161 (auto generated comment)
|
||||||
let cpt = k.cpt
|
? cpt.checkInStaticContext()
|
||||||
? checkInStaticContext(cpt)
|
|
||||||
|
|
||||||
let
|
let
|
||||||
beneficiary = ? cpt.stack.popAddress()
|
beneficiary = ? cpt.stack.popAddress()
|
||||||
isDead = not cpt.accountExists(beneficiary)
|
isDead = not cpt.accountExists(beneficiary)
|
||||||
balance = cpt.getBalance(cpt.msg.contractAddress)
|
balance = cpt.getBalance(cpt.msg.contractAddress)
|
||||||
condition = isDead and not balance.isZero
|
condition = isDead and not balance.isZero
|
||||||
gasCost = cpt.gasCosts[SelfDestruct].sc_handler(condition)
|
gasCost = cpt.gasCosts[SelfDestruct].sc_handler(condition)
|
||||||
|
|
||||||
? cpt.opcodeGasCost(SelfDestruct,
|
? cpt.opcodeGasCost(SelfDestruct,
|
||||||
gasCost, reason = "SELFDESTRUCT EIP161")
|
gasCost, reason = "SELFDESTRUCT EIP161")
|
||||||
cpt.selfDestruct(beneficiary)
|
cpt.selfDestruct(beneficiary)
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc selfDestructEIP2929Op(k: var VmCtx): EvmResultVoid =
|
proc selfDestructEIP2929Op(cpt: VmCpt): EvmResultVoid =
|
||||||
## selfDestructEIP2929 (auto generated comment)
|
## selfDestructEIP2929 (auto generated comment)
|
||||||
let cpt = k.cpt
|
? cpt.checkInStaticContext()
|
||||||
? checkInStaticContext(cpt)
|
|
||||||
|
|
||||||
let
|
let
|
||||||
beneficiary = ? cpt.stack.popAddress()
|
beneficiary = ? cpt.stack.popAddress()
|
||||||
|
|
|
@ -38,10 +38,8 @@ when optimizationCondition:
|
||||||
# this is a top level pragma since nim 1.6.16
|
# this is a top level pragma since nim 1.6.16
|
||||||
{.optimization: speed.}
|
{.optimization: speed.}
|
||||||
|
|
||||||
proc selectVM(c: Computation, fork: EVMFork, shouldPrepareTracer: bool): EvmResultVoid =
|
proc selectVM(c: VmCpt, fork: EVMFork, shouldPrepareTracer: bool): EvmResultVoid =
|
||||||
## Op code execution handler main loop.
|
## Op code execution handler main loop.
|
||||||
var desc: VmCtx
|
|
||||||
desc.cpt = c
|
|
||||||
|
|
||||||
# It's important not to re-prepare the tracer after
|
# It's important not to re-prepare the tracer after
|
||||||
# an async operation, only after a call/create.
|
# an async operation, only after a call/create.
|
||||||
|
@ -99,12 +97,12 @@ proc selectVM(c: Computation, fork: EVMFork, shouldPrepareTracer: bool): EvmResu
|
||||||
else:
|
else:
|
||||||
{.warning: "*** Unsupported OS => no handler switch optimisation".}
|
{.warning: "*** Unsupported OS => no handler switch optimisation".}
|
||||||
|
|
||||||
genOptimisedDispatcher(fork, c.instr, desc)
|
genOptimisedDispatcher(fork, c.instr, c)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
{.warning: "*** low memory compiler mode => program will be slow".}
|
{.warning: "*** low memory compiler mode => program will be slow".}
|
||||||
|
|
||||||
genLowMemDispatcher(fork, c.instr, desc)
|
genLowMemDispatcher(fork, c.instr, c)
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue