Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions EIPS/eip-4200.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ If the code is valid EOF1:

1. `RJUMP relative_offset` sets the `PC` to `PC_post_instruction + relative_offset`.
2. `RJUMPI relative_offset` pops a value (`condition`) from the stack, and sets the `PC` to `PC_post_instruction + ((condition == 0) ? 0 : relative_offset)`.
3. `RJUMPV count relative_offset+` pops a value (`case`) from the stack, and sets the `PC` to `PC_post_instruction + ((case >= count) ? 0 : relative_offset[case])`.
3. `RJUMPV max_index relative_offset+` pops a value (`case`) from the stack, and sets the `PC` to `PC_post_instruction + ((case > max_index) ? 0 : relative_offset[case])`.

The immediate argument `relative_offset` is encoded as a 16-bit **signed** (two's-complement) big-endian value. Under `PC_post_instruction` we mean the `PC` position after the entire immediate value.

The immediate encoding of `RJUMPV` is more special: the 8-bit `count` value determines the number of `relative_offset` values following. Validation algorithm of [EIP-3670](./eip-3670.md) is extended to verify that `count >= 1`. The encoding of `RJUMPV` must have at least one `relative_offset` and thus it will take at minimum 4 bytes. Furthermore, the `case >= count` condition falling through means that in many use cases one would place the *default* path following the `RJUMPV` instruction. An interesting feature is that `RJUMPV 1 relative_offset` is an inverted-`RJUMPI`, which can be used in many cases instead of `ISZERO RJUMPI relative_offset`.
The immediate encoding of `RJUMPV` is more special: the unsigned 8-bit `max_index` value determines the maximum index in the jump table. The number of `relative_offset` values following is `max_index+1`. This allows table sizes up to 256. The encoding of `RJUMPV` must have at least one `relative_offset` and thus it will take at minimum 4 bytes. Furthermore, the `case > max_index` condition falling through means that in many use cases, one would place the *default* path following the `RJUMPV` instruction. An interesting feature is that `RJUMPV 0 relative_offset` is an inverted-`RJUMPI`, which can be used in many cases instead of `ISZERO RJUMPI relative_offset`.

We also extend the validation algorithm of [EIP-3670](./eip-3670.md) to verify that each `RJUMP`/`RJUMPI`/`RJUMPV` has a `relative_offset` pointing to an instruction. This means it cannot point to an immediate data of `PUSHn`/`RJUMP`/`RJUMPI`/`RJUMPV`. It cannot point outside of code bounds. It is allowed to point to a `JUMPDEST`, but is not required to.

Expand Down Expand Up @@ -126,7 +126,7 @@ This change poses no risk to backwards compatibility, as it is introduced at the
- `relative_offset` is positive/negative/`0`
- `RJUMP`/`RJUMPI`/`RJUMPV` with instruction other than `JUMPDEST` as target
- `relative_offset` is positive/negative/`0`
- `RJUMPV` with various valid table sizes from 1 to 255
- `RJUMPV` with various valid table sizes from 1 to 256

#### Invalid cases

Expand All @@ -135,7 +135,6 @@ This change poses no risk to backwards compatibility, as it is introduced at the
- `RJUMP`/`RJUMPI`/`RJUMPV` target outside of code section bounds
- `RJUMP`/`RJUMPI`/`RJUMPV` target push data
- `RJUMP`/`RJUMPI`/`RJUMPV` target another `RJUMP`/`RJUMPI`/`RJUMPV` immediate argument
- `RJUMPV` with table size 0

### Execution

Expand All @@ -146,13 +145,13 @@ This change poses no risk to backwards compatibility, as it is introduced at the
- `relative_offset` is positive/negative/`0`
- `condition` equals `0`
- `condition` does not equal `0`
- `RJUMPV 1 relative_offset`
- `RJUMPV 0 relative_offset`
- `case` equals `0`
- `case` does not equal `0`
- `RJUMPV` with table containing positive, negative, `0` offsets
- `case` equals `0`
- `case` does not equal `0`
- `case` outside of table bounds (`case >= count`, fallback case)
- `case` outside of table bounds (`case > max_index`, fallback case)
- `case` > 255

## Reference Implementation
Expand Down Expand Up @@ -216,9 +215,7 @@ def validate_code(code: bytes):
elif opcode == 0x5e:
if pos + 1 > len(code):
raise ValidationException("truncated jump table")
jump_table_size = code[pos]
if jump_table_size == 0:
raise ValidationException("empty jump table")
jump_table_size = code[pos] + 1

pc_post_instruction = pos + 1 + 2 * jump_table_size
if pc_post_instruction > len(code):
Expand Down