Skip to content

Commit ef24703

Browse files
committed
EIP-4750: EOF - Functions
1 parent 79c2771 commit ef24703

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
@@ -191,7 +191,8 @@ proc newComputation*(vmState: BaseVMState, message: Message,
191191
result.msg = message
192192
result.memory = Memory()
193193
result.stack = newStack()
194-
result.returnStack = @[]
194+
# disable EIP-2315
195+
# result.returnStack = @[]
195196
result.gasMeter.init(message.gas)
196197
result.touchedAccounts = initHashSet[EthAddress]()
197198
result.selfDestructs = initHashSet[EthAddress]()
@@ -204,18 +205,29 @@ proc newComputation*(vmState: BaseVMState, message: Message,
204205
result.code = newCodeStream(
205206
vmState.readOnlyStateDB.getCode(message.codeAddress))
206207
208+
# EIP-4750
209+
result.returnStack = @[
210+
ReturnContext(section: 0, pc: 0, stackHeight: 0)
211+
]
212+
207213
proc newComputation*(vmState: BaseVMState, message: Message, code: seq[byte]): Computation =
208214
new result
209215
result.vmState = vmState
210216
result.msg = message
211217
result.memory = Memory()
212218
result.stack = newStack()
213-
result.returnStack = @[]
219+
# disable EIP-2315
220+
# result.returnStack = @[]
214221
result.gasMeter.init(message.gas)
215222
result.touchedAccounts = initHashSet[EthAddress]()
216223
result.selfDestructs = initHashSet[EthAddress]()
217224
result.code = newCodeStream(code)
218225
226+
# EIP-4750
227+
result.returnStack = @[
228+
ReturnContext(section: 0, pc: 0, stackHeight: 0)
229+
]
230+
219231
template gasCosts*(c: Computation): untyped =
220232
c.vmState.gasCosts
221233

nimbus/evm/interpreter/gas_costs.nim

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

704+
# b0s: Function Operations
705+
CallF: fixed GasLow,
706+
RetF: fixed GasVeryLow,
707+
704708
# f0s: System operations
705709
Create: complex `prefix gasCreate`,
706710
Call: complex `prefix gasCall`,

nimbus/evm/interpreter/op_codes.nim

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

174174
Nop0xA5, Nop0xA6, Nop0xA7, Nop0xA8, Nop0xA9, Nop0xAA,
175-
Nop0xAB, Nop0xAC, Nop0xAD, Nop0xAE, Nop0xAF, Nop0xB0,
176-
Nop0xB1, Nop0xB2, Nop0xB3, Nop0xB4, Nop0xB5, Nop0xB6,
175+
Nop0xAB, Nop0xAC, Nop0xAD, Nop0xAE, Nop0xAF,
176+
177+
CallF = 0xb0, ## call a function (EIP4750)
178+
RetF = 0xb1, ## return from a function (EIP4750)
179+
180+
Nop0xB2, Nop0xB3, Nop0xB4, Nop0xB5, Nop0xB6,
177181
Nop0xB7, Nop0xB8, Nop0xB9, Nop0xBA, Nop0xBB, Nop0xBC,
178182
Nop0xBD, Nop0xBE, Nop0xBF, Nop0xC0, Nop0xC1, Nop0xC2,
179183
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
@@ -107,6 +107,14 @@ proc toCaseStmt(forkArg, opArg, k: NimNode): NimNode =
107107
quote do:
108108
`forkCaseSubExpr`
109109
break
110+
of RetF:
111+
quote do:
112+
`forkCaseSubExpr`
113+
# EIP-4750: If returning from top frame, exit cleanly.
114+
let c = `k`.cpt
115+
if c.fork >= FkEOF and
116+
c.returnStack.len == 0:
117+
break
110118
else:
111119
quote do:
112120
`forkCaseSubExpr`
@@ -140,6 +148,11 @@ template genLowMemDispatcher*(fork: EVMFork; op: Op; k: Vm2Ctx) =
140148
break
141149
of Return, Revert, SelfDestruct:
142150
break
151+
of RetF:
152+
# EIP-4750: If returning from top frame, exit cleanly.
153+
if fork >= FkEOF and
154+
k.cpt.returnStack.len == 0:
155+
break
143156
else:
144157
discard
145158

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
@@ -468,23 +468,23 @@ const
468468
post: vm2OpIgnore)),
469469

470470
(opCode: Jump, ## 0x56, Jump
471-
forks: Vm2OpAllForks,
471+
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
472472
name: "jump",
473473
info: "Alter the program counter",
474474
exec: (prep: vm2OpIgnore,
475475
run: jumpOp,
476476
post: vm2OpIgnore)),
477477

478478
(opCode: JumpI, ## 0x57, Conditional jump
479-
forks: Vm2OpAllForks,
479+
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
480480
name: "jumpI",
481481
info: "Conditionally alter the program counter",
482482
exec: (prep: vm2OpIgnore,
483483
run: jumpIOp,
484484
post: vm2OpIgnore)),
485485

486486
(opCode: Pc, ## 0x58, Program counter prior to instruction
487-
forks: Vm2OpAllForks,
487+
forks: Vm2OpAllForks - Vm2OpEOFAndLater,
488488
name: "pc",
489489
info: "Get the value of the program counter prior to the increment "&
490490
"corresponding to this instruction",

nimbus/evm/types.nim

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,20 @@ type
7474
storageKeys*: seq[HashSet[UInt256]]
7575
gasUsed*: GasInt
7676

77+
# EIP-4750
78+
ReturnContext* = object
79+
section*: int
80+
pc*: int
81+
stackHeight*: int
82+
7783
Computation* = ref object
7884
# The execution computation
7985
vmState*: BaseVMState
8086
msg*: Message
8187
memory*: Memory
8288
stack*: Stack
83-
returnStack*: seq[int]
89+
# disable EIP-2315
90+
# returnStack*: seq[int]
8491
gasMeter*: GasMeter
8592
code*: CodeStream
8693
output*: seq[byte]
@@ -101,6 +108,7 @@ type
101108
pendingAsyncOperation*: Future[void]
102109
continuation*: proc() {.gcsafe.}
103110
initcodeEOF*: bool
111+
returnStack*: seq[ReturnContext]
104112

105113
Error* = ref object
106114
info*: string

nimbus/vm_types.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ export
2121
vmt.MsgFlags,
2222
vmt.TracerFlags,
2323
vmt.TransactionTracer,
24-
vmt.VMFlag
24+
vmt.VMFlag,
25+
vmt.ReturnContext
2526

2627
when defined(evmc_enabled):
2728
import

0 commit comments

Comments
 (0)