forked from ethereum/EIPs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Incorporate @xinbenlv review (ethereum#5599)
- Loading branch information
1 parent
b328ed1
commit b6cedd3
Showing
1 changed file
with
15 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
--- | ||
eip: 2315 | ||
title: Simple Subroutines for the EVM | ||
description: Two opcodes for static, safe and efficient subroutines. | ||
description: Two opcodes for efficient, safe, and static subroutines. | ||
author: Greg Colvin (@gcolvin), Greg Colvin <[email protected]>, Martin Holst Swende (@holiman), Brooklyn Zelenka (@expede), John Max Skaller <[email protected]> | ||
discussions-to: https://ethereum-magicians.org/t/eip-2315-simple-subroutines-for-the-evm/3941 | ||
status: Draft | ||
|
@@ -13,19 +13,19 @@ requires: 3540, 3670, 4200 | |
|
||
## Abstract | ||
|
||
This proposal provides a _complete_, _static_, _safe_ and _efficient_ control-flow facility. | ||
This proposal provides a _complete_, _efficient_, _safe_ and _static_ control-flow facility. | ||
|
||
It deprecates `JUMP` and `JUMPI`. | ||
|
||
It depends on the two opcodes proposed by [EIP-4200](./eip-4200.md): | ||
It depends on the two new opcodes proposed by [EIP-4200](./eip-4200.md): | ||
* `RJUMP relative_offset` — relative jump to `PC + relative_offset` | ||
* `RJUMPI relative_offset` — conditional relative jump | ||
|
||
It introduces two opcodes to support calling and returning from subroutines: | ||
It introduces two new opcodes to support calling and returning from subroutines: | ||
* `RJUMPSUB relative_offset` -- relative jump to subroutine | ||
* `RETURNSUB` -- return to `PC` after most recent `RJUMPSUB`. | ||
|
||
In concert with [EIP-3540](./eip-4200.md) and [EIP-3670](./eip-3670.md) it ensures, at initialization time, that valid code will not execute invalid instructions or jump to invalid locations, will not underflow stack, will maintain consistent numbers of inputs and outputs for subroutines, and will have bounded stack height in the absence of recursion. | ||
In concert with [EIP-3540](./eip-3540.md) and [EIP-3670](./eip-3670.md) it ensures, at initialization time, that valid code will not execute invalid instructions or jump to invalid locations, will not underflow stack, will maintain consistent numbers of inputs and outputs for subroutines, and will have bounded stack height in the absence of recursion. | ||
|
||
Valid code will support streaming, one-pass, and other near-linear compilers. | ||
|
||
|
@@ -38,28 +38,28 @@ This is among the simplest possible proposals that meets these requirements. | |
Jumps, conditional jumps and subroutines were proposed by Alan Turing in 1945 as a means of organizing the logic of the code and the design of the memory crystals for his Automatic Computing Engine: | ||
> "We wish to be able to arrange that sequences of orders can divide at various points, continuing in different ways according to the outcome of the calculations to date... We also wish to be able to arrange for the splitting up of operations into subsidiary operations... To start on a subsidiary operation we need only make a note of where we left off the major operation and then apply the first instruction of the subsidiary. When the subsidiary is over we look up the note and continue with the major operation." | ||
> | ||
> — Alan Turing — in B.E. Carpenter, R.W. Doran, "The other Turing machine." The Computer Journal, Volume 20, Issue 3, DOI: , January 1977. | ||
> — Alan Turing — in [B.E. Carpenter, R.W. Doran, "The other Turing machine." The Computer Journal, Volume 20, Issue 3, DOI: 10.1093/comjnl/20.3.269, January 1977. | ||
In more contemporary terms, we have sequences of instructions, jumps and conditional jumps that divide sequences into blocks, subroutine calls, and a stack of addresses to return to. The details vary, but similar facilities have proven their value across a long line of important machines over the last 75 years, from the ACE to the Cray to the ARM. | ||
|
||
Unlike these machines, the Ethereum Virtual Machine _does not_ provide subroutine operations. Instead, they must be synthesized using the dynamic `JUMP` instruction, which takes its destination on the stack. Further, the EVM provides _only_ dynamic jumps, impeding the static analysis we need. | ||
Unlike these machines, the Ethereum Virtual Machine _does not_ provide subroutine operations. Instead, they must be synthesized using the dynamic `JUMP` instruction, which takes its destination on the stack. Further, the EVM provides _only_ dynamic jumps, impeding the static analysis we need. | ||
|
||
### We need efficient control-flow. | ||
|
||
Efficient to write by hand, compile from high level labguages, validate at deploy time, interpret by VMs, and compile to machine code. | ||
|
||
Static jumps, conditional jumps, and subroutines are sufficient and efficient in space and time, as shown by historical experience and as we will show for the EVM below. | ||
|
||
### We need safe control-flow. | ||
|
||
The EVM has unusually high requirements for safety. Not only do many smart contracts control inordinately large amounts of valuable Ether, but once placed on the blockchain any defects are visible to attackers and cannot be repaired. In valid code is an We need to statically validate important safety constraints code at initialization time. | ||
The EVM has unusually high requirements for safety. Not only do many smart contracts control inordinately large amounts of valuable Ether, but once placed on the blockchain any defects are visible to attackers and cannot be repaired. We need to statically validate important safety constraints code at initialization time. | ||
|
||
### We need static control-flow. | ||
|
||
The EVM's lone dynamic jumps cause two major problems. First, the need to synthesize static jumps and subroutines with dynamic jumps uses space and gas with needlessly complex code, as we will show below. | ||
|
||
Worse, jumps that can dynamically branch to any destination in the code can cause quadratic "path explosions" when traversing the flow of control. For Ethereum, this is a denial-of-service vulnerability that prevents us, at initialization time, from validating the safe use of EVM code and from compiling EVM code to machine code. | ||
|
||
### We need efficient control-flow. | ||
|
||
Efficient to write by hand, compile from high level labguages, validate at deploy time, interpret by VMs, and compile to machine code. | ||
|
||
Static jumps, conditional jumps, and subroutines are sufficient and efficient in space and time, as shown by historical experience and as we will show for the EVM below. | ||
|
||
**We need static jumps and subroutines and must deprecate dynamic jumps.** | ||
|
||
## Specification | ||
|
@@ -334,7 +334,7 @@ The following is a pseudo-Python implementation of an algorithm for predicating | |
|
||
This algorithm performs a symbolic execution of the program that recursively traverses the _code_, emulating its control flow and stack use and checking for violations of the rules above. | ||
|
||
It runs in time equal to `O(vertices + edges)` in the program's control-flow graph, where edges represent control flow and the vertices represent _basic blocks_ — thusa the algorithm takes time proportional to the size of the _code_. It uses recursion to maintain a stack of continuations for conditional jumps, the size of which is at most proportional to the size of the _code_. | ||
It runs in time equal to `O(vertices + edges)` in the program's control-flow graph, where edges represent control flow and the vertices represent _basic blocks_ — thus the algorithm takes time proportional to the size of the _code_. It uses recursion to maintain a stack of continuations for conditional jumps, the size of which is at most proportional to the size of the _code_. | ||
|
||
### Validation Function | ||
|
||
|