Skip to content

Commit

Permalink
Update EIP-4200: New opcodes for RJUMP*
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
gumb0 authored Jul 13, 2023
1 parent 4c5b64a commit d73953e
Showing 1 changed file with 3 additions and 97 deletions.
100 changes: 3 additions & 97 deletions EIPS/eip-4200.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ The main benefit of these instruction is reduced gas cost (both at deploy and ex

We introduce three new instructions on the same block number [EIP-3540](./eip-3540.md) is activated on:

1. `RJUMP` (0x5c) - relative jump
2. `RJUMPI` (0x5d) - conditional relative jump
3. `RJUMPV` (0x5e) - relative jump via jump table
1. `RJUMP` (0xe0) - relative jump
2. `RJUMPI` (0xe1) - conditional relative jump
3. `RJUMPV` (0xe2) - relative jump via jump table

If the code is legacy bytecode, all of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*)

Expand Down Expand Up @@ -154,100 +154,6 @@ This change poses no risk to backwards compatibility, as it is introduced at the
- `case` outside of table bounds (`case > max_index`, fallback case)
- `case` > 255

## Reference Implementation

```python
# The ranges below are as specified in the Yellow Paper.
# Note: range(s, e) excludes e, hence the +1
valid_opcodes = [
*range(0x00, 0x0b + 1),
*range(0x10, 0x1d + 1),
0x20,
*range(0x30, 0x3f + 1),
*range(0x40, 0x48 + 1),
*range(0x50, 0x5e + 1),
*range(0x60, 0x6f + 1),
*range(0x70, 0x7f + 1),
*range(0x80, 0x8f + 1),
*range(0x90, 0x9f + 1),
*range(0xa0, 0xa4 + 1),
# Note: 0xfe is considered assigned.
*range(0xf0, 0xf5 + 1), 0xfa, 0xfd, 0xfe, 0xff
]

# STOP, RETURN, REVERT, INVALID, SELFDESTRUCT
terminating_opcodes = [ 0x00, 0xf3, 0xfd, 0xfe, 0xff ]

immediate_sizes = 256 * [0]
immediate_sizes[0x5c] = 2 # RJUMP
immediate_sizes[0x5d] = 2 # RJUMPI
for opcode in range(0x60, 0x7f + 1): # PUSH1..PUSH32
immediate_sizes[opcode] = opcode - 0x60 + 1

# Raises ValidationException on invalid code
def validate_code(code: bytes):
# Note that EOF1 already asserts this with the code section requirements
assert len(code) > 0

opcode = 0
pos = 0
rjumpdests = set()
immediates = set()
while pos < len(code):
# Ensure the opcode is valid
opcode = code[pos]
pos += 1
if not opcode in valid_opcodes:
raise ValidationException("undefined instruction")

pc_post_instruction = pos + immediate_sizes[opcode]

if opcode == 0x5c or opcode == 0x5d:
if pos + 2 > len(code):
raise ValidationException("truncated relative jump offset")
offset = int.from_bytes(code[pos:pos+2], byteorder = "big", signed = True)

rjumpdest = pc_post_instruction + offset
if rjumpdest < 0 or rjumpdest >= len(code):
raise ValidationException("relative jump destination out of bounds")

rjumpdests.add(rjumpdest)
elif opcode == 0x5e:
if pos + 1 > len(code):
raise ValidationException("truncated jump table")
jump_table_size = code[pos] + 1

pc_post_instruction = pos + 1 + 2 * jump_table_size
if pc_post_instruction > len(code):
raise ValidationException("truncated jump table")

for offset_pos in range(pos + 1, pc_post_instruction, 2):
offset = int.from_bytes(code[offset_pos:offset_pos+2], byteorder = "big", signed = True)

rjumpdest = pc_post_instruction + offset
if rjumpdest < 0 or rjumpdest >= len(code):
raise ValidationException("relative jump destination out of bounds")
rjumpdests.add(rjumpdest)


# Save immediate value positions
immediates.update(range(pos, pc_post_instruction))
# Skip immediates
pos = pc_post_instruction

# Ensure last opcode's immediate doesn't go over code end
if pos != len(code):
raise ValidationException("truncated immediate")

# opcode is the *last opcode*
if not opcode in terminating_opcodes:
raise ValidationException("no terminating instruction")

# Ensure relative jump destinations don't target immediates
if not rjumpdests.isdisjoint(immediates):
raise ValidationException("relative jump destination targets immediate")
```

## Security Considerations

TBA
Expand Down

0 comments on commit d73953e

Please sign in to comment.