ethereum.forks.bpo5.vm.runtimeethereum.forks.amsterdam.vm.runtime
Ethereum Virtual Machine (EVM) Runtime Operations.
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Runtime related operations used while executing EVM code.
get_valid_jump_destinations ¶
Analyze the EVM code to obtain the set of valid jump destinations.
Valid jump destinations are defined as follows:
* The jump destination is less than the length of the code.
* The jump destination should have the JUMPDEST opcode (0x5B).
* The jump destination shouldn't be part of the data corresponding to
PUSH-N opcodes.
* The jump destination shouldn't be part of the immediate byte
corresponding to DUPN, SWAPN, or EXCHANGE opcodes (EIP-8024).
Note - Jump destinations are 0-indexed.
Parameters
code : The EVM code which is to be executed.
Returns
valid_jump_destinations: Set[Uint]
The set of valid jump destinations in the code.
def get_valid_jump_destinations(code: Bytes) -> Set[Uint]:
| 23 | <snip> |
|---|---|
| 47 | valid_jump_destinations = set() |
| 48 | pc = Uint(0) |
| 49 | |
| 50 | while pc < ulen(code): |
| 51 | try: |
| 52 | current_opcode = Ops(code[pc]) |
| 53 | except ValueError: |
| 54 | # Skip invalid opcodes, as they don't affect the jumpdest |
| 55 | # analysis. Nevertheless, such invalid opcodes would be caught |
| 56 | # and raised when the interpreter runs. |
| 57 | pc += Uint(1) |
| 58 | continue |
| 59 | |
| 60 | if current_opcode == Ops.JUMPDEST: |
| 61 | valid_jump_destinations.add(pc) |
| 62 | elif Ops.PUSH1.value <= current_opcode.value <= Ops.PUSH32.value: |
| 63 | # If PUSH-N opcodes are encountered, skip the current opcode along |
| 64 | # with the trailing data segment corresponding to the PUSH-N |
| 65 | # opcodes. |
| 66 | push_data_size = current_opcode.value - Ops.PUSH1.value + 1 |
| 65 | pc += Uint(push_data_size) |
| 67 | pc += Uint(push_data_size) |
| 68 | elif current_opcode in (Ops.DUPN, Ops.SWAPN): |
| 69 | # EIP-8024: DUPN/SWAPN invalid immediate range is |
| 70 | # 90 < x < 128, i.e. 0x5B (91) to 0x7F (127). |
| 71 | # Invalid immediates are not skipped so the byte |
| 72 | # remains at an instruction boundary. |
| 73 | if ( |
| 74 | pc + Uint(1) < ulen(code) |
| 75 | and 0x5B <= code[pc + Uint(1)] <= 0x7F |
| 76 | ): |
| 77 | pass |
| 78 | else: |
| 79 | pc += Uint(1) |
| 80 | elif current_opcode == Ops.EXCHANGE: |
| 81 | # EIP-8024: EXCHANGE invalid immediate range is |
| 82 | # 81 < x < 128, i.e. 0x52 (82) to 0x7F (127). |
| 83 | # Invalid immediates are not skipped so the byte |
| 84 | # remains at an instruction boundary. |
| 85 | if ( |
| 86 | pc + Uint(1) < ulen(code) |
| 87 | and 0x52 <= code[pc + Uint(1)] <= 0x7F |
| 88 | ): |
| 89 | pass |
| 90 | else: |
| 91 | pc += Uint(1) |
| 92 | |
| 93 | pc += Uint(1) |
| 94 | |
| 95 | return valid_jump_destinations |