ethereum.gray_glacier.forkethereum.paris.fork

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

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

Introduction

Entry point for the Ethereum specification.

BLOCK_REWARD

59
BLOCK_REWARD = U256(2 * 10**18)

BASE_FEE_MAX_CHANGE_DENOMINATOR

57
BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8)

ELASTICITY_MULTIPLIER

58
ELASTICITY_MULTIPLIER = Uint(2)

GAS_LIMIT_ADJUSTMENT_FACTOR

59
GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024)

GAS_LIMIT_MINIMUM

60
GAS_LIMIT_MINIMUM = Uint(5000)

MINIMUM_DIFFICULTY

64
MINIMUM_DIFFICULTY = Uint(131072)

MAX_OMMER_DEPTH

65
MAX_OMMER_DEPTH = Uint(6)

BOMB_DELAY_BLOCKS

66
BOMB_DELAY_BLOCKS = 11400000

EMPTY_OMMER_HASH

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

BlockChain

History and current state of the block chain.

64
@dataclass
class BlockChain:

blocks

70
    blocks: List[Block]

state

71
    state: State

chain_id

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

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

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

generate_header_hash_for_pow

Generate rlp hash of the header which is to be used for Proof-of-Work verification.

In other words, the PoW artefacts mix_digest and nonce are ignored while calculating this hash.

A particular PoW is valid for a single hash, that hash is computed by this function. The nonce and mix_digest are omitted from this hash because they are being changed by miners in their search for a sufficient proof-of-work.

Parameters

header : The header object for which the hash is to be generated.

Returns

hash : Hash32 The PoW valid rlp hash of the passed in header.

def generate_header_hash_for_pow(header: Header) -> Hash32:
319
    """
320
    Generate rlp hash of the header which is to be used for Proof-of-Work
321
    verification.
322
323
    In other words, the PoW artefacts `mix_digest` and `nonce` are ignored
324
    while calculating this hash.
325
326
    A particular PoW is valid for a single hash, that hash is computed by
327
    this function. The `nonce` and `mix_digest` are omitted from this hash
328
    because they are being changed by miners in their search for a sufficient
329
    proof-of-work.
330
331
    Parameters
332
    ----------
333
    header :
334
        The header object for which the hash is to be generated.
335
336
    Returns
337
    -------
338
    hash : `Hash32`
339
        The PoW valid rlp hash of the passed in header.
340
    """
341
    header_data_without_pow_artefacts = (
342
        header.parent_hash,
343
        header.ommers_hash,
344
        header.coinbase,
345
        header.state_root,
346
        header.transactions_root,
347
        header.receipt_root,
348
        header.bloom,
349
        header.difficulty,
350
        header.number,
351
        header.gas_limit,
352
        header.gas_used,
353
        header.timestamp,
354
        header.extra_data,
355
        header.base_fee_per_gas,
356
    )
357
358
    return rlp.rlp_hash(header_data_without_pow_artefacts)

validate_proof_of_work

Validates the Proof of Work constraints.

In order to verify that a miner's proof-of-work is valid for a block, a mix-digest and result are calculated using the hashimoto_light hash function. The mix digest is a hash of the header and the nonce that is passed through and it confirms whether or not proof-of-work was done on the correct block. The result is the actual hash value of the block.

Parameters

header : Header of interest.

def validate_proof_of_work(header: Header) -> None:
362
    """
363
    Validates the Proof of Work constraints.
364
365
    In order to verify that a miner's proof-of-work is valid for a block, a
366
    ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``
367
    hash function. The mix digest is a hash of the header and the nonce that
368
    is passed through and it confirms whether or not proof-of-work was done
369
    on the correct block. The result is the actual hash value of the block.
370
371
    Parameters
372
    ----------
373
    header :
374
        Header of interest.
375
    """
376
    header_hash = generate_header_hash_for_pow(header)
377
    # TODO: Memoize this somewhere and read from that data instead of
378
    # calculating cache for every block validation.
379
    cache = generate_cache(header.number)
380
    mix_digest, result = hashimoto_light(
381
        header_hash, header.nonce, cache, dataset_size(header.number)
382
    )
383
    if mix_digest != header.mix_digest:
384
        raise InvalidBlock
385
386
    limit = Uint(U256.MAX_VALUE) + Uint(1)
387
    if Uint.from_be_bytes(result) > (limit // header.difficulty):
388
        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]:
310
    """
311
    Check if the transaction is includable in the block.
312
313
    Parameters
314
    ----------
315
    tx :
316
        The transaction.
317
    base_fee_per_gas :
318
        The block base fee.
319
    gas_available :
320
        The gas remaining in the block.
321
    chain_id :
322
        The ID of the current chain.
323
324
    Returns
325
    -------
326
    sender_address :
327
        The sender of the transaction.
328
    effective_gas_price :
329
        The price to charge for gas when the transaction is executed.
330
331
    Raises
332
    ------
333
    InvalidBlock :
334
        If the transaction is not includable.
335
    """
336
    if tx.gas > gas_available:
337
        raise InvalidBlock
338
    sender_address = recover_sender(chain_id, tx)
339
340
    if isinstance(tx, FeeMarketTransaction):
341
        if tx.max_fee_per_gas < tx.max_priority_fee_per_gas:
342
            raise InvalidBlock
343
        if tx.max_fee_per_gas < base_fee_per_gas:
344
            raise InvalidBlock
345
346
        priority_fee_per_gas = min(
347
            tx.max_priority_fee_per_gas,
348
            tx.max_fee_per_gas - base_fee_per_gas,
349
        )
350
        effective_gas_price = priority_fee_per_gas + base_fee_per_gas
351
    else:
352
        if tx.gas_price < base_fee_per_gas:
353
            raise InvalidBlock
354
        effective_gas_price = tx.gas_price
355
356
    return sender_address, effective_gas_price

make_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.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]:
365
    """
366
    Make the receipt for a transaction that was executed.
367
368
    Parameters
369
    ----------
370
    tx :
371
        The executed transaction.
372
    error :
460
        Error in the top level frame of the transaction, if any.
373
        The error from the execution if any.
374
    cumulative_gas_used :
375
        The total gas used so far in the block after the transaction was
376
        executed.
377
    logs :
378
        The logs produced by the transaction.
379
380
    Returns
381
    -------
382
    receipt :
383
        The receipt for the transaction.
384
    """
385
    receipt = Receipt(
386
        succeeded=error is None,
387
        cumulative_gas_used=cumulative_gas_used,
388
        bloom=logs_bloom(logs),
389
        logs=logs,
390
    )
391
392
    if isinstance(tx, AccessListTransaction):
393
        return b"\x01" + rlp.encode(receipt)
394
    elif isinstance(tx, FeeMarketTransaction):
395
        return b"\x02" + rlp.encode(receipt)
396
    else:
397
        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.

400
@dataclass
class ApplyBodyOutput:

block_gas_used

420
    block_gas_used: Uint

transactions_root

421
    transactions_root: Root

receipt_root

422
    receipt_root: Root

block_logs_bloom

423
    block_logs_bloom: Bloom

state_root

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

validate_ommers

Validates the ommers mentioned in the block.

An ommer block is a block that wasn't canonically added to the blockchain because it wasn't validated as fast as the canonical block but was mined at the same time.

To be considered valid, the ommers must adhere to the rules defined in the Ethereum protocol. The maximum amount of ommers is 2 per block and there cannot be duplicate ommers in a block. Many of the other ommer constraints are listed in the in-line comments of this function.

Parameters

ommers : List of ommers mentioned in the current block. block_header: The header of current block. chain : History and current state.

def validate_ommers(ommers: Tuple[Header, ...], ​​block_header: Header, ​​chain: BlockChain) -> None:
636
    """
637
    Validates the ommers mentioned in the block.
638
639
    An ommer block is a block that wasn't canonically added to the
640
    blockchain because it wasn't validated as fast as the canonical block
641
    but was mined at the same time.
642
643
    To be considered valid, the ommers must adhere to the rules defined in
644
    the Ethereum protocol. The maximum amount of ommers is 2 per block and
645
    there cannot be duplicate ommers in a block. Many of the other ommer
646
    constraints are listed in the in-line comments of this function.
647
648
    Parameters
649
    ----------
650
    ommers :
651
        List of ommers mentioned in the current block.
652
    block_header:
653
        The header of current block.
654
    chain :
655
        History and current state.
656
    """
657
    block_hash = rlp.rlp_hash(block_header)
658
    if rlp.rlp_hash(ommers) != block_header.ommers_hash:
659
        raise InvalidBlock
660
661
    if len(ommers) == 0:
662
        # Nothing to validate
663
        return
664
665
    # Check that each ommer satisfies the constraints of a header
666
    for ommer in ommers:
667
        if Uint(1) > ommer.number or ommer.number >= block_header.number:
668
            raise InvalidBlock
669
        ommer_parent_header = chain.blocks[
670
            -(block_header.number - ommer.number) - 1
671
        ].header
672
        validate_header(ommer, ommer_parent_header)
673
    if len(ommers) > 2:
674
        raise InvalidBlock
675
676
    ommers_hashes = [rlp.rlp_hash(ommer) for ommer in ommers]
677
    if len(ommers_hashes) != len(set(ommers_hashes)):
678
        raise InvalidBlock
679
680
    recent_canonical_blocks = chain.blocks[-(MAX_OMMER_DEPTH + Uint(1)) :]
681
    recent_canonical_block_hashes = {
682
        rlp.rlp_hash(block.header) for block in recent_canonical_blocks
683
    }
684
    recent_ommers_hashes: Set[Hash32] = set()
685
    for block in recent_canonical_blocks:
686
        recent_ommers_hashes = recent_ommers_hashes.union(
687
            {rlp.rlp_hash(ommer) for ommer in block.ommers}
688
        )
689
690
    for ommer_index, ommer in enumerate(ommers):
691
        ommer_hash = ommers_hashes[ommer_index]
692
        if ommer_hash == block_hash:
693
            raise InvalidBlock
694
        if ommer_hash in recent_canonical_block_hashes:
695
            raise InvalidBlock
696
        if ommer_hash in recent_ommers_hashes:
697
            raise InvalidBlock
698
699
        # Ommer age with respect to the current block. For example, an age of
700
        # 1 indicates that the ommer is a sibling of previous block.
701
        ommer_age = block_header.number - ommer.number
702
        if Uint(1) > ommer_age or ommer_age > MAX_OMMER_DEPTH:
703
            raise InvalidBlock
704
        if ommer.parent_hash not in recent_canonical_block_hashes:
705
            raise InvalidBlock
706
        if ommer.parent_hash == block_header.parent_hash:
707
            raise InvalidBlock

pay_rewards

Pay rewards to the block miner as well as the ommers miners.

The miner of the canonical block is rewarded with the predetermined block reward, BLOCK_REWARD, plus a variable award based off of the number of ommer blocks that were mined around the same time, and included in the canonical block's header. An ommer block is a block that wasn't added to the canonical blockchain because it wasn't validated as fast as the accepted block but was mined at the same time. Although not all blocks that are mined are added to the canonical chain, miners are still paid a reward for their efforts. This reward is called an ommer reward and is calculated based on the number associated with the ommer block that they mined.

Parameters

state : Current account state. block_number : Position of the block within the chain. coinbase : Address of account which receives block reward and transaction fees. ommers : List of ommers mentioned in the current block.

def pay_rewards(state: State, ​​block_number: Uint, ​​coinbase: Address, ​​ommers: Tuple[Header, ...]) -> None:
716
    """
717
    Pay rewards to the block miner as well as the ommers miners.
718
719
    The miner of the canonical block is rewarded with the predetermined
720
    block reward, ``BLOCK_REWARD``, plus a variable award based off of the
721
    number of ommer blocks that were mined around the same time, and included
722
    in the canonical block's header. An ommer block is a block that wasn't
723
    added to the canonical blockchain because it wasn't validated as fast as
724
    the accepted block but was mined at the same time. Although not all blocks
725
    that are mined are added to the canonical chain, miners are still paid a
726
    reward for their efforts. This reward is called an ommer reward and is
727
    calculated based on the number associated with the ommer block that they
728
    mined.
729
730
    Parameters
731
    ----------
732
    state :
733
        Current account state.
734
    block_number :
735
        Position of the block within the chain.
736
    coinbase :
737
        Address of account which receives block reward and transaction fees.
738
    ommers :
739
        List of ommers mentioned in the current block.
740
    """
741
    ommer_count = U256(len(ommers))
742
    miner_reward = BLOCK_REWARD + (ommer_count * (BLOCK_REWARD // U256(32)))
743
    create_ether(state, coinbase, miner_reward)
744
745
    for ommer in ommers:
746
        # Ommer age with respect to the current block.
747
        ommer_age = U256(block_number - ommer.number)
748
        ommer_miner_reward = ((U256(8) - ommer_age) * BLOCK_REWARD) // U256(8)
749
        create_ether(state, ommer.coinbase, ommer_miner_reward)

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.gray_glacier.vm.Environmentethereum.paris.vm.Environment, ​​tx: Transaction) -> 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.blocks.Log, ...]`
570
        Logs generated during execution.
571
    """
572
    if not validate_transaction(tx):
573
        raise InvalidBlock
574
575
    sender = env.origin
576
    sender_account = get_account(env.state, sender)
577
787
    max_gas_fee: Uint
578
    if isinstance(tx, FeeMarketTransaction):
789
        max_gas_fee = Uint(tx.gas) * Uint(tx.max_fee_per_gas)
579
        max_gas_fee = tx.gas * tx.max_fee_per_gas
580
    else:
791
        max_gas_fee = Uint(tx.gas) * Uint(tx.gas_price)
581
        max_gas_fee = tx.gas * tx.gas_price
582
    if sender_account.nonce != tx.nonce:
583
        raise InvalidBlock
584
    if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
585
        raise InvalidBlock
586
    if sender_account.code != bytearray():
587
        raise InvalidSenderError("not EOA")
588
589
    effective_gas_fee = tx.gas * env.gas_price
590
591
    gas = tx.gas - calculate_intrinsic_cost(tx)
592
    increment_nonce(env.state, sender)
593
594
    sender_balance_after_gas_fee = (
595
        Uint(sender_account.balance) - effective_gas_fee
596
    )
597
    set_account_balance(env.state, sender, U256(sender_balance_after_gas_fee))
598
599
    preaccessed_addresses = set()
600
    preaccessed_storage_keys = set()
601
    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
602
        for address, keys in tx.access_list:
603
            preaccessed_addresses.add(address)
604
            for key in keys:
605
                preaccessed_storage_keys.add((address, key))
606
607
    message = prepare_message(
608
        sender,
609
        tx.to,
610
        tx.value,
611
        tx.data,
612
        gas,
613
        env,
614
        preaccessed_addresses=frozenset(preaccessed_addresses),
615
        preaccessed_storage_keys=frozenset(preaccessed_storage_keys),
616
    )
617
618
    output = process_message_call(message, env)
619
620
    gas_used = tx.gas - output.gas_left
621
    gas_refund = min(gas_used // Uint(5), Uint(output.refund_counter))
622
    gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price
623
624
    # For non-1559 transactions env.gas_price == tx.gas_price
625
    priority_fee_per_gas = env.gas_price - env.base_fee_per_gas
626
    transaction_fee = (
627
        tx.gas - output.gas_left - gas_refund
628
    ) * priority_fee_per_gas
629
630
    total_gas_used = gas_used - gas_refund
631
632
    # refund gas
633
    sender_balance_after_refund = get_account(
634
        env.state, sender
635
    ).balance + U256(gas_refund_amount)
636
    set_account_balance(env.state, sender, sender_balance_after_refund)
637
638
    # transfer miner fees
639
    coinbase_balance_after_mining_fee = get_account(
640
        env.state, env.coinbase
641
    ).balance + U256(transaction_fee)
642
    if coinbase_balance_after_mining_fee != 0:
643
        set_account_balance(
644
            env.state, env.coinbase, coinbase_balance_after_mining_fee
645
        )
646
    elif account_exists_and_is_empty(env.state, env.coinbase):
647
        destroy_account(env.state, env.coinbase)
648
649
    for address in output.accounts_to_delete:
650
        destroy_account(env.state, address)
651
652
    for address in output.touched_accounts:
653
        if account_exists_and_is_empty(env.state, address):
654
            destroy_account(env.state, address)
655
656
    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:
660
    """
661
    Verifies a transaction.
662
663
    The gas in a transaction gets used to pay for the intrinsic cost of
664
    operations, therefore if there is insufficient gas then it would not
665
    be possible to execute a transaction and it will be declared invalid.
666
667
    Additionally, the nonce of a transaction must not equal or exceed the
668
    limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
669
    In practice, defining the limit as ``2**64-1`` has no impact because
670
    sending ``2**64-1`` transactions is improbable. It's not strictly
671
    impossible though, ``2**64-1`` transactions is the entire capacity of the
672
    Ethereum blockchain at 2022 gas limits for a little over 22 years.
673
674
    Parameters
675
    ----------
676
    tx :
677
        Transaction to validate.
678
679
    Returns
680
    -------
681
    verified : `bool`
682
        True if the transaction can be executed, or False otherwise.
683
    """
894
    if calculate_intrinsic_cost(tx) > Uint(tx.gas):
684
    if calculate_intrinsic_cost(tx) > tx.gas:
685
        return False
686
    if tx.nonce >= U256(U64.MAX_VALUE):
687
        return False
688
    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:
692
    """
693
    Calculates the gas that is charged before execution is started.
694
695
    The intrinsic cost of the transaction is charged before execution has
696
    begun. Functions/operations in the EVM cost money to execute so this
697
    intrinsic cost is for the operations that need to be paid for as part of
698
    the transaction. Data transfer, for example, is part of this intrinsic
699
    cost. It costs ether to send data over the wire and that ether is
700
    accounted for in the intrinsic cost calculated in this function. This
701
    intrinsic cost must be calculated and paid for before execution in order
702
    for all operations to be implemented.
703
704
    Parameters
705
    ----------
706
    tx :
707
        Transaction to compute the intrinsic cost of.
708
709
    Returns
710
    -------
711
    verified : `ethereum.base_types.Uint`
712
        The intrinsic cost of the transaction.
713
    """
714
    data_cost = 0
715
716
    for byte in tx.data:
717
        if byte == 0:
718
            data_cost += TX_DATA_COST_PER_ZERO
719
        else:
720
            data_cost += TX_DATA_COST_PER_NON_ZERO
721
722
    if tx.to == Bytes0(b""):
723
        create_cost = TX_CREATE_COST
724
    else:
725
        create_cost = 0
726
727
    access_list_cost = 0
728
    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
729
        for _address, keys in tx.access_list:
730
            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
731
            access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
732
733
    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:
737
    """
738
    Extracts the sender address from a transaction.
739
740
    The v, r, and s values are the three parts that make up the signature
741
    of a transaction. In order to recover the sender of a transaction the two
742
    components needed are the signature (``v``, ``r``, and ``s``) and the
743
    signing hash of the transaction. The sender's public key can be obtained
744
    with these two values and therefore the sender address can be retrieved.
745
746
    Parameters
747
    ----------
748
    tx :
749
        Transaction of interest.
750
    chain_id :
751
        ID of the executing chain.
752
753
    Returns
754
    -------
755
    sender : `ethereum.fork_types.Address`
756
        The address of the account that signed the transaction.
757
    """
758
    r, s = tx.r, tx.s
759
    if U256(0) >= r or r >= SECP256K1N:
760
        raise InvalidBlock
761
    if U256(0) >= s or s > SECP256K1N // U256(2):
762
        raise InvalidBlock
763
764
    if isinstance(tx, LegacyTransaction):
765
        v = tx.v
766
        if v == 27 or v == 28:
767
            public_key = secp256k1_recover(
768
                r, s, v - U256(27), signing_hash_pre155(tx)
769
            )
770
        else:
771
            chain_id_x2 = U256(chain_id) * U256(2)
772
            if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
773
                raise InvalidBlock
774
            public_key = secp256k1_recover(
775
                r,
776
                s,
777
                v - U256(35) - chain_id_x2,
778
                signing_hash_155(tx, chain_id),
779
            )
780
    elif isinstance(tx, AccessListTransaction):
781
        public_key = secp256k1_recover(
782
            r, s, tx.y_parity, signing_hash_2930(tx)
783
        )
784
    elif isinstance(tx, FeeMarketTransaction):
785
        public_key = secp256k1_recover(
786
            r, s, tx.y_parity, signing_hash_1559(tx)
787
        )
788
789
    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:
793
    """
794
    Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
795
796
    Parameters
797
    ----------
798
    tx :
799
        Transaction of interest.
800
801
    Returns
802
    -------
803
    hash : `ethereum.crypto.hash.Hash32`
804
        Hash of the transaction.
805
    """
806
    return keccak256(
807
        rlp.encode(
808
            (
809
                tx.nonce,
810
                tx.gas_price,
811
                tx.gas,
812
                tx.to,
813
                tx.value,
814
                tx.data,
815
            )
816
        )
817
    )

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:
821
    """
822
    Compute the hash of a transaction used in a EIP 155 signature.
823
824
    Parameters
825
    ----------
826
    tx :
827
        Transaction of interest.
828
    chain_id :
829
        The id of the current chain.
830
831
    Returns
832
    -------
833
    hash : `ethereum.crypto.hash.Hash32`
834
        Hash of the transaction.
835
    """
836
    return keccak256(
837
        rlp.encode(
838
            (
839
                tx.nonce,
840
                tx.gas_price,
841
                tx.gas,
842
                tx.to,
843
                tx.value,
844
                tx.data,
845
                chain_id,
846
                Uint(0),
847
                Uint(0),
848
            )
849
        )
850
    )

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:
854
    """
855
    Compute the hash of a transaction used in a EIP 2930 signature.
856
857
    Parameters
858
    ----------
859
    tx :
860
        Transaction of interest.
861
862
    Returns
863
    -------
864
    hash : `ethereum.crypto.hash.Hash32`
865
        Hash of the transaction.
866
    """
867
    return keccak256(
868
        b"\x01"
869
        + rlp.encode(
870
            (
871
                tx.chain_id,
872
                tx.nonce,
873
                tx.gas_price,
874
                tx.gas,
875
                tx.to,
876
                tx.value,
877
                tx.data,
878
                tx.access_list,
879
            )
880
        )
881
    )

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:
885
    """
886
    Compute the hash of a transaction used in a EIP 1559 signature.
887
888
    Parameters
889
    ----------
890
    tx :
891
        Transaction of interest.
892
893
    Returns
894
    -------
895
    hash : `ethereum.crypto.hash.Hash32`
896
        Hash of the transaction.
897
    """
898
    return keccak256(
899
        b"\x02"
900
        + rlp.encode(
901
            (
902
                tx.chain_id,
903
                tx.nonce,
904
                tx.max_priority_fee_per_gas,
905
                tx.max_fee_per_gas,
906
                tx.gas,
907
                tx.to,
908
                tx.value,
909
                tx.data,
910
                tx.access_list,
911
            )
912
        )
913
    )

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

calculate_block_difficulty

Computes difficulty of a block using its header and parent header.

The difficulty is determined by the time the block was created after its parent. The offset is calculated using the parent block's difficulty, parent_difficulty, and the timestamp between blocks. This offset is then added to the parent difficulty and is stored as the difficulty variable. If the time between the block and its parent is too short, the offset will result in a positive number thus making the sum of parent_difficulty and offset to be a greater value in order to avoid mass forking. But, if the time is long enough, then the offset results in a negative value making the block less difficult than its parent.

The base standard for a block's difficulty is the predefined value set for the genesis block since it has no parent. So, a block can't be less difficult than the genesis block, therefore each block's difficulty is set to the maximum value between the calculated difficulty and the GENESIS_DIFFICULTY.

Parameters

block_number : Block number of the block. block_timestamp : Timestamp of the block. parent_timestamp : Timestamp of the parent block. parent_difficulty : difficulty of the parent block. parent_has_ommers: does the parent have ommers.

Returns

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

def calculate_block_difficulty(block_number: Uint, ​​block_timestamp: U256, ​​parent_timestamp: U256, ​​parent_difficulty: Uint, ​​parent_has_ommers: bool) -> Uint:
1207
    """
1208
    Computes difficulty of a block using its header and parent header.
1209
1210
    The difficulty is determined by the time the block was created after its
1211
    parent. The ``offset`` is calculated using the parent block's difficulty,
1212
    ``parent_difficulty``, and the timestamp between blocks. This offset is
1213
    then added to the parent difficulty and is stored as the ``difficulty``
1214
    variable. If the time between the block and its parent is too short, the
1215
    offset will result in a positive number thus making the sum of
1216
    ``parent_difficulty`` and ``offset`` to be a greater value in order to
1217
    avoid mass forking. But, if the time is long enough, then the offset
1218
    results in a negative value making the block less difficult than
1219
    its parent.
1220
1221
    The base standard for a block's difficulty is the predefined value
1222
    set for the genesis block since it has no parent. So, a block
1223
    can't be less difficult than the genesis block, therefore each block's
1224
    difficulty is set to the maximum value between the calculated
1225
    difficulty and the ``GENESIS_DIFFICULTY``.
1226
1227
    Parameters
1228
    ----------
1229
    block_number :
1230
        Block number of the block.
1231
    block_timestamp :
1232
        Timestamp of the block.
1233
    parent_timestamp :
1234
        Timestamp of the parent block.
1235
    parent_difficulty :
1236
        difficulty of the parent block.
1237
    parent_has_ommers:
1238
        does the parent have ommers.
1239
1240
    Returns
1241
    -------
1242
    difficulty : `ethereum.base_types.Uint`
1243
        Computed difficulty for a block.
1244
    """
1245
    offset = (
1246
        int(parent_difficulty)
1247
        // 2048
1248
        * max(
1249
            (2 if parent_has_ommers else 1)
1250
            - int(block_timestamp - parent_timestamp) // 9,
1251
            -99,
1252
        )
1253
    )
1254
    difficulty = int(parent_difficulty) + offset
1255
    # Historical Note: The difficulty bomb was not present in Ethereum at the
1256
    # start of Frontier, but was added shortly after launch. However since the
1257
    # bomb has no effect prior to block 200000 we pretend it existed from
1258
    # genesis.
1259
    # See https://github.com/ethereum/go-ethereum/pull/1588
1260
    num_bomb_periods = ((int(block_number) - BOMB_DELAY_BLOCKS) // 100000) - 2
1261
    if num_bomb_periods >= 0:
1262
        difficulty += 2**num_bomb_periods
1263
1264
    # Some clients raise the difficulty to `MINIMUM_DIFFICULTY` prior to adding
1265
    # the bomb. This bug does not matter because the difficulty is always much
1266
    # greater than `MINIMUM_DIFFICULTY` on Mainnet.
1267
    return Uint(max(difficulty, int(MINIMUM_DIFFICULTY)))