Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing
3.4 KiB
eip | title | status | type | category | author | discussions-to | created |
---|---|---|---|---|---|---|---|
2315 | Simple Subroutines for the EVM | Draft | Standards Track | Core | Greg Colvin (greg@colvin.org) | https://ethereum-magicians.org/t/eip-2315-simple-subroutines-for-the-evm/3941 | 2019-10-17 |
Abstract
This proposal introduces two opcodes to support subroutines: JUMPSUB
and RETURNSUB
.
Motivation
The EVM does not provide subroutines as a primitive. Instead, calls must be synthesized by fetching and pushing the current program counter on the data stack and jumping to the subroutine address; returns must be synthesized by getting the return address to the top of stack and jumping back to it.
Specification
JUMPSUB
Jumps to the address on top of the stack, which must be the offset of a JUMPDEST
.
RETURNSUB
Returns to the most recently executed JUMPSUB
and advances to the following instruction.
A program may JUMPSUB
at most 1023 times without an intervening RETURNSUB
. A program which executes RETURNSUB
without no prior BEGINSUB
will STOP
.
Rationale
This is the smallest possible change that provides native subroutines without breaking backwards compatibility.
Backwards Compatibility
These changes do not affect the semantics of existing EVM code.
Test Cases
offset step op stack
0 0 PUSH1 3 []
1 1 JUMPSUB [3]
2 4 STOP []
3 2 JUMPDEST []
4 3 RETURNSUB []
This code should terminate after 4 steps with an empty stack.
offset step op stack
0 0 PUSH1 2 []
1 1 JUMPSUB [2]
2 2 JUMPDEST []
3 3 RETURNSUB []
This code should terminate after 4 steps with an empty stack.
offset step op stack
0 0 PUSH1 2 []
1 1 JUMPSUB [3]
2 8 STOP []
3 2 JUMPDEST []
4 3 PUSH1 7 []
5 4 JUMPSUB [7]
6 7 RETURNSUB []
7 5 JUMPDEST []
8 6 RETURNSUB []
This code should terminate after 8 steps with an empty stack.
Implementations
No clients have implemented this proposal as of yet.
The new operators proposed here are implemented by the following pseudocode, which in eight lines adds a return stack and cases for JUMPSUB
and RETURNSUB
to a simple loop-and-switch interpreter.
bytecode[code_size]
data_stack[1024]
return_stack[1024]
push(return_stack, code_size)
PC = 0
while PC < code_size {
opcode = bytecode[PC]
switch opcode {
...
case JUMPSUB:
push(return_stack, PC)
PC = pop(data_stack)
continue
case RETURNSUB:
PC = pop(return_stack)
}
++PC
}
Execution of EVM bytecode begins with one value on the return stack—the size of the bytecode. The virtual byte of 0 at this offset is the EVM STOP
opcode, so executing a RETURNSUB
with no prior JUMPSUB
executes a STOP
. A STOP
or RETURN
ends the execution of the subroutine and the program.
Costs and Codes
We suggest the cost of JUMPSUB
should be low, and RETURNSUB
should be verylow.
Measurement will tell. We suggest the following opcodes:
0xb3 JUMPSUB
0xb7 RETURNSUB
Security Considerations
Program flow analysis frameworks will need to be updated to allow for a new type of branch -JUMPSUB
- and new type of branching - RETURNSUB
- which will cause a jump to a destination which is a JUMPSUB
, not a JUMPDEST
.
Copyright and related rights waived via CC0.