ethereum.paris.fork

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

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

Introduction

Entry point for the Ethereum specification.

BASE_FEE_MAX_CHANGE_DENOMINATOR

56
BASE_FEE_MAX_CHANGE_DENOMINATOR = 8

ELASTICITY_MULTIPLIER

57
ELASTICITY_MULTIPLIER = 2

GAS_LIMIT_ADJUSTMENT_FACTOR

58
GAS_LIMIT_ADJUSTMENT_FACTOR = 1024

GAS_LIMIT_MINIMUM

59
GAS_LIMIT_MINIMUM = 5000

EMPTY_OMMER_HASH

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

BlockChain

History and current state of the block chain.

63
@dataclass
class BlockChain:

blocks

69
    blocks: List[Block]

state

70
    state: State

chain_id

71
    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:
75
    """
76
    Transforms the state from the previous hard fork (`old`) into the block
77
    chain object for this hard fork and returns it.
78
79
    When forks need to implement an irregular state transition, this function
80
    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
81
    an example.
82
83
    Parameters
84
    ----------
85
    old :
86
        Previous block chain object.
87
88
    Returns
89
    -------
90
    new : `BlockChain`
91
        Upgraded block chain object for this hard fork.
92
    """
93
    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]:
97
    """
98
    Obtain the list of hashes of the previous 256 blocks in order of
99
    increasing block number.
100
101
    This function will return less hashes for the first 256 blocks.
102
103
    The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,
104
    therefore this function retrieves them.
105
106
    Parameters
107
    ----------
108
    chain :
109
        History and current state.
110
111
    Returns
112
    -------
113
    recent_block_hashes : `List[Hash32]`
114
        Hashes of the recent 256 blocks in order of increasing block number.
115
    """
116
    recent_blocks = chain.blocks[-255:]
117
    # TODO: This function has not been tested rigorously
118
    if len(recent_blocks) == 0:
119
        return []
120
121
    recent_block_hashes = []
122
123
    for block in recent_blocks:
124
        prev_block_hash = block.header.parent_hash
125
        recent_block_hashes.append(prev_block_hash)
126
127
    # We are computing the hash only for the most recent block and not for
128
    # the rest of the blocks as they have successors which have the hash of
129
    # the current block as parent hash.
130
    most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header))
131
    recent_block_hashes.append(most_recent_block_hash)
132
133
    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:
137
    """
138
    Attempts to apply a block to an existing block chain.
139
140
    All parts of the block's contents need to be verified before being added
141
    to the chain. Blocks are verified by ensuring that the contents of the
142
    block make logical sense with the contents of the parent block. The
143
    information in the block's header must also match the corresponding
144
    information in the block.
145
146
    To implement Ethereum, in theory clients are only required to store the
147
    most recent 255 blocks of the chain since as far as execution is
148
    concerned, only those blocks are accessed. Practically, however, clients
149
    should store more blocks to handle reorgs.
150
151
    Parameters
152
    ----------
153
    chain :
154
        History and current state.
155
    block :
156
        Block to apply to `chain`.
157
    """
158
    parent_header = chain.blocks[-1].header
159
    validate_header(block.header, parent_header)
160
    if block.ommers != ():
161
        raise InvalidBlock
162
    apply_body_output = apply_body(
163
        chain.state,
164
        get_last_256_block_hashes(chain),
165
        block.header.coinbase,
166
        block.header.number,
167
        block.header.base_fee_per_gas,
168
        block.header.gas_limit,
169
        block.header.timestamp,
170
        block.header.prev_randao,
171
        block.transactions,
172
        chain.chain_id,
173
    )
174
    if apply_body_output.block_gas_used != block.header.gas_used:
175
        raise InvalidBlock
176
    if apply_body_output.transactions_root != block.header.transactions_root:
177
        raise InvalidBlock
178
    if apply_body_output.state_root != block.header.state_root:
179
        raise InvalidBlock
180
    if apply_body_output.receipt_root != block.header.receipt_root:
181
        raise InvalidBlock
182
    if apply_body_output.block_logs_bloom != block.header.bloom:
183
        raise InvalidBlock
184
185
    chain.blocks.append(block)
186
    if len(chain.blocks) > 255:
187
        # Real clients have to store more blocks to deal with reorgs, but the
188
        # protocol only requires the last 255
189
        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:
198
    """
199
    Calculates the base fee per gas for the block.
200
201
    Parameters
202
    ----------
203
    block_gas_limit :
204
        Gas limit of the block for which the base fee is being calculated.
205
    parent_gas_limit :
206
        Gas limit of the parent block.
207
    parent_gas_used :
208
        Gas used in the parent block.
209
    parent_base_fee_per_gas :
210
        Base fee per gas of the parent block.
211
212
    Returns
213
    -------
214
    base_fee_per_gas : `Uint`
215
        Base fee per gas for the block.
216
    """
217
    parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER
218
    if not check_gas_limit(block_gas_limit, parent_gas_limit):
219
        raise InvalidBlock
220
221
    if parent_gas_used == parent_gas_target:
222
        expected_base_fee_per_gas = parent_base_fee_per_gas
223
    elif parent_gas_used > parent_gas_target:
224
        gas_used_delta = parent_gas_used - parent_gas_target
225
226
        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
227
        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
228
229
        base_fee_per_gas_delta = max(
230
            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR,
231
            1,
232
        )
233
234
        expected_base_fee_per_gas = (
235
            parent_base_fee_per_gas + base_fee_per_gas_delta
236
        )
237
    else:
238
        gas_used_delta = parent_gas_target - parent_gas_used
239
240
        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
241
        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
242
243
        base_fee_per_gas_delta = (
244
            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR
245
        )
246
247
        expected_base_fee_per_gas = (
248
            parent_base_fee_per_gas - base_fee_per_gas_delta
249
        )
250
251
    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:
255
    """
256
    Verifies a block header.
257
258
    In order to consider a block's header valid, the logic for the
259
    quantities in the header should match the logic for the block itself.
260
    For example the header timestamp should be greater than the block's parent
261
    timestamp because the block was created *after* the parent block.
262
    Additionally, the block's number should be directly following the parent
263
    block's number since it is the next block in the sequence.
264
265
    Parameters
266
    ----------
267
    header :
268
        Header to check for correctness.
269
    parent_header :
270
        Parent Header of the header to check for correctness
271
    """
272
    if header.gas_used > header.gas_limit:
273
        raise InvalidBlock
274
275
    expected_base_fee_per_gas = calculate_base_fee_per_gas(
276
        header.gas_limit,
277
        parent_header.gas_limit,
278
        parent_header.gas_used,
279
        parent_header.base_fee_per_gas,
280
    )
281
    if expected_base_fee_per_gas != header.base_fee_per_gas:
282
        raise InvalidBlock
283
    if header.timestamp <= parent_header.timestamp:
284
        raise InvalidBlock
285
    if header.number != parent_header.number + 1:
286
        raise InvalidBlock
287
    if len(header.extra_data) > 32:
288
        raise InvalidBlock
289
    if header.difficulty != 0:
290
        raise InvalidBlock
291
    if header.nonce != b"\x00\x00\x00\x00\x00\x00\x00\x00":
292
        raise InvalidBlock
293
    if header.ommers_hash != EMPTY_OMMER_HASH:
294
        raise InvalidBlock
295
296
    block_parent_hash = keccak256(rlp.encode(parent_header))
297
    if header.parent_hash != block_parent_hash:
298
        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]:
307
    """
308
    Check if the transaction is includable in the block.
309
310
    Parameters
311
    ----------
312
    tx :
313
        The transaction.
314
    base_fee_per_gas :
315
        The block base fee.
316
    gas_available :
317
        The gas remaining in the block.
318
    chain_id :
319
        The ID of the current chain.
320
321
    Returns
322
    -------
323
    sender_address :
324
        The sender of the transaction.
325
    effective_gas_price :
326
        The price to charge for gas when the transaction is executed.
327
328
    Raises
329
    ------
330
    InvalidBlock :
331
        If the transaction is not includable.
332
    """
333
    if tx.gas > gas_available:
334
        raise InvalidBlock
335
    sender_address = recover_sender(chain_id, tx)
336
337
    if isinstance(tx, FeeMarketTransaction):
338
        if tx.max_fee_per_gas < tx.max_priority_fee_per_gas:
339
            raise InvalidBlock
340
        if tx.max_fee_per_gas < base_fee_per_gas:
341
            raise InvalidBlock
342
343
        priority_fee_per_gas = min(
344
            tx.max_priority_fee_per_gas,
345
            tx.max_fee_per_gas - base_fee_per_gas,
346
        )
347
        effective_gas_price = priority_fee_per_gas + base_fee_per_gas
348
    else:
349
        if tx.gas_price < base_fee_per_gas:
350
            raise InvalidBlock
351
        effective_gas_price = tx.gas_price
352
353
    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. 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]:
362
    """
363
    Make the receipt for a transaction that was executed.
364
365
    Parameters
366
    ----------
367
    tx :
368
        The executed transaction.
369
    error :
370
        The error from the execution if any.
371
    cumulative_gas_used :
372
        The total gas used so far in the block after the transaction was
373
        executed.
374
    logs :
375
        The logs produced by the transaction.
376
377
    Returns
378
    -------
379
    receipt :
380
        The receipt for the transaction.
381
    """
382
    receipt = Receipt(
383
        succeeded=error is None,
384
        cumulative_gas_used=cumulative_gas_used,
385
        bloom=logs_bloom(logs),
386
        logs=logs,
387
    )
388
389
    if isinstance(tx, AccessListTransaction):
390
        return b"\x01" + rlp.encode(receipt)
391
    elif isinstance(tx, FeeMarketTransaction):
392
        return b"\x02" + rlp.encode(receipt)
393
    else:
394
        return receipt

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.

397
@dataclass
class ApplyBodyOutput:

block_gas_used

417
    block_gas_used: Uint

transactions_root

418
    transactions_root: Root

receipt_root

419
    receipt_root: Root

block_logs_bloom

420
    block_logs_bloom: Bloom

state_root

421
    state_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.

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

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.Environment, ​​tx: Transaction) -> Tuple[Uint, Tuple[Log, ...], Optional[Exception]]:
543
    """
544
    Execute a transaction against the provided environment.
545
546
    This function processes the actions needed to execute a transaction.
547
    It decrements the sender's account after calculating the gas fee and
548
    refunds them the proper amount after execution. Calling contracts,
549
    deploying code, and incrementing nonces are all examples of actions that
550
    happen within this function or from a call made within this function.
551
552
    Accounts that are marked for deletion are processed and destroyed after
553
    execution.
554
555
    Parameters
556
    ----------
557
    env :
558
        Environment for the Ethereum Virtual Machine.
559
    tx :
560
        Transaction to execute.
561
562
    Returns
563
    -------
564
    gas_left : `ethereum.base_types.U256`
565
        Remaining gas after execution.
566
    logs : `Tuple[ethereum.blocks.Log, ...]`
567
        Logs generated during execution.
568
    """
569
    if not validate_transaction(tx):
570
        raise InvalidBlock
571
572
    sender = env.origin
573
    sender_account = get_account(env.state, sender)
574
575
    if isinstance(tx, FeeMarketTransaction):
576
        max_gas_fee = tx.gas * tx.max_fee_per_gas
577
    else:
578
        max_gas_fee = tx.gas * tx.gas_price
579
    if sender_account.nonce != tx.nonce:
580
        raise InvalidBlock
581
    if sender_account.balance < max_gas_fee + tx.value:
582
        raise InvalidBlock
583
    if sender_account.code != bytearray():
584
        raise 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
    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

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:
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
    return calculate_intrinsic_cost(tx) <= tx.gas and tx.nonce < 2**64 - 1

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:
683
    """
684
    Calculates the gas that is charged before execution is started.
685
686
    The intrinsic cost of the transaction is charged before execution has
687
    begun. Functions/operations in the EVM cost money to execute so this
688
    intrinsic cost is for the operations that need to be paid for as part of
689
    the transaction. Data transfer, for example, is part of this intrinsic
690
    cost. It costs ether to send data over the wire and that ether is
691
    accounted for in the intrinsic cost calculated in this function. This
692
    intrinsic cost must be calculated and paid for before execution in order
693
    for all operations to be implemented.
694
695
    Parameters
696
    ----------
697
    tx :
698
        Transaction to compute the intrinsic cost of.
699
700
    Returns
701
    -------
702
    verified : `ethereum.base_types.Uint`
703
        The intrinsic cost of the transaction.
704
    """
705
    data_cost = 0
706
707
    for byte in tx.data:
708
        if byte == 0:
709
            data_cost += TX_DATA_COST_PER_ZERO
710
        else:
711
            data_cost += TX_DATA_COST_PER_NON_ZERO
712
713
    if tx.to == Bytes0(b""):
714
        create_cost = TX_CREATE_COST
715
    else:
716
        create_cost = 0
717
718
    access_list_cost = 0
719
    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
720
        for _address, keys in tx.access_list:
721
            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
722
            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
723
724
    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:
728
    """
729
    Extracts the sender address from a transaction.
730
731
    The v, r, and s values are the three parts that make up the signature
732
    of a transaction. In order to recover the sender of a transaction the two
733
    components needed are the signature (``v``, ``r``, and ``s``) and the
734
    signing hash of the transaction. The sender's public key can be obtained
735
    with these two values and therefore the sender address can be retrieved.
736
737
    Parameters
738
    ----------
739
    tx :
740
        Transaction of interest.
741
    chain_id :
742
        ID of the executing chain.
743
744
    Returns
745
    -------
746
    sender : `ethereum.fork_types.Address`
747
        The address of the account that signed the transaction.
748
    """
749
    r, s = tx.r, tx.s
750
    if 0 >= r or r >= SECP256K1N:
751
        raise InvalidBlock
752
    if 0 >= s or s > SECP256K1N // 2:
753
        raise InvalidBlock
754
755
    if isinstance(tx, LegacyTransaction):
756
        v = tx.v
757
        if v == 27 or v == 28:
758
            public_key = secp256k1_recover(
759
                r, s, v - 27, signing_hash_pre155(tx)
760
            )
761
        else:
762
            if v != 35 + chain_id * 2 and v != 36 + chain_id * 2:
763
                raise InvalidBlock
764
            public_key = secp256k1_recover(
765
                r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id)
766
            )
767
    elif isinstance(tx, AccessListTransaction):
768
        public_key = secp256k1_recover(
769
            r, s, tx.y_parity, signing_hash_2930(tx)
770
        )
771
    elif isinstance(tx, FeeMarketTransaction):
772
        public_key = secp256k1_recover(
773
            r, s, tx.y_parity, signing_hash_1559(tx)
774
        )
775
776
    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:
780
    """
781
    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
782
783
    Parameters
784
    ----------
785
    tx :
786
        Transaction of interest.
787
788
    Returns
789
    -------
790
    hash : `ethereum.crypto.hash.Hash32`
791
        Hash of the transaction.
792
    """
793
    return keccak256(
794
        rlp.encode(
795
            (
796
                tx.nonce,
797
                tx.gas_price,
798
                tx.gas,
799
                tx.to,
800
                tx.value,
801
                tx.data,
802
            )
803
        )
804
    )

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:
808
    """
809
    Compute the hash of a transaction used in a EIP 155 signature.
810
811
    Parameters
812
    ----------
813
    tx :
814
        Transaction of interest.
815
    chain_id :
816
        The id of the current chain.
817
818
    Returns
819
    -------
820
    hash : `ethereum.crypto.hash.Hash32`
821
        Hash of the transaction.
822
    """
823
    return keccak256(
824
        rlp.encode(
825
            (
826
                tx.nonce,
827
                tx.gas_price,
828
                tx.gas,
829
                tx.to,
830
                tx.value,
831
                tx.data,
832
                chain_id,
833
                Uint(0),
834
                Uint(0),
835
            )
836
        )
837
    )

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:
841
    """
842
    Compute the hash of a transaction used in a EIP 2930 signature.
843
844
    Parameters
845
    ----------
846
    tx :
847
        Transaction of interest.
848
849
    Returns
850
    -------
851
    hash : `ethereum.crypto.hash.Hash32`
852
        Hash of the transaction.
853
    """
854
    return keccak256(
855
        b"\x01"
856
        + rlp.encode(
857
            (
858
                tx.chain_id,
859
                tx.nonce,
860
                tx.gas_price,
861
                tx.gas,
862
                tx.to,
863
                tx.value,
864
                tx.data,
865
                tx.access_list,
866
            )
867
        )
868
    )

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:
872
    """
873
    Compute the hash of a transaction used in a EIP 1559 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"\x02"
887
        + rlp.encode(
888
            (
889
                tx.chain_id,
890
                tx.nonce,
891
                tx.max_priority_fee_per_gas,
892
                tx.max_fee_per_gas,
893
                tx.gas,
894
                tx.to,
895
                tx.value,
896
                tx.data,
897
                tx.access_list,
898
            )
899
        )
900
    )

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