-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update EIP-5450: Align with EOF megaspec #8388
Conversation
✅ All reviewers have approved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I left some comments. However, I would still opt for not mentioning JUMPF. To me it seems it can just be left out and this EIP is well formed. EIP-6206 does a good job in building upon this foundation. To add to this, mentioning JUMPF requires referencing EIP-6206, we should not weasel around it, and then if we do mention, we get more circular deps :(
EIPS/eip-5450.md
Outdated
- for any other instruction the recodrded stack height lower bound must be at least the number of inputs required by instruction | ||
- there is no additional check for terminating instructions other than `RETF` and `JUMPF`, this implies that extra items left on stack at instruction ending EVM execution are allowed. | ||
2. For `CALLF` and `JUMPF` **check** for possible stack overflow: if recorded stack height upper bound is greater than `1024 - types[target_section_index].max_stack_height + types[target_section_index].inputs`, validation fails. | ||
3. Compute new stack height bounds after the instruction execution. Upper and lower bound are updated by the same value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
specify the value of the update, esp. for CALLF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
EIPS/eip-5450.md
Outdated
2. Add the instruction to the *worklist*. | ||
3. Otherwise, **check** if the recorded stack height equals the value computed in 1.2. | ||
2. If the successor is reached via forwards jump or sequential flow from previous instruction: | ||
1. If the instruction does not have stack height bounds recorded (visited for the first time), record the instruction stack height bound as the value computed in 2.2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. If the instruction does not have stack height bounds recorded (visited for the first time), record the instruction stack height bound as the value computed in 2.2. | |
1. If the instruction does not have stack height bounds recorded (visited for the first time), record the instruction stack height bound as the value computed in 2.3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
EIPS/eip-5450.md
Outdated
3. Otherwise, **check** if the recorded stack height equals the value computed in 1.2. | ||
2. If the successor is reached via forwards jump or sequential flow from previous instruction: | ||
1. If the instruction does not have stack height bounds recorded (visited for the first time), record the instruction stack height bound as the value computed in 2.2. | ||
2. Otherwise instruction was already visited (by previously seen forward jump). Update this instruction's recorded stack height bounds so that they contain the bounds computed in 2.2, i.e. `target_stack_min = min(target_stack_min, current_stack_min)` and `target_stack_max = max(target_stack_max, current_stack_min)`, where `(target_stack_min, target_stack_max)` are successor bounds and `(current_stack_min, current_stack_max)` are bounds computed in 2.2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2. Otherwise instruction was already visited (by previously seen forward jump). Update this instruction's recorded stack height bounds so that they contain the bounds computed in 2.2, i.e. `target_stack_min = min(target_stack_min, current_stack_min)` and `target_stack_max = max(target_stack_max, current_stack_min)`, where `(target_stack_min, target_stack_max)` are successor bounds and `(current_stack_min, current_stack_max)` are bounds computed in 2.2. | |
2. Otherwise instruction was already visited (by previously seen forward jump). Update this instruction's recorded stack height bounds so that they contain the bounds computed in 2.3, i.e. `target_stack_min = min(target_stack_min, current_stack_min)` and `target_stack_max = max(target_stack_max, current_stack_min)`, where `(target_stack_min, target_stack_max)` are successor bounds and `(current_stack_min, current_stack_max)` are bounds computed in 2.3. |
- some more occurrences of this below
EIPS/eip-5450.md
Outdated
- for `RETF` instruction the recorded stack height must be exactly the number of outputs of the function matching the code. | ||
2. Compute new stack height after the instruction execution. | ||
2. Determine the list of successor instructions that can follow the current instructions: | ||
1. **Check** if this instruction has recorded stack height bounds. If it does not, it means it was neither referenced by previous forward jump, nor is part of sequential instruction flow, and this code fails validation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should mention the ordering of blocks as in eof.md, somewhere above: "Code basic blocks must be ordered in a way that every block is reachable either by a forward jump or sequential flow of instructions. In other words, there is no basic block reachable only by a backward jump."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mentioned it, but decided to put it into as a sub-point.
It feels not as important for implementers of the algorithm, and mainly important for code generators, so I thought it fits as a note. wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
totally can be a note 👍
2. **Check** if the maximum stack height does not exceed the limit of 1023 (`0x3FF`). | ||
3. **Check** if the maximum stack height matches the corresponding code section's `max_stack_height` within the type section. | ||
|
||
The computational and space complexity of this pass is *O(len(code))*. Each instruction is visited at most once. | ||
|
||
### Execution | ||
|
||
Given the deploy-time validation guarantees, an EVM implementation is not required anymore to have run-time stack underflow nor overflow checks for each executed instruction. The exception is the `CALLF` performing operand stack overflow check for the entire called function. | ||
Given the deploy-time validation guarantees, an EVM implementation is not required anymore to have run-time stack underflow nor overflow checks for each executed instruction. The exception is the `CALLF` and `JUMPF` performing operand stack overflow check for the entire called function. | ||
|
||
## Rationale |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we're done with the specifications part, needs adding justification of going down the relaxed validation path
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in Rationale.
56474fc
to
df368b7
Compare
Spec out new stack validation algorithm.
The commit cdc54ac (as a parent of 09172eb) contains errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, just some nitpicks/suggestions to consider
EIPS/eip-5450.md
Outdated
@@ -27,14 +27,16 @@ and preventing the execution and deployment of any invalid code. | |||
The operand stack validation provides several benefits: | |||
|
|||
- removes the run-time stack underflow check for all instructions, | |||
- removes the run-time stack overflow check for all instruction except `CALLF`, | |||
- removes the run-time stack overflow check for all instructions except `CALLF` and `JUMPF`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reference a "separate EIP" for JUMPF, like in 4750?
EIPS/eip-5450.md
Outdated
- allows for multiple forward jump instructions executing at different stack heights to target the same instruction; the stack of target basic stack is validated for all possible heights, | ||
- does not allow backwards jump instructions to target an instruction, that can be executed with different stack height; this prevents deployment of the loops with unbounded stack pushing or popping, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these two bullets belong more in the Rationale section IMO, unless they are already covered there. At most this "prevents deployment of the loops with unbounded stack pushing or popping" sentence is a Motivation of the EIP as a whole.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just wanted to have a neat list of all code properties achieved by validation. I put it now into Rationale, but this way it duplicates a bit what is said in other parts, ptal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, much better this way, thank you. Allowing for "multiple forwards jump instructions... etc" sounded weird in Motivation, as it is possible with dynamic JUMP. As such, it is motivation for choosing a certain design over alternatives, rather than the entire EIP over status quo.
@@ -58,50 +60,59 @@ In the second validation phase control-flow analysis is performed on the code. | |||
|
|||
*Terminating instructions* refers to the instructions either: | |||
|
|||
- ending function execution: `RETF`, or | |||
- ending whole EVM execution: `STOP`, `RETURN`, `REVERT`, `INVALID`. | |||
- ending function execution: `RETF`, `JUMPF`, or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"separate EIP" again, the following ones are OK to not have it, but at least once for the Spec section is good to have
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should RETURNCONTRACT
mention have the same then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh boy, I've missed RETURNCONTRACT popping up here... my top-level opinion doesn't really change (should not mention at all), but if we mention, we should consistent in how we mention :(. We cannot leave the reader puzzled whether RETURNCONTRACT is something in legacy EVM, a typo, copy-pasta or leftovers from prev revision or whatnot.
But once more, I really think these EIPs should be as independent as possible, rather than trying to be the megaspec and cover all aspects in each thoroughly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All Reviewers Have Approved; Performing Automatic Merge...
- for `JUMPF` into non-returning function the recorded stack height lower bound must be at least the number of inputs of the target function according to its type defined in the type section, | ||
- for any other instruction the recodrded stack height lower bound must be at least the number of inputs required by instruction, | ||
- there is no additional check for terminating instructions other than `RETF` and `JUMPF`, this implies that extra items left on stack at instruction ending EVM execution are allowed. | ||
2. For `CALLF` and `JUMPF` **check** for possible stack overflow: if recorded stack height upper bound is greater than `1024 - types[target_section_index].max_stack_height + types[target_section_index].inputs`, validation fails. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be inside 2.1 check list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2.1 are the checks that guarantee no stack underflow,
2.2 is the check that prevents (some) stack overflows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All Reviewers Have Approved; Performing Automatic Merge...
Stack validation algorithm is updated to be less restrictive.