ethereum.berlin.fork

Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^

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

Introduction

Entry point for the Ethereum specification.

   1"""
   2Ethereum Specification
   3^^^^^^^^^^^^^^^^^^^^^^
   4
   5.. contents:: Table of Contents
   6    :backlinks: none
   7    :local:
   8
   9Introduction
  10------------
  11
  12Entry point for the Ethereum specification.
  13"""
  14
  15from dataclasses import dataclass
  16from typing import List, Optional, Set, Tuple, Union
  17
  18from ethereum.base_types import Bytes0
  19from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover
  20from ethereum.crypto.hash import Hash32, keccak256
  21from ethereum.ethash import dataset_size, generate_cache, hashimoto_light
  22from ethereum.exceptions import InvalidBlock
  23from ethereum.utils.ensure import ensure
  24
  25from .. import rlp
  26from ..base_types import U64, U256, U256_CEIL_VALUE, Bytes, Uint
  27from . import vm
  28from .bloom import logs_bloom
  29from .fork_types import (
  30    TX_ACCESS_LIST_ADDRESS_COST,
  31    TX_ACCESS_LIST_STORAGE_KEY_COST,
  32    TX_BASE_COST,
  33    TX_CREATE_COST,
  34    TX_DATA_COST_PER_NON_ZERO,
  35    TX_DATA_COST_PER_ZERO,
  36    AccessListTransaction,
  37    Address,
  38    Block,
  39    Bloom,
  40    Header,
  41    LegacyTransaction,
  42    Log,
  43    Receipt,
  44    Root,
  45    Transaction,
  46    decode_transaction,
  47    encode_transaction,
  48)
  49from .state import (
  50    State,
  51    account_exists_and_is_empty,
  52    create_ether,
  53    destroy_account,
  54    get_account,
  55    increment_nonce,
  56    set_account_balance,
  57    state_root,
  58)
  59from .trie import Trie, root, trie_set
  60from .utils.message import prepare_message
  61from .vm.interpreter import process_message_call
  62
  63BLOCK_REWARD = U256(2 * 10**18)
  64GAS_LIMIT_ADJUSTMENT_FACTOR = 1024
  65GAS_LIMIT_MINIMUM = 5000
  66MINIMUM_DIFFICULTY = Uint(131072)
  67MAX_OMMER_DEPTH = 6
  68BOMB_DELAY_BLOCKS = 9000000
  69EMPTY_OMMER_HASH = keccak256(rlp.encode([]))
  70
  71
  72@dataclass
  73class BlockChain:
  74    """
  75    History and current state of the block chain.
  76    """
  77
  78    blocks: List[Block]
  79    state: State
  80    chain_id: U64
  81
  82
  83def apply_fork(old: BlockChain) -> BlockChain:
  84    """
  85    Transforms the state from the previous hard fork (`old`) into the block
  86    chain object for this hard fork and returns it.
  87
  88    When forks need to implement an irregular state transition, this function
  89    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
  90    an example.
  91
  92    Parameters
  93    ----------
  94    old :
  95        Previous block chain object.
  96
  97    Returns
  98    -------
  99    new : `BlockChain`
 100        Upgraded block chain object for this hard fork.
 101    """
 102    return old
 103
 104
 105def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]:
 106    """
 107    Obtain the list of hashes of the previous 256 blocks in order of
 108    increasing block number.
 109
 110    This function will return less hashes for the first 256 blocks.
 111
 112    The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,
 113    therefore this function retrieves them.
 114
 115    Parameters
 116    ----------
 117    chain :
 118        History and current state.
 119
 120    Returns
 121    -------
 122    recent_block_hashes : `List[Hash32]`
 123        Hashes of the recent 256 blocks in order of increasing block number.
 124    """
 125    recent_blocks = chain.blocks[-255:]
 126    # TODO: This function has not been tested rigorously
 127    if len(recent_blocks) == 0:
 128        return []
 129
 130    recent_block_hashes = []
 131
 132    for block in recent_blocks:
 133        prev_block_hash = block.header.parent_hash
 134        recent_block_hashes.append(prev_block_hash)
 135
 136    # We are computing the hash only for the most recent block and not for
 137    # the rest of the blocks as they have successors which have the hash of
 138    # the current block as parent hash.
 139    most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header))
 140    recent_block_hashes.append(most_recent_block_hash)
 141
 142    return recent_block_hashes
 143
 144
 145def state_transition(chain: BlockChain, block: Block) -> None:
 146    """
 147    Attempts to apply a block to an existing block chain.
 148
 149    All parts of the block's contents need to be verified before being added
 150    to the chain. Blocks are verified by ensuring that the contents of the
 151    block make logical sense with the contents of the parent block. The
 152    information in the block's header must also match the corresponding
 153    information in the block.
 154
 155    To implement Ethereum, in theory clients are only required to store the
 156    most recent 255 blocks of the chain since as far as execution is
 157    concerned, only those blocks are accessed. Practically, however, clients
 158    should store more blocks to handle reorgs.
 159
 160    Parameters
 161    ----------
 162    chain :
 163        History and current state.
 164    block :
 165        Block to apply to `chain`.
 166    """
 167    parent_header = chain.blocks[-1].header
 168    validate_header(block.header, parent_header)
 169    validate_ommers(block.ommers, block.header, chain)
 170    (
 171        gas_used,
 172        transactions_root,
 173        receipt_root,
 174        block_logs_bloom,
 175        state,
 176    ) = apply_body(
 177        chain.state,
 178        get_last_256_block_hashes(chain),
 179        block.header.coinbase,
 180        block.header.number,
 181        block.header.gas_limit,
 182        block.header.timestamp,
 183        block.header.difficulty,
 184        block.transactions,
 185        block.ommers,
 186        chain.chain_id,
 187    )
 188    ensure(gas_used == block.header.gas_used, InvalidBlock)
 189    ensure(transactions_root == block.header.transactions_root, InvalidBlock)
 190    ensure(state_root(state) == block.header.state_root, InvalidBlock)
 191    ensure(receipt_root == block.header.receipt_root, InvalidBlock)
 192    ensure(block_logs_bloom == block.header.bloom, InvalidBlock)
 193
 194    chain.blocks.append(block)
 195    if len(chain.blocks) > 255:
 196        # Real clients have to store more blocks to deal with reorgs, but the
 197        # protocol only requires the last 255
 198        chain.blocks = chain.blocks[-255:]
 199
 200
 201def validate_header(header: Header, parent_header: Header) -> None:
 202    """
 203    Verifies a block header.
 204
 205    In order to consider a block's header valid, the logic for the
 206    quantities in the header should match the logic for the block itself.
 207    For example the header timestamp should be greater than the block's parent
 208    timestamp because the block was created *after* the parent block.
 209    Additionally, the block's number should be directly following the parent
 210    block's number since it is the next block in the sequence.
 211
 212    Parameters
 213    ----------
 214    header :
 215        Header to check for correctness.
 216    parent_header :
 217        Parent Header of the header to check for correctness
 218    """
 219    parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH
 220    ensure(header.timestamp > parent_header.timestamp, InvalidBlock)
 221    ensure(header.number == parent_header.number + 1, InvalidBlock)
 222    ensure(
 223        check_gas_limit(header.gas_limit, parent_header.gas_limit),
 224        InvalidBlock,
 225    )
 226    ensure(len(header.extra_data) <= 32, InvalidBlock)
 227
 228    block_difficulty = calculate_block_difficulty(
 229        header.number,
 230        header.timestamp,
 231        parent_header.timestamp,
 232        parent_header.difficulty,
 233        parent_has_ommers,
 234    )
 235    ensure(header.difficulty == block_difficulty, InvalidBlock)
 236
 237    block_parent_hash = keccak256(rlp.encode(parent_header))
 238    ensure(header.parent_hash == block_parent_hash, InvalidBlock)
 239
 240    validate_proof_of_work(header)
 241
 242
 243def generate_header_hash_for_pow(header: Header) -> Hash32:
 244    """
 245    Generate rlp hash of the header which is to be used for Proof-of-Work
 246    verification.
 247
 248    In other words, the PoW artefacts `mix_digest` and `nonce` are ignored
 249    while calculating this hash.
 250
 251    A particular PoW is valid for a single hash, that hash is computed by
 252    this function. The `nonce` and `mix_digest` are omitted from this hash
 253    because they are being changed by miners in their search for a sufficient
 254    proof-of-work.
 255
 256    Parameters
 257    ----------
 258    header :
 259        The header object for which the hash is to be generated.
 260
 261    Returns
 262    -------
 263    hash : `Hash32`
 264        The PoW valid rlp hash of the passed in header.
 265    """
 266    header_data_without_pow_artefacts = [
 267        header.parent_hash,
 268        header.ommers_hash,
 269        header.coinbase,
 270        header.state_root,
 271        header.transactions_root,
 272        header.receipt_root,
 273        header.bloom,
 274        header.difficulty,
 275        header.number,
 276        header.gas_limit,
 277        header.gas_used,
 278        header.timestamp,
 279        header.extra_data,
 280    ]
 281
 282    return rlp.rlp_hash(header_data_without_pow_artefacts)
 283
 284
 285def validate_proof_of_work(header: Header) -> None:
 286    """
 287    Validates the Proof of Work constraints.
 288
 289    In order to verify that a miner's proof-of-work is valid for a block, a
 290    ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``
 291    hash function. The mix digest is a hash of the header and the nonce that
 292    is passed through and it confirms whether or not proof-of-work was done
 293    on the correct block. The result is the actual hash value of the block.
 294
 295    Parameters
 296    ----------
 297    header :
 298        Header of interest.
 299    """
 300    header_hash = generate_header_hash_for_pow(header)
 301    # TODO: Memoize this somewhere and read from that data instead of
 302    # calculating cache for every block validation.
 303    cache = generate_cache(header.number)
 304    mix_digest, result = hashimoto_light(
 305        header_hash, header.nonce, cache, dataset_size(header.number)
 306    )
 307
 308    ensure(mix_digest == header.mix_digest, InvalidBlock)
 309    ensure(
 310        Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty),
 311        InvalidBlock,
 312    )
 313
 314
 315def check_transaction(
 316    tx: Transaction,
 317    gas_available: Uint,
 318    chain_id: U64,
 319) -> Address:
 320    """
 321    Check if the transaction is includable in the block.
 322
 323    Parameters
 324    ----------
 325    tx :
 326        The transaction.
 327    gas_available :
 328        The gas remaining in the block.
 329    chain_id :
 330        The ID of the current chain.
 331
 332    Returns
 333    -------
 334    sender_address :
 335        The sender of the transaction.
 336
 337    Raises
 338    ------
 339    InvalidBlock :
 340        If the transaction is not includable.
 341    """
 342    ensure(tx.gas <= gas_available, InvalidBlock)
 343    sender_address = recover_sender(chain_id, tx)
 344
 345    return sender_address
 346
 347
 348def make_receipt(
 349    tx: Transaction,
 350    error: Optional[Exception],
 351    cumulative_gas_used: Uint,
 352    logs: Tuple[Log, ...],
 353) -> Union[Bytes, Receipt]:
 354    """
 355    Make the receipt for a transaction that was executed.
 356
 357    Parameters
 358    ----------
 359    tx :
 360        The executed transaction.
 361    error :
 362        Error in the top level frame of the transaction, if any.
 363    cumulative_gas_used :
 364        The total gas used so far in the block after the transaction was
 365        executed.
 366    logs :
 367        The logs produced by the transaction.
 368
 369    Returns
 370    -------
 371    receipt :
 372        The receipt for the transaction.
 373    """
 374    receipt = Receipt(
 375        succeeded=error is None,
 376        cumulative_gas_used=cumulative_gas_used,
 377        bloom=logs_bloom(logs),
 378        logs=logs,
 379    )
 380
 381    if isinstance(tx, AccessListTransaction):
 382        return b"\x01" + rlp.encode(receipt)
 383    else:
 384        return receipt
 385
 386
 387def apply_body(
 388    state: State,
 389    block_hashes: List[Hash32],
 390    coinbase: Address,
 391    block_number: Uint,
 392    block_gas_limit: Uint,
 393    block_time: U256,
 394    block_difficulty: Uint,
 395    transactions: Tuple[Union[LegacyTransaction, Bytes], ...],
 396    ommers: Tuple[Header, ...],
 397    chain_id: U64,
 398) -> Tuple[Uint, Root, Root, Bloom, State]:
 399    """
 400    Executes a block.
 401
 402    Many of the contents of a block are stored in data structures called
 403    tries. There is a transactions trie which is similar to a ledger of the
 404    transactions stored in the current block. There is also a receipts trie
 405    which stores the results of executing a transaction, like the post state
 406    and gas used. This function creates and executes the block that is to be
 407    added to the chain.
 408
 409    Parameters
 410    ----------
 411    state :
 412        Current account state.
 413    block_hashes :
 414        List of hashes of the previous 256 blocks in the order of
 415        increasing block number.
 416    coinbase :
 417        Address of account which receives block reward and transaction fees.
 418    block_number :
 419        Position of the block within the chain.
 420    block_gas_limit :
 421        Initial amount of gas available for execution in this block.
 422    block_time :
 423        Time the block was produced, measured in seconds since the epoch.
 424    block_difficulty :
 425        Difficulty of the block.
 426    transactions :
 427        Transactions included in the block.
 428    ommers :
 429        Headers of ancestor blocks which are not direct parents (formerly
 430        uncles.)
 431    chain_id :
 432        ID of the executing chain.
 433
 434    Returns
 435    -------
 436    block_gas_used : `ethereum.base_types.Uint`
 437        Gas used for executing all transactions.
 438    transactions_root : `ethereum.fork_types.Root`
 439        Trie root of all the transactions in the block.
 440    receipt_root : `ethereum.fork_types.Root`
 441        Trie root of all the receipts in the block.
 442    block_logs_bloom : `Bloom`
 443        Logs bloom of all the logs included in all the transactions of the
 444        block.
 445    state : `ethereum.fork_types.State`
 446        State after all transactions have been executed.
 447    """
 448    gas_available = block_gas_limit
 449    transactions_trie: Trie[
 450        Bytes, Optional[Union[Bytes, LegacyTransaction]]
 451    ] = Trie(secured=False, default=None)
 452    receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie(
 453        secured=False, default=None
 454    )
 455    block_logs: Tuple[Log, ...] = ()
 456
 457    for i, tx in enumerate(map(decode_transaction, transactions)):
 458        trie_set(
 459            transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx)
 460        )
 461
 462        sender_address = check_transaction(tx, gas_available, chain_id)
 463
 464        env = vm.Environment(
 465            caller=sender_address,
 466            origin=sender_address,
 467            block_hashes=block_hashes,
 468            coinbase=coinbase,
 469            number=block_number,
 470            gas_limit=block_gas_limit,
 471            gas_price=tx.gas_price,
 472            time=block_time,
 473            difficulty=block_difficulty,
 474            state=state,
 475            chain_id=chain_id,
 476            traces=[],
 477        )
 478
 479        gas_used, logs, error = process_transaction(env, tx)
 480        gas_available -= gas_used
 481
 482        receipt = make_receipt(
 483            tx, error, (block_gas_limit - gas_available), logs
 484        )
 485
 486        trie_set(
 487            receipts_trie,
 488            rlp.encode(Uint(i)),
 489            receipt,
 490        )
 491
 492        block_logs += logs
 493
 494    pay_rewards(state, block_number, coinbase, ommers)
 495
 496    block_gas_used = block_gas_limit - gas_available
 497
 498    block_logs_bloom = logs_bloom(block_logs)
 499
 500    return (
 501        block_gas_used,
 502        root(transactions_trie),
 503        root(receipts_trie),
 504        block_logs_bloom,
 505        state,
 506    )
 507
 508
 509def validate_ommers(
 510    ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain
 511) -> None:
 512    """
 513    Validates the ommers mentioned in the block.
 514
 515    An ommer block is a block that wasn't canonically added to the
 516    blockchain because it wasn't validated as fast as the canonical block
 517    but was mined at the same time.
 518
 519    To be considered valid, the ommers must adhere to the rules defined in
 520    the Ethereum protocol. The maximum amount of ommers is 2 per block and
 521    there cannot be duplicate ommers in a block. Many of the other ommer
 522    constraints are listed in the in-line comments of this function.
 523
 524    Parameters
 525    ----------
 526    ommers :
 527        List of ommers mentioned in the current block.
 528    block_header:
 529        The header of current block.
 530    chain :
 531        History and current state.
 532    """
 533    block_hash = rlp.rlp_hash(block_header)
 534
 535    ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock)
 536
 537    if len(ommers) == 0:
 538        # Nothing to validate
 539        return
 540
 541    # Check that each ommer satisfies the constraints of a header
 542    for ommer in ommers:
 543        ensure(1 <= ommer.number < block_header.number, InvalidBlock)
 544        ommer_parent_header = chain.blocks[
 545            -(block_header.number - ommer.number) - 1
 546        ].header
 547        validate_header(ommer, ommer_parent_header)
 548
 549    # Check that there can be only at most 2 ommers for a block.
 550    ensure(len(ommers) <= 2, InvalidBlock)
 551
 552    ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers]
 553    # Check that there are no duplicates in the ommers of current block
 554    ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock)
 555
 556    recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :]
 557    recent_canonical_block_hashes = {
 558        rlp.rlp_hash(block.header) for block in recent_canonical_blocks
 559    }
 560    recent_ommers_hashes: Set[Hash32] = set()
 561    for block in recent_canonical_blocks:
 562        recent_ommers_hashes = recent_ommers_hashes.union(
 563            {rlp.rlp_hash(ommer) for ommer in block.ommers}
 564        )
 565
 566    for ommer_index, ommer in enumerate(ommers):
 567        ommer_hash = ommers_hashes[ommer_index]
 568        # The current block shouldn't be the ommer
 569        ensure(ommer_hash != block_hash, InvalidBlock)
 570
 571        # Ommer shouldn't be one of the recent canonical blocks
 572        ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock)
 573
 574        # Ommer shouldn't be one of the uncles mentioned in the recent
 575        # canonical blocks
 576        ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock)
 577
 578        # Ommer age with respect to the current block. For example, an age of
 579        # 1 indicates that the ommer is a sibling of previous block.
 580        ommer_age = block_header.number - ommer.number
 581        ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock)
 582
 583        ensure(
 584            ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock
 585        )
 586        ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock)
 587
 588
 589def pay_rewards(
 590    state: State,
 591    block_number: Uint,
 592    coinbase: Address,
 593    ommers: Tuple[Header, ...],
 594) -> None:
 595    """
 596    Pay rewards to the block miner as well as the ommers miners.
 597
 598    The miner of the canonical block is rewarded with the predetermined
 599    block reward, ``BLOCK_REWARD``, plus a variable award based off of the
 600    number of ommer blocks that were mined around the same time, and included
 601    in the canonical block's header. An ommer block is a block that wasn't
 602    added to the canonical blockchain because it wasn't validated as fast as
 603    the accepted block but was mined at the same time. Although not all blocks
 604    that are mined are added to the canonical chain, miners are still paid a
 605    reward for their efforts. This reward is called an ommer reward and is
 606    calculated based on the number associated with the ommer block that they
 607    mined.
 608
 609    Parameters
 610    ----------
 611    state :
 612        Current account state.
 613    block_number :
 614        Position of the block within the chain.
 615    coinbase :
 616        Address of account which receives block reward and transaction fees.
 617    ommers :
 618        List of ommers mentioned in the current block.
 619    """
 620    miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32))
 621    create_ether(state, coinbase, miner_reward)
 622
 623    for ommer in ommers:
 624        # Ommer age with respect to the current block.
 625        ommer_age = U256(block_number - ommer.number)
 626        ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8
 627        create_ether(state, ommer.coinbase, ommer_miner_reward)
 628
 629
 630def process_transaction(
 631    env: vm.Environment, tx: Transaction
 632) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]:
 633    """
 634    Execute a transaction against the provided environment.
 635
 636    This function processes the actions needed to execute a transaction.
 637    It decrements the sender's account after calculating the gas fee and
 638    refunds them the proper amount after execution. Calling contracts,
 639    deploying code, and incrementing nonces are all examples of actions that
 640    happen within this function or from a call made within this function.
 641
 642    Accounts that are marked for deletion are processed and destroyed after
 643    execution.
 644
 645    Parameters
 646    ----------
 647    env :
 648        Environment for the Ethereum Virtual Machine.
 649    tx :
 650        Transaction to execute.
 651
 652    Returns
 653    -------
 654    gas_left : `ethereum.base_types.U256`
 655        Remaining gas after execution.
 656    logs : `Tuple[ethereum.fork_types.Log, ...]`
 657        Logs generated during execution.
 658    """
 659    ensure(validate_transaction(tx), InvalidBlock)
 660
 661    sender = env.origin
 662    sender_account = get_account(env.state, sender)
 663    gas_fee = tx.gas * tx.gas_price
 664    ensure(sender_account.nonce == tx.nonce, InvalidBlock)
 665    ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
 666    ensure(sender_account.code == bytearray(), InvalidBlock)
 667
 668    gas = tx.gas - calculate_intrinsic_cost(tx)
 669    increment_nonce(env.state, sender)
 670    sender_balance_after_gas_fee = sender_account.balance - gas_fee
 671    set_account_balance(env.state, sender, sender_balance_after_gas_fee)
 672
 673    preaccessed_addresses = set()
 674    preaccessed_storage_keys = set()
 675    if isinstance(tx, AccessListTransaction):
 676        for address, keys in tx.access_list:
 677            preaccessed_addresses.add(address)
 678            for key in keys:
 679                preaccessed_storage_keys.add((address, key))
 680
 681    message = prepare_message(
 682        sender,
 683        tx.to,
 684        tx.value,
 685        tx.data,
 686        gas,
 687        env,
 688        preaccessed_addresses=frozenset(preaccessed_addresses),
 689        preaccessed_storage_keys=frozenset(preaccessed_storage_keys),
 690    )
 691
 692    output = process_message_call(message, env)
 693
 694    gas_used = tx.gas - output.gas_left
 695    gas_refund = min(gas_used // 2, output.refund_counter)
 696    gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price
 697    transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price
 698    total_gas_used = gas_used - gas_refund
 699
 700    # refund gas
 701    sender_balance_after_refund = (
 702        get_account(env.state, sender).balance + gas_refund_amount
 703    )
 704    set_account_balance(env.state, sender, sender_balance_after_refund)
 705
 706    # transfer miner fees
 707    coinbase_balance_after_mining_fee = (
 708        get_account(env.state, env.coinbase).balance + transaction_fee
 709    )
 710    if coinbase_balance_after_mining_fee != 0:
 711        set_account_balance(
 712            env.state, env.coinbase, coinbase_balance_after_mining_fee
 713        )
 714    elif account_exists_and_is_empty(env.state, env.coinbase):
 715        destroy_account(env.state, env.coinbase)
 716
 717    for address in output.accounts_to_delete:
 718        destroy_account(env.state, address)
 719
 720    for address in output.touched_accounts:
 721        if account_exists_and_is_empty(env.state, address):
 722            destroy_account(env.state, address)
 723
 724    return total_gas_used, output.logs, output.error
 725
 726
 727def validate_transaction(tx: Transaction) -> bool:
 728    """
 729    Verifies a transaction.
 730
 731    The gas in a transaction gets used to pay for the intrinsic cost of
 732    operations, therefore if there is insufficient gas then it would not
 733    be possible to execute a transaction and it will be declared invalid.
 734
 735    Additionally, the nonce of a transaction must not equal or exceed the
 736    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
 737    In practice, defining the limit as ``2**64-1`` has no impact because
 738    sending ``2**64-1`` transactions is improbable. It's not strictly
 739    impossible though, ``2**64-1`` transactions is the entire capacity of the
 740    Ethereum blockchain at 2022 gas limits for a little over 22 years.
 741
 742    Parameters
 743    ----------
 744    tx :
 745        Transaction to validate.
 746
 747    Returns
 748    -------
 749    verified : `bool`
 750        True if the transaction can be executed, or False otherwise.
 751    """
 752    return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1
 753
 754
 755def calculate_intrinsic_cost(tx: Transaction) -> Uint:
 756    """
 757    Calculates the gas that is charged before execution is started.
 758
 759    The intrinsic cost of the transaction is charged before execution has
 760    begun. Functions/operations in the EVM cost money to execute so this
 761    intrinsic cost is for the operations that need to be paid for as part of
 762    the transaction. Data transfer, for example, is part of this intrinsic
 763    cost. It costs ether to send data over the wire and that ether is
 764    accounted for in the intrinsic cost calculated in this function. This
 765    intrinsic cost must be calculated and paid for before execution in order
 766    for all operations to be implemented.
 767
 768    Parameters
 769    ----------
 770    tx :
 771        Transaction to compute the intrinsic cost of.
 772
 773    Returns
 774    -------
 775    verified : `ethereum.base_types.Uint`
 776        The intrinsic cost of the transaction.
 777    """
 778    data_cost = 0
 779
 780    for byte in tx.data:
 781        if byte == 0:
 782            data_cost += TX_DATA_COST_PER_ZERO
 783        else:
 784            data_cost += TX_DATA_COST_PER_NON_ZERO
 785
 786    if tx.to == Bytes0(b""):
 787        create_cost = TX_CREATE_COST
 788    else:
 789        create_cost = 0
 790
 791    access_list_cost = 0
 792    if isinstance(tx, AccessListTransaction):
 793        for _address, keys in tx.access_list:
 794            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
 795            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
 796
 797    return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost)
 798
 799
 800def recover_sender(chain_id: U64, tx: Transaction) -> Address:
 801    """
 802    Extracts the sender address from a transaction.
 803
 804    The v, r, and s values are the three parts that make up the signature
 805    of a transaction. In order to recover the sender of a transaction the two
 806    components needed are the signature (``v``, ``r``, and ``s``) and the
 807    signing hash of the transaction. The sender's public key can be obtained
 808    with these two values and therefore the sender address can be retrieved.
 809
 810    Parameters
 811    ----------
 812    tx :
 813        Transaction of interest.
 814    chain_id :
 815        ID of the executing chain.
 816
 817    Returns
 818    -------
 819    sender : `ethereum.fork_types.Address`
 820        The address of the account that signed the transaction.
 821    """
 822    r, s = tx.r, tx.s
 823
 824    ensure(0 < r and r < SECP256K1N, InvalidBlock)
 825    ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock)
 826
 827    if isinstance(tx, LegacyTransaction):
 828        v = tx.v
 829        if v == 27 or v == 28:
 830            public_key = secp256k1_recover(
 831                r, s, v - 27, signing_hash_pre155(tx)
 832            )
 833        else:
 834            ensure(
 835                v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock
 836            )
 837            public_key = secp256k1_recover(
 838                r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
 839            )
 840    elif isinstance(tx, AccessListTransaction):
 841        public_key = secp256k1_recover(
 842            r, s, tx.y_parity, signing_hash_2930(tx)
 843        )
 844
 845    return Address(keccak256(public_key)[12:32])
 846
 847
 848def signing_hash_pre155(tx: Transaction) -> Hash32:
 849    """
 850    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
 851
 852    Parameters
 853    ----------
 854    tx :
 855        Transaction of interest.
 856
 857    Returns
 858    -------
 859    hash : `ethereum.crypto.hash.Hash32`
 860        Hash of the transaction.
 861    """
 862    return keccak256(
 863        rlp.encode(
 864            (
 865                tx.nonce,
 866                tx.gas_price,
 867                tx.gas,
 868                tx.to,
 869                tx.value,
 870                tx.data,
 871            )
 872        )
 873    )
 874
 875
 876def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32:
 877    """
 878    Compute the hash of a transaction used in a EIP 155 signature.
 879
 880    Parameters
 881    ----------
 882    tx :
 883        Transaction of interest.
 884    chain_id :
 885        The id of the current chain.
 886
 887    Returns
 888    -------
 889    hash : `ethereum.crypto.hash.Hash32`
 890        Hash of the transaction.
 891    """
 892    return keccak256(
 893        rlp.encode(
 894            (
 895                tx.nonce,
 896                tx.gas_price,
 897                tx.gas,
 898                tx.to,
 899                tx.value,
 900                tx.data,
 901                chain_id,
 902                Uint(0),
 903                Uint(0),
 904            )
 905        )
 906    )
 907
 908
 909def signing_hash_2930(tx: AccessListTransaction) -> Hash32:
 910    """
 911    Compute the hash of a transaction used in a EIP 2930 signature.
 912
 913    Parameters
 914    ----------
 915    tx :
 916        Transaction of interest.
 917
 918    Returns
 919    -------
 920    hash : `ethereum.crypto.hash.Hash32`
 921        Hash of the transaction.
 922    """
 923    return keccak256(
 924        b"\x01"
 925        + rlp.encode(
 926            (
 927                tx.chain_id,
 928                tx.nonce,
 929                tx.gas_price,
 930                tx.gas,
 931                tx.to,
 932                tx.value,
 933                tx.data,
 934                tx.access_list,
 935            )
 936        )
 937    )
 938
 939
 940def compute_header_hash(header: Header) -> Hash32:
 941    """
 942    Computes the hash of a block header.
 943
 944    The header hash of a block is the canonical hash that is used to refer
 945    to a specific block and completely distinguishes a block from another.
 946
 947    ``keccak256`` is a function that produces a 256 bit hash of any input.
 948    It also takes in any number of bytes as an input and produces a single
 949    hash for them. A hash is a completely unique output for a single input.
 950    So an input corresponds to one unique hash that can be used to identify
 951    the input exactly.
 952
 953    Prior to using the ``keccak256`` hash function, the header must be
 954    encoded using the Recursive-Length Prefix. See :ref:`rlp`.
 955    RLP encoding the header converts it into a space-efficient format that
 956    allows for easy transfer of data between nodes. The purpose of RLP is to
 957    encode arbitrarily nested arrays of binary data, and RLP is the primary
 958    encoding method used to serialize objects in Ethereum's execution layer.
 959    The only purpose of RLP is to encode structure; encoding specific data
 960    types (e.g. strings, floats) is left up to higher-order protocols.
 961
 962    Parameters
 963    ----------
 964    header :
 965        Header of interest.
 966
 967    Returns
 968    -------
 969    hash : `ethereum.crypto.hash.Hash32`
 970        Hash of the header.
 971    """
 972    return keccak256(rlp.encode(header))
 973
 974
 975def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool:
 976    """
 977    Validates the gas limit for a block.
 978
 979    The bounds of the gas limit, ``max_adjustment_delta``, is set as the
 980    quotient of the parent block's gas limit and the
 981    ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is
 982    passed through as a parameter is greater than or equal to the *sum* of
 983    the parent's gas and the adjustment delta then the limit for gas is too
 984    high and fails this function's check. Similarly, if the limit is less
 985    than or equal to the *difference* of the parent's gas and the adjustment
 986    delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's
 987    check fails because the gas limit doesn't allow for a sufficient or
 988    reasonable amount of gas to be used on a block.
 989
 990    Parameters
 991    ----------
 992    gas_limit :
 993        Gas limit to validate.
 994
 995    parent_gas_limit :
 996        Gas limit of the parent block.
 997
 998    Returns
 999    -------
1000    check : `bool`
1001        True if gas limit constraints are satisfied, False otherwise.
1002    """
1003    max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
1004    if gas_limit >= parent_gas_limit + max_adjustment_delta:
1005        return False
1006    if gas_limit <= parent_gas_limit - max_adjustment_delta:
1007        return False
1008    if gas_limit < GAS_LIMIT_MINIMUM:
1009        return False
1010
1011    return True
1012
1013
1014def calculate_block_difficulty(
1015    block_number: Uint,
1016    block_timestamp: U256,
1017    parent_timestamp: U256,
1018    parent_difficulty: Uint,
1019    parent_has_ommers: bool,
1020) -> Uint:
1021    """
1022    Computes difficulty of a block using its header and parent header.
1023
1024    The difficulty is determined by the time the block was created after its
1025    parent. The ``offset`` is calculated using the parent block's difficulty,
1026    ``parent_difficulty``, and the timestamp between blocks. This offset is
1027    then added to the parent difficulty and is stored as the ``difficulty``
1028    variable. If the time between the block and its parent is too short, the
1029    offset will result in a positive number thus making the sum of
1030    ``parent_difficulty`` and ``offset`` to be a greater value in order to
1031    avoid mass forking. But, if the time is long enough, then the offset
1032    results in a negative value making the block less difficult than
1033    its parent.
1034
1035    The base standard for a block's difficulty is the predefined value
1036    set for the genesis block since it has no parent. So, a block
1037    can't be less difficult than the genesis block, therefore each block's
1038    difficulty is set to the maximum value between the calculated
1039    difficulty and the ``GENESIS_DIFFICULTY``.
1040
1041    Parameters
1042    ----------
1043    block_number :
1044        Block number of the block.
1045    block_timestamp :
1046        Timestamp of the block.
1047    parent_timestamp :
1048        Timestamp of the parent block.
1049    parent_difficulty :
1050        difficulty of the parent block.
1051    parent_has_ommers:
1052        does the parent have ommers.
1053
1054    Returns
1055    -------
1056    difficulty : `ethereum.base_types.Uint`
1057        Computed difficulty for a block.
1058    """
1059    offset = (
1060        int(parent_difficulty)
1061        // 2048
1062        * max(
1063            (2 if parent_has_ommers else 1)
1064            - int(block_timestamp - parent_timestamp) // 9,
1065            -99,
1066        )
1067    )
1068    difficulty = int(parent_difficulty) + offset
1069    # Historical Note: The difficulty bomb was not present in Ethereum at the
1070    # start of Frontier, but was added shortly after launch. However since the
1071    # bomb has no effect prior to block 200000 we pretend it existed from
1072    # genesis.
1073    # See https://github.com/ethereum/go-ethereum/pull/1588
1074    num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2
1075    if num_bomb_periods >= 0:
1076        difficulty += 2**num_bomb_periods
1077
1078    # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding
1079    # the bomb. This bug does not matter because the difficulty is always much
1080    # greater than `MINIMUM_DIFFICULTY` on Mainnet.
1081    return Uint(max(difficulty, MINIMUM_DIFFICULTY))
@dataclass
class BlockChain:
73@dataclass
74class BlockChain:
75    """
76    History and current state of the block chain.
77    """
78
79    blocks: List[Block]
80    state: State
81    chain_id: U64

History and current state of the block chain.

def apply_fork(old: BlockChain) -> BlockChain:
 84def apply_fork(old: BlockChain) -> BlockChain:
 85    """
 86    Transforms the state from the previous hard fork (`old`) into the block
 87    chain object for this hard fork and returns it.
 88
 89    When forks need to implement an irregular state transition, this function
 90    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
 91    an example.
 92
 93    Parameters
 94    ----------
 95    old :
 96        Previous block chain object.
 97
 98    Returns
 99    -------
100    new : `BlockChain`
101        Upgraded block chain object for this hard fork.
102    """
103    return old

Transforms the state from the previous hard fork (old) into the block chain object for this hard fork and returns it.

When forks need to implement an irregular state transition, this function is used to handle the irregularity. See the :ref:DAO Fork <dao-fork> for an example.

Parameters

old : Previous block chain object.

Returns

new : BlockChain Upgraded block chain object for this hard fork.

def get_last_256_block_hashes( chain: BlockChain) -> List[ethereum.base_types.Bytes32]:
106def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]:
107    """
108    Obtain the list of hashes of the previous 256 blocks in order of
109    increasing block number.
110
111    This function will return less hashes for the first 256 blocks.
112
113    The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,
114    therefore this function retrieves them.
115
116    Parameters
117    ----------
118    chain :
119        History and current state.
120
121    Returns
122    -------
123    recent_block_hashes : `List[Hash32]`
124        Hashes of the recent 256 blocks in order of increasing block number.
125    """
126    recent_blocks = chain.blocks[-255:]
127    # TODO: This function has not been tested rigorously
128    if len(recent_blocks) == 0:
129        return []
130
131    recent_block_hashes = []
132
133    for block in recent_blocks:
134        prev_block_hash = block.header.parent_hash
135        recent_block_hashes.append(prev_block_hash)
136
137    # We are computing the hash only for the most recent block and not for
138    # the rest of the blocks as they have successors which have the hash of
139    # the current block as parent hash.
140    most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header))
141    recent_block_hashes.append(most_recent_block_hash)
142
143    return recent_block_hashes

Obtain the list of hashes of the previous 256 blocks in order of increasing block number.

This function will return less hashes for the first 256 blocks.

The BLOCKHASH opcode needs to access the latest hashes on the chain, therefore this function retrieves them.

Parameters

chain : History and current state.

Returns

recent_block_hashes : List[Hash32] Hashes of the recent 256 blocks in order of increasing block number.

def state_transition( chain: BlockChain, block: ethereum.berlin.fork_types.Block) -> None:
146def state_transition(chain: BlockChain, block: Block) -> None:
147    """
148    Attempts to apply a block to an existing block chain.
149
150    All parts of the block's contents need to be verified before being added
151    to the chain. Blocks are verified by ensuring that the contents of the
152    block make logical sense with the contents of the parent block. The
153    information in the block's header must also match the corresponding
154    information in the block.
155
156    To implement Ethereum, in theory clients are only required to store the
157    most recent 255 blocks of the chain since as far as execution is
158    concerned, only those blocks are accessed. Practically, however, clients
159    should store more blocks to handle reorgs.
160
161    Parameters
162    ----------
163    chain :
164        History and current state.
165    block :
166        Block to apply to `chain`.
167    """
168    parent_header = chain.blocks[-1].header
169    validate_header(block.header, parent_header)
170    validate_ommers(block.ommers, block.header, chain)
171    (
172        gas_used,
173        transactions_root,
174        receipt_root,
175        block_logs_bloom,
176        state,
177    ) = apply_body(
178        chain.state,
179        get_last_256_block_hashes(chain),
180        block.header.coinbase,
181        block.header.number,
182        block.header.gas_limit,
183        block.header.timestamp,
184        block.header.difficulty,
185        block.transactions,
186        block.ommers,
187        chain.chain_id,
188    )
189    ensure(gas_used == block.header.gas_used, InvalidBlock)
190    ensure(transactions_root == block.header.transactions_root, InvalidBlock)
191    ensure(state_root(state) == block.header.state_root, InvalidBlock)
192    ensure(receipt_root == block.header.receipt_root, InvalidBlock)
193    ensure(block_logs_bloom == block.header.bloom, InvalidBlock)
194
195    chain.blocks.append(block)
196    if len(chain.blocks) > 255:
197        # Real clients have to store more blocks to deal with reorgs, but the
198        # protocol only requires the last 255
199        chain.blocks = chain.blocks[-255:]

Attempts to apply a block to an existing block chain.

All parts of the block's contents need to be verified before being added to the chain. Blocks are verified by ensuring that the contents of the block make logical sense with the contents of the parent block. The information in the block's header must also match the corresponding information in the block.

To implement Ethereum, in theory clients are only required to store the most recent 255 blocks of the chain since as far as execution is concerned, only those blocks are accessed. Practically, however, clients should store more blocks to handle reorgs.

Parameters

chain : History and current state. block : Block to apply to chain.

def validate_header( header: ethereum.berlin.fork_types.Header, parent_header: ethereum.berlin.fork_types.Header) -> None:
202def validate_header(header: Header, parent_header: Header) -> None:
203    """
204    Verifies a block header.
205
206    In order to consider a block's header valid, the logic for the
207    quantities in the header should match the logic for the block itself.
208    For example the header timestamp should be greater than the block's parent
209    timestamp because the block was created *after* the parent block.
210    Additionally, the block's number should be directly following the parent
211    block's number since it is the next block in the sequence.
212
213    Parameters
214    ----------
215    header :
216        Header to check for correctness.
217    parent_header :
218        Parent Header of the header to check for correctness
219    """
220    parent_has_ommers = parent_header.ommers_hash != EMPTY_OMMER_HASH
221    ensure(header.timestamp > parent_header.timestamp, InvalidBlock)
222    ensure(header.number == parent_header.number + 1, InvalidBlock)
223    ensure(
224        check_gas_limit(header.gas_limit, parent_header.gas_limit),
225        InvalidBlock,
226    )
227    ensure(len(header.extra_data) <= 32, InvalidBlock)
228
229    block_difficulty = calculate_block_difficulty(
230        header.number,
231        header.timestamp,
232        parent_header.timestamp,
233        parent_header.difficulty,
234        parent_has_ommers,
235    )
236    ensure(header.difficulty == block_difficulty, InvalidBlock)
237
238    block_parent_hash = keccak256(rlp.encode(parent_header))
239    ensure(header.parent_hash == block_parent_hash, InvalidBlock)
240
241    validate_proof_of_work(header)

Verifies a block header.

In order to consider a block's header valid, the logic for the quantities in the header should match the logic for the block itself. For example the header timestamp should be greater than the block's parent timestamp because the block was created after the parent block. Additionally, the block's number should be directly following the parent block's number since it is the next block in the sequence.

Parameters

header : Header to check for correctness. parent_header : Parent Header of the header to check for correctness

def generate_header_hash_for_pow(header: ethereum.berlin.fork_types.Header) -> ethereum.base_types.Bytes32:
244def generate_header_hash_for_pow(header: Header) -> Hash32:
245    """
246    Generate rlp hash of the header which is to be used for Proof-of-Work
247    verification.
248
249    In other words, the PoW artefacts `mix_digest` and `nonce` are ignored
250    while calculating this hash.
251
252    A particular PoW is valid for a single hash, that hash is computed by
253    this function. The `nonce` and `mix_digest` are omitted from this hash
254    because they are being changed by miners in their search for a sufficient
255    proof-of-work.
256
257    Parameters
258    ----------
259    header :
260        The header object for which the hash is to be generated.
261
262    Returns
263    -------
264    hash : `Hash32`
265        The PoW valid rlp hash of the passed in header.
266    """
267    header_data_without_pow_artefacts = [
268        header.parent_hash,
269        header.ommers_hash,
270        header.coinbase,
271        header.state_root,
272        header.transactions_root,
273        header.receipt_root,
274        header.bloom,
275        header.difficulty,
276        header.number,
277        header.gas_limit,
278        header.gas_used,
279        header.timestamp,
280        header.extra_data,
281    ]
282
283    return rlp.rlp_hash(header_data_without_pow_artefacts)

Generate rlp hash of the header which is to be used for Proof-of-Work verification.

In other words, the PoW artefacts mix_digest and nonce are ignored while calculating this hash.

A particular PoW is valid for a single hash, that hash is computed by this function. The nonce and mix_digest are omitted from this hash because they are being changed by miners in their search for a sufficient proof-of-work.

Parameters

header : The header object for which the hash is to be generated.

Returns

hash : Hash32 The PoW valid rlp hash of the passed in header.

def validate_proof_of_work(header: ethereum.berlin.fork_types.Header) -> None:
286def validate_proof_of_work(header: Header) -> None:
287    """
288    Validates the Proof of Work constraints.
289
290    In order to verify that a miner's proof-of-work is valid for a block, a
291    ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``
292    hash function. The mix digest is a hash of the header and the nonce that
293    is passed through and it confirms whether or not proof-of-work was done
294    on the correct block. The result is the actual hash value of the block.
295
296    Parameters
297    ----------
298    header :
299        Header of interest.
300    """
301    header_hash = generate_header_hash_for_pow(header)
302    # TODO: Memoize this somewhere and read from that data instead of
303    # calculating cache for every block validation.
304    cache = generate_cache(header.number)
305    mix_digest, result = hashimoto_light(
306        header_hash, header.nonce, cache, dataset_size(header.number)
307    )
308
309    ensure(mix_digest == header.mix_digest, InvalidBlock)
310    ensure(
311        Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty),
312        InvalidBlock,
313    )

Validates the Proof of Work constraints.

In order to verify that a miner's proof-of-work is valid for a block, a mix-digest and result are calculated using the hashimoto_light hash function. The mix digest is a hash of the header and the nonce that is passed through and it confirms whether or not proof-of-work was done on the correct block. The result is the actual hash value of the block.

Parameters

header : Header of interest.

316def check_transaction(
317    tx: Transaction,
318    gas_available: Uint,
319    chain_id: U64,
320) -> Address:
321    """
322    Check if the transaction is includable in the block.
323
324    Parameters
325    ----------
326    tx :
327        The transaction.
328    gas_available :
329        The gas remaining in the block.
330    chain_id :
331        The ID of the current chain.
332
333    Returns
334    -------
335    sender_address :
336        The sender of the transaction.
337
338    Raises
339    ------
340    InvalidBlock :
341        If the transaction is not includable.
342    """
343    ensure(tx.gas <= gas_available, InvalidBlock)
344    sender_address = recover_sender(chain_id, tx)
345
346    return sender_address

Check if the transaction is includable in the block.

Parameters

tx : The transaction. gas_available : The gas remaining in the block. chain_id : The ID of the current chain.

Returns

sender_address : The sender of the transaction.

Raises

InvalidBlock : If the transaction is not includable.

def make_receipt( tx: Union[ethereum.berlin.fork_types.LegacyTransaction, ethereum.berlin.fork_types.AccessListTransaction], error: Optional[Exception], cumulative_gas_used: ethereum.base_types.Uint, logs: Tuple[ethereum.berlin.fork_types.Log, ...]) -> Union[bytes, ethereum.berlin.fork_types.Receipt]:
349def make_receipt(
350    tx: Transaction,
351    error: Optional[Exception],
352    cumulative_gas_used: Uint,
353    logs: Tuple[Log, ...],
354) -> Union[Bytes, Receipt]:
355    """
356    Make the receipt for a transaction that was executed.
357
358    Parameters
359    ----------
360    tx :
361        The executed transaction.
362    error :
363        Error in the top level frame of the transaction, if any.
364    cumulative_gas_used :
365        The total gas used so far in the block after the transaction was
366        executed.
367    logs :
368        The logs produced by the transaction.
369
370    Returns
371    -------
372    receipt :
373        The receipt for the transaction.
374    """
375    receipt = Receipt(
376        succeeded=error is None,
377        cumulative_gas_used=cumulative_gas_used,
378        bloom=logs_bloom(logs),
379        logs=logs,
380    )
381
382    if isinstance(tx, AccessListTransaction):
383        return b"\x01" + rlp.encode(receipt)
384    else:
385        return receipt

Make the receipt for a transaction that was executed.

Parameters

tx : The executed transaction. error : Error in the top level frame of the transaction, if any. cumulative_gas_used : The total gas used so far in the block after the transaction was executed. logs : The logs produced by the transaction.

Returns

receipt : The receipt for the transaction.

388def apply_body(
389    state: State,
390    block_hashes: List[Hash32],
391    coinbase: Address,
392    block_number: Uint,
393    block_gas_limit: Uint,
394    block_time: U256,
395    block_difficulty: Uint,
396    transactions: Tuple[Union[LegacyTransaction, Bytes], ...],
397    ommers: Tuple[Header, ...],
398    chain_id: U64,
399) -> Tuple[Uint, Root, Root, Bloom, State]:
400    """
401    Executes a block.
402
403    Many of the contents of a block are stored in data structures called
404    tries. There is a transactions trie which is similar to a ledger of the
405    transactions stored in the current block. There is also a receipts trie
406    which stores the results of executing a transaction, like the post state
407    and gas used. This function creates and executes the block that is to be
408    added to the chain.
409
410    Parameters
411    ----------
412    state :
413        Current account state.
414    block_hashes :
415        List of hashes of the previous 256 blocks in the order of
416        increasing block number.
417    coinbase :
418        Address of account which receives block reward and transaction fees.
419    block_number :
420        Position of the block within the chain.
421    block_gas_limit :
422        Initial amount of gas available for execution in this block.
423    block_time :
424        Time the block was produced, measured in seconds since the epoch.
425    block_difficulty :
426        Difficulty of the block.
427    transactions :
428        Transactions included in the block.
429    ommers :
430        Headers of ancestor blocks which are not direct parents (formerly
431        uncles.)
432    chain_id :
433        ID of the executing chain.
434
435    Returns
436    -------
437    block_gas_used : `ethereum.base_types.Uint`
438        Gas used for executing all transactions.
439    transactions_root : `ethereum.fork_types.Root`
440        Trie root of all the transactions in the block.
441    receipt_root : `ethereum.fork_types.Root`
442        Trie root of all the receipts in the block.
443    block_logs_bloom : `Bloom`
444        Logs bloom of all the logs included in all the transactions of the
445        block.
446    state : `ethereum.fork_types.State`
447        State after all transactions have been executed.
448    """
449    gas_available = block_gas_limit
450    transactions_trie: Trie[
451        Bytes, Optional[Union[Bytes, LegacyTransaction]]
452    ] = Trie(secured=False, default=None)
453    receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie(
454        secured=False, default=None
455    )
456    block_logs: Tuple[Log, ...] = ()
457
458    for i, tx in enumerate(map(decode_transaction, transactions)):
459        trie_set(
460            transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx)
461        )
462
463        sender_address = check_transaction(tx, gas_available, chain_id)
464
465        env = vm.Environment(
466            caller=sender_address,
467            origin=sender_address,
468            block_hashes=block_hashes,
469            coinbase=coinbase,
470            number=block_number,
471            gas_limit=block_gas_limit,
472            gas_price=tx.gas_price,
473            time=block_time,
474            difficulty=block_difficulty,
475            state=state,
476            chain_id=chain_id,
477            traces=[],
478        )
479
480        gas_used, logs, error = process_transaction(env, tx)
481        gas_available -= gas_used
482
483        receipt = make_receipt(
484            tx, error, (block_gas_limit - gas_available), logs
485        )
486
487        trie_set(
488            receipts_trie,
489            rlp.encode(Uint(i)),
490            receipt,
491        )
492
493        block_logs += logs
494
495    pay_rewards(state, block_number, coinbase, ommers)
496
497    block_gas_used = block_gas_limit - gas_available
498
499    block_logs_bloom = logs_bloom(block_logs)
500
501    return (
502        block_gas_used,
503        root(transactions_trie),
504        root(receipts_trie),
505        block_logs_bloom,
506        state,
507    )

Executes a block.

Many of the contents of a block are stored in data structures called tries. There is a transactions trie which is similar to a ledger of the transactions stored in the current block. There is also a receipts trie which stores the results of executing a transaction, like the post state and gas used. This function creates and executes the block that is to be added to the chain.

Parameters

state : Current account state. block_hashes : List of hashes of the previous 256 blocks in the order of increasing block number. coinbase : Address of account which receives block reward and transaction fees. block_number : Position of the block within the chain. block_gas_limit : Initial amount of gas available for execution in this block. block_time : Time the block was produced, measured in seconds since the epoch. block_difficulty : Difficulty of the block. transactions : Transactions included in the block. ommers : Headers of ancestor blocks which are not direct parents (formerly uncles.) chain_id : ID of the executing chain.

Returns

block_gas_used : ethereum.base_types.Uint Gas used for executing all transactions. transactions_root : ethereum.fork_types.Root Trie root of all the transactions in the block. receipt_root : ethereum.fork_types.Root Trie root of all the receipts in the block. block_logs_bloom : Bloom Logs bloom of all the logs included in all the transactions of the block. state : ethereum.fork_types.State State after all transactions have been executed.

def validate_ommers( ommers: Tuple[ethereum.berlin.fork_types.Header, ...], block_header: ethereum.berlin.fork_types.Header, chain: BlockChain) -> None:
510def validate_ommers(
511    ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain
512) -> None:
513    """
514    Validates the ommers mentioned in the block.
515
516    An ommer block is a block that wasn't canonically added to the
517    blockchain because it wasn't validated as fast as the canonical block
518    but was mined at the same time.
519
520    To be considered valid, the ommers must adhere to the rules defined in
521    the Ethereum protocol. The maximum amount of ommers is 2 per block and
522    there cannot be duplicate ommers in a block. Many of the other ommer
523    constraints are listed in the in-line comments of this function.
524
525    Parameters
526    ----------
527    ommers :
528        List of ommers mentioned in the current block.
529    block_header:
530        The header of current block.
531    chain :
532        History and current state.
533    """
534    block_hash = rlp.rlp_hash(block_header)
535
536    ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock)
537
538    if len(ommers) == 0:
539        # Nothing to validate
540        return
541
542    # Check that each ommer satisfies the constraints of a header
543    for ommer in ommers:
544        ensure(1 <= ommer.number < block_header.number, InvalidBlock)
545        ommer_parent_header = chain.blocks[
546            -(block_header.number - ommer.number) - 1
547        ].header
548        validate_header(ommer, ommer_parent_header)
549
550    # Check that there can be only at most 2 ommers for a block.
551    ensure(len(ommers) <= 2, InvalidBlock)
552
553    ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers]
554    # Check that there are no duplicates in the ommers of current block
555    ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock)
556
557    recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :]
558    recent_canonical_block_hashes = {
559        rlp.rlp_hash(block.header) for block in recent_canonical_blocks
560    }
561    recent_ommers_hashes: Set[Hash32] = set()
562    for block in recent_canonical_blocks:
563        recent_ommers_hashes = recent_ommers_hashes.union(
564            {rlp.rlp_hash(ommer) for ommer in block.ommers}
565        )
566
567    for ommer_index, ommer in enumerate(ommers):
568        ommer_hash = ommers_hashes[ommer_index]
569        # The current block shouldn't be the ommer
570        ensure(ommer_hash != block_hash, InvalidBlock)
571
572        # Ommer shouldn't be one of the recent canonical blocks
573        ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock)
574
575        # Ommer shouldn't be one of the uncles mentioned in the recent
576        # canonical blocks
577        ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock)
578
579        # Ommer age with respect to the current block. For example, an age of
580        # 1 indicates that the ommer is a sibling of previous block.
581        ommer_age = block_header.number - ommer.number
582        ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock)
583
584        ensure(
585            ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock
586        )
587        ensure(ommer.parent_hash != block_header.parent_hash, InvalidBlock)

Validates the ommers mentioned in the block.

An ommer block is a block that wasn't canonically added to the blockchain because it wasn't validated as fast as the canonical block but was mined at the same time.

To be considered valid, the ommers must adhere to the rules defined in the Ethereum protocol. The maximum amount of ommers is 2 per block and there cannot be duplicate ommers in a block. Many of the other ommer constraints are listed in the in-line comments of this function.

Parameters

ommers : List of ommers mentioned in the current block. block_header: The header of current block. chain : History and current state.

def pay_rewards( state: ethereum.berlin.state.State, block_number: ethereum.base_types.Uint, coinbase: ethereum.base_types.Bytes20, ommers: Tuple[ethereum.berlin.fork_types.Header, ...]) -> None:
590def pay_rewards(
591    state: State,
592    block_number: Uint,
593    coinbase: Address,
594    ommers: Tuple[Header, ...],
595) -> None:
596    """
597    Pay rewards to the block miner as well as the ommers miners.
598
599    The miner of the canonical block is rewarded with the predetermined
600    block reward, ``BLOCK_REWARD``, plus a variable award based off of the
601    number of ommer blocks that were mined around the same time, and included
602    in the canonical block's header. An ommer block is a block that wasn't
603    added to the canonical blockchain because it wasn't validated as fast as
604    the accepted block but was mined at the same time. Although not all blocks
605    that are mined are added to the canonical chain, miners are still paid a
606    reward for their efforts. This reward is called an ommer reward and is
607    calculated based on the number associated with the ommer block that they
608    mined.
609
610    Parameters
611    ----------
612    state :
613        Current account state.
614    block_number :
615        Position of the block within the chain.
616    coinbase :
617        Address of account which receives block reward and transaction fees.
618    ommers :
619        List of ommers mentioned in the current block.
620    """
621    miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32))
622    create_ether(state, coinbase, miner_reward)
623
624    for ommer in ommers:
625        # Ommer age with respect to the current block.
626        ommer_age = U256(block_number - ommer.number)
627        ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8
628        create_ether(state, ommer.coinbase, ommer_miner_reward)

Pay rewards to the block miner as well as the ommers miners.

The miner of the canonical block is rewarded with the predetermined block reward, BLOCK_REWARD, plus a variable award based off of the number of ommer blocks that were mined around the same time, and included in the canonical block's header. An ommer block is a block that wasn't added to the canonical blockchain because it wasn't validated as fast as the accepted block but was mined at the same time. Although not all blocks that are mined are added to the canonical chain, miners are still paid a reward for their efforts. This reward is called an ommer reward and is calculated based on the number associated with the ommer block that they mined.

Parameters

state : Current account state. block_number : Position of the block within the chain. coinbase : Address of account which receives block reward and transaction fees. ommers : List of ommers mentioned in the current block.

631def process_transaction(
632    env: vm.Environment, tx: Transaction
633) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]:
634    """
635    Execute a transaction against the provided environment.
636
637    This function processes the actions needed to execute a transaction.
638    It decrements the sender's account after calculating the gas fee and
639    refunds them the proper amount after execution. Calling contracts,
640    deploying code, and incrementing nonces are all examples of actions that
641    happen within this function or from a call made within this function.
642
643    Accounts that are marked for deletion are processed and destroyed after
644    execution.
645
646    Parameters
647    ----------
648    env :
649        Environment for the Ethereum Virtual Machine.
650    tx :
651        Transaction to execute.
652
653    Returns
654    -------
655    gas_left : `ethereum.base_types.U256`
656        Remaining gas after execution.
657    logs : `Tuple[ethereum.fork_types.Log, ...]`
658        Logs generated during execution.
659    """
660    ensure(validate_transaction(tx), InvalidBlock)
661
662    sender = env.origin
663    sender_account = get_account(env.state, sender)
664    gas_fee = tx.gas * tx.gas_price
665    ensure(sender_account.nonce == tx.nonce, InvalidBlock)
666    ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
667    ensure(sender_account.code == bytearray(), InvalidBlock)
668
669    gas = tx.gas - calculate_intrinsic_cost(tx)
670    increment_nonce(env.state, sender)
671    sender_balance_after_gas_fee = sender_account.balance - gas_fee
672    set_account_balance(env.state, sender, sender_balance_after_gas_fee)
673
674    preaccessed_addresses = set()
675    preaccessed_storage_keys = set()
676    if isinstance(tx, AccessListTransaction):
677        for address, keys in tx.access_list:
678            preaccessed_addresses.add(address)
679            for key in keys:
680                preaccessed_storage_keys.add((address, key))
681
682    message = prepare_message(
683        sender,
684        tx.to,
685        tx.value,
686        tx.data,
687        gas,
688        env,
689        preaccessed_addresses=frozenset(preaccessed_addresses),
690        preaccessed_storage_keys=frozenset(preaccessed_storage_keys),
691    )
692
693    output = process_message_call(message, env)
694
695    gas_used = tx.gas - output.gas_left
696    gas_refund = min(gas_used // 2, output.refund_counter)
697    gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price
698    transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price
699    total_gas_used = gas_used - gas_refund
700
701    # refund gas
702    sender_balance_after_refund = (
703        get_account(env.state, sender).balance + gas_refund_amount
704    )
705    set_account_balance(env.state, sender, sender_balance_after_refund)
706
707    # transfer miner fees
708    coinbase_balance_after_mining_fee = (
709        get_account(env.state, env.coinbase).balance + transaction_fee
710    )
711    if coinbase_balance_after_mining_fee != 0:
712        set_account_balance(
713            env.state, env.coinbase, coinbase_balance_after_mining_fee
714        )
715    elif account_exists_and_is_empty(env.state, env.coinbase):
716        destroy_account(env.state, env.coinbase)
717
718    for address in output.accounts_to_delete:
719        destroy_account(env.state, address)
720
721    for address in output.touched_accounts:
722        if account_exists_and_is_empty(env.state, address):
723            destroy_account(env.state, address)
724
725    return total_gas_used, output.logs, output.error

Execute a transaction against the provided environment.

This function processes the actions needed to execute a transaction. It decrements the sender's account after calculating the gas fee and refunds them the proper amount after execution. Calling contracts, deploying code, and incrementing nonces are all examples of actions that happen within this function or from a call made within this function.

Accounts that are marked for deletion are processed and destroyed after execution.

Parameters

env : Environment for the Ethereum Virtual Machine. tx : Transaction to execute.

Returns

gas_left : ethereum.base_types.U256 Remaining gas after execution. logs : Tuple[ethereum.fork_types.Log, ...] Logs generated during execution.

def validate_transaction( tx: Union[ethereum.berlin.fork_types.LegacyTransaction, ethereum.berlin.fork_types.AccessListTransaction]) -> bool:
728def validate_transaction(tx: Transaction) -> bool:
729    """
730    Verifies a transaction.
731
732    The gas in a transaction gets used to pay for the intrinsic cost of
733    operations, therefore if there is insufficient gas then it would not
734    be possible to execute a transaction and it will be declared invalid.
735
736    Additionally, the nonce of a transaction must not equal or exceed the
737    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
738    In practice, defining the limit as ``2**64-1`` has no impact because
739    sending ``2**64-1`` transactions is improbable. It's not strictly
740    impossible though, ``2**64-1`` transactions is the entire capacity of the
741    Ethereum blockchain at 2022 gas limits for a little over 22 years.
742
743    Parameters
744    ----------
745    tx :
746        Transaction to validate.
747
748    Returns
749    -------
750    verified : `bool`
751        True if the transaction can be executed, or False otherwise.
752    """
753    return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1

Verifies a transaction.

The gas in a transaction gets used to pay for the intrinsic cost of operations, therefore if there is insufficient gas then it would not be possible to execute a transaction and it will be declared invalid.

Additionally, the nonce of a transaction must not equal or exceed the limit defined in EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>_. In practice, defining the limit as 2**64-1 has no impact because sending 2**64-1 transactions is improbable. It's not strictly impossible though, 2**64-1 transactions is the entire capacity of the Ethereum blockchain at 2022 gas limits for a little over 22 years.

Parameters

tx : Transaction to validate.

Returns

verified : bool True if the transaction can be executed, or False otherwise.

756def calculate_intrinsic_cost(tx: Transaction) -> Uint:
757    """
758    Calculates the gas that is charged before execution is started.
759
760    The intrinsic cost of the transaction is charged before execution has
761    begun. Functions/operations in the EVM cost money to execute so this
762    intrinsic cost is for the operations that need to be paid for as part of
763    the transaction. Data transfer, for example, is part of this intrinsic
764    cost. It costs ether to send data over the wire and that ether is
765    accounted for in the intrinsic cost calculated in this function. This
766    intrinsic cost must be calculated and paid for before execution in order
767    for all operations to be implemented.
768
769    Parameters
770    ----------
771    tx :
772        Transaction to compute the intrinsic cost of.
773
774    Returns
775    -------
776    verified : `ethereum.base_types.Uint`
777        The intrinsic cost of the transaction.
778    """
779    data_cost = 0
780
781    for byte in tx.data:
782        if byte == 0:
783            data_cost += TX_DATA_COST_PER_ZERO
784        else:
785            data_cost += TX_DATA_COST_PER_NON_ZERO
786
787    if tx.to == Bytes0(b""):
788        create_cost = TX_CREATE_COST
789    else:
790        create_cost = 0
791
792    access_list_cost = 0
793    if isinstance(tx, AccessListTransaction):
794        for _address, keys in tx.access_list:
795            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
796            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
797
798    return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost)

Calculates the gas that is charged before execution is started.

The intrinsic cost of the transaction is charged before execution has begun. Functions/operations in the EVM cost money to execute so this intrinsic cost is for the operations that need to be paid for as part of the transaction. Data transfer, for example, is part of this intrinsic cost. It costs ether to send data over the wire and that ether is accounted for in the intrinsic cost calculated in this function. This intrinsic cost must be calculated and paid for before execution in order for all operations to be implemented.

Parameters

tx : Transaction to compute the intrinsic cost of.

Returns

verified : ethereum.base_types.Uint The intrinsic cost of the transaction.

801def recover_sender(chain_id: U64, tx: Transaction) -> Address:
802    """
803    Extracts the sender address from a transaction.
804
805    The v, r, and s values are the three parts that make up the signature
806    of a transaction. In order to recover the sender of a transaction the two
807    components needed are the signature (``v``, ``r``, and ``s``) and the
808    signing hash of the transaction. The sender's public key can be obtained
809    with these two values and therefore the sender address can be retrieved.
810
811    Parameters
812    ----------
813    tx :
814        Transaction of interest.
815    chain_id :
816        ID of the executing chain.
817
818    Returns
819    -------
820    sender : `ethereum.fork_types.Address`
821        The address of the account that signed the transaction.
822    """
823    r, s = tx.r, tx.s
824
825    ensure(0 < r and r < SECP256K1N, InvalidBlock)
826    ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock)
827
828    if isinstance(tx, LegacyTransaction):
829        v = tx.v
830        if v == 27 or v == 28:
831            public_key = secp256k1_recover(
832                r, s, v - 27, signing_hash_pre155(tx)
833            )
834        else:
835            ensure(
836                v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock
837            )
838            public_key = secp256k1_recover(
839                r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
840            )
841    elif isinstance(tx, AccessListTransaction):
842        public_key = secp256k1_recover(
843            r, s, tx.y_parity, signing_hash_2930(tx)
844        )
845
846    return Address(keccak256(public_key)[12:32])

Extracts the sender address from a transaction.

The v, r, and s values are the three parts that make up the signature of a transaction. In order to recover the sender of a transaction the two components needed are the signature (v, r, and s) and the signing hash of the transaction. The sender's public key can be obtained with these two values and therefore the sender address can be retrieved.

Parameters

tx : Transaction of interest. chain_id : ID of the executing chain.

Returns

sender : ethereum.fork_types.Address The address of the account that signed the transaction.

849def signing_hash_pre155(tx: Transaction) -> Hash32:
850    """
851    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
852
853    Parameters
854    ----------
855    tx :
856        Transaction of interest.
857
858    Returns
859    -------
860    hash : `ethereum.crypto.hash.Hash32`
861        Hash of the transaction.
862    """
863    return keccak256(
864        rlp.encode(
865            (
866                tx.nonce,
867                tx.gas_price,
868                tx.gas,
869                tx.to,
870                tx.value,
871                tx.data,
872            )
873        )
874    )

Compute the hash of a transaction used in a legacy (pre EIP 155) signature.

Parameters

tx : Transaction of interest.

Returns

hash : ethereum.crypto.hash.Hash32 Hash of the transaction.

877def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32:
878    """
879    Compute the hash of a transaction used in a EIP 155 signature.
880
881    Parameters
882    ----------
883    tx :
884        Transaction of interest.
885    chain_id :
886        The id of the current chain.
887
888    Returns
889    -------
890    hash : `ethereum.crypto.hash.Hash32`
891        Hash of the transaction.
892    """
893    return keccak256(
894        rlp.encode(
895            (
896                tx.nonce,
897                tx.gas_price,
898                tx.gas,
899                tx.to,
900                tx.value,
901                tx.data,
902                chain_id,
903                Uint(0),
904                Uint(0),
905            )
906        )
907    )

Compute the hash of a transaction used in a EIP 155 signature.

Parameters

tx : Transaction of interest. chain_id : The id of the current chain.

Returns

hash : ethereum.crypto.hash.Hash32 Hash of the transaction.

910def signing_hash_2930(tx: AccessListTransaction) -> Hash32:
911    """
912    Compute the hash of a transaction used in a EIP 2930 signature.
913
914    Parameters
915    ----------
916    tx :
917        Transaction of interest.
918
919    Returns
920    -------
921    hash : `ethereum.crypto.hash.Hash32`
922        Hash of the transaction.
923    """
924    return keccak256(
925        b"\x01"
926        + rlp.encode(
927            (
928                tx.chain_id,
929                tx.nonce,
930                tx.gas_price,
931                tx.gas,
932                tx.to,
933                tx.value,
934                tx.data,
935                tx.access_list,
936            )
937        )
938    )

Compute the hash of a transaction used in a EIP 2930 signature.

Parameters

tx : Transaction of interest.

Returns

hash : ethereum.crypto.hash.Hash32 Hash of the transaction.

def compute_header_hash(header: ethereum.berlin.fork_types.Header) -> ethereum.base_types.Bytes32:
941def compute_header_hash(header: Header) -> Hash32:
942    """
943    Computes the hash of a block header.
944
945    The header hash of a block is the canonical hash that is used to refer
946    to a specific block and completely distinguishes a block from another.
947
948    ``keccak256`` is a function that produces a 256 bit hash of any input.
949    It also takes in any number of bytes as an input and produces a single
950    hash for them. A hash is a completely unique output for a single input.
951    So an input corresponds to one unique hash that can be used to identify
952    the input exactly.
953
954    Prior to using the ``keccak256`` hash function, the header must be
955    encoded using the Recursive-Length Prefix. See :ref:`rlp`.
956    RLP encoding the header converts it into a space-efficient format that
957    allows for easy transfer of data between nodes. The purpose of RLP is to
958    encode arbitrarily nested arrays of binary data, and RLP is the primary
959    encoding method used to serialize objects in Ethereum's execution layer.
960    The only purpose of RLP is to encode structure; encoding specific data
961    types (e.g. strings, floats) is left up to higher-order protocols.
962
963    Parameters
964    ----------
965    header :
966        Header of interest.
967
968    Returns
969    -------
970    hash : `ethereum.crypto.hash.Hash32`
971        Hash of the header.
972    """
973    return keccak256(rlp.encode(header))

Computes the hash of a block header.

The header hash of a block is the canonical hash that is used to refer to a specific block and completely distinguishes a block from another.

keccak256 is a function that produces a 256 bit hash of any input. It also takes in any number of bytes as an input and produces a single hash for them. A hash is a completely unique output for a single input. So an input corresponds to one unique hash that can be used to identify the input exactly.

Prior to using the keccak256 hash function, the header must be encoded using the Recursive-Length Prefix. See :ref:rlp. RLP encoding the header converts it into a space-efficient format that allows for easy transfer of data between nodes. The purpose of RLP is to encode arbitrarily nested arrays of binary data, and RLP is the primary encoding method used to serialize objects in Ethereum's execution layer. The only purpose of RLP is to encode structure; encoding specific data types (e.g. strings, floats) is left up to higher-order protocols.

Parameters

header : Header of interest.

Returns

hash : ethereum.crypto.hash.Hash32 Hash of the header.

def check_gas_limit( gas_limit: ethereum.base_types.Uint, parent_gas_limit: ethereum.base_types.Uint) -> bool:
 976def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool:
 977    """
 978    Validates the gas limit for a block.
 979
 980    The bounds of the gas limit, ``max_adjustment_delta``, is set as the
 981    quotient of the parent block's gas limit and the
 982    ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is
 983    passed through as a parameter is greater than or equal to the *sum* of
 984    the parent's gas and the adjustment delta then the limit for gas is too
 985    high and fails this function's check. Similarly, if the limit is less
 986    than or equal to the *difference* of the parent's gas and the adjustment
 987    delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's
 988    check fails because the gas limit doesn't allow for a sufficient or
 989    reasonable amount of gas to be used on a block.
 990
 991    Parameters
 992    ----------
 993    gas_limit :
 994        Gas limit to validate.
 995
 996    parent_gas_limit :
 997        Gas limit of the parent block.
 998
 999    Returns
1000    -------
1001    check : `bool`
1002        True if gas limit constraints are satisfied, False otherwise.
1003    """
1004    max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
1005    if gas_limit >= parent_gas_limit + max_adjustment_delta:
1006        return False
1007    if gas_limit <= parent_gas_limit - max_adjustment_delta:
1008        return False
1009    if gas_limit < GAS_LIMIT_MINIMUM:
1010        return False
1011
1012    return True

Validates the gas limit for a block.

The bounds of the gas limit, max_adjustment_delta, is set as the quotient of the parent block's gas limit and the GAS_LIMIT_ADJUSTMENT_FACTOR. Therefore, if the gas limit that is passed through as a parameter is greater than or equal to the sum of the parent's gas and the adjustment delta then the limit for gas is too high and fails this function's check. Similarly, if the limit is less than or equal to the difference of the parent's gas and the adjustment delta or the predefined GAS_LIMIT_MINIMUM then this function's check fails because the gas limit doesn't allow for a sufficient or reasonable amount of gas to be used on a block.

Parameters

gas_limit : Gas limit to validate.

parent_gas_limit : Gas limit of the parent block.

Returns

check : bool True if gas limit constraints are satisfied, False otherwise.

def calculate_block_difficulty( block_number: ethereum.base_types.Uint, block_timestamp: ethereum.base_types.U256, parent_timestamp: ethereum.base_types.U256, parent_difficulty: ethereum.base_types.Uint, parent_has_ommers: bool) -> ethereum.base_types.Uint:
1015def calculate_block_difficulty(
1016    block_number: Uint,
1017    block_timestamp: U256,
1018    parent_timestamp: U256,
1019    parent_difficulty: Uint,
1020    parent_has_ommers: bool,
1021) -> Uint:
1022    """
1023    Computes difficulty of a block using its header and parent header.
1024
1025    The difficulty is determined by the time the block was created after its
1026    parent. The ``offset`` is calculated using the parent block's difficulty,
1027    ``parent_difficulty``, and the timestamp between blocks. This offset is
1028    then added to the parent difficulty and is stored as the ``difficulty``
1029    variable. If the time between the block and its parent is too short, the
1030    offset will result in a positive number thus making the sum of
1031    ``parent_difficulty`` and ``offset`` to be a greater value in order to
1032    avoid mass forking. But, if the time is long enough, then the offset
1033    results in a negative value making the block less difficult than
1034    its parent.
1035
1036    The base standard for a block's difficulty is the predefined value
1037    set for the genesis block since it has no parent. So, a block
1038    can't be less difficult than the genesis block, therefore each block's
1039    difficulty is set to the maximum value between the calculated
1040    difficulty and the ``GENESIS_DIFFICULTY``.
1041
1042    Parameters
1043    ----------
1044    block_number :
1045        Block number of the block.
1046    block_timestamp :
1047        Timestamp of the block.
1048    parent_timestamp :
1049        Timestamp of the parent block.
1050    parent_difficulty :
1051        difficulty of the parent block.
1052    parent_has_ommers:
1053        does the parent have ommers.
1054
1055    Returns
1056    -------
1057    difficulty : `ethereum.base_types.Uint`
1058        Computed difficulty for a block.
1059    """
1060    offset = (
1061        int(parent_difficulty)
1062        // 2048
1063        * max(
1064            (2 if parent_has_ommers else 1)
1065            - int(block_timestamp - parent_timestamp) // 9,
1066            -99,
1067        )
1068    )
1069    difficulty = int(parent_difficulty) + offset
1070    # Historical Note: The difficulty bomb was not present in Ethereum at the
1071    # start of Frontier, but was added shortly after launch. However since the
1072    # bomb has no effect prior to block 200000 we pretend it existed from
1073    # genesis.
1074    # See https://github.com/ethereum/go-ethereum/pull/1588
1075    num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2
1076    if num_bomb_periods >= 0:
1077        difficulty += 2**num_bomb_periods
1078
1079    # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding
1080    # the bomb. This bug does not matter because the difficulty is always much
1081    # greater than `MINIMUM_DIFFICULTY` on Mainnet.
1082    return Uint(max(difficulty, MINIMUM_DIFFICULTY))

Computes difficulty of a block using its header and parent header.

The difficulty is determined by the time the block was created after its parent. The offset is calculated using the parent block's difficulty, parent_difficulty, and the timestamp between blocks. This offset is then added to the parent difficulty and is stored as the difficulty variable. If the time between the block and its parent is too short, the offset will result in a positive number thus making the sum of parent_difficulty and offset to be a greater value in order to avoid mass forking. But, if the time is long enough, then the offset results in a negative value making the block less difficult than its parent.

The base standard for a block's difficulty is the predefined value set for the genesis block since it has no parent. So, a block can't be less difficult than the genesis block, therefore each block's difficulty is set to the maximum value between the calculated difficulty and the GENESIS_DIFFICULTY.

Parameters

block_number : Block number of the block. block_timestamp : Timestamp of the block. parent_timestamp : Timestamp of the parent block. parent_difficulty : difficulty of the parent block. parent_has_ommers: does the parent have ommers.

Returns

difficulty : ethereum.base_types.Uint Computed difficulty for a block.