EVM cosmetic changes, one less indirect access of VmCpt (#2503)

This commit is contained in:
andri lim 2024-07-19 08:44:01 +07:00 committed by GitHub
parent 5ac362fe6f
commit fb196849ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 282 additions and 326 deletions

View File

@ -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

View File

@ -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

View File

@ -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 twos complement signed integer. ## Extend length of twos 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

View File

@ -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 chains EIP-155 unique identifier. ## 0x46, Get current chains 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
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -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,

View File

@ -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)

View File

@ -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* =

View File

@ -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)

View File

@ -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 contracts code ## 0x3f, Returns the keccak256 hash of a contracts 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 contracts code ## 0x3f, EIP2929: Returns the keccak256 hash of a contracts 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

View File

@ -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

View File

@ -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()
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -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

View File

@ -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)

View File

@ -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] = @[

View File

@ -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)

View File

@ -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()

View File

@ -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()