EIPs/EIPS/eip-2315.md
Greg Colvin 2490b642f0
Automatically merged updates to draft EIP(s) 2315 (#2504)
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
2020-02-03 18:26:07 +13:00

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.