Skip to content

Commit

Permalink
EIP-4750: EOF - Functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jangko committed Oct 31, 2023
1 parent dd3bb6e commit 7637250
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 11 deletions.
6 changes: 6 additions & 0 deletions nimbus/evm/code_stream.nim
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ proc parseEOF*(c: CodeStream): Result[void, EOFV1Error] =
func hasEOFCode*(c: CodeStream): bool =
hasEOFMagic(c.legacyCode)

func getType*(c: CodeStream, idx: int): FunctionMetaData =
c.container.types[idx]

func section*(c: CodeStream): int =
c.section

proc next*(c: var CodeStream): Op =
if c.pc != c.codeLen:
result = Op(c.codeView[c.pc])
Expand Down
16 changes: 14 additions & 2 deletions nimbus/evm/computation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ proc newComputation*(vmState: BaseVMState, sysCall: bool, message: Message,
result.msg = message
result.memory = Memory()
result.stack = newStack()
result.returnStack = @[]
# disable EIP-2315
# result.returnStack = @[]
result.gasMeter.init(message.gas)
result.sysCall = sysCall

Expand All @@ -238,18 +239,29 @@ proc newComputation*(vmState: BaseVMState, sysCall: bool, message: Message,
result.code = newCodeStream(
vmState.readOnlyStateDB.getCode(message.codeAddress))

# EIP-4750
result.returnStack = @[
ReturnContext(section: 0, pc: 0, stackHeight: 0)
]

proc newComputation*(vmState: BaseVMState, sysCall: bool,
message: Message, code: seq[byte]): Computation =
new result
result.vmState = vmState
result.msg = message
result.memory = Memory()
result.stack = newStack()
result.returnStack = @[]
# disable EIP-2315
# result.returnStack = @[]
result.gasMeter.init(message.gas)
result.code = newCodeStream(code)
result.sysCall = sysCall

# EIP-4750
result.returnStack = @[
ReturnContext(section: 0, pc: 0, stackHeight: 0)
]

template gasCosts*(c: Computation): untyped =
c.vmState.gasCosts

Expand Down
4 changes: 4 additions & 0 deletions nimbus/evm/interpreter/gas_costs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,10 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
Log3: memExpansion `prefix gasLog3`,
Log4: memExpansion `prefix gasLog4`,

# b0s: Function Operations
CallF: fixed GasLow,
RetF: fixed GasVeryLow,

# e0s: Static jumps
RJump: fixed GasBase,
RJumpI: fixed GasMidLow,
Expand Down
8 changes: 6 additions & 2 deletions nimbus/evm/interpreter/op_codes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,12 @@ type
Log4 = 0xa4, ## Append log record with four topics.

Nop0xA5, Nop0xA6, Nop0xA7, Nop0xA8, Nop0xA9, Nop0xAA,
Nop0xAB, Nop0xAC, Nop0xAD, Nop0xAE, Nop0xAF, Nop0xB0,
Nop0xB1, Nop0xB2, Nop0xB3, Nop0xB4, Nop0xB5, Nop0xB6,
Nop0xAB, Nop0xAC, Nop0xAD, Nop0xAE, Nop0xAF,

CallF = 0xb0, ## call a function (EIP4750)
RetF = 0xb1, ## return from a function (EIP4750)

Nop0xB2, Nop0xB3, Nop0xB4, Nop0xB5, Nop0xB6,
Nop0xB7, Nop0xB8, Nop0xB9, Nop0xBA, Nop0xBB, Nop0xBC,
Nop0xBD, Nop0xBE, Nop0xBF, Nop0xC0, Nop0xC1, Nop0xC2,
Nop0xC3, Nop0xC4, Nop0xC5, Nop0xC6, Nop0xC7, Nop0xC8,
Expand Down
13 changes: 13 additions & 0 deletions nimbus/evm/interpreter/op_dispatcher.nim
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
quote do:
`forkCaseSubExpr`
break
of RetF:
quote do:
`forkCaseSubExpr`
# EIP-4750: If returning from top frame, exit cleanly.
let c = `k`.cpt
if c.fork >= FkEOF and
c.returnStack.len == 0:
break
else:
# FIXME-manyOpcodesNowRequireContinuations
# We used to have another clause in this case statement for various
Expand Down Expand Up @@ -150,6 +158,11 @@ template genLowMemDispatcher*(fork: EVMFork; op: Op; k: Vm2Ctx) =
case c.instr
of Return, Revert, SelfDestruct:
break
of RetF:
# EIP-4750: If returning from top frame, exit cleanly.
if fork >= FkEOF and
k.cpt.returnStack.len == 0:
break
else:
# FIXME-manyOpcodesNowRequireContinuations
if not k.cpt.continuation.isNil:
Expand Down
5 changes: 3 additions & 2 deletions nimbus/evm/interpreter/op_handlers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import
./op_handlers/[oph_defs,
oph_arithmetic, oph_hash, oph_envinfo, oph_blockdata,
oph_memory, oph_push, oph_dup, oph_swap, oph_log,
oph_create, oph_call, oph_sysops]
oph_create, oph_call, oph_sysops, oph_function]

const
allHandlersList = @[
Expand All @@ -40,7 +40,8 @@ const
(vm2OpExecLog, "Log"),
(vm2OpExecCreate, "Create"),
(vm2OpExecCall, "Call"),
(vm2OpExecSysOp, "SysOp")]
(vm2OpExecSysOp, "SysOp"),
(vm2OpExecFunction, "Function")]

# ------------------------------------------------------------------------------
# Helper
Expand Down
78 changes: 78 additions & 0 deletions nimbus/evm/interpreter/op_handlers/oph_function.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# 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: Function Operations
## ======================================
##

import
../../../errors,
../../code_stream,
../../stack,
../../types,
../op_codes,
./oph_defs

# ------------------------------------------------------------------------------
# Private, op handlers implementation
# ------------------------------------------------------------------------------

const
callfOp: Vm2OpFn = proc (k: var Vm2Ctx) =
## 0xb0, Call a function.
let
idx = k.cpt.code.readInt16()
typ = k.cpt.code.getType(idx)

if k.cpt.stack.len + typ.maxStackHeight.int >= 1024:
raise newException(
StackDepthError, "CallF stack overflow")

k.cpt.returnStack.add ReturnContext(
section : k.cpt.code.section,
pc : k.cpt.code.pc,
stackHeight: k.cpt.stack.len - typ.input.int
)

k.cpt.code.setSection(idx)
k.cpt.code.pc = 0

retfOp: Vm2OpFn = proc (k: var Vm2Ctx) =
## 0x50, Return from a function.
let ctx = k.cpt.returnStack.pop()
k.cpt.code.setSection(ctx.section)
k.cpt.code.pc = ctx.pc

# ------------------------------------------------------------------------------
# Public, op exec table entries
# ------------------------------------------------------------------------------

const
vm2OpExecFunction*: seq[Vm2OpExec] = @[

(opCode: CallF, ## 0xb0, Call a function
forks: Vm2OpEOFAndLater,
name: "CallF",
info: "Create a new account with associated code",
exec: (prep: vm2OpIgnore,
run: callfOp,
post: vm2OpIgnore)),

(opCode: RetF, ## 0xb1, Return from a function
forks: Vm2OpEOFAndLater,
name: "RetF",
info: "Behaves identically to CREATE, except using keccak256",
exec: (prep: vm2OpIgnore,
run: retfOp,
post: vm2OpIgnore))]

# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------
6 changes: 3 additions & 3 deletions nimbus/evm/interpreter/op_handlers/oph_memory.nim
Original file line number Diff line number Diff line change
Expand Up @@ -488,23 +488,23 @@ const
post: vm2OpIgnore)),

(opCode: Jump, ## 0x56, Jump
forks: Vm2OpAllForks,
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
name: "jump",
info: "Alter the program counter",
exec: (prep: vm2OpIgnore,
run: jumpOp,
post: vm2OpIgnore)),

(opCode: JumpI, ## 0x57, Conditional jump
forks: Vm2OpAllForks,
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
name: "jumpI",
info: "Conditionally alter the program counter",
exec: (prep: vm2OpIgnore,
run: jumpIOp,
post: vm2OpIgnore)),

(opCode: Pc, ## 0x58, Program counter prior to instruction
forks: Vm2OpAllForks,
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
name: "pc",
info: "Get the value of the program counter prior to the increment "&
"corresponding to this instruction",
Expand Down
10 changes: 9 additions & 1 deletion nimbus/evm/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,20 @@ type
gasCosts* : GasCosts
asyncFactory* : AsyncOperationFactory

# EIP-4750
ReturnContext* = object
section*: int
pc*: int
stackHeight*: int

Computation* = ref object
# The execution computation
vmState*: BaseVMState
msg*: Message
memory*: Memory
stack*: Stack
returnStack*: seq[int]
# disable EIP-2315
# returnStack*: seq[int]
gasMeter*: GasMeter
code*: CodeStream
output*: seq[byte]
Expand All @@ -97,6 +104,7 @@ type
continuation*: proc() {.gcsafe, raises: [CatchableError].}
sysCall*: bool
initcodeEOF*: bool
returnStack*: seq[ReturnContext]

Error* = ref object
statusCode*: evmc_status_code
Expand Down
3 changes: 2 additions & 1 deletion nimbus/vm_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export
vmt.TracerRef,
vmt.VMFlag,
vmt.BlockContext,
vmt.TxContext
vmt.TxContext,
vmt.ReturnContext

when defined(evmc_enabled):
import
Expand Down

0 comments on commit 7637250

Please sign in to comment.