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

History and current state of the block chain.

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

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

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

Parameters

old : Previous block chain object.

Returns

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

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

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

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

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

Parameters

chain : History and current state.

Returns

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

def state_transition( chain: BlockChain, block: ethereum.shanghai.fork_types.Block) -> None:
146def state_transition(chain: BlockChain, block: Block) -> None:
147    """
148    Attempts to apply a block to an existing block chain.
149
150    All parts of the block's contents need to be verified before being added
151    to the chain. Blocks are verified by ensuring that the contents of the
152    block make logical sense with the contents of the parent block. The
153    information in the block's header must also match the corresponding
154    information in the block.
155
156    To implement Ethereum, in theory clients are only required to store the
157    most recent 255 blocks of the chain since as far as execution is
158    concerned, only those blocks are accessed. Practically, however, clients
159    should store more blocks to handle reorgs.
160
161    Parameters
162    ----------
163    chain :
164        History and current state.
165    block :
166        Block to apply to `chain`.
167    """
168    parent_header = chain.blocks[-1].header
169    validate_header(block.header, parent_header)
170    ensure(block.ommers == (), InvalidBlock)
171    (
172        gas_used,
173        transactions_root,
174        receipt_root,
175        block_logs_bloom,
176        state,
177        withdrawals_root,
178    ) = apply_body(
179        chain.state,
180        get_last_256_block_hashes(chain),
181        block.header.coinbase,
182        block.header.number,
183        block.header.base_fee_per_gas,
184        block.header.gas_limit,
185        block.header.timestamp,
186        block.header.prev_randao,
187        block.transactions,
188        chain.chain_id,
189        block.withdrawals,
190    )
191    ensure(gas_used == block.header.gas_used, InvalidBlock)
192    ensure(transactions_root == block.header.transactions_root, InvalidBlock)
193    ensure(state_root(state) == block.header.state_root, InvalidBlock)
194    ensure(receipt_root == block.header.receipt_root, InvalidBlock)
195    ensure(block_logs_bloom == block.header.bloom, InvalidBlock)
196    ensure(withdrawals_root == block.header.withdrawals_root, InvalidBlock)
197
198    chain.blocks.append(block)
199    if len(chain.blocks) > 255:
200        # Real clients have to store more blocks to deal with reorgs, but the
201        # protocol only requires the last 255
202        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:
205def calculate_base_fee_per_gas(
206    block_gas_limit: Uint,
207    parent_gas_limit: Uint,
208    parent_gas_used: Uint,
209    parent_base_fee_per_gas: Uint,
210) -> Uint:
211    """
212    Calculates the base fee per gas for the block.
213
214    Parameters
215    ----------
216    block_gas_limit :
217        Gas limit of the block for which the base fee is being calculated.
218    parent_gas_limit :
219        Gas limit of the parent block.
220    parent_gas_used :
221        Gas used in the parent block.
222    parent_base_fee_per_gas :
223        Base fee per gas of the parent block.
224
225    Returns
226    -------
227    base_fee_per_gas : `Uint`
228        Base fee per gas for the block.
229    """
230    parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER
231
232    ensure(
233        check_gas_limit(block_gas_limit, parent_gas_limit),
234        InvalidBlock,
235    )
236
237    if parent_gas_used == parent_gas_target:
238        expected_base_fee_per_gas = parent_base_fee_per_gas
239    elif parent_gas_used > parent_gas_target:
240        gas_used_delta = parent_gas_used - parent_gas_target
241
242        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
243        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
244
245        base_fee_per_gas_delta = max(
246            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR,
247            1,
248        )
249
250        expected_base_fee_per_gas = (
251            parent_base_fee_per_gas + base_fee_per_gas_delta
252        )
253    else:
254        gas_used_delta = parent_gas_target - parent_gas_used
255
256        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
257        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
258
259        base_fee_per_gas_delta = (
260            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR
261        )
262
263        expected_base_fee_per_gas = (
264            parent_base_fee_per_gas - base_fee_per_gas_delta
265        )
266
267    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.shanghai.fork_types.Header, parent_header: ethereum.shanghai.fork_types.Header) -> None:
270def validate_header(header: Header, parent_header: Header) -> None:
271    """
272    Verifies a block header.
273
274    In order to consider a block's header valid, the logic for the
275    quantities in the header should match the logic for the block itself.
276    For example the header timestamp should be greater than the block's parent
277    timestamp because the block was created *after* the parent block.
278    Additionally, the block's number should be directly following the parent
279    block's number since it is the next block in the sequence.
280
281    Parameters
282    ----------
283    header :
284        Header to check for correctness.
285    parent_header :
286        Parent Header of the header to check for correctness
287    """
288    ensure(header.gas_used <= header.gas_limit, InvalidBlock)
289
290    expected_base_fee_per_gas = calculate_base_fee_per_gas(
291        header.gas_limit,
292        parent_header.gas_limit,
293        parent_header.gas_used,
294        parent_header.base_fee_per_gas,
295    )
296
297    ensure(expected_base_fee_per_gas == header.base_fee_per_gas, InvalidBlock)
298
299    ensure(header.timestamp > parent_header.timestamp, InvalidBlock)
300    ensure(header.number == parent_header.number + 1, InvalidBlock)
301    ensure(len(header.extra_data) <= 32, InvalidBlock)
302
303    ensure(header.difficulty == 0, InvalidBlock)
304    ensure(header.nonce == b"\x00\x00\x00\x00\x00\x00\x00\x00", InvalidBlock)
305    ensure(header.ommers_hash == EMPTY_OMMER_HASH, InvalidBlock)
306
307    block_parent_hash = keccak256(rlp.encode(parent_header))
308    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

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

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

Make the receipt for a transaction that was executed.

Parameters

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

Returns

receipt : The receipt for the transaction.

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

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. withdrawals : Withdrawals to be processed in the current block.

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.

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

655def validate_transaction(tx: Transaction) -> bool:
656    """
657    Verifies a transaction.
658
659    The gas in a transaction gets used to pay for the intrinsic cost of
660    operations, therefore if there is insufficient gas then it would not
661    be possible to execute a transaction and it will be declared invalid.
662
663    Additionally, the nonce of a transaction must not equal or exceed the
664    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
665    In practice, defining the limit as ``2**64-1`` has no impact because
666    sending ``2**64-1`` transactions is improbable. It's not strictly
667    impossible though, ``2**64-1`` transactions is the entire capacity of the
668    Ethereum blockchain at 2022 gas limits for a little over 22 years.
669
670    Parameters
671    ----------
672    tx :
673        Transaction to validate.
674
675    Returns
676    -------
677    verified : `bool`
678        True if the transaction can be executed, or False otherwise.
679    """
680    if calculate_intrinsic_cost(tx) > tx.gas:
681        return False
682    if tx.nonce >= 2**64 - 1:
683        return False
684    if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE:
685        return False
686
687    return True

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.

690def calculate_intrinsic_cost(tx: Transaction) -> Uint:
691    """
692    Calculates the gas that is charged before execution is started.
693
694    The intrinsic cost of the transaction is charged before execution has
695    begun. Functions/operations in the EVM cost money to execute so this
696    intrinsic cost is for the operations that need to be paid for as part of
697    the transaction. Data transfer, for example, is part of this intrinsic
698    cost. It costs ether to send data over the wire and that ether is
699    accounted for in the intrinsic cost calculated in this function. This
700    intrinsic cost must be calculated and paid for before execution in order
701    for all operations to be implemented.
702
703    Parameters
704    ----------
705    tx :
706        Transaction to compute the intrinsic cost of.
707
708    Returns
709    -------
710    verified : `ethereum.base_types.Uint`
711        The intrinsic cost of the transaction.
712    """
713    data_cost = 0
714
715    for byte in tx.data:
716        if byte == 0:
717            data_cost += TX_DATA_COST_PER_ZERO
718        else:
719            data_cost += TX_DATA_COST_PER_NON_ZERO
720
721    if tx.to == Bytes0(b""):
722        create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data))))
723    else:
724        create_cost = 0
725
726    access_list_cost = 0
727    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
728        for _address, keys in tx.access_list:
729            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
730            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
731
732    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.

735def recover_sender(chain_id: U64, tx: Transaction) -> Address:
736    """
737    Extracts the sender address from a transaction.
738
739    The v, r, and s values are the three parts that make up the signature
740    of a transaction. In order to recover the sender of a transaction the two
741    components needed are the signature (``v``, ``r``, and ``s``) and the
742    signing hash of the transaction. The sender's public key can be obtained
743    with these two values and therefore the sender address can be retrieved.
744
745    Parameters
746    ----------
747    tx :
748        Transaction of interest.
749    chain_id :
750        ID of the executing chain.
751
752    Returns
753    -------
754    sender : `ethereum.fork_types.Address`
755        The address of the account that signed the transaction.
756    """
757    r, s = tx.r, tx.s
758
759    ensure(0 < r and r < SECP256K1N, InvalidBlock)
760    ensure(0 < s and s <= SECP256K1N // 2, InvalidBlock)
761
762    if isinstance(tx, LegacyTransaction):
763        v = tx.v
764        if v == 27 or v == 28:
765            public_key = secp256k1_recover(
766                r, s, v - 27, signing_hash_pre155(tx)
767            )
768        else:
769            ensure(
770                v == 35 + chain_id * 2 or v == 36 + chain_id * 2, InvalidBlock
771            )
772            public_key = secp256k1_recover(
773                r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
774            )
775    elif isinstance(tx, AccessListTransaction):
776        public_key = secp256k1_recover(
777            r, s, tx.y_parity, signing_hash_2930(tx)
778        )
779    elif isinstance(tx, FeeMarketTransaction):
780        public_key = secp256k1_recover(
781            r, s, tx.y_parity, signing_hash_1559(tx)
782        )
783
784    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.shanghai.fork_types.LegacyTransaction) -> ethereum.base_types.Bytes32:
787def signing_hash_pre155(tx: LegacyTransaction) -> Hash32:
788    """
789    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
790
791    Parameters
792    ----------
793    tx :
794        Transaction of interest.
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            )
811        )
812    )

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.

815def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32:
816    """
817    Compute the hash of a transaction used in a EIP 155 signature.
818
819    Parameters
820    ----------
821    tx :
822        Transaction of interest.
823    chain_id :
824        The id of the current chain.
825
826    Returns
827    -------
828    hash : `ethereum.crypto.hash.Hash32`
829        Hash of the transaction.
830    """
831    return keccak256(
832        rlp.encode(
833            (
834                tx.nonce,
835                tx.gas_price,
836                tx.gas,
837                tx.to,
838                tx.value,
839                tx.data,
840                chain_id,
841                Uint(0),
842                Uint(0),
843            )
844        )
845    )

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.

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

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.

879def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32:
880    """
881    Compute the hash of a transaction used in a EIP 1559 signature.
882
883    Parameters
884    ----------
885    tx :
886        Transaction of interest.
887
888    Returns
889    -------
890    hash : `ethereum.crypto.hash.Hash32`
891        Hash of the transaction.
892    """
893    return keccak256(
894        b"\x02"
895        + rlp.encode(
896            (
897                tx.chain_id,
898                tx.nonce,
899                tx.max_priority_fee_per_gas,
900                tx.max_fee_per_gas,
901                tx.gas,
902                tx.to,
903                tx.value,
904                tx.data,
905                tx.access_list,
906            )
907        )
908    )

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.shanghai.fork_types.Header) -> ethereum.base_types.Bytes32:
911def compute_header_hash(header: Header) -> Hash32:
912    """
913    Computes the hash of a block header.
914
915    The header hash of a block is the canonical hash that is used to refer
916    to a specific block and completely distinguishes a block from another.
917
918    ``keccak256`` is a function that produces a 256 bit hash of any input.
919    It also takes in any number of bytes as an input and produces a single
920    hash for them. A hash is a completely unique output for a single input.
921    So an input corresponds to one unique hash that can be used to identify
922    the input exactly.
923
924    Prior to using the ``keccak256`` hash function, the header must be
925    encoded using the Recursive-Length Prefix. See :ref:`rlp`.
926    RLP encoding the header converts it into a space-efficient format that
927    allows for easy transfer of data between nodes. The purpose of RLP is to
928    encode arbitrarily nested arrays of binary data, and RLP is the primary
929    encoding method used to serialize objects in Ethereum's execution layer.
930    The only purpose of RLP is to encode structure; encoding specific data
931    types (e.g. strings, floats) is left up to higher-order protocols.
932
933    Parameters
934    ----------
935    header :
936        Header of interest.
937
938    Returns
939    -------
940    hash : `ethereum.crypto.hash.Hash32`
941        Hash of the header.
942    """
943    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:
946def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool:
947    """
948    Validates the gas limit for a block.
949
950    The bounds of the gas limit, ``max_adjustment_delta``, is set as the
951    quotient of the parent block's gas limit and the
952    ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is
953    passed through as a parameter is greater than or equal to the *sum* of
954    the parent's gas and the adjustment delta then the limit for gas is too
955    high and fails this function's check. Similarly, if the limit is less
956    than or equal to the *difference* of the parent's gas and the adjustment
957    delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's
958    check fails because the gas limit doesn't allow for a sufficient or
959    reasonable amount of gas to be used on a block.
960
961    Parameters
962    ----------
963    gas_limit :
964        Gas limit to validate.
965
966    parent_gas_limit :
967        Gas limit of the parent block.
968
969    Returns
970    -------
971    check : `bool`
972        True if gas limit constraints are satisfied, False otherwise.
973    """
974    max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
975    if gas_limit >= parent_gas_limit + max_adjustment_delta:
976        return False
977    if gas_limit <= parent_gas_limit - max_adjustment_delta:
978        return False
979    if gas_limit < GAS_LIMIT_MINIMUM:
980        return False
981
982    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.