ethereum.byzantium.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 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    traces: List[dict]
 46
 47
 48@dataclass
 49class Message:
 50    """
 51    Items that are used by contract creation or message call.
 52    """
 53
 54    caller: Address
 55    target: Union[Bytes0, Address]
 56    current_target: Address
 57    gas: Uint
 58    value: U256
 59    data: Bytes
 60    code_address: Optional[Address]
 61    code: Bytes
 62    depth: Uint
 63    should_transfer_value: bool
 64    is_static: bool
 65    parent_evm: Optional["Evm"]
 66
 67
 68@dataclass
 69class Evm:
 70    """The internal state of the virtual machine."""
 71
 72    pc: Uint
 73    stack: List[U256]
 74    memory: bytearray
 75    code: Bytes
 76    gas_left: Uint
 77    env: Environment
 78    valid_jump_destinations: Set[Uint]
 79    logs: Tuple[Log, ...]
 80    refund_counter: U256
 81    running: bool
 82    message: Message
 83    output: Bytes
 84    accounts_to_delete: Set[Address]
 85    touched_accounts: Set[Address]
 86    return_data: Bytes
 87    error: Optional[Exception]
 88
 89
 90def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None:
 91    """
 92    Incorporate the state of a successful `child_evm` into the parent `evm`.
 93
 94    Parameters
 95    ----------
 96    evm :
 97        The parent `EVM`.
 98    child_evm :
 99        The child evm to incorporate.
100    """
101    evm.gas_left += child_evm.gas_left
102    evm.logs += child_evm.logs
103    evm.refund_counter += child_evm.refund_counter
104    evm.accounts_to_delete.update(child_evm.accounts_to_delete)
105    evm.touched_accounts.update(child_evm.touched_accounts)
106    if account_exists_and_is_empty(
107        evm.env.state, child_evm.message.current_target
108    ):
109        evm.touched_accounts.add(child_evm.message.current_target)
110
111
112def incorporate_child_on_error(evm: Evm, child_evm: Evm) -> None:
113    """
114    Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.
115
116    Parameters
117    ----------
118    evm :
119        The parent `EVM`.
120    child_evm :
121        The child evm to incorporate.
122    """
123    # In block 2675119, the empty account at 0x3 (the RIPEMD160 precompile) was
124    # cleared despite running out of gas. This is an obscure edge case that can
125    # only happen to a precompile.
126    # According to the general rules governing clearing of empty accounts, the
127    # touch should have been reverted. Due to client bugs, this event went
128    # unnoticed and 0x3 has been exempted from the rule that touches are
129    # reverted in order to preserve this historical behaviour.
130    if RIPEMD160_ADDRESS in child_evm.touched_accounts:
131        evm.touched_accounts.add(RIPEMD160_ADDRESS)
132    if child_evm.message.current_target == RIPEMD160_ADDRESS:
133        if account_exists_and_is_empty(
134            evm.env.state, child_evm.message.current_target
135        ):
136            evm.touched_accounts.add(RIPEMD160_ADDRESS)
137    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    traces: List[dict]

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

@dataclass
class Evm:
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: U256
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]

The internal state of the virtual machine.

@dataclass
class Message:
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"]

Items that are used by contract creation or message call.