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