ethereum.istanbul.vm

Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. contents:: Table of Contents :backlinks: none :local:

Introduction

The abstract computer which runs the code stored in an .fork_types.Account.

  1"""
  2Ethereum Virtual Machine (EVM)
  3^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  4
  5.. contents:: Table of Contents
  6    :backlinks: none
  7    :local:
  8
  9Introduction
 10------------
 11
 12The abstract computer which runs the code stored in an
 13`.fork_types.Account`.
 14"""
 15
 16from dataclasses import dataclass
 17from typing import List, Optional, Set, Tuple, Union
 18
 19from ethereum.base_types import U64, U256, Bytes, Bytes0, Uint
 20from ethereum.crypto.hash import Hash32
 21
 22from ..fork_types import Address, Log
 23from ..state import State, account_exists_and_is_empty
 24from .precompiled_contracts import RIPEMD160_ADDRESS
 25
 26__all__ = ("Environment", "Evm", "Message")
 27
 28
 29@dataclass
 30class Environment:
 31    """
 32    Items external to the virtual machine itself, provided by the environment.
 33    """
 34
 35    caller: Address
 36    block_hashes: List[Hash32]
 37    origin: Address
 38    coinbase: Address
 39    number: Uint
 40    gas_limit: Uint
 41    gas_price: Uint
 42    time: U256
 43    difficulty: Uint
 44    state: State
 45    chain_id: U64
 46    traces: List[dict]
 47
 48
 49@dataclass
 50class Message:
 51    """
 52    Items that are used by contract creation or message call.
 53    """
 54
 55    caller: Address
 56    target: Union[Bytes0, Address]
 57    current_target: Address
 58    gas: Uint
 59    value: U256
 60    data: Bytes
 61    code_address: Optional[Address]
 62    code: Bytes
 63    depth: Uint
 64    should_transfer_value: bool
 65    is_static: bool
 66    parent_evm: Optional["Evm"]
 67
 68
 69@dataclass
 70class Evm:
 71    """The internal state of the virtual machine."""
 72
 73    pc: Uint
 74    stack: List[U256]
 75    memory: bytearray
 76    code: Bytes
 77    gas_left: Uint
 78    env: Environment
 79    valid_jump_destinations: Set[Uint]
 80    logs: Tuple[Log, ...]
 81    refund_counter: int
 82    running: bool
 83    message: Message
 84    output: Bytes
 85    accounts_to_delete: Set[Address]
 86    touched_accounts: Set[Address]
 87    return_data: Bytes
 88    error: Optional[Exception]
 89
 90
 91def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None:
 92    """
 93    Incorporate the state of a successful `child_evm` into the parent `evm`.
 94
 95    Parameters
 96    ----------
 97    evm :
 98        The parent `EVM`.
 99    child_evm :
100        The child evm to incorporate.
101    """
102    evm.gas_left += child_evm.gas_left
103    evm.logs += child_evm.logs
104    evm.refund_counter += child_evm.refund_counter
105    evm.accounts_to_delete.update(child_evm.accounts_to_delete)
106    evm.touched_accounts.update(child_evm.touched_accounts)
107    if account_exists_and_is_empty(
108        evm.env.state, child_evm.message.current_target
109    ):
110        evm.touched_accounts.add(child_evm.message.current_target)
111
112
113def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None:
114    """
115    Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.
116
117    Parameters
118    ----------
119    evm :
120        The parent `EVM`.
121    child_evm :
122        The child evm to incorporate.
123    """
124    # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was
125    # cleared despite running out of gas. This is an obscure edge case that can
126    # only happen to a precompile.
127    # According to the general rules governing clearing of empty accounts, the
128    # touch should have been reverted. Due to client bugs, this event went
129    # unnoticed and 0x3 has been exempted from the rule that touches are
130    # reverted in order to preserve this historical behaviour.
131    if RIPEMD160_ADDRESS in child_evm.touched_accounts:
132        evm.touched_accounts.add(RIPEMD160_ADDRESS)
133    if child_evm.message.current_target == RIPEMD160_ADDRESS:
134        if account_exists_and_is_empty(
135            evm.env.state, child_evm.message.current_target
136        ):
137            evm.touched_accounts.add(RIPEMD160_ADDRESS)
138    evm.gas_left += child_evm.gas_left
@dataclass
class Environment:
30@dataclass
31class Environment:
32    """
33    Items external to the virtual machine itself, provided by the environment.
34    """
35
36    caller: Address
37    block_hashes: List[Hash32]
38    origin: Address
39    coinbase: Address
40    number: Uint
41    gas_limit: Uint
42    gas_price: Uint
43    time: U256
44    difficulty: Uint
45    state: State
46    chain_id: U64
47    traces: List[dict]

Items external to the virtual machine itself, provided by the environment.

@dataclass
class Evm:
70@dataclass
71class Evm:
72    """The internal state of the virtual machine."""
73
74    pc: Uint
75    stack: List[U256]
76    memory: bytearray
77    code: Bytes
78    gas_left: Uint
79    env: Environment
80    valid_jump_destinations: Set[Uint]
81    logs: Tuple[Log, ...]
82    refund_counter: int
83    running: bool
84    message: Message
85    output: Bytes
86    accounts_to_delete: Set[Address]
87    touched_accounts: Set[Address]
88    return_data: Bytes
89    error: Optional[Exception]

The internal state of the virtual machine.

@dataclass
class Message:
50@dataclass
51class Message:
52    """
53    Items that are used by contract creation or message call.
54    """
55
56    caller: Address
57    target: Union[Bytes0, Address]
58    current_target: Address
59    gas: Uint
60    value: U256
61    data: Bytes
62    code_address: Optional[Address]
63    code: Bytes
64    depth: Uint
65    should_transfer_value: bool
66    is_static: bool
67    parent_evm: Optional["Evm"]

Items that are used by contract creation or message call.