re-integrated 0x60..0xaf (push, dup, swap, log) op handlers

This commit is contained in:
Jordan Hrycaj 2021-04-15 14:40:31 +01:00 committed by zah
parent f4bc9c4561
commit 716bd64419
9 changed files with 698 additions and 64 deletions

View File

@ -21,7 +21,7 @@ import
./op_codes, ./op_codes,
./op_handlers/[oph_defs, ./op_handlers/[oph_defs,
oph_arithmetic, oph_hash, oph_envinfo, oph_blockdata, oph_arithmetic, oph_hash, oph_envinfo, oph_blockdata,
oph_memory, oph_memory, oph_push, oph_dup, oph_swap, oph_log,
oph_sysops] oph_sysops]
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -47,6 +47,10 @@ proc mkOpTable(select: Fork): array[Op,Vm2OpExec] {.compileTime.} =
result.importList(select, vm2OpExecEnvInfo, "EnvInfo") result.importList(select, vm2OpExecEnvInfo, "EnvInfo")
result.importList(select, vm2OpExecBlockData, "BlockData") result.importList(select, vm2OpExecBlockData, "BlockData")
result.importList(select, vm2OpExecMemory, "Memory") result.importList(select, vm2OpExecMemory, "Memory")
result.importList(select, vm2OpExecPush, "Push")
result.importList(select, vm2OpExecDup, "Dup")
result.importList(select, vm2OpExecSwap, "Swap")
result.importList(select, vm2OpExecLog, "Log")
result.importList(select, vm2OpExecSysOP, "SysOp") result.importList(select, vm2OpExecSysOP, "SysOp")
for op in Op: for op in Op:
@ -88,6 +92,18 @@ when isMainModule and isNoisy:
echo ">>> berlin[shl]: ", echo ">>> berlin[shl]: ",
vm2OpHandlers[FkBerlin][Shl].info vm2OpHandlers[FkBerlin][Shl].info
echo ">>> berlin[push32]: ",
vm2OpHandlers[FkBerlin][Push32].info
echo ">>> berlin[dup16]: ",
vm2OpHandlers[FkBerlin][Dup16].info
echo ">>> berlin[swap16]: ",
vm2OpHandlers[FkBerlin][Swap16].info
echo ">>> berlin[log4]: ",
vm2OpHandlers[FkBerlin][Log4].info
echo ">>> frontier[sstore]: ", echo ">>> frontier[sstore]: ",
vm2OpHandlers[FkFrontier][Sstore].info vm2OpHandlers[FkFrontier][Sstore].info

View File

@ -20,7 +20,8 @@ import
../forks_list, ../forks_list,
../op_codes, ../op_codes,
../../memory_defs, ../../memory_defs,
../../stack_defs ../../stack_defs,
eth/common/eth_types
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Kludge BEGIN # Kludge BEGIN
@ -50,7 +51,7 @@ else:
accountDb*: ReadOnlyStateDB accountDb*: ReadOnlyStateDB
Message* = ref object Message* = ref object
contractAddress*: UInt256 contractAddress*: EthAddress
sender*: UInt256 sender*: UInt256
value*: UInt256 value*: UInt256
data*: seq[byte] data*: seq[byte]
@ -71,7 +72,7 @@ else:
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
export export
Op, Fork, Computation, Memory, Stack, UInt256, Message Op, Fork, Computation, Memory, Stack, UInt256, Message, EthAddress
type type
Vm2Ctx* = object of RootObj Vm2Ctx* = object of RootObj

View File

@ -0,0 +1,82 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
## EVM Opcode Handlers: Duplication Operations
## ===========================================
##
const
kludge {.intdefine.}: int = 0
breakCircularDependency {.used.} = kludge > 0
import
./oph_defs,
./oph_helpers,
sequtils,
strformat,
stint
# ------------------------------------------------------------------------------
# Kludge BEGIN
# ------------------------------------------------------------------------------
when not breakCircularDependency:
import
../../stack
else:
# function stubs from stack.nim (to satisfy compiler logic)
proc dup(stack: var Stack, position: int | UInt256) = discard
# ------------------------------------------------------------------------------
# Kludge END
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
proc fnName(n: int): string {.compileTime.} =
&"dup{n}Op"
proc opName(n: int): string {.compileTime.} =
&"Dup{n}"
proc fnInfo(n: int): string {.compileTime.} =
var blurb = case n
of 1: "first"
of 2: "second"
of 3: "third"
else: &"{n}th"
&"Duplicate {blurb} item in the stack"
proc dupImpl(k: Vm2Ctx; n: int) =
k.cpt.stack.dup(n)
const
inxRange = toSeq(1 .. 16)
# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------
genOphHandlers fnName, fnInfo, inxRange, dupImpl
# ------------------------------------------------------------------------------
# Public, op exec table entries
# ------------------------------------------------------------------------------
genOphList fnName, fnInfo, inxRange, "vm2OpExecDup", opName
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -0,0 +1,153 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
## EVM Opcode Handlers: Helper Functions & Macros
## ==============================================
##
const
kludge {.intdefine.}: int = 0
breakCircularDependency {.used.} = kludge > 0
import
../../../errors,
./oph_defs,
macros,
stint
type
OphNumToTextFn* = proc(n: int): string
OpHanldlerImplFn* = proc(k: Vm2Ctx; n: int)
const
recForkSet = "Vm2OpAllForks"
# ------------------------------------------------------------------------------
# Kludge BEGIN
# ------------------------------------------------------------------------------
when not breakCircularDependency:
import
../../v2types
else:
const
emvcStatic = 1
# ------------------------------------------------------------------------------
# Kludge END
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
proc asIdent(id, name: string): NimNode {.compileTime.} =
result = nnkExprColonExpr.newTree(
newIdentNode(id),
newIdentNode(name))
proc asText(id, name: string): NimNode {.compileTime.} =
result = nnkExprColonExpr.newTree(
newIdentNode(id),
newLit(name))
# ------------------------------------------------------------------------------
# Public
# ------------------------------------------------------------------------------
template checkInStaticContext*(c: Computation) =
## Verify static context in handler function, raise an error otherwise
if emvcStatic == c.msg.flags:
# TODO: if possible, this check only appear
# when fork >= FkByzantium
raise newException(
StaticContextError,
"Cannot modify state while inside of STATICCALL context")
macro genOphHandlers*(runHandler: static[OphNumToTextFn];
itemInfo: static[OphNumToTextFn];
inxList: static[openArray[int]];
body: static[OpHanldlerImplFn]): untyped =
## Generate the equivalent of
## ::
## const <runHandler>: Vm2OpFn = proc (k: Vm2Ctx) =
## ## <itemInfo(n)>,
## <body(k,n)>
##
## for all `n` in `inxList`
##
result = newStmtList()
for n in inxList:
let
fnName = ident(n.runHandler)
comment = newCommentStmtNode(n.itemInfo)
# => push##Op: Vm2OpFn = proc (k: Vm2Ctx) = ...
result.add quote do:
const `fnName`: Vm2OpFn = proc(k: Vm2Ctx) =
`comment`
`body`(k,`n`)
# echo ">>>", result.repr
macro genOphList*(runHandler: static[OphNumToTextFn];
handlerInfo: static[OphNumToTextFn];
inxList: static[openArray[int]];
varName: static[string];
opCode: static[OphNumToTextFn]): untyped =
## Generate
## ::
## const <varName>*: seq[Vm2OpExec] = @[ <records> ]
##
## where <records> is a sequence of <record(n)> items like
## ::
## (opCode: <opCode(n)>,
## forks: Vm2OpAllForks,
## info: <handlerInfo(n)>,
## exec: (prep: vm2OpIgnore,
## run: <runHandler(n)>,
## post: vm2OpIgnore))
##
## for all `n` in `inxList`
##
var records = nnkBracket.newTree()
for n in inxList:
records.add nnkPar.newTree(
"opCode".asIdent(n.opCode),
"forks".asIdent(recForkSet),
"info".asText(n.handlerInfo),
nnkExprColonExpr.newTree(
newIdentNode("exec"),
nnkPar.newTree(
"prep".asIdent("vm2OpIgnore"),
"run".asIdent(n.runHandler),
"post".asIdent("vm2OpIgnore"))))
# => const <varName>*: seq[Vm2OpExec] = @[ <records> ]
result = nnkStmtList.newTree(
nnkConstSection.newTree(
nnkConstDef.newTree(
nnkPostfix.newTree(
newIdentNode("*"),
newIdentNode(varName)),
nnkBracketExpr.newTree(
newIdentNode("seq"),
newIdentNode("Vm2OpExec")),
nnkPrefix.newTree(
newIdentNode("@"), records))))
# echo ">>> ", result.repr
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -0,0 +1,151 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
## EVM Opcode Handlers: Logging Operations
## =======================================
##
const
kludge {.intdefine.}: int = 0
breakCircularDependency {.used.} = kludge > 0
import
../../../errors,
./oph_defs,
./oph_helpers,
sequtils,
eth/common,
strformat,
stint
# ------------------------------------------------------------------------------
# Kludge BEGIN
# ------------------------------------------------------------------------------
when not breakCircularDependency:
import
../../../constants,
../../stack,
../../v2computation,
../../v2memory,
../../v2state,
../../v2types,
../gas_meter,
../utils/v2utils_numeric,
../v2gas_costs,
eth/common
else:
import
macros
var blindGasCosts: array[Op,int]
var blindTopic: Topic
# copied from stack.nim
macro genTupleType(len: static[int], elemType: untyped): untyped =
result = nnkTupleConstr.newNimNode()
for i in 0 ..< len: result.add(elemType)
# function stubs from stack.nim (to satisfy compiler logic)
proc popTopic(x: var Stack): Topic = blindTopic
proc popInt(x: var Stack, n: static[int]): auto =
var rc: genTupleType(n, UInt256)
return rc
# function stubs from v2computation.nim (to satisfy compiler logic)
proc gasCosts(c: Computation): array[Op,int] = blindGasCosts
proc addLogEntry(c: Computation, log: Log) = discard
# function stubs from v2utils_numeric.nim
func cleanMemRef(x: UInt256): int = 0
# function stubs from v2memory.nim
proc len(mem: Memory): int = 0
proc extend(mem: var Memory; startPos: Natural; size: Natural) = discard
proc read(mem: var Memory, startPos: Natural, size: Natural): seq[byte] = @[]
# function stubs from gas_meter.nim
proc consumeGas(gasMeter: var GasMeter; amount: int; reason: string) = discard
# stubs from v2gas_costs.nim
proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = 0
# ------------------------------------------------------------------------------
# Kludge END
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Private, names & settings
# ------------------------------------------------------------------------------
proc fnName(n: int): string {.compileTime.} =
&"Log{n}Op"
proc opName(n: int): string {.compileTime.} =
&"Log{n}"
proc fnInfo(n: int): string {.compileTime.} =
var blurb = case n
of 1: "topic"
else: "topics"
&"Append log record with {n} {blurb}"
proc logImpl(c: Computation, opcode: Op, topicCount: int) =
doAssert(topicCount in 0 .. 4)
checkInStaticContext(c)
let (memStartPosition, size) = c.stack.popInt(2)
let (memPos, len) = (memStartPosition.cleanMemRef, size.cleanMemRef)
if memPos < 0 or len < 0:
raise newException(OutOfBoundsRead, "Out of bounds memory access")
c.gasMeter.consumeGas(
c.gasCosts[opcode].m_handler(c.memory.len, memPos, len),
reason = "Memory expansion, Log topic and data gas cost")
c.memory.extend(memPos, len)
var log: Log
log.topics = newSeqOfCap[Topic](topicCount)
for i in 0 ..< topicCount:
log.topics.add(c.stack.popTopic())
log.data = c.memory.read(memPos, len)
log.address = c.msg.contractAddress
c.addLogEntry(log)
const
inxRange = toSeq(0 .. 4)
logOpArg = block:
var rc: array[inxRange.len + 1, Op]
for n in inxRange:
rc[n] = Op(Log0.int + n)
rc
# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------
proc wrapperFn(k: Vm2Ctx; n: int) =
logImpl(k.cpt, logOpArg[n], n)
genOphHandlers fnName, fnInfo, inxRange, wrapperFn
# ------------------------------------------------------------------------------
# Public, op exec table entries
# ------------------------------------------------------------------------------
genOphList fnName, fnInfo, inxRange, "vm2OpExecLog", opName
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -19,6 +19,7 @@ const
import import
../../../errors, ../../../errors,
./oph_defs, ./oph_defs,
./oph_helpers,
strformat, strformat,
stint stint
@ -44,7 +45,6 @@ when not breakCircularDependency:
else: else:
import macros import macros
const emvcStatic = 1
var blindGasCosts: array[Op,int] var blindGasCosts: array[Op,int]
# copied from stack.nim # copied from stack.nim
@ -97,7 +97,7 @@ else:
proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = 0 proc m_handler(x: int; curMemSize, memOffset, memLen: int64): int = 0
# function stubs from state_db.nim # function stubs from state_db.nim
proc getCommittedStorage(x: ReadOnlyStateDB; y,z: Uint256): Uint256 = 0.u256 proc getCommittedStorage[A,B](x: A; y: B; z: Uint256): Uint256 = 0.u256
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Kludge END # Kludge END
@ -107,14 +107,6 @@ else:
# Private helpers # Private helpers
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
template checkInStaticContext(c: Computation) =
# TODO: if possible, this check only appear
# when fork >= FkByzantium
if emvcStatic == c.msg.flags:
raise newException(
StaticContextError,
"Cannot modify state while inside of STATICCALL context")
proc sstoreNetGasMeteringImpl(c: Computation; slot, newValue: Uint256) = proc sstoreNetGasMeteringImpl(c: Computation; slot, newValue: Uint256) =
let let
stateDB = c.vmState.readOnlyStateDB stateDB = c.vmState.readOnlyStateDB

View File

@ -0,0 +1,85 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
## EVM Opcode Handlers: Push Operations
## ====================================
##
const
kludge {.intdefine.}: int = 0
breakCircularDependency {.used.} = kludge > 0
import
./oph_defs,
./oph_helpers,
sequtils,
strformat,
stint
# ------------------------------------------------------------------------------
# Kludge BEGIN
# ------------------------------------------------------------------------------
when not breakCircularDependency:
import
../../code_stream,
../../stack
else:
# function stubs from stack.nim (to satisfy compiler logic)
proc push[T](x: Stack; n: T) = discard
# function stubs from code_stream.nim
proc readVmWord(c: var CodeStream, n: int): UInt256 = 0.u256
# ------------------------------------------------------------------------------
# Kludge END
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Private helpers
# ------------------------------------------------------------------------------
proc fnName(n: int): string {.compileTime.} =
&"push{n}Op"
proc opName(n: int): string {.compileTime.} =
&"Push{n}"
proc fnInfo(n: int): string {.compileTime.} =
var blurb = case n
of 1: "byte"
else: &"{n} bytes"
&"Push {blurb} on the stack"
proc pushImpl(k: Vm2Ctx; n: int) =
k.cpt.stack.push:
k.cpt.code.readVmWord(n)
const
inxRange = toSeq(1 .. 32)
# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------
genOphHandlers fnName, fnInfo, inxRange, pushImpl
# ------------------------------------------------------------------------------
# Public, op exec table entries
# ------------------------------------------------------------------------------
genOphList fnName, fnInfo, inxRange, "vm2OpExecPush", opName
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -0,0 +1,81 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed except
# according to those terms.
## EVM Opcode Handlers: Swap Operations
## ====================================
##
const
kludge {.intdefine.}: int = 0
breakCircularDependency {.used.} = kludge > 0
import
./oph_defs,
./oph_helpers,
sequtils,
strformat
# ------------------------------------------------------------------------------
# Kludge BEGIN
# ------------------------------------------------------------------------------
when not breakCircularDependency:
import
../../stack
else:
# function stubs from stack.nim (to satisfy compiler logic)
proc swap(stack: var Stack, position: int) = discard
# ------------------------------------------------------------------------------
# Kludge END
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Private, names & settings
# ------------------------------------------------------------------------------
proc fnName(n: int): string {.compileTime.} =
&"swap{n}Op"
proc opName(n: int): string {.compileTime.} =
&"Swap{n}"
proc fnInfo(n: int): string {.compileTime.} =
var blurb = case n+1
of 1: "first"
of 2: "second"
of 3: "third"
else: &"{n+1}th"
&"Exchange first and {blurb} stack items"
proc swapImpl(k: Vm2Ctx; n: int) =
k.cpt.stack.swap(n)
const
inxRange = toSeq(1 .. 16)
# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------
genOphHandlers fnName, fnInfo, inxRange, swapImpl
# ------------------------------------------------------------------------------
# Public, op exec table entries
# ------------------------------------------------------------------------------
genOphList fnName, fnInfo, inxRange, "vm2OpExecSwap", opName
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -118,9 +118,15 @@ opHandler orOp, Op.Or
opHandler xorOp, Op.Xor opHandler xorOp, Op.Xor
opHandler notOp, Op.Not opHandler notOp, Op.Not
opHandler byteOp, Op.Byte opHandler byteOp, Op.Byte
opHandler shlOp, Op.Shl
opHandler shrOp, Op.Shr
opHandler sarOp, Op.Sar
opHandler sha3, Op.Sha3 opHandler sha3, Op.Sha3
opHandler address, Op.Address opHandler address, Op.Address
opHandler balance, Op.Balance
opHandler balance, Op.Balance, FkFrontier
opHandler balanceEIP2929, Op.Balance
opHandler origin, Op.Origin opHandler origin, Op.Origin
opHandler caller, Op.Caller opHandler caller, Op.Caller
opHandler callValue, Op.CallValue opHandler callValue, Op.CallValue
@ -130,8 +136,13 @@ opHandler callDataCopy, Op.CallDataCopy
opHandler codeSize, Op.CodeSize opHandler codeSize, Op.CodeSize
opHandler codeCopy, Op.CodeCopy opHandler codeCopy, Op.CodeCopy
opHandler gasprice, Op.GasPrice opHandler gasprice, Op.GasPrice
opHandler extCodeSize, Op.ExtCodeSize
opHandler extCodeCopy, Op.ExtCodeCopy opHandler extCodeSize, Op.ExtCodeSize, FkFrontier
opHandler extCodeSizeEIP2929, Op.ExtCodeSize
opHandler extCodeCopy, Op.ExtCodeCopy, FkFrontier
opHandler extCodeCopyEIP2929, Op.ExtCodeCopy
opHandler returnDataSize, Op.ReturnDataSize opHandler returnDataSize, Op.ReturnDataSize
opHandler returnDataCopy, Op.ReturnDataCopy opHandler returnDataCopy, Op.ReturnDataCopy
opHandler blockhash, Op.Blockhash opHandler blockhash, Op.Blockhash
@ -146,10 +157,15 @@ opHandler pop, Op.Pop
opHandler mload, Op.Mload opHandler mload, Op.Mload
opHandler mstore, Op.Mstore opHandler mstore, Op.Mstore
opHandler mstore8, Op.Mstore8 opHandler mstore8, Op.Mstore8
opHandler sload, Op.Sload
opHandler sload, Op.Sload, FkFrontier
opHandler sloadEIP2929, Op.Sload
opHandler sstore, Op.Sstore, FkFrontier opHandler sstore, Op.Sstore, FkFrontier
opHandler sstoreEIP1283, Op.Sstore, FkConstantinople opHandler sstoreEIP1283, Op.Sstore, FkConstantinople
opHandler sstoreEIP2200, Op.Sstore opHandler sstoreEIP2200, Op.Sstore, FkIstanbul
opHandler sstoreEIP2929, Op.Sstore
opHandler jump, Op.Jump opHandler jump, Op.Jump
opHandler jumpI, Op.JumpI opHandler jumpI, Op.JumpI
opHandler pc, Op.Pc opHandler pc, Op.Pc
@ -159,17 +175,75 @@ opHandler jumpDest, Op.JumpDest
opHandler beginSub, Op.BeginSub opHandler beginSub, Op.BeginSub
opHandler returnSub, Op.ReturnSub opHandler returnSub, Op.ReturnSub
opHandler jumpSub, Op.JumpSub opHandler jumpSub, Op.JumpSub
opHandler push1, Op.Push1
# ########################################## opHandler push2, Op.Push2
# 60s & 70s: Push Operations. opHandler push3, Op.Push3
# 80s: Duplication Operations opHandler push4, Op.Push4
# 90s: Exchange Operations opHandler push5, Op.Push5
# a0s: Logging Operations opHandler push6, Op.Push6
opHandler push7, Op.Push7
genPush() opHandler push8, Op.Push8
genDup() opHandler push9, Op.Push9
genSwap() opHandler push10, Op.Push10
genLog() opHandler push11, Op.Push11
opHandler push12, Op.Push12
opHandler push13, Op.Push13
opHandler push14, Op.Push14
opHandler push15, Op.Push15
opHandler push16, Op.Push16
opHandler push17, Op.Push17
opHandler push18, Op.Push18
opHandler push19, Op.Push19
opHandler push20, Op.Push20
opHandler push21, Op.Push21
opHandler push22, Op.Push22
opHandler push23, Op.Push23
opHandler push24, Op.Push24
opHandler push25, Op.Push25
opHandler push26, Op.Push26
opHandler push27, Op.Push27
opHandler push28, Op.Push28
opHandler push29, Op.Push29
opHandler push30, Op.Push30
opHandler push31, Op.Push31
opHandler push32, Op.Push32
opHandler dup1, Op.Dup1
opHandler dup2, Op.Dup2
opHandler dup3, Op.Dup3
opHandler dup4, Op.Dup4
opHandler dup5, Op.Dup5
opHandler dup6, Op.Dup6
opHandler dup7, Op.Dup7
opHandler dup8, Op.Dup8
opHandler dup9, Op.Dup9
opHandler dup10, Op.Dup10
opHandler dup11, Op.Dup11
opHandler dup12, Op.Dup12
opHandler dup13, Op.Dup13
opHandler dup14, Op.Dup14
opHandler dup15, Op.Dup15
opHandler dup16, Op.Dup16
opHandler swap1, Op.Swap1
opHandler swap2, Op.Swap2
opHandler swap3, Op.Swap3
opHandler swap4, Op.Swap4
opHandler swap5, Op.Swap5
opHandler swap6, Op.Swap6
opHandler swap7, Op.Swap7
opHandler swap8, Op.Swap8
opHandler swap9, Op.Swap9
opHandler swap10, Op.Swap10
opHandler swap11, Op.Swap11
opHandler swap12, Op.Swap12
opHandler swap13, Op.Swap13
opHandler swap14, Op.Swap14
opHandler swap15, Op.Swap15
opHandler swap16, Op.Swap16
opHandler log0, Op.Log0
opHandler log1, Op.Log1
opHandler log2, Op.Log2
opHandler log3, Op.Log3
opHandler log4, Op.Log4
# ########################################## # ##########################################
# f0s: System operations. # f0s: System operations.
@ -471,48 +545,17 @@ op selfDestructEip161, inline = false:
c.selfDestruct(beneficiary) c.selfDestruct(beneficiary)
# Constantinople's new opcodes # Constantinople's new opcodes
#################################
opHandler shlOp, Op.Shl
opHandler shrOp, Op.Shr
opHandler sarOp, Op.Sar
op extCodeHash, inline = true: op extCodeHash, inline = true:
let address = c.stack.popAddress() let address = c.stack.popAddress()
push: c.getCodeHash(address) push: c.getCodeHash(address)
op balanceEIP2929, inline = true:
## 0x31, Get balance of the given account.
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasBalance])
push: c.getBalance(address)
op extCodeHashEIP2929, inline = true: op extCodeHashEIP2929, inline = true:
let address = c.stack.popAddress() let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCodeHash]) c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCodeHash])
push: c.getCodeHash(address) push: c.getCodeHash(address)
op extCodeSizeEIP2929, inline = true:
## 0x3b, Get size of an account's code
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCode])
push: c.getCodeSize(address)
op extCodeCopyEIP2929, inline = true:
## 0x3c, Copy an account's code to memory.
let address = c.stack.popAddress()
let (memStartPos, codeStartPos, size) = c.stack.popInt(3)
let (memPos, codePos, len) = (memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef)
c.gasMeter.consumeGas(
c.gasCosts[ExtCodeCopy].m_handler(c.memory.len, memPos, len),
reason="ExtCodeCopy fee")
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCode])
let codeBytes = c.getCode(address)
c.memory.writePaddedResult(codeBytes, memPos, codePos, len)
op selfDestructEIP2929, inline = false: op selfDestructEIP2929, inline = false:
checkInStaticContext(c) checkInStaticContext(c)
@ -535,7 +578,37 @@ op selfDestructEIP2929, inline = false:
c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161") c.gasMeter.consumeGas(gasCost, reason = "SELFDESTRUCT EIP161")
c.selfDestruct(beneficiary) c.selfDestruct(beneficiary)
op sloadEIP2929, inline = true, slot: # ---------------------------------------------------
op balanceEIP2929x, inline = true:
## 0x31, Get balance of the given account.
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasBalance])
push: c.getBalance(address)
op extCodeSizeEIP2929x, inline = true:
## 0x3b, Get size of an account's code
let address = c.stack.popAddress()
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCode])
push: c.getCodeSize(address)
op extCodeCopyEIP2929x, inline = true:
## 0x3c, Copy an account's code to memory.
let address = c.stack.popAddress()
let (memStartPos, codeStartPos, size) = c.stack.popInt(3)
let (memPos, codePos, len) = (memStartPos.cleanMemRef, codeStartPos.cleanMemRef, size.cleanMemRef)
c.gasMeter.consumeGas(
c.gasCosts[ExtCodeCopy].m_handler(c.memory.len, memPos, len),
reason="ExtCodeCopy fee")
c.gasEip2929AccountCheck(address, gasFees[c.fork][GasExtCode])
let codeBytes = c.getCode(address)
c.memory.writePaddedResult(codeBytes, memPos, codePos, len)
op sloadEIP2929x, inline = true, slot:
## 0x54, Load word from storage. ## 0x54, Load word from storage.
c.vmState.mutateStateDB: c.vmState.mutateStateDB:
let gasCost = if not db.inAccessList(c.msg.contractAddress, slot): let gasCost = if not db.inAccessList(c.msg.contractAddress, slot):
@ -547,7 +620,7 @@ op sloadEIP2929, inline = true, slot:
push: c.getStorage(slot) push: c.getStorage(slot)
op sstoreEIP2929, inline = false, slot, newValue: op sstoreEIP2929x, inline = false, slot, newValue:
checkInStaticContext(c) checkInStaticContext(c)
const SentryGasEIP2200 = 2300 # Minimum gas required to be present for an SSTORE call, not consumed const SentryGasEIP2200 = 2300 # Minimum gas required to be present for an SSTORE call, not consumed