Skip to content

Commit 7637250

Browse files
committed
EIP-4750: EOF - Functions
1 parent dd3bb6e commit 7637250

File tree

10 files changed

+138
-11
lines changed

10 files changed

+138
-11
lines changed

nimbus/evm/code_stream.nim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ proc parseEOF*(c: CodeStream): Result[void, EOFV1Error] =
119119
func hasEOFCode*(c: CodeStream): bool =
120120
hasEOFMagic(c.legacyCode)
121121

122+
func getType*(c: CodeStream, idx: int): FunctionMetaData =
123+
c.container.types[idx]
124+
125+
func section*(c: CodeStream): int =
126+
c.section
127+
122128
proc next*(c: var CodeStream): Op =
123129
if c.pc != c.codeLen:
124130
result = Op(c.codeView[c.pc])

nimbus/evm/computation.nim

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ proc newComputation*(vmState: BaseVMState, sysCall: bool, message: Message,
226226
result.msg = message
227227
result.memory = Memory()
228228
result.stack = newStack()
229-
result.returnStack = @[]
229+
# disable EIP-2315
230+
# result.returnStack = @[]
230231
result.gasMeter.init(message.gas)
231232
result.sysCall = sysCall
232233

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

242+
# EIP-4750
243+
result.returnStack = @[
244+
ReturnContext(section: 0, pc: 0, stackHeight: 0)
245+
]
246+
241247
proc newComputation*(vmState: BaseVMState, sysCall: bool,
242248
message: Message, code: seq[byte]): Computation =
243249
new result
244250
result.vmState = vmState
245251
result.msg = message
246252
result.memory = Memory()
247253
result.stack = newStack()
248-
result.returnStack = @[]
254+
# disable EIP-2315
255+
# result.returnStack = @[]
249256
result.gasMeter.init(message.gas)
250257
result.code = newCodeStream(code)
251258
result.sysCall = sysCall
252259

260+
# EIP-4750
261+
result.returnStack = @[
262+
ReturnContext(section: 0, pc: 0, stackHeight: 0)
263+
]
264+
253265
template gasCosts*(c: Computation): untyped =
254266
c.vmState.gasCosts
255267

nimbus/evm/interpreter/gas_costs.nim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,10 @@ template gasCosts(fork: EVMFork, prefix, ResultGasCostsName: untyped) =
722722
Log3: memExpansion `prefix gasLog3`,
723723
Log4: memExpansion `prefix gasLog4`,
724724

725+
# b0s: Function Operations
726+
CallF: fixed GasLow,
727+
RetF: fixed GasVeryLow,
728+
725729
# e0s: Static jumps
726730
RJump: fixed GasBase,
727731
RJumpI: fixed GasMidLow,

nimbus/evm/interpreter/op_codes.nim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,12 @@ type
176176
Log4 = 0xa4, ## Append log record with four topics.
177177

178178
Nop0xA5, Nop0xA6, Nop0xA7, Nop0xA8, Nop0xA9, Nop0xAA,
179-
Nop0xAB, Nop0xAC, Nop0xAD, Nop0xAE, Nop0xAF, Nop0xB0,
180-
Nop0xB1, Nop0xB2, Nop0xB3, Nop0xB4, Nop0xB5, Nop0xB6,
179+
Nop0xAB, Nop0xAC, Nop0xAD, Nop0xAE, Nop0xAF,
180+
181+
CallF = 0xb0, ## call a function (EIP4750)
182+
RetF = 0xb1, ## return from a function (EIP4750)
183+
184+
Nop0xB2, Nop0xB3, Nop0xB4, Nop0xB5, Nop0xB6,
181185
Nop0xB7, Nop0xB8, Nop0xB9, Nop0xBA, Nop0xBB, Nop0xBC,
182186
Nop0xBD, Nop0xBE, Nop0xBF, Nop0xC0, Nop0xC1, Nop0xC2,
183187
Nop0xC3, Nop0xC4, Nop0xC5, Nop0xC6, Nop0xC7, Nop0xC8,

nimbus/evm/interpreter/op_dispatcher.nim

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
105105
quote do:
106106
`forkCaseSubExpr`
107107
break
108+
of RetF:
109+
quote do:
110+
`forkCaseSubExpr`
111+
# EIP-4750: If returning from top frame, exit cleanly.
112+
let c = `k`.cpt
113+
if c.fork >= FkEOF and
114+
c.returnStack.len == 0:
115+
break
108116
else:
109117
# FIXME-manyOpcodesNowRequireContinuations
110118
# We used to have another clause in this case statement for various
@@ -150,6 +158,11 @@ template genLowMemDispatcher*(fork: EVMFork; op: Op; k: Vm2Ctx) =
150158
case c.instr
151159
of Return, Revert, SelfDestruct:
152160
break
161+
of RetF:
162+
# EIP-4750: If returning from top frame, exit cleanly.
163+
if fork >= FkEOF and
164+
k.cpt.returnStack.len == 0:
165+
break
153166
else:
154167
# FIXME-manyOpcodesNowRequireContinuations
155168
if not k.cpt.continuation.isNil:

nimbus/evm/interpreter/op_handlers.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import
2424
./op_handlers/[oph_defs,
2525
oph_arithmetic, oph_hash, oph_envinfo, oph_blockdata,
2626
oph_memory, oph_push, oph_dup, oph_swap, oph_log,
27-
oph_create, oph_call, oph_sysops]
27+
oph_create, oph_call, oph_sysops, oph_function]
2828

2929
const
3030
allHandlersList = @[
@@ -40,7 +40,8 @@ const
4040
(vm2OpExecLog, "Log"),
4141
(vm2OpExecCreate, "Create"),
4242
(vm2OpExecCall, "Call"),
43-
(vm2OpExecSysOp, "SysOp")]
43+
(vm2OpExecSysOp, "SysOp"),
44+
(vm2OpExecFunction, "Function")]
4445

4546
# ------------------------------------------------------------------------------
4647
# Helper
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Nimbus
2+
# Copyright (c) 2018 Status Research & Development GmbH
3+
# Licensed under either of
4+
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
5+
# http://www.apache.org/licenses/LICENSE-2.0)
6+
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
7+
# http://opensource.org/licenses/MIT)
8+
# at your option. This file may not be copied, modified, or distributed except
9+
# according to those terms.
10+
11+
## EVM Opcode Handlers: Function Operations
12+
## ======================================
13+
##
14+
15+
import
16+
../../../errors,
17+
../../code_stream,
18+
../../stack,
19+
../../types,
20+
../op_codes,
21+
./oph_defs
22+
23+
# ------------------------------------------------------------------------------
24+
# Private, op handlers implementation
25+
# ------------------------------------------------------------------------------
26+
27+
const
28+
callfOp: Vm2OpFn = proc (k: var Vm2Ctx) =
29+
## 0xb0, Call a function.
30+
let
31+
idx = k.cpt.code.readInt16()
32+
typ = k.cpt.code.getType(idx)
33+
34+
if k.cpt.stack.len + typ.maxStackHeight.int >= 1024:
35+
raise newException(
36+
StackDepthError, "CallF stack overflow")
37+
38+
k.cpt.returnStack.add ReturnContext(
39+
section : k.cpt.code.section,
40+
pc : k.cpt.code.pc,
41+
stackHeight: k.cpt.stack.len - typ.input.int
42+
)
43+
44+
k.cpt.code.setSection(idx)
45+
k.cpt.code.pc = 0
46+
47+
retfOp: Vm2OpFn = proc (k: var Vm2Ctx) =
48+
## 0x50, Return from a function.
49+
let ctx = k.cpt.returnStack.pop()
50+
k.cpt.code.setSection(ctx.section)
51+
k.cpt.code.pc = ctx.pc
52+
53+
# ------------------------------------------------------------------------------
54+
# Public, op exec table entries
55+
# ------------------------------------------------------------------------------
56+
57+
const
58+
vm2OpExecFunction*: seq[Vm2OpExec] = @[
59+
60+
(opCode: CallF, ## 0xb0, Call a function
61+
forks: Vm2OpEOFAndLater,
62+
name: "CallF",
63+
info: "Create a new account with associated code",
64+
exec: (prep: vm2OpIgnore,
65+
run: callfOp,
66+
post: vm2OpIgnore)),
67+
68+
(opCode: RetF, ## 0xb1, Return from a function
69+
forks: Vm2OpEOFAndLater,
70+
name: "RetF",
71+
info: "Behaves identically to CREATE, except using keccak256",
72+
exec: (prep: vm2OpIgnore,
73+
run: retfOp,
74+
post: vm2OpIgnore))]
75+
76+
# ------------------------------------------------------------------------------
77+
# End
78+
# ------------------------------------------------------------------------------

nimbus/evm/interpreter/op_handlers/oph_memory.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -488,23 +488,23 @@ const
488488
post: vm2OpIgnore)),
489489

490490
(opCode: Jump, ## 0x56, Jump
491-
forks: Vm2OpAllForks,
491+
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
492492
name: "jump",
493493
info: "Alter the program counter",
494494
exec: (prep: vm2OpIgnore,
495495
run: jumpOp,
496496
post: vm2OpIgnore)),
497497

498498
(opCode: JumpI, ## 0x57, Conditional jump
499-
forks: Vm2OpAllForks,
499+
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
500500
name: "jumpI",
501501
info: "Conditionally alter the program counter",
502502
exec: (prep: vm2OpIgnore,
503503
run: jumpIOp,
504504
post: vm2OpIgnore)),
505505

506506
(opCode: Pc, ## 0x58, Program counter prior to instruction
507-
forks: Vm2OpAllForks,
507+
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
508508
name: "pc",
509509
info: "Get the value of the program counter prior to the increment "&
510510
"corresponding to this instruction",

nimbus/evm/types.nim

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,20 @@ type
7272
gasCosts* : GasCosts
7373
asyncFactory* : AsyncOperationFactory
7474

75+
# EIP-4750
76+
ReturnContext* = object
77+
section*: int
78+
pc*: int
79+
stackHeight*: int
80+
7581
Computation* = ref object
7682
# The execution computation
7783
vmState*: BaseVMState
7884
msg*: Message
7985
memory*: Memory
8086
stack*: Stack
81-
returnStack*: seq[int]
87+
# disable EIP-2315
88+
# returnStack*: seq[int]
8289
gasMeter*: GasMeter
8390
code*: CodeStream
8491
output*: seq[byte]
@@ -97,6 +104,7 @@ type
97104
continuation*: proc() {.gcsafe, raises: [CatchableError].}
98105
sysCall*: bool
99106
initcodeEOF*: bool
107+
returnStack*: seq[ReturnContext]
100108

101109
Error* = ref object
102110
statusCode*: evmc_status_code

nimbus/vm_types.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export
2323
vmt.TracerRef,
2424
vmt.VMFlag,
2525
vmt.BlockContext,
26-
vmt.TxContext
26+
vmt.TxContext,
27+
vmt.ReturnContext
2728

2829
when defined(evmc_enabled):
2930
import

0 commit comments

Comments
 (0)