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

History and current state of the block chain.

def apply_fork( old: BlockChain) -> BlockChain:
76def apply_fork(old: BlockChain) -> BlockChain:
77    """
78    Transforms the state from the previous hard fork (`old`) into the block
79    chain object for this hard fork and returns it.
80
81    When forks need to implement an irregular state transition, this function
82    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
83    an example.
84
85    Parameters
86    ----------
87    old :
88        Previous block chain object.
89
90    Returns
91    -------
92    new : `BlockChain`
93        Upgraded block chain object for this hard fork.
94    """
95    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]:
 98def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]:
 99    """
100    Obtain the list of hashes of the previous 256 blocks in order of
101    increasing block number.
102
103    This function will return less hashes for the first 256 blocks.
104
105    The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,
106    therefore this function retrieves them.
107
108    Parameters
109    ----------
110    chain :
111        History and current state.
112
113    Returns
114    -------
115    recent_block_hashes : `List[Hash32]`
116        Hashes of the recent 256 blocks in order of increasing block number.
117    """
118    recent_blocks = chain.blocks[-255:]
119    # TODO: This function has not been tested rigorously
120    if len(recent_blocks) == 0:
121        return []
122
123    recent_block_hashes = []
124
125    for block in recent_blocks:
126        prev_block_hash = block.header.parent_hash
127        recent_block_hashes.append(prev_block_hash)
128
129    # We are computing the hash only for the most recent block and not for
130    # the rest of the blocks as they have successors which have the hash of
131    # the current block as parent hash.
132    most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header))
133    recent_block_hashes.append(most_recent_block_hash)
134
135    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.spurious_dragon.fork_types.Block) -> None:
138def state_transition(chain: BlockChain, block: Block) -> None:
139    """
140    Attempts to apply a block to an existing block chain.
141
142    All parts of the block's contents need to be verified before being added
143    to the chain. Blocks are verified by ensuring that the contents of the
144    block make logical sense with the contents of the parent block. The
145    information in the block's header must also match the corresponding
146    information in the block.
147
148    To implement Ethereum, in theory clients are only required to store the
149    most recent 255 blocks of the chain since as far as execution is
150    concerned, only those blocks are accessed. Practically, however, clients
151    should store more blocks to handle reorgs.
152
153    Parameters
154    ----------
155    chain :
156        History and current state.
157    block :
158        Block to apply to `chain`.
159    """
160    parent_header = chain.blocks[-1].header
161    validate_header(block.header, parent_header)
162    validate_ommers(block.ommers, block.header, chain)
163    (
164        gas_used,
165        transactions_root,
166        receipt_root,
167        block_logs_bloom,
168        state,
169    ) = apply_body(
170        chain.state,
171        get_last_256_block_hashes(chain),
172        block.header.coinbase,
173        block.header.number,
174        block.header.gas_limit,
175        block.header.timestamp,
176        block.header.difficulty,
177        block.transactions,
178        block.ommers,
179        chain.chain_id,
180    )
181    ensure(gas_used == block.header.gas_used, InvalidBlock)
182    ensure(transactions_root == block.header.transactions_root, InvalidBlock)
183    ensure(state_root(state) == block.header.state_root, InvalidBlock)
184    ensure(receipt_root == block.header.receipt_root, InvalidBlock)
185    ensure(block_logs_bloom == block.header.bloom, InvalidBlock)
186
187    chain.blocks.append(block)
188    if len(chain.blocks) > 255:
189        # Real clients have to store more blocks to deal with reorgs, but the
190        # protocol only requires the last 255
191        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.spurious_dragon.fork_types.Header, parent_header: ethereum.spurious_dragon.fork_types.Header) -> None:
194def validate_header(header: Header, parent_header: Header) -> None:
195    """
196    Verifies a block header.
197
198    In order to consider a block's header valid, the logic for the
199    quantities in the header should match the logic for the block itself.
200    For example the header timestamp should be greater than the block's parent
201    timestamp because the block was created *after* the parent block.
202    Additionally, the block's number should be directly following the parent
203    block's number since it is the next block in the sequence.
204
205    Parameters
206    ----------
207    header :
208        Header to check for correctness.
209    parent_header :
210        Parent Header of the header to check for correctness
211    """
212    ensure(header.timestamp > parent_header.timestamp, InvalidBlock)
213    ensure(header.number == parent_header.number + 1, InvalidBlock)
214    ensure(
215        check_gas_limit(header.gas_limit, parent_header.gas_limit),
216        InvalidBlock,
217    )
218    ensure(len(header.extra_data) <= 32, InvalidBlock)
219
220    block_difficulty = calculate_block_difficulty(
221        header.number,
222        header.timestamp,
223        parent_header.timestamp,
224        parent_header.difficulty,
225    )
226    ensure(header.difficulty == block_difficulty, InvalidBlock)
227
228    block_parent_hash = keccak256(rlp.encode(parent_header))
229    ensure(header.parent_hash == block_parent_hash, InvalidBlock)
230
231    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.spurious_dragon.fork_types.Header) -> ethereum.base_types.Bytes32:
234def generate_header_hash_for_pow(header: Header) -> Hash32:
235    """
236    Generate rlp hash of the header which is to be used for Proof-of-Work
237    verification.
238
239    In other words, the PoW artefacts `mix_digest` and `nonce` are ignored
240    while calculating this hash.
241
242    A particular PoW is valid for a single hash, that hash is computed by
243    this function. The `nonce` and `mix_digest` are omitted from this hash
244    because they are being changed by miners in their search for a sufficient
245    proof-of-work.
246
247    Parameters
248    ----------
249    header :
250        The header object for which the hash is to be generated.
251
252    Returns
253    -------
254    hash : `Hash32`
255        The PoW valid rlp hash of the passed in header.
256    """
257    header_data_without_pow_artefacts = [
258        header.parent_hash,
259        header.ommers_hash,
260        header.coinbase,
261        header.state_root,
262        header.transactions_root,
263        header.receipt_root,
264        header.bloom,
265        header.difficulty,
266        header.number,
267        header.gas_limit,
268        header.gas_used,
269        header.timestamp,
270        header.extra_data,
271    ]
272
273    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.spurious_dragon.fork_types.Header) -> None:
276def validate_proof_of_work(header: Header) -> None:
277    """
278    Validates the Proof of Work constraints.
279
280    In order to verify that a miner's proof-of-work is valid for a block, a
281    ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``
282    hash function. The mix digest is a hash of the header and the nonce that
283    is passed through and it confirms whether or not proof-of-work was done
284    on the correct block. The result is the actual hash value of the block.
285
286    Parameters
287    ----------
288    header :
289        Header of interest.
290    """
291    header_hash = generate_header_hash_for_pow(header)
292    # TODO: Memoize this somewhere and read from that data instead of
293    # calculating cache for every block validation.
294    cache = generate_cache(header.number)
295    mix_digest, result = hashimoto_light(
296        header_hash, header.nonce, cache, dataset_size(header.number)
297    )
298
299    ensure(mix_digest == header.mix_digest, InvalidBlock)
300    ensure(
301        Uint.from_be_bytes(result) <= (U256_CEIL_VALUE // header.difficulty),
302        InvalidBlock,
303    )

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.

306def check_transaction(
307    tx: Transaction,
308    gas_available: Uint,
309    chain_id: U64,
310) -> Address:
311    """
312    Check if the transaction is includable in the block.
313
314    Parameters
315    ----------
316    tx :
317        The transaction.
318    gas_available :
319        The gas remaining in the block.
320    chain_id :
321        The ID of the current chain.
322
323    Returns
324    -------
325    sender_address :
326        The sender of the transaction.
327
328    Raises
329    ------
330    InvalidBlock :
331        If the transaction is not includable.
332    """
333    ensure(tx.gas <= gas_available, InvalidBlock)
334    sender_address = recover_sender(chain_id, tx)
335
336    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.

339def make_receipt(
340    tx: Transaction,
341    post_state: Bytes32,
342    cumulative_gas_used: Uint,
343    logs: Tuple[Log, ...],
344) -> Receipt:
345    """
346    Make the receipt for a transaction that was executed.
347
348    Parameters
349    ----------
350    tx :
351        The executed transaction.
352    post_state :
353        The state root immediately after this transaction.
354    cumulative_gas_used :
355        The total gas used so far in the block after the transaction was
356        executed.
357    logs :
358        The logs produced by the transaction.
359
360    Returns
361    -------
362    receipt :
363        The receipt for the transaction.
364    """
365    receipt = Receipt(
366        post_state=post_state,
367        cumulative_gas_used=cumulative_gas_used,
368        bloom=logs_bloom(logs),
369        logs=logs,
370    )
371
372    return receipt

Make the receipt for a transaction that was executed.

Parameters

tx : The executed transaction. post_state : The state root immediately after this transaction. 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.

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

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.spurious_dragon.fork_types.Header, ...], block_header: ethereum.spurious_dragon.fork_types.Header, chain: BlockChain) -> None:
494def validate_ommers(
495    ommers: Tuple[Header, ...], block_header: Header, chain: BlockChain
496) -> None:
497    """
498    Validates the ommers mentioned in the block.
499
500    An ommer block is a block that wasn't canonically added to the
501    blockchain because it wasn't validated as fast as the canonical block
502    but was mined at the same time.
503
504    To be considered valid, the ommers must adhere to the rules defined in
505    the Ethereum protocol. The maximum amount of ommers is 2 per block and
506    there cannot be duplicate ommers in a block. Many of the other ommer
507    constraints are listed in the in-line comments of this function.
508
509    Parameters
510    ----------
511    ommers :
512        List of ommers mentioned in the current block.
513    block_header:
514        The header of current block.
515    chain :
516        History and current state.
517    """
518    block_hash = rlp.rlp_hash(block_header)
519
520    ensure(rlp.rlp_hash(ommers) == block_header.ommers_hash, InvalidBlock)
521
522    if len(ommers) == 0:
523        # Nothing to validate
524        return
525
526    # Check that each ommer satisfies the constraints of a header
527    for ommer in ommers:
528        ensure(1 <= ommer.number < block_header.number, InvalidBlock)
529        ommer_parent_header = chain.blocks[
530            -(block_header.number - ommer.number) - 1
531        ].header
532        validate_header(ommer, ommer_parent_header)
533
534    # Check that there can be only at most 2 ommers for a block.
535    ensure(len(ommers) <= 2, InvalidBlock)
536
537    ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers]
538    # Check that there are no duplicates in the ommers of current block
539    ensure(len(ommers_hashes) == len(set(ommers_hashes)), InvalidBlock)
540
541    recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + 1) :]
542    recent_canonical_block_hashes = {
543        rlp.rlp_hash(block.header) for block in recent_canonical_blocks
544    }
545    recent_ommers_hashes: Set[Hash32] = set()
546    for block in recent_canonical_blocks:
547        recent_ommers_hashes = recent_ommers_hashes.union(
548            {rlp.rlp_hash(ommer) for ommer in block.ommers}
549        )
550
551    for ommer_index, ommer in enumerate(ommers):
552        ommer_hash = ommers_hashes[ommer_index]
553        # The current block shouldn't be the ommer
554        ensure(ommer_hash != block_hash, InvalidBlock)
555
556        # Ommer shouldn't be one of the recent canonical blocks
557        ensure(ommer_hash not in recent_canonical_block_hashes, InvalidBlock)
558
559        # Ommer shouldn't be one of the uncles mentioned in the recent
560        # canonical blocks
561        ensure(ommer_hash not in recent_ommers_hashes, InvalidBlock)
562
563        # Ommer age with respect to the current block. For example, an age of
564        # 1 indicates that the ommer is a sibling of previous block.
565        ommer_age = block_header.number - ommer.number
566        ensure(1 <= ommer_age <= MAX_OMMER_DEPTH, InvalidBlock)
567
568        ensure(
569            ommer.parent_hash in recent_canonical_block_hashes, InvalidBlock
570        )
571        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.spurious_dragon.state.State, block_number: ethereum.base_types.Uint, coinbase: ethereum.base_types.Bytes20, ommers: Tuple[ethereum.spurious_dragon.fork_types.Header, ...]) -> None:
574def pay_rewards(
575    state: State,
576    block_number: Uint,
577    coinbase: Address,
578    ommers: Tuple[Header, ...],
579) -> None:
580    """
581    Pay rewards to the block miner as well as the ommers miners.
582
583    The miner of the canonical block is rewarded with the predetermined
584    block reward, ``BLOCK_REWARD``, plus a variable award based off of the
585    number of ommer blocks that were mined around the same time, and included
586    in the canonical block's header. An ommer block is a block that wasn't
587    added to the canonical blockchain because it wasn't validated as fast as
588    the accepted block but was mined at the same time. Although not all blocks
589    that are mined are added to the canonical chain, miners are still paid a
590    reward for their efforts. This reward is called an ommer reward and is
591    calculated based on the number associated with the ommer block that they
592    mined.
593
594    Parameters
595    ----------
596    state :
597        Current account state.
598    block_number :
599        Position of the block within the chain.
600    coinbase :
601        Address of account which receives block reward and transaction fees.
602    ommers :
603        List of ommers mentioned in the current block.
604    """
605    miner_reward = BLOCK_REWARD + (len(ommers) * (BLOCK_REWARD // 32))
606    create_ether(state, coinbase, miner_reward)
607
608    for ommer in ommers:
609        # Ommer age with respect to the current block.
610        ommer_age = U256(block_number - ommer.number)
611        ommer_miner_reward = ((8 - ommer_age) * BLOCK_REWARD) // 8
612        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.

615def process_transaction(
616    env: vm.Environment, tx: Transaction
617) -> Tuple[Uint, Tuple[Log, ...]]:
618    """
619    Execute a transaction against the provided environment.
620
621    This function processes the actions needed to execute a transaction.
622    It decrements the sender's account after calculating the gas fee and
623    refunds them the proper amount after execution. Calling contracts,
624    deploying code, and incrementing nonces are all examples of actions that
625    happen within this function or from a call made within this function.
626
627    Accounts that are marked for deletion are processed and destroyed after
628    execution.
629
630    Parameters
631    ----------
632    env :
633        Environment for the Ethereum Virtual Machine.
634    tx :
635        Transaction to execute.
636
637    Returns
638    -------
639    gas_left : `ethereum.base_types.U256`
640        Remaining gas after execution.
641    logs : `Tuple[ethereum.fork_types.Log, ...]`
642        Logs generated during execution.
643    """
644    ensure(validate_transaction(tx), InvalidBlock)
645
646    sender = env.origin
647    sender_account = get_account(env.state, sender)
648    gas_fee = tx.gas * tx.gas_price
649    ensure(sender_account.nonce == tx.nonce, InvalidBlock)
650    ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
651    ensure(sender_account.code == bytearray(), InvalidBlock)
652
653    gas = tx.gas - calculate_intrinsic_cost(tx)
654    increment_nonce(env.state, sender)
655    sender_balance_after_gas_fee = sender_account.balance - gas_fee
656    set_account_balance(env.state, sender, sender_balance_after_gas_fee)
657
658    message = prepare_message(
659        sender,
660        tx.to,
661        tx.value,
662        tx.data,
663        gas,
664        env,
665    )
666
667    output = process_message_call(message, env)
668
669    gas_used = tx.gas - output.gas_left
670    gas_refund = min(gas_used // 2, output.refund_counter)
671    gas_refund_amount = (output.gas_left + gas_refund) * tx.gas_price
672    transaction_fee = (tx.gas - output.gas_left - gas_refund) * tx.gas_price
673    total_gas_used = gas_used - gas_refund
674
675    # refund gas
676    sender_balance_after_refund = (
677        get_account(env.state, sender).balance + gas_refund_amount
678    )
679    set_account_balance(env.state, sender, sender_balance_after_refund)
680
681    # transfer miner fees
682    coinbase_balance_after_mining_fee = (
683        get_account(env.state, env.coinbase).balance + transaction_fee
684    )
685    if coinbase_balance_after_mining_fee != 0:
686        set_account_balance(
687            env.state, env.coinbase, coinbase_balance_after_mining_fee
688        )
689    elif account_exists_and_is_empty(env.state, env.coinbase):
690        destroy_account(env.state, env.coinbase)
691
692    for address in output.accounts_to_delete:
693        destroy_account(env.state, address)
694
695    for address in output.touched_accounts:
696        if account_exists_and_is_empty(env.state, address):
697            destroy_account(env.state, address)
698
699    return total_gas_used, output.logs

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: ethereum.spurious_dragon.fork_types.Transaction) -> bool:
702def validate_transaction(tx: Transaction) -> bool:
703    """
704    Verifies a transaction.
705
706    The gas in a transaction gets used to pay for the intrinsic cost of
707    operations, therefore if there is insufficient gas then it would not
708    be possible to execute a transaction and it will be declared invalid.
709
710    Additionally, the nonce of a transaction must not equal or exceed the
711    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
712    In practice, defining the limit as ``2**64-1`` has no impact because
713    sending ``2**64-1`` transactions is improbable. It's not strictly
714    impossible though, ``2**64-1`` transactions is the entire capacity of the
715    Ethereum blockchain at 2022 gas limits for a little over 22 years.
716
717    Parameters
718    ----------
719    tx :
720        Transaction to validate.
721
722    Returns
723    -------
724    verified : `bool`
725        True if the transaction can be executed, or False otherwise.
726    """
727    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.

def calculate_intrinsic_cost( tx: ethereum.spurious_dragon.fork_types.Transaction) -> ethereum.base_types.Uint:
730def calculate_intrinsic_cost(tx: Transaction) -> Uint:
731    """
732    Calculates the gas that is charged before execution is started.
733
734    The intrinsic cost of the transaction is charged before execution has
735    begun. Functions/operations in the EVM cost money to execute so this
736    intrinsic cost is for the operations that need to be paid for as part of
737    the transaction. Data transfer, for example, is part of this intrinsic
738    cost. It costs ether to send data over the wire and that ether is
739    accounted for in the intrinsic cost calculated in this function. This
740    intrinsic cost must be calculated and paid for before execution in order
741    for all operations to be implemented.
742
743    Parameters
744    ----------
745    tx :
746        Transaction to compute the intrinsic cost of.
747
748    Returns
749    -------
750    verified : `ethereum.base_types.Uint`
751        The intrinsic cost of the transaction.
752    """
753    data_cost = 0
754
755    for byte in tx.data:
756        if byte == 0:
757            data_cost += TX_DATA_COST_PER_ZERO
758        else:
759            data_cost += TX_DATA_COST_PER_NON_ZERO
760
761    if tx.to == Bytes0(b""):
762        create_cost = TX_CREATE_COST
763    else:
764        create_cost = 0
765
766    return Uint(TX_BASE_COST + data_cost + create_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.

769def recover_sender(chain_id: U64, tx: Transaction) -> Address:
770    """
771    Extracts the sender address from a transaction.
772
773    The v, r, and s values are the three parts that make up the signature
774    of a transaction. In order to recover the sender of a transaction the two
775    components needed are the signature (``v``, ``r``, and ``s``) and the
776    signing hash of the transaction. The sender's public key can be obtained
777    with these two values and therefore the sender address can be retrieved.
778
779    Parameters
780    ----------
781    tx :
782        Transaction of interest.
783    chain_id :
784        ID of the executing chain.
785
786    Returns
787    -------
788    sender : `ethereum.fork_types.Address`
789        The address of the account that signed the transaction.
790    """
791    v, r, s = tx.v, tx.r, tx.s
792
793    ensure(0 < r and r < SECP256K1N, InvalidBlock)
794    ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock)
795
796    if v == 27 or v == 28:
797        public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx))
798    else:
799        ensure(v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock)
800        public_key = secp256k1_recover(
801            r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
802        )
803    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.

806def signing_hash_pre155(tx: Transaction) -> Hash32:
807    """
808    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
809
810    Parameters
811    ----------
812    tx :
813        Transaction of interest.
814
815    Returns
816    -------
817    hash : `ethereum.crypto.hash.Hash32`
818        Hash of the transaction.
819    """
820    return keccak256(
821        rlp.encode(
822            (
823                tx.nonce,
824                tx.gas_price,
825                tx.gas,
826                tx.to,
827                tx.value,
828                tx.data,
829            )
830        )
831    )

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.

834def signing_hash_155(tx: Transaction, chain_id: U64) -> Hash32:
835    """
836    Compute the hash of a transaction used in a EIP 155 signature.
837
838    Parameters
839    ----------
840    tx :
841        Transaction of interest.
842    chain_id :
843        The id of the current chain.
844
845    Returns
846    -------
847    hash : `ethereum.crypto.hash.Hash32`
848        Hash of the transaction.
849    """
850    return keccak256(
851        rlp.encode(
852            (
853                tx.nonce,
854                tx.gas_price,
855                tx.gas,
856                tx.to,
857                tx.value,
858                tx.data,
859                chain_id,
860                Uint(0),
861                Uint(0),
862            )
863        )
864    )

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.

def compute_header_hash( header: ethereum.spurious_dragon.fork_types.Header) -> ethereum.base_types.Bytes32:
867def compute_header_hash(header: Header) -> Hash32:
868    """
869    Computes the hash of a block header.
870
871    The header hash of a block is the canonical hash that is used to refer
872    to a specific block and completely distinguishes a block from another.
873
874    ``keccak256`` is a function that produces a 256 bit hash of any input.
875    It also takes in any number of bytes as an input and produces a single
876    hash for them. A hash is a completely unique output for a single input.
877    So an input corresponds to one unique hash that can be used to identify
878    the input exactly.
879
880    Prior to using the ``keccak256`` hash function, the header must be
881    encoded using the Recursive-Length Prefix. See :ref:`rlp`.
882    RLP encoding the header converts it into a space-efficient format that
883    allows for easy transfer of data between nodes. The purpose of RLP is to
884    encode arbitrarily nested arrays of binary data, and RLP is the primary
885    encoding method used to serialize objects in Ethereum's execution layer.
886    The only purpose of RLP is to encode structure; encoding specific data
887    types (e.g. strings, floats) is left up to higher-order protocols.
888
889    Parameters
890    ----------
891    header :
892        Header of interest.
893
894    Returns
895    -------
896    hash : `ethereum.crypto.hash.Hash32`
897        Hash of the header.
898    """
899    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:
902def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool:
903    """
904    Validates the gas limit for a block.
905
906    The bounds of the gas limit, ``max_adjustment_delta``, is set as the
907    quotient of the parent block's gas limit and the
908    ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is
909    passed through as a parameter is greater than or equal to the *sum* of
910    the parent's gas and the adjustment delta then the limit for gas is too
911    high and fails this function's check. Similarly, if the limit is less
912    than or equal to the *difference* of the parent's gas and the adjustment
913    delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's
914    check fails because the gas limit doesn't allow for a sufficient or
915    reasonable amount of gas to be used on a block.
916
917    Parameters
918    ----------
919    gas_limit :
920        Gas limit to validate.
921
922    parent_gas_limit :
923        Gas limit of the parent block.
924
925    Returns
926    -------
927    check : `bool`
928        True if gas limit constraints are satisfied, False otherwise.
929    """
930    max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
931    if gas_limit >= parent_gas_limit + max_adjustment_delta:
932        return False
933    if gas_limit <= parent_gas_limit - max_adjustment_delta:
934        return False
935    if gas_limit < GAS_LIMIT_MINIMUM:
936        return False
937
938    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) -> ethereum.base_types.Uint:
 941def calculate_block_difficulty(
 942    block_number: Uint,
 943    block_timestamp: U256,
 944    parent_timestamp: U256,
 945    parent_difficulty: Uint,
 946) -> Uint:
 947    """
 948    Computes difficulty of a block using its header and parent header.
 949
 950    The difficulty is determined by the time the block was created after its
 951    parent. The ``offset`` is calculated using the parent block's difficulty,
 952    ``parent_difficulty``, and the timestamp between blocks. This offset is
 953    then added to the parent difficulty and is stored as the ``difficulty``
 954    variable. If the time between the block and its parent is too short, the
 955    offset will result in a positive number thus making the sum of
 956    ``parent_difficulty`` and ``offset`` to be a greater value in order to
 957    avoid mass forking. But, if the time is long enough, then the offset
 958    results in a negative value making the block less difficult than
 959    its parent.
 960
 961    The base standard for a block's difficulty is the predefined value
 962    set for the genesis block since it has no parent. So, a block
 963    can't be less difficult than the genesis block, therefore each block's
 964    difficulty is set to the maximum value between the calculated
 965    difficulty and the ``GENESIS_DIFFICULTY``.
 966
 967    Parameters
 968    ----------
 969    block_number :
 970        Block number of the block.
 971    block_timestamp :
 972        Timestamp of the block.
 973    parent_timestamp :
 974        Timestamp of the parent block.
 975    parent_difficulty :
 976        difficulty of the parent block.
 977
 978    Returns
 979    -------
 980    difficulty : `ethereum.base_types.Uint`
 981        Computed difficulty for a block.
 982    """
 983    offset = (
 984        int(parent_difficulty)
 985        // 2048
 986        * max(1 - int(block_timestamp - parent_timestamp) // 10, -99)
 987    )
 988    difficulty = int(parent_difficulty) + offset
 989    # Historical Note: The difficulty bomb was not present in Ethereum at the
 990    # start of Frontier, but was added shortly after launch. However since the
 991    # bomb has no effect prior to block 200000 we pretend it existed from
 992    # genesis.
 993    # See https://github.com/ethereum/go-ethereum/pull/1588
 994    num_bomb_periods = (int(block_number) // 100000) - 2
 995    if num_bomb_periods >= 0:
 996        difficulty += 2**num_bomb_periods
 997
 998    # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding
 999    # the bomb. This bug does not matter because the difficulty is always much
1000    # greater than `MINIMUM_DIFFICULTY` on Mainnet.
1001    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.

Returns

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