ethereum.paris.forkethereum.shanghai.fork

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

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

Introduction

Entry point for the Ethereum specification.

BASE_FEE_MAX_CHANGE_DENOMINATOR

58
BASE_FEE_MAX_CHANGE_DENOMINATOR = 8

ELASTICITY_MULTIPLIER

59
ELASTICITY_MULTIPLIER = 2

GAS_LIMIT_ADJUSTMENT_FACTOR

60
GAS_LIMIT_ADJUSTMENT_FACTOR = 1024

GAS_LIMIT_MINIMUM

61
GAS_LIMIT_MINIMUM = 5000

EMPTY_OMMER_HASH

62
EMPTY_OMMER_HASH = keccak256(rlp.encode([]))

BlockChain

History and current state of the block chain.

65
@dataclass
class BlockChain:

blocks

71
    blocks: List[Block]

state

72
    state: State

chain_id

73
    chain_id: U64

apply_fork

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 apply_fork(old: BlockChain) -> BlockChain:
77
    """
78
    Transforms the state from the previous hard fork (`old`) into the block
79
    chain object for this hard fork and returns it.
80
81
    When forks need to implement an irregular state transition, this function
82
    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
83
    an example.
84
85
    Parameters
86
    ----------
87
    old :
88
        Previous block chain object.
89
90
    Returns
91
    -------
92
    new : `BlockChain`
93
        Upgraded block chain object for this hard fork.
94
    """
95
    return old

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

state_transition

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

calculate_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 calculate_base_fee_per_gas(block_gas_limit: Uint, ​​parent_gas_limit: Uint, ​​parent_gas_used: Uint, ​​parent_base_fee_per_gas: Uint) -> Uint:
203
    """
204
    Calculates the base fee per gas for the block.
205
206
    Parameters
207
    ----------
208
    block_gas_limit :
209
        Gas limit of the block for which the base fee is being calculated.
210
    parent_gas_limit :
211
        Gas limit of the parent block.
212
    parent_gas_used :
213
        Gas used in the parent block.
214
    parent_base_fee_per_gas :
215
        Base fee per gas of the parent block.
216
217
    Returns
218
    -------
219
    base_fee_per_gas : `Uint`
220
        Base fee per gas for the block.
221
    """
222
    parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER
223
    if not check_gas_limit(block_gas_limit, parent_gas_limit):
224
        raise InvalidBlock
225
226
    if parent_gas_used == parent_gas_target:
227
        expected_base_fee_per_gas = parent_base_fee_per_gas
228
    elif parent_gas_used > parent_gas_target:
229
        gas_used_delta = parent_gas_used - parent_gas_target
230
231
        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
232
        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
233
234
        base_fee_per_gas_delta = max(
235
            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR,
236
            1,
237
        )
238
239
        expected_base_fee_per_gas = (
240
            parent_base_fee_per_gas + base_fee_per_gas_delta
241
        )
242
    else:
243
        gas_used_delta = parent_gas_target - parent_gas_used
244
245
        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
246
        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
247
248
        base_fee_per_gas_delta = (
249
            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR
250
        )
251
252
        expected_base_fee_per_gas = (
253
            parent_base_fee_per_gas - base_fee_per_gas_delta
254
        )
255
256
    return Uint(expected_base_fee_per_gas)

validate_header

Verifies a block header.

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

Parameters

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

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

check_transaction

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.

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

make_receipt

Make the receipt for a transaction that was executed.

Parameters

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

def make_receipt(tx: Transaction, ​​error: Optional[Exception], ​​cumulative_gas_used: Uint, ​​logs: Tuple[Log, ...]) -> 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 :
370
        The error from the execution if any.
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

ApplyBodyOutput

Output from applying the block body to the present state.

Contains the following:

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_root : ethereum.fork_types.Root State root after all transactions have been executed. withdrawals_root : ethereum.fork_types.Root Trie root of all the withdrawals in the block.

402
@dataclass
class ApplyBodyOutput:

block_gas_used

424
    block_gas_used: Uint

transactions_root

425
    transactions_root: Root

receipt_root

426
    receipt_root: Root

block_logs_bloom

427
    block_logs_bloom: Bloom

state_root

428
    state_root: Root

withdrawals_root

429
    withdrawals_root: Root

apply_body

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

apply_body_output : ApplyBodyOutput Output of applying the block body to the state.

def apply_body(state: State, ​​block_hashes: List[Hash32], ​​coinbase: Address, ​​block_number: Uint, ​​base_fee_per_gas: Uint, ​​block_gas_limit: Uint, ​​block_time: U256, ​​prev_randao: Bytes32, ​​transactions: Tuple[Union[LegacyTransaction, Bytes], ...], ​​chain_id: U64, ​​withdrawals: Tuple[Withdrawal, ...]) -> ApplyBodyOutput:
445
    """
446
    Executes a block.
447
448
    Many of the contents of a block are stored in data structures called
449
    tries. There is a transactions trie which is similar to a ledger of the
450
    transactions stored in the current block. There is also a receipts trie
451
    which stores the results of executing a transaction, like the post state
452
    and gas used. This function creates and executes the block that is to be
453
    added to the chain.
454
455
    Parameters
456
    ----------
457
    state :
458
        Current account state.
459
    block_hashes :
460
        List of hashes of the previous 256 blocks in the order of
461
        increasing block number.
462
    coinbase :
463
        Address of account which receives block reward and transaction fees.
464
    block_number :
465
        Position of the block within the chain.
466
    base_fee_per_gas :
467
        Base fee per gas of within the block.
468
    block_gas_limit :
469
        Initial amount of gas available for execution in this block.
470
    block_time :
471
        Time the block was produced, measured in seconds since the epoch.
472
    prev_randao :
473
        The previous randao from the beacon chain.
474
    transactions :
475
        Transactions included in the block.
476
    ommers :
477
        Headers of ancestor blocks which are not direct parents (formerly
478
        uncles.)
479
    chain_id :
480
        ID of the executing chain.
481
    withdrawals :
482
        Withdrawals to be processed in the current block.
483
484
    Returns
485
    -------
486
    apply_body_output : `ApplyBodyOutput`
487
        Output of applying the block body to the state.
488
    """
489
    gas_available = block_gas_limit
490
    transactions_trie: Trie[
491
        Bytes, Optional[Union[Bytes, LegacyTransaction]]
492
    ] = Trie(secured=False, default=None)
493
    receipts_trie: Trie[Bytes, Optional[Union[Bytes, Receipt]]] = Trie(
494
        secured=False, default=None
495
    )
496
    withdrawals_trie: Trie[Bytes, Optional[Union[Bytes, Withdrawal]]] = Trie(
497
        secured=False, default=None
498
    )
499
    block_logs: Tuple[Log, ...] = ()
500
501
    for i, tx in enumerate(map(decode_transaction, transactions)):
502
        trie_set(
503
            transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx)
504
        )
505
506
        sender_address, effective_gas_price = check_transaction(
507
            tx, base_fee_per_gas, gas_available, chain_id
508
        )
509
510
        env = vm.Environment(
511
            caller=sender_address,
512
            origin=sender_address,
513
            block_hashes=block_hashes,
514
            coinbase=coinbase,
515
            number=block_number,
516
            gas_limit=block_gas_limit,
517
            base_fee_per_gas=base_fee_per_gas,
518
            gas_price=effective_gas_price,
519
            time=block_time,
520
            prev_randao=prev_randao,
521
            state=state,
522
            chain_id=chain_id,
523
            traces=[],
524
        )
525
526
        gas_used, logs, error = process_transaction(env, tx)
527
        gas_available -= gas_used
528
529
        receipt = make_receipt(
530
            tx, error, (block_gas_limit - gas_available), logs
531
        )
532
533
        trie_set(
534
            receipts_trie,
535
            rlp.encode(Uint(i)),
536
            receipt,
537
        )
538
539
        block_logs += logs
540
541
    block_gas_used = block_gas_limit - gas_available
542
543
    block_logs_bloom = logs_bloom(block_logs)
544
545
    for i, wd in enumerate(withdrawals):
546
        trie_set(withdrawals_trie, rlp.encode(Uint(i)), rlp.encode(wd))
547
548
        process_withdrawal(state, wd)
549
550
        if account_exists_and_is_empty(state, wd.address):
551
            destroy_account(state, wd.address)
552
553
    return ApplyBodyOutput(
554
        block_gas_used,
555
        root(transactions_trie),
556
        root(receipts_trie),
557
        block_logs_bloom,
558
        state_root(state),
559
        root(withdrawals_trie),
560
    )

process_transaction

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.blocks.Log, ...] Logs generated during execution.

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

validate_transaction

Verifies a transaction.

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

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

Parameters

tx : Transaction to validate.

Returns

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

def validate_transaction(tx: Transaction) -> bool:
679
    """
680
    Verifies a transaction.
681
682
    The gas in a transaction gets used to pay for the intrinsic cost of
683
    operations, therefore if there is insufficient gas then it would not
684
    be possible to execute a transaction and it will be declared invalid.
685
686
    Additionally, the nonce of a transaction must not equal or exceed the
687
    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
688
    In practice, defining the limit as ``2**64-1`` has no impact because
689
    sending ``2**64-1`` transactions is improbable. It's not strictly
690
    impossible though, ``2**64-1`` transactions is the entire capacity of the
691
    Ethereum blockchain at 2022 gas limits for a little over 22 years.
692
693
    Parameters
694
    ----------
695
    tx :
696
        Transaction to validate.
697
698
    Returns
699
    -------
700
    verified : `bool`
701
        True if the transaction can be executed, or False otherwise.
702
    """
679
    return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1
703
    if calculate_intrinsic_cost(tx) > tx.gas:
704
        return False
705
    if tx.nonce >= 2**64 - 1:
706
        return False
707
    if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE:
708
        return False
709
710
    return True

calculate_intrinsic_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.

def calculate_intrinsic_cost(tx: Transaction) -> Uint:
714
    """
715
    Calculates the gas that is charged before execution is started.
716
717
    The intrinsic cost of the transaction is charged before execution has
718
    begun. Functions/operations in the EVM cost money to execute so this
719
    intrinsic cost is for the operations that need to be paid for as part of
720
    the transaction. Data transfer, for example, is part of this intrinsic
721
    cost. It costs ether to send data over the wire and that ether is
722
    accounted for in the intrinsic cost calculated in this function. This
723
    intrinsic cost must be calculated and paid for before execution in order
724
    for all operations to be implemented.
725
726
    Parameters
727
    ----------
728
    tx :
729
        Transaction to compute the intrinsic cost of.
730
731
    Returns
732
    -------
733
    verified : `ethereum.base_types.Uint`
734
        The intrinsic cost of the transaction.
735
    """
736
    data_cost = 0
737
738
    for byte in tx.data:
739
        if byte == 0:
740
            data_cost += TX_DATA_COST_PER_ZERO
741
        else:
742
            data_cost += TX_DATA_COST_PER_NON_ZERO
743
744
    if tx.to == Bytes0(b""):
714
        create_cost = TX_CREATE_COST
745
        create_cost = TX_CREATE_COST + int(init_code_cost(Uint(len(tx.data))))
746
    else:
747
        create_cost = 0
748
749
    access_list_cost = 0
750
    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
751
        for _address, keys in tx.access_list:
752
            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
753
            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
754
755
    return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost)

recover_sender

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 recover_sender(chain_id: U64, ​​tx: Transaction) -> Address:
759
    """
760
    Extracts the sender address from a transaction.
761
762
    The v, r, and s values are the three parts that make up the signature
763
    of a transaction. In order to recover the sender of a transaction the two
764
    components needed are the signature (``v``, ``r``, and ``s``) and the
765
    signing hash of the transaction. The sender's public key can be obtained
766
    with these two values and therefore the sender address can be retrieved.
767
768
    Parameters
769
    ----------
770
    tx :
771
        Transaction of interest.
772
    chain_id :
773
        ID of the executing chain.
774
775
    Returns
776
    -------
777
    sender : `ethereum.fork_types.Address`
778
        The address of the account that signed the transaction.
779
    """
780
    r, s = tx.r, tx.s
781
    if 0 >= r or r >= SECP256K1N:
782
        raise InvalidBlock
783
    if 0 >= s or s > SECP256K1N // 2:
784
        raise InvalidBlock
785
786
    if isinstance(tx, LegacyTransaction):
787
        v = tx.v
788
        if v == 27 or v == 28:
789
            public_key = secp256k1_recover(
790
                r, s, v - 27, signing_hash_pre155(tx)
791
            )
792
        else:
793
            if v != 35 + chain_id * 2 and v != 36 + chain_id * 2:
794
                raise InvalidBlock
795
            public_key = secp256k1_recover(
796
                r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
797
            )
798
    elif isinstance(tx, AccessListTransaction):
799
        public_key = secp256k1_recover(
800
            r, s, tx.y_parity, signing_hash_2930(tx)
801
        )
802
    elif isinstance(tx, FeeMarketTransaction):
803
        public_key = secp256k1_recover(
804
            r, s, tx.y_parity, signing_hash_1559(tx)
805
        )
806
807
    return Address(keccak256(public_key)[12:32])

signing_hash_pre155

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.

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

signing_hash_155

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

Parameters

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

Returns

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

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

signing_hash_2930

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

Parameters

tx : Transaction of interest.

Returns

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

def signing_hash_2930(tx: AccessListTransaction) -> Hash32:
872
    """
873
    Compute the hash of a transaction used in a EIP 2930 signature.
874
875
    Parameters
876
    ----------
877
    tx :
878
        Transaction of interest.
879
880
    Returns
881
    -------
882
    hash : `ethereum.crypto.hash.Hash32`
883
        Hash of the transaction.
884
    """
885
    return keccak256(
886
        b"\x01"
887
        + rlp.encode(
888
            (
889
                tx.chain_id,
890
                tx.nonce,
891
                tx.gas_price,
892
                tx.gas,
893
                tx.to,
894
                tx.value,
895
                tx.data,
896
                tx.access_list,
897
            )
898
        )
899
    )

signing_hash_1559

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 signing_hash_1559(tx: FeeMarketTransaction) -> Hash32:
903
    """
904
    Compute the hash of a transaction used in a EIP 1559 signature.
905
906
    Parameters
907
    ----------
908
    tx :
909
        Transaction of interest.
910
911
    Returns
912
    -------
913
    hash : `ethereum.crypto.hash.Hash32`
914
        Hash of the transaction.
915
    """
916
    return keccak256(
917
        b"\x02"
918
        + rlp.encode(
919
            (
920
                tx.chain_id,
921
                tx.nonce,
922
                tx.max_priority_fee_per_gas,
923
                tx.max_fee_per_gas,
924
                tx.gas,
925
                tx.to,
926
                tx.value,
927
                tx.data,
928
                tx.access_list,
929
            )
930
        )
931
    )

compute_header_hash

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

check_gas_limit

Validates the gas limit for a block.

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

Parameters

gas_limit : Gas limit to validate.

parent_gas_limit : Gas limit of the parent block.

Returns

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

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