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

History and current state of the block chain.

def apply_fork(old: BlockChain) -> BlockChain:
 81def apply_fork(old: BlockChain) -> BlockChain:
 82    """
 83    Transforms the state from the previous hard fork (`old`) into the block
 84    chain object for this hard fork and returns it.
 85
 86    When forks need to implement an irregular state transition, this function
 87    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
 88    an example.
 89
 90    Parameters
 91    ----------
 92    old :
 93        Previous block chain object.
 94
 95    Returns
 96    -------
 97    new : `BlockChain`
 98        Upgraded block chain object for this hard fork.
 99    """
100    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]:
103def get_last_256_block_hashes(chain: BlockChain) -> List[Hash32]:
104    """
105    Obtain the list of hashes of the previous 256 blocks in order of
106    increasing block number.
107
108    This function will return less hashes for the first 256 blocks.
109
110    The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,
111    therefore this function retrieves them.
112
113    Parameters
114    ----------
115    chain :
116        History and current state.
117
118    Returns
119    -------
120    recent_block_hashes : `List[Hash32]`
121        Hashes of the recent 256 blocks in order of increasing block number.
122    """
123    recent_blocks = chain.blocks[-255:]
124    # TODO: This function has not been tested rigorously
125    if len(recent_blocks) == 0:
126        return []
127
128    recent_block_hashes = []
129
130    for block in recent_blocks:
131        prev_block_hash = block.header.parent_hash
132        recent_block_hashes.append(prev_block_hash)
133
134    # We are computing the hash only for the most recent block and not for
135    # the rest of the blocks as they have successors which have the hash of
136    # the current block as parent hash.
137    most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header))
138    recent_block_hashes.append(most_recent_block_hash)
139
140    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.paris.fork_types.Block) -> None:
143def state_transition(chain: BlockChain, block: Block) -> None:
144    """
145    Attempts to apply a block to an existing block chain.
146
147    All parts of the block's contents need to be verified before being added
148    to the chain. Blocks are verified by ensuring that the contents of the
149    block make logical sense with the contents of the parent block. The
150    information in the block's header must also match the corresponding
151    information in the block.
152
153    To implement Ethereum, in theory clients are only required to store the
154    most recent 255 blocks of the chain since as far as execution is
155    concerned, only those blocks are accessed. Practically, however, clients
156    should store more blocks to handle reorgs.
157
158    Parameters
159    ----------
160    chain :
161        History and current state.
162    block :
163        Block to apply to `chain`.
164    """
165    parent_header = chain.blocks[-1].header
166    validate_header(block.header, parent_header)
167    ensure(block.ommers == (), InvalidBlock)
168    (
169        gas_used,
170        transactions_root,
171        receipt_root,
172        block_logs_bloom,
173        state,
174    ) = apply_body(
175        chain.state,
176        get_last_256_block_hashes(chain),
177        block.header.coinbase,
178        block.header.number,
179        block.header.base_fee_per_gas,
180        block.header.gas_limit,
181        block.header.timestamp,
182        block.header.prev_randao,
183        block.transactions,
184        chain.chain_id,
185    )
186    ensure(gas_used == block.header.gas_used, InvalidBlock)
187    ensure(transactions_root == block.header.transactions_root, InvalidBlock)
188    ensure(state_root(state) == block.header.state_root, InvalidBlock)
189    ensure(receipt_root == block.header.receipt_root, InvalidBlock)
190    ensure(block_logs_bloom == block.header.bloom, InvalidBlock)
191
192    chain.blocks.append(block)
193    if len(chain.blocks) > 255:
194        # Real clients have to store more blocks to deal with reorgs, but the
195        # protocol only requires the last 255
196        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 calculate_base_fee_per_gas( block_gas_limit: ethereum.base_types.Uint, parent_gas_limit: ethereum.base_types.Uint, parent_gas_used: ethereum.base_types.Uint, parent_base_fee_per_gas: ethereum.base_types.Uint) -> ethereum.base_types.Uint:
199def calculate_base_fee_per_gas(
200    block_gas_limit: Uint,
201    parent_gas_limit: Uint,
202    parent_gas_used: Uint,
203    parent_base_fee_per_gas: Uint,
204) -> Uint:
205    """
206    Calculates the base fee per gas for the block.
207
208    Parameters
209    ----------
210    block_gas_limit :
211        Gas limit of the block for which the base fee is being calculated.
212    parent_gas_limit :
213        Gas limit of the parent block.
214    parent_gas_used :
215        Gas used in the parent block.
216    parent_base_fee_per_gas :
217        Base fee per gas of the parent block.
218
219    Returns
220    -------
221    base_fee_per_gas : `Uint`
222        Base fee per gas for the block.
223    """
224    parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER
225
226    ensure(
227        check_gas_limit(block_gas_limit, parent_gas_limit),
228        InvalidBlock,
229    )
230
231    if parent_gas_used == parent_gas_target:
232        expected_base_fee_per_gas = parent_base_fee_per_gas
233    elif parent_gas_used > parent_gas_target:
234        gas_used_delta = parent_gas_used - parent_gas_target
235
236        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
237        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
238
239        base_fee_per_gas_delta = max(
240            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR,
241            1,
242        )
243
244        expected_base_fee_per_gas = (
245            parent_base_fee_per_gas + base_fee_per_gas_delta
246        )
247    else:
248        gas_used_delta = parent_gas_target - parent_gas_used
249
250        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
251        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
252
253        base_fee_per_gas_delta = (
254            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR
255        )
256
257        expected_base_fee_per_gas = (
258            parent_base_fee_per_gas - base_fee_per_gas_delta
259        )
260
261    return Uint(expected_base_fee_per_gas)

Calculates the base fee per gas for the block.

Parameters

block_gas_limit : Gas limit of the block for which the base fee is being calculated. parent_gas_limit : Gas limit of the parent block. parent_gas_used : Gas used in the parent block. parent_base_fee_per_gas : Base fee per gas of the parent block.

Returns

base_fee_per_gas : Uint Base fee per gas for the block.

def validate_header( header: ethereum.paris.fork_types.Header, parent_header: ethereum.paris.fork_types.Header) -> None:
264def validate_header(header: Header, parent_header: Header) -> None:
265    """
266    Verifies a block header.
267
268    In order to consider a block's header valid, the logic for the
269    quantities in the header should match the logic for the block itself.
270    For example the header timestamp should be greater than the block's parent
271    timestamp because the block was created *after* the parent block.
272    Additionally, the block's number should be directly following the parent
273    block's number since it is the next block in the sequence.
274
275    Parameters
276    ----------
277    header :
278        Header to check for correctness.
279    parent_header :
280        Parent Header of the header to check for correctness
281    """
282    ensure(header.gas_used <= header.gas_limit, InvalidBlock)
283
284    expected_base_fee_per_gas = calculate_base_fee_per_gas(
285        header.gas_limit,
286        parent_header.gas_limit,
287        parent_header.gas_used,
288        parent_header.base_fee_per_gas,
289    )
290
291    ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock)
292
293    ensure(header.timestamp > parent_header.timestamp, InvalidBlock)
294    ensure(header.number == parent_header.number + 1, InvalidBlock)
295    ensure(len(header.extra_data) <= 32, InvalidBlock)
296
297    ensure(header.difficulty == 0, InvalidBlock)
298    ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock)
299    ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock)
300
301    block_parent_hash = keccak256(rlp.encode(parent_header))
302    ensure(header.parent_hash == block_parent_hash, InvalidBlock)

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

305def check_transaction(
306    tx: Transaction,
307    base_fee_per_gas: Uint,
308    gas_available: Uint,
309    chain_id: U64,
310) -> Tuple[Address, Uint]:
311    """
312    Check if the transaction is includable in the block.
313
314    Parameters
315    ----------
316    tx :
317        The transaction.
318    base_fee_per_gas :
319        The block base fee.
320    gas_available :
321        The gas remaining in the block.
322    chain_id :
323        The ID of the current chain.
324
325    Returns
326    -------
327    sender_address :
328        The sender of the transaction.
329    effective_gas_price :
330        The price to charge for gas when the transaction is executed.
331
332    Raises
333    ------
334    InvalidBlock :
335        If the transaction is not includable.
336    """
337    ensure(tx.gas <= gas_available, InvalidBlock)
338    sender_address = recover_sender(chain_id, tx)
339
340    if isinstance(tx, FeeMarketTransaction):
341        ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock)
342        ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock)
343
344        priority_fee_per_gas = min(
345            tx.max_priority_fee_per_gas,
346            tx.max_fee_per_gas - base_fee_per_gas,
347        )
348        effective_gas_price = priority_fee_per_gas + base_fee_per_gas
349    else:
350        ensure(tx.gas_price >= base_fee_per_gas, InvalidBlock)
351        effective_gas_price = tx.gas_price
352
353    return sender_address, effective_gas_price

Check if the transaction is includable in the block.

Parameters

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

Returns

sender_address : The sender of the transaction. effective_gas_price : The price to charge for gas when the transaction is executed.

Raises

InvalidBlock : If the transaction is not includable.

356def make_receipt(
357    tx: Transaction,
358    error: Optional[Exception],
359    cumulative_gas_used: Uint,
360    logs: Tuple[Log, ...],
361) -> Union[Bytes, Receipt]:
362    """
363    Make the receipt for a transaction that was executed.
364
365    Parameters
366    ----------
367    tx :
368        The executed transaction.
369    error :
370        The error from the execution if any.
371    cumulative_gas_used :
372        The total gas used so far in the block after the transaction was
373        executed.
374    logs :
375        The logs produced by the transaction.
376
377    Returns
378    -------
379    receipt :
380        The receipt for the transaction.
381    """
382    receipt = Receipt(
383        succeeded=error is None,
384        cumulative_gas_used=cumulative_gas_used,
385        bloom=logs_bloom(logs),
386        logs=logs,
387    )
388
389    if isinstance(tx, AccessListTransaction):
390        return b"\x01" + rlp.encode(receipt)
391    elif isinstance(tx, FeeMarketTransaction):
392        return b"\x02" + rlp.encode(receipt)
393    else:
394        return receipt

Make the receipt for a transaction that was executed.

Parameters

tx : The executed transaction. error : The error from the execution 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.

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

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. base_fee_per_gas : Base fee per gas of within the block. 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. prev_randao : The previous randao from the beacon chain. 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.

522def process_transaction(
523    env: vm.Environment, tx: Transaction
524) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]:
525    """
526    Execute a transaction against the provided environment.
527
528    This function processes the actions needed to execute a transaction.
529    It decrements the sender's account after calculating the gas fee and
530    refunds them the proper amount after execution. Calling contracts,
531    deploying code, and incrementing nonces are all examples of actions that
532    happen within this function or from a call made within this function.
533
534    Accounts that are marked for deletion are processed and destroyed after
535    execution.
536
537    Parameters
538    ----------
539    env :
540        Environment for the Ethereum Virtual Machine.
541    tx :
542        Transaction to execute.
543
544    Returns
545    -------
546    gas_left : `ethereum.base_types.U256`
547        Remaining gas after execution.
548    logs : `Tuple[ethereum.fork_types.Log, ...]`
549        Logs generated during execution.
550    """
551    ensure(validate_transaction(tx), InvalidBlock)
552
553    sender = env.origin
554    sender_account = get_account(env.state, sender)
555
556    if isinstance(tx, FeeMarketTransaction):
557        max_gas_fee = tx.gas * tx.max_fee_per_gas
558    else:
559        max_gas_fee = tx.gas * tx.gas_price
560
561    ensure(sender_account.nonce == tx.nonce, InvalidBlock)
562    ensure(sender_account.balance >= max_gas_fee + tx.value, InvalidBlock)
563    ensure(sender_account.code == bytearray(), InvalidBlock)
564
565    effective_gas_fee = tx.gas * env.gas_price
566
567    gas = tx.gas - calculate_intrinsic_cost(tx)
568    increment_nonce(env.state, sender)
569
570    sender_balance_after_gas_fee = sender_account.balance - effective_gas_fee
571    set_account_balance(env.state, sender, sender_balance_after_gas_fee)
572
573    preaccessed_addresses = set()
574    preaccessed_storage_keys = set()
575    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
576        for address, keys in tx.access_list:
577            preaccessed_addresses.add(address)
578            for key in keys:
579                preaccessed_storage_keys.add((address, key))
580
581    message = prepare_message(
582        sender,
583        tx.to,
584        tx.value,
585        tx.data,
586        gas,
587        env,
588        preaccessed_addresses=frozenset(preaccessed_addresses),
589        preaccessed_storage_keys=frozenset(preaccessed_storage_keys),
590    )
591
592    output = process_message_call(message, env)
593
594    gas_used = tx.gas - output.gas_left
595    gas_refund = min(gas_used // 5, output.refund_counter)
596    gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price
597
598    # For non-1559 transactions env.gas_price == tx.gas_price
599    priority_fee_per_gas = env.gas_price - env.base_fee_per_gas
600    transaction_fee = (
601        tx.gas - output.gas_left - gas_refund
602    ) * priority_fee_per_gas
603
604    total_gas_used = gas_used - gas_refund
605
606    # refund gas
607    sender_balance_after_refund = (
608        get_account(env.state, sender).balance + gas_refund_amount
609    )
610    set_account_balance(env.state, sender, sender_balance_after_refund)
611
612    # transfer miner fees
613    coinbase_balance_after_mining_fee = (
614        get_account(env.state, env.coinbase).balance + transaction_fee
615    )
616    if coinbase_balance_after_mining_fee != 0:
617        set_account_balance(
618            env.state, env.coinbase, coinbase_balance_after_mining_fee
619        )
620    elif account_exists_and_is_empty(env.state, env.coinbase):
621        destroy_account(env.state, env.coinbase)
622
623    for address in output.accounts_to_delete:
624        destroy_account(env.state, address)
625
626    for address in output.touched_accounts:
627        if account_exists_and_is_empty(env.state, address):
628            destroy_account(env.state, address)
629
630    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.

633def validate_transaction(tx: Transaction) -> bool:
634    """
635    Verifies a transaction.
636
637    The gas in a transaction gets used to pay for the intrinsic cost of
638    operations, therefore if there is insufficient gas then it would not
639    be possible to execute a transaction and it will be declared invalid.
640
641    Additionally, the nonce of a transaction must not equal or exceed the
642    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
643    In practice, defining the limit as ``2**64-1`` has no impact because
644    sending ``2**64-1`` transactions is improbable. It's not strictly
645    impossible though, ``2**64-1`` transactions is the entire capacity of the
646    Ethereum blockchain at 2022 gas limits for a little over 22 years.
647
648    Parameters
649    ----------
650    tx :
651        Transaction to validate.
652
653    Returns
654    -------
655    verified : `bool`
656        True if the transaction can be executed, or False otherwise.
657    """
658    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.

661def calculate_intrinsic_cost(tx: Transaction) -> Uint:
662    """
663    Calculates the gas that is charged before execution is started.
664
665    The intrinsic cost of the transaction is charged before execution has
666    begun. Functions/operations in the EVM cost money to execute so this
667    intrinsic cost is for the operations that need to be paid for as part of
668    the transaction. Data transfer, for example, is part of this intrinsic
669    cost. It costs ether to send data over the wire and that ether is
670    accounted for in the intrinsic cost calculated in this function. This
671    intrinsic cost must be calculated and paid for before execution in order
672    for all operations to be implemented.
673
674    Parameters
675    ----------
676    tx :
677        Transaction to compute the intrinsic cost of.
678
679    Returns
680    -------
681    verified : `ethereum.base_types.Uint`
682        The intrinsic cost of the transaction.
683    """
684    data_cost = 0
685
686    for byte in tx.data:
687        if byte == 0:
688            data_cost += TX_DATA_COST_PER_ZERO
689        else:
690            data_cost += TX_DATA_COST_PER_NON_ZERO
691
692    if tx.to == Bytes0(b""):
693        create_cost = TX_CREATE_COST
694    else:
695        create_cost = 0
696
697    access_list_cost = 0
698    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
699        for _address, keys in tx.access_list:
700            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
701            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
702
703    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.

706def recover_sender(chain_id: U64, tx: Transaction) -> Address:
707    """
708    Extracts the sender address from a transaction.
709
710    The v, r, and s values are the three parts that make up the signature
711    of a transaction. In order to recover the sender of a transaction the two
712    components needed are the signature (``v``, ``r``, and ``s``) and the
713    signing hash of the transaction. The sender's public key can be obtained
714    with these two values and therefore the sender address can be retrieved.
715
716    Parameters
717    ----------
718    tx :
719        Transaction of interest.
720    chain_id :
721        ID of the executing chain.
722
723    Returns
724    -------
725    sender : `ethereum.fork_types.Address`
726        The address of the account that signed the transaction.
727    """
728    r, s = tx.r, tx.s
729
730    ensure(0 < r and r < SECP256K1N, InvalidBlock)
731    ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock)
732
733    if isinstance(tx, LegacyTransaction):
734        v = tx.v
735        if v == 27 or v == 28:
736            public_key = secp256k1_recover(
737                r, s, v - 27, signing_hash_pre155(tx)
738            )
739        else:
740            ensure(
741                v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock
742            )
743            public_key = secp256k1_recover(
744                r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
745            )
746    elif isinstance(tx, AccessListTransaction):
747        public_key = secp256k1_recover(
748            r, s, tx.y_parity, signing_hash_2930(tx)
749        )
750    elif isinstance(tx, FeeMarketTransaction):
751        public_key = secp256k1_recover(
752            r, s, tx.y_parity, signing_hash_1559(tx)
753        )
754
755    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.

def signing_hash_pre155( tx: ethereum.paris.fork_types.LegacyTransaction) -> ethereum.base_types.Bytes32:
758def signing_hash_pre155(tx: LegacyTransaction) -> Hash32:
759    """
760    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
761
762    Parameters
763    ----------
764    tx :
765        Transaction of interest.
766
767    Returns
768    -------
769    hash : `ethereum.crypto.hash.Hash32`
770        Hash of the transaction.
771    """
772    return keccak256(
773        rlp.encode(
774            (
775                tx.nonce,
776                tx.gas_price,
777                tx.gas,
778                tx.to,
779                tx.value,
780                tx.data,
781            )
782        )
783    )

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.

786def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32:
787    """
788    Compute the hash of a transaction used in a EIP 155 signature.
789
790    Parameters
791    ----------
792    tx :
793        Transaction of interest.
794    chain_id :
795        The id of the current chain.
796
797    Returns
798    -------
799    hash : `ethereum.crypto.hash.Hash32`
800        Hash of the transaction.
801    """
802    return keccak256(
803        rlp.encode(
804            (
805                tx.nonce,
806                tx.gas_price,
807                tx.gas,
808                tx.to,
809                tx.value,
810                tx.data,
811                chain_id,
812                Uint(0),
813                Uint(0),
814            )
815        )
816    )

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.

819def signing_hash_2930(tx: AccessListTransaction) -> Hash32:
820    """
821    Compute the hash of a transaction used in a EIP 2930 signature.
822
823    Parameters
824    ----------
825    tx :
826        Transaction of interest.
827
828    Returns
829    -------
830    hash : `ethereum.crypto.hash.Hash32`
831        Hash of the transaction.
832    """
833    return keccak256(
834        b"\x01"
835        + rlp.encode(
836            (
837                tx.chain_id,
838                tx.nonce,
839                tx.gas_price,
840                tx.gas,
841                tx.to,
842                tx.value,
843                tx.data,
844                tx.access_list,
845            )
846        )
847    )

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.

850def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32:
851    """
852    Compute the hash of a transaction used in a EIP 1559 signature.
853
854    Parameters
855    ----------
856    tx :
857        Transaction of interest.
858
859    Returns
860    -------
861    hash : `ethereum.crypto.hash.Hash32`
862        Hash of the transaction.
863    """
864    return keccak256(
865        b"\x02"
866        + rlp.encode(
867            (
868                tx.chain_id,
869                tx.nonce,
870                tx.max_priority_fee_per_gas,
871                tx.max_fee_per_gas,
872                tx.gas,
873                tx.to,
874                tx.value,
875                tx.data,
876                tx.access_list,
877            )
878        )
879    )

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

Parameters

tx : Transaction of interest.

Returns

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

def compute_header_hash(header: ethereum.paris.fork_types.Header) -> ethereum.base_types.Bytes32:
882def compute_header_hash(header: Header) -> Hash32:
883    """
884    Computes the hash of a block header.
885
886    The header hash of a block is the canonical hash that is used to refer
887    to a specific block and completely distinguishes a block from another.
888
889    ``keccak256`` is a function that produces a 256 bit hash of any input.
890    It also takes in any number of bytes as an input and produces a single
891    hash for them. A hash is a completely unique output for a single input.
892    So an input corresponds to one unique hash that can be used to identify
893    the input exactly.
894
895    Prior to using the ``keccak256`` hash function, the header must be
896    encoded using the Recursive-Length Prefix. See :ref:`rlp`.
897    RLP encoding the header converts it into a space-efficient format that
898    allows for easy transfer of data between nodes. The purpose of RLP is to
899    encode arbitrarily nested arrays of binary data, and RLP is the primary
900    encoding method used to serialize objects in Ethereum's execution layer.
901    The only purpose of RLP is to encode structure; encoding specific data
902    types (e.g. strings, floats) is left up to higher-order protocols.
903
904    Parameters
905    ----------
906    header :
907        Header of interest.
908
909    Returns
910    -------
911    hash : `ethereum.crypto.hash.Hash32`
912        Hash of the header.
913    """
914    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:
917def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool:
918    """
919    Validates the gas limit for a block.
920
921    The bounds of the gas limit, ``max_adjustment_delta``, is set as the
922    quotient of the parent block's gas limit and the
923    ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is
924    passed through as a parameter is greater than or equal to the *sum* of
925    the parent's gas and the adjustment delta then the limit for gas is too
926    high and fails this function's check. Similarly, if the limit is less
927    than or equal to the *difference* of the parent's gas and the adjustment
928    delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's
929    check fails because the gas limit doesn't allow for a sufficient or
930    reasonable amount of gas to be used on a block.
931
932    Parameters
933    ----------
934    gas_limit :
935        Gas limit to validate.
936
937    parent_gas_limit :
938        Gas limit of the parent block.
939
940    Returns
941    -------
942    check : `bool`
943        True if gas limit constraints are satisfied, False otherwise.
944    """
945    max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
946    if gas_limit >= parent_gas_limit + max_adjustment_delta:
947        return False
948    if gas_limit <= parent_gas_limit - max_adjustment_delta:
949        return False
950    if gas_limit < GAS_LIMIT_MINIMUM:
951        return False
952
953    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.