ethereum.forks.bpo5.forkethereum.forks.amsterdam.fork

Ethereum Specification.

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

Introduction

Entry point for the Ethereum specification.

BASE_FEE_MAX_CHANGE_DENOMINATOR

107
BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8)

ELASTICITY_MULTIPLIER

108
ELASTICITY_MULTIPLIER = Uint(2)

GAS_LIMIT_ADJUSTMENT_FACTOR

109
GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024)

GAS_LIMIT_MINIMUM

110
GAS_LIMIT_MINIMUM = Uint(5000)

EMPTY_OMMER_HASH

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

SYSTEM_ADDRESS

112
SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe")

BEACON_ROOTS_ADDRESS

113
BEACON_ROOTS_ADDRESS = hex_to_address(
114
    "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"
115
)

SYSTEM_TRANSACTION_GAS

116
SYSTEM_TRANSACTION_GAS = Uint(30000000)

MAX_BLOB_GAS_PER_BLOCK

117
MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB

VERSIONED_HASH_VERSION_KZG

118
VERSIONED_HASH_VERSION_KZG = b"\x01"

GWEI_TO_WEI

119
GWEI_TO_WEI = U256(10**9)

WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS

121
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address(
122
    "0x00000961Ef480Eb55e80D19ad83579A64c007002"
123
)

CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS

124
CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS = hex_to_address(
125
    "0x0000BBdDc7CE488642fb579F8B00f3a590007251"
126
)

HISTORY_STORAGE_ADDRESS

127
HISTORY_STORAGE_ADDRESS = hex_to_address(
128
    "0x0000F90827F1C53a10cb7A02335B175320002935"
129
)

MAX_BLOCK_SIZE

130
MAX_BLOCK_SIZE = 10_485_760

SAFETY_MARGIN

131
SAFETY_MARGIN = 2_097_152

MAX_RLP_BLOCK_SIZE

132
MAX_RLP_BLOCK_SIZE = MAX_BLOCK_SIZE - SAFETY_MARGIN

BLOB_COUNT_LIMIT

133
BLOB_COUNT_LIMIT = 6

ChainContext

Chain context needed for block execution.

136
@slotted_freezable
137
@dataclass
class ChainContext:

chain_id

Identify the chain for transaction signature recovery.

143
    chain_id: U64

block_hashes

Recent ancestor hashes (up to 256) for the BLOCKHASH opcode.

146
    block_hashes: List[Hash32]

parent_header

Parent header used for header validation and system contracts.

149
    parent_header: Header | PreviousHeader

BlockChain

History and current state of the block chain.

153
@dataclass
class BlockChain:

blocks

159
    blocks: List[Block]

state

160
    state: State

chain_id

161
    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:
165
    """
166
    Transforms the state from the previous hard fork (`old`) into the block
167
    chain object for this hard fork and returns it.
168
169
    When forks need to implement an irregular state transition, this function
170
    is used to handle the irregularity. See the :ref:`DAO Fork <dao-fork>` for
171
    an example.
172
173
    Parameters
174
    ----------
175
    old :
176
        Previous block chain object.
177
178
    Returns
179
    -------
180
    new : `BlockChain`
181
        Upgraded block chain object for this hard fork.
182
183
    """
184
    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]:
188
    """
189
    Obtain the list of hashes of the previous 256 blocks in order of
190
    increasing block number.
191
192
    This function will return less hashes for the first 256 blocks.
193
194
    The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,
195
    therefore this function retrieves them.
196
197
    Parameters
198
    ----------
199
    chain :
200
        History and current state.
201
202
    Returns
203
    -------
204
    recent_block_hashes : `List[Hash32]`
205
        Hashes of the recent 256 blocks in order of increasing block number.
206
207
    """
208
    recent_blocks = chain.blocks[-255:]
209
    # TODO: This function has not been tested rigorously
210
    if len(recent_blocks) == 0:
211
        return []
212
213
    recent_block_hashes = []
214
215
    for block in recent_blocks:
216
        prev_block_hash = block.header.parent_hash
217
        recent_block_hashes.append(prev_block_hash)
218
219
    # We are computing the hash only for the most recent block and not for
220
    # the rest of the blocks as they have successors which have the hash of
221
    # the current block as parent hash.
222
    most_recent_block_hash = keccak256(rlp.encode(recent_blocks[-1].header))
223
    recent_block_hashes.append(most_recent_block_hash)
224
225
    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:
229
    """
230
    Attempts to apply a block to an existing block chain.
231
232
    All parts of the block's contents need to be verified before being added
233
    to the chain. Blocks are verified by ensuring that the contents of the
234
    block make logical sense with the contents of the parent block. The
235
    information in the block's header must also match the corresponding
236
    information in the block.
237
238
    To implement Ethereum, in theory clients are only required to store the
239
    most recent 255 blocks of the chain since as far as execution is
240
    concerned, only those blocks are accessed. Practically, however, clients
241
    should store more blocks to handle reorgs.
242
243
    Parameters
244
    ----------
245
    chain :
246
        History and current state.
247
    block :
248
        Block to apply to `chain`.
249
250
    """
219
    if len(rlp.encode(block)) > MAX_RLP_BLOCK_SIZE:
220
        raise InvalidBlock("Block rlp size exceeds MAX_RLP_BLOCK_SIZE")
221
222
    validate_header(chain, block.header)
223
    if block.ommers != ():
224
        raise InvalidBlock
225
226
    block_env = vm.BlockEnvironment(
251
    chain_context = ChainContext(
252
        chain_id=chain.chain_id,
228
        state=chain.state,
229
        block_gas_limit=block.header.gas_limit,
253
        block_hashes=get_last_256_block_hashes(chain),
231
        coinbase=block.header.coinbase,
232
        number=block.header.number,
233
        base_fee_per_gas=block.header.base_fee_per_gas,
234
        time=block.header.timestamp,
235
        prev_randao=block.header.prev_randao,
236
        excess_blob_gas=block.header.excess_blob_gas,
237
        parent_beacon_block_root=block.header.parent_beacon_block_root,
254
        parent_header=chain.blocks[-1].header,
255
    )
256
240
    block_output = apply_body(
241
        block_env=block_env,
242
        transactions=block.transactions,
243
        withdrawals=block.withdrawals,
244
    )
245
    block_state_root = state_root(block_env.state)
246
    transactions_root = root(block_output.transactions_trie)
247
    receipt_root = root(block_output.receipts_trie)
248
    block_logs_bloom = logs_bloom(block_output.block_logs)
249
    withdrawals_root = root(block_output.withdrawals_trie)
250
    requests_hash = compute_requests_hash(block_output.requests)
257
    block_diff = execute_block(block, chain.state, chain_context)
258
252
    if block_output.block_gas_used != block.header.gas_used:
253
        raise InvalidBlock(
254
            f"{block_output.block_gas_used} != {block.header.gas_used}"
255
        )
256
    if transactions_root != block.header.transactions_root:
257
        raise InvalidBlock
258
    if block_state_root != block.header.state_root:
259
        raise InvalidBlock
260
    if receipt_root != block.header.receipt_root:
261
        raise InvalidBlock
262
    if block_logs_bloom != block.header.bloom:
263
        raise InvalidBlock
264
    if withdrawals_root != block.header.withdrawals_root:
265
        raise InvalidBlock
266
    if block_output.blob_gas_used != block.header.blob_gas_used:
267
        raise InvalidBlock
268
    if requests_hash != block.header.requests_hash:
269
        raise InvalidBlock
270
259
    apply_changes_to_state(chain.state, block_diff)
260
    chain.blocks.append(block)
261
    if len(chain.blocks) > 255:
262
        # Real clients have to store more blocks to deal with reorgs, but the
263
        # protocol only requires the last 255
264
        chain.blocks = chain.blocks[-255:]

execute_block

Execute a block and validate the resulting roots against the header.

This method is idempotent.

Parameters

block : Block to validate and execute. pre_state : Pre-execution state provider. chain_context : Chain context that the block may need during execution.

Returns

block_diff : BlockDiff Account, storage, and code changes produced by block execution.

def execute_block(block: Block, ​​pre_state: PreState, ​​chain_context: ChainContext) -> BlockDiff:
272
    """
273
    Execute a block and validate the resulting roots against the header.
274
275
    This method is idempotent.
276
277
    Parameters
278
    ----------
279
    block :
280
        Block to validate and execute.
281
    pre_state :
282
        Pre-execution state provider.
283
    chain_context :
284
        Chain context that the block may need during execution.
285
286
    Returns
287
    -------
288
    block_diff : `BlockDiff`
289
        Account, storage, and code changes produced by block execution.
290
291
    """
292
    if len(rlp.encode(block)) > MAX_RLP_BLOCK_SIZE:
293
        raise InvalidBlock("Block rlp size exceeds MAX_RLP_BLOCK_SIZE")
294
295
    parent_header = chain_context.parent_header
296
    validate_header(parent_header, block.header)
297
298
    if block.ommers != ():
299
        raise InvalidBlock
300
301
    block_state = BlockState(pre_state=pre_state)
302
303
    block_env = vm.BlockEnvironment(
304
        chain_id=chain_context.chain_id,
305
        state=block_state,
306
        block_gas_limit=block.header.gas_limit,
307
        block_hashes=chain_context.block_hashes,
308
        coinbase=block.header.coinbase,
309
        number=block.header.number,
310
        base_fee_per_gas=block.header.base_fee_per_gas,
311
        time=block.header.timestamp,
312
        prev_randao=block.header.prev_randao,
313
        excess_blob_gas=block.header.excess_blob_gas,
314
        parent_beacon_block_root=block.header.parent_beacon_block_root,
315
        block_access_list_builder=BlockAccessListBuilder(),
316
    )
317
318
    block_output = apply_body(
319
        block_env=block_env,
320
        transactions=block.transactions,
321
        withdrawals=block.withdrawals,
322
    )
323
    block_diff = extract_block_diff(block_state)
324
    block_state_root, _ = pre_state.compute_state_root_and_trie_changes(
325
        block_diff.account_changes, block_diff.storage_changes
326
    )
327
    transactions_root = root(block_output.transactions_trie)
328
    receipt_root = root(block_output.receipts_trie)
329
    block_logs_bloom = logs_bloom(block_output.block_logs)
330
    withdrawals_root = root(block_output.withdrawals_trie)
331
    requests_hash = compute_requests_hash(block_output.requests)
332
    computed_block_access_list_hash = hash_block_access_list(
333
        block_output.block_access_list
334
    )
335
336
    if block_output.block_gas_used != block.header.gas_used:
337
        raise InvalidBlock(
338
            f"{block_output.block_gas_used} != {block.header.gas_used}"
339
        )
340
    if transactions_root != block.header.transactions_root:
341
        raise InvalidBlock
342
    if block_state_root != block.header.state_root:
343
        raise InvalidBlock
344
    if receipt_root != block.header.receipt_root:
345
        raise InvalidBlock
346
    if block_logs_bloom != block.header.bloom:
347
        raise InvalidBlock
348
    if withdrawals_root != block.header.withdrawals_root:
349
        raise InvalidBlock
350
    if block_output.blob_gas_used != block.header.blob_gas_used:
351
        raise InvalidBlock
352
    if requests_hash != block.header.requests_hash:
353
        raise InvalidBlock
354
    if computed_block_access_list_hash != block.header.block_access_list_hash:
355
        raise InvalidBlock("Invalid block access list hash")
356
357
    return block_diff

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:
366
    """
367
    Calculates the base fee per gas for the block.
368
369
    Parameters
370
    ----------
371
    block_gas_limit :
372
        Gas limit of the block for which the base fee is being calculated.
373
    parent_gas_limit :
374
        Gas limit of the parent block.
375
    parent_gas_used :
376
        Gas used in the parent block.
377
    parent_base_fee_per_gas :
378
        Base fee per gas of the parent block.
379
380
    Returns
381
    -------
382
    base_fee_per_gas : `Uint`
383
        Base fee per gas for the block.
384
385
    """
386
    parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER
387
    if not check_gas_limit(block_gas_limit, parent_gas_limit):
388
        raise InvalidBlock
389
390
    if parent_gas_used == parent_gas_target:
391
        expected_base_fee_per_gas = parent_base_fee_per_gas
392
    elif parent_gas_used > parent_gas_target:
393
        gas_used_delta = parent_gas_used - parent_gas_target
394
395
        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
396
        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
397
398
        base_fee_per_gas_delta = max(
399
            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR,
400
            Uint(1),
401
        )
402
403
        expected_base_fee_per_gas = (
404
            parent_base_fee_per_gas + base_fee_per_gas_delta
405
        )
406
    else:
407
        gas_used_delta = parent_gas_target - parent_gas_used
408
409
        parent_fee_gas_delta = parent_base_fee_per_gas * gas_used_delta
410
        target_fee_gas_delta = parent_fee_gas_delta // parent_gas_target
411
412
        base_fee_per_gas_delta = (
413
            target_fee_gas_delta // BASE_FEE_MAX_CHANGE_DENOMINATOR
414
        )
415
416
        expected_base_fee_per_gas = (
417
            parent_base_fee_per_gas - base_fee_per_gas_delta
418
        )
419
420
    return Uint(expected_base_fee_per_gas)

validate_header

Verifies a block header.Verify a block header against its parent.

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

chain :parent_header : History and current state.Header of the parent block. header : Header to check for correctness.

def validate_header(chainparent_header: BlockChainHeader | PreviousHeader, ​​header: Header) -> None:
426
    """
343
    Verifies a block header.
427
    Verify a block header against its parent.
428
429
    In order to consider a block's header valid, the logic for the
430
    quantities in the header should match the logic for the block itself.
431
    For example the header timestamp should be greater than the block's parent
432
    timestamp because the block was created *after* the parent block.
433
    Additionally, the block's number should be directly following the parent
434
    block's number since it is the next block in the sequence.
435
436
    Parameters
437
    ----------
354
    chain :
355
        History and current state.
438
    parent_header :
439
        Header of the parent block.
440
    header :
441
        Header to check for correctness.
442
443
    """
444
    if header.number < Uint(1):
445
        raise InvalidBlock
362
363
    parent_header = chain.blocks[-1].header
446
447
    excess_blob_gas = calculate_excess_blob_gas(parent_header)
448
    if header.excess_blob_gas != excess_blob_gas:
449
        raise InvalidBlock
450
451
    if header.gas_used > header.gas_limit:
452
        raise InvalidBlock
453
454
    expected_base_fee_per_gas = calculate_base_fee_per_gas(
455
        header.gas_limit,
456
        parent_header.gas_limit,
457
        parent_header.gas_used,
458
        parent_header.base_fee_per_gas,
459
    )
460
    if expected_base_fee_per_gas != header.base_fee_per_gas:
461
        raise InvalidBlock
462
    if header.timestamp <= parent_header.timestamp:
463
        raise InvalidBlock
464
    if header.number != parent_header.number + Uint(1):
465
        raise InvalidBlock
466
    if len(header.extra_data) > 32:
467
        raise InvalidBlock
468
    if header.difficulty != 0:
469
        raise InvalidBlock
470
    if header.nonce != b"\x00\x00\x00\x00\x00\x00\x00\x00":
471
        raise InvalidBlock
472
    if header.ommers_hash != EMPTY_OMMER_HASH:
473
        raise InvalidBlock
474
475
    block_parent_hash = keccak256(rlp.encode(parent_header))
476
    if header.parent_hash != block_parent_hash:
477
        raise InvalidBlock

check_transaction

Check if the transaction is includable in the block.

Parameters

block_env : The block scoped environment. block_output : The block output for the current block. tx : The transaction. tx_state : The transaction state tracker.

Returns

sender_address : The sender of the transaction. effective_gas_price : The price to charge for gas when the transaction is executed. blob_versioned_hashes : The blob versioned hashes of the transaction. tx_blob_gas_used: The blob gas used by the transaction.

Raises

InvalidBlock : If the transaction is not includable. GasUsedExceedsLimitError : If the gas used by the transaction exceeds the block's gas limit. NonceMismatchError : If the nonce of the transaction is not equal to the sender's nonce. InsufficientBalanceError : If the sender's balance is not enough to pay for the transaction. InvalidSenderError : If the transaction is from an address that does not exist anymore. PriorityFeeGreaterThanMaxFeeError : If the priority fee is greater than the maximum fee per gas. InsufficientMaxFeePerGasError : If the maximum fee per gas is insufficient for the transaction. InsufficientMaxFeePerBlobGasError : If the maximum fee per blob gas is insufficient for the transaction. BlobGasLimitExceededError : If the blob gas used by the transaction exceeds the block's blob gas limit. InvalidBlobVersionedHashError : If the transaction contains a blob versioned hash with an invalid version. NoBlobDataError : If the transaction is a type 3 but has no blobs. BlobCountExceededError : If the transaction is a type 3 and has more blobs than the limit. TransactionTypeContractCreationError: If the transaction type is not allowed to create contracts. EmptyAuthorizationListError : If the transaction is a SetCodeTransaction and the authorization list is empty.

def check_transaction(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​block_output: ethereum.forks.bpo5.vm.BlockOutputethereum.forks.amsterdam.vm.BlockOutput, ​​tx: Transaction, ​​tx_state: TransactionState) -> Tuple[Address, Uint, Tuple[VersionedHash, ...], U64]:
486
    """
487
    Check if the transaction is includable in the block.
488
489
    Parameters
490
    ----------
491
    block_env :
492
        The block scoped environment.
493
    block_output :
494
        The block output for the current block.
495
    tx :
496
        The transaction.
497
    tx_state :
498
        The transaction state tracker.
499
500
    Returns
501
    -------
502
    sender_address :
503
        The sender of the transaction.
504
    effective_gas_price :
505
        The price to charge for gas when the transaction is executed.
506
    blob_versioned_hashes :
507
        The blob versioned hashes of the transaction.
508
    tx_blob_gas_used:
509
        The blob gas used by the transaction.
510
511
    Raises
512
    ------
513
    InvalidBlock :
514
        If the transaction is not includable.
515
    GasUsedExceedsLimitError :
516
        If the gas used by the transaction exceeds the block's gas limit.
517
    NonceMismatchError :
518
        If the nonce of the transaction is not equal to the sender's nonce.
519
    InsufficientBalanceError :
520
        If the sender's balance is not enough to pay for the transaction.
521
    InvalidSenderError :
522
        If the transaction is from an address that does not exist anymore.
523
    PriorityFeeGreaterThanMaxFeeError :
524
        If the priority fee is greater than the maximum fee per gas.
525
    InsufficientMaxFeePerGasError :
526
        If the maximum fee per gas is insufficient for the transaction.
527
    InsufficientMaxFeePerBlobGasError :
528
        If the maximum fee per blob gas is insufficient for the transaction.
529
    BlobGasLimitExceededError :
530
        If the blob gas used by the transaction exceeds the block's blob gas
531
        limit.
532
    InvalidBlobVersionedHashError :
533
        If the transaction contains a blob versioned hash with an invalid
534
        version.
535
    NoBlobDataError :
536
        If the transaction is a type 3 but has no blobs.
537
    BlobCountExceededError :
538
        If the transaction is a type 3 and has more blobs than the limit.
539
    TransactionTypeContractCreationError:
540
        If the transaction type is not allowed to create contracts.
541
    EmptyAuthorizationListError :
542
        If the transaction is a SetCodeTransaction and the authorization list
543
        is empty.
544
545
    """
546
    gas_available = block_env.block_gas_limit - block_output.block_gas_used
547
    blob_gas_available = MAX_BLOB_GAS_PER_BLOCK - block_output.blob_gas_used
548
549
    if tx.gas > gas_available:
550
        raise GasUsedExceedsLimitError("gas used exceeds limit")
551
552
    tx_blob_gas_used = calculate_total_blob_gas(tx)
553
    if tx_blob_gas_used > blob_gas_available:
554
        raise BlobGasLimitExceededError("blob gas limit exceeded")
555
556
    sender_address = recover_sender(block_env.chain_id, tx)
472
    sender_account = get_account(block_env.state, sender_address)
557
    sender_account = get_account(tx_state, sender_address)
558
559
    if isinstance(
560
        tx, (FeeMarketTransaction, BlobTransaction, SetCodeTransaction)
561
    ):
562
        if tx.max_fee_per_gas < tx.max_priority_fee_per_gas:
563
            raise PriorityFeeGreaterThanMaxFeeError(
564
                "priority fee greater than max fee"
565
            )
566
        if tx.max_fee_per_gas < block_env.base_fee_per_gas:
567
            raise InsufficientMaxFeePerGasError(
568
                tx.max_fee_per_gas, block_env.base_fee_per_gas
569
            )
570
571
        priority_fee_per_gas = min(
572
            tx.max_priority_fee_per_gas,
573
            tx.max_fee_per_gas - block_env.base_fee_per_gas,
574
        )
575
        effective_gas_price = priority_fee_per_gas + block_env.base_fee_per_gas
576
        max_gas_fee = tx.gas * tx.max_fee_per_gas
577
    else:
578
        if tx.gas_price < block_env.base_fee_per_gas:
579
            raise InvalidBlock
580
        effective_gas_price = tx.gas_price
581
        max_gas_fee = tx.gas * tx.gas_price
582
583
    if isinstance(tx, BlobTransaction):
584
        blob_count = len(tx.blob_versioned_hashes)
585
        if blob_count == 0:
586
            raise NoBlobDataError("no blob data in transaction")
587
        if blob_count > BLOB_COUNT_LIMIT:
588
            raise BlobCountExceededError(
589
                f"Tx has {blob_count} blobs. Max allowed: {BLOB_COUNT_LIMIT}"
590
            )
591
        for blob_versioned_hash in tx.blob_versioned_hashes:
592
            if blob_versioned_hash[0:1] != VERSIONED_HASH_VERSION_KZG:
593
                raise InvalidBlobVersionedHashError(
594
                    "invalid blob versioned hash"
595
                )
596
597
        blob_gas_price = calculate_blob_gas_price(block_env.excess_blob_gas)
598
        if Uint(tx.max_fee_per_blob_gas) < blob_gas_price:
599
            raise InsufficientMaxFeePerBlobGasError(
600
                "insufficient max fee per blob gas"
601
            )
602
603
        max_gas_fee += Uint(calculate_total_blob_gas(tx)) * Uint(
604
            tx.max_fee_per_blob_gas
605
        )
606
        blob_versioned_hashes = tx.blob_versioned_hashes
607
    else:
608
        blob_versioned_hashes = ()
609
610
    if isinstance(tx, (BlobTransaction, SetCodeTransaction)):
611
        if not isinstance(tx.to, Address):
612
            raise TransactionTypeContractCreationError(tx)
613
614
    if isinstance(tx, SetCodeTransaction):
615
        if not any(tx.authorizations):
616
            raise EmptyAuthorizationListError("empty authorization list")
617
618
    if sender_account.nonce > Uint(tx.nonce):
619
        raise NonceMismatchError("nonce too low")
620
    elif sender_account.nonce < Uint(tx.nonce):
621
        raise NonceMismatchError("nonce too high")
622
623
    if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
624
        raise InsufficientBalanceError("insufficient sender balance")
540
    sender_code = get_code(block_env.state, sender_account.code_hash)
625
    sender_code = get_code(tx_state, sender_account.code_hash)
626
    if sender_account.code_hash != EMPTY_CODE_HASH and not is_valid_delegation(
627
        sender_code
628
    ):
629
        raise InvalidSenderError("not EOA")
630
631
    return (
632
        sender_address,
633
        effective_gas_price,
634
        blob_versioned_hashes,
635
        tx_blob_gas_used,
636
    )

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. 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[EthereumException], ​​cumulative_gas_used: Uint, ​​logs: Tuple[Log, ...]) -> Bytes | Receipt:
645
    """
646
    Make the receipt for a transaction that was executed.
647
648
    Parameters
649
    ----------
650
    tx :
651
        The executed transaction.
652
    error :
653
        Error in the top level frame of the transaction, if any.
654
    cumulative_gas_used :
655
        The total gas used so far in the block after the transaction was
656
        executed.
657
    logs :
658
        The logs produced by the transaction.
659
660
    Returns
661
    -------
662
    receipt :
663
        The receipt for the transaction.
664
665
    """
666
    receipt = Receipt(
667
        succeeded=error is None,
668
        cumulative_gas_used=cumulative_gas_used,
669
        bloom=logs_bloom(logs),
670
        logs=logs,
671
    )
672
673
    return encode_receipt(tx, receipt)

process_system_transaction

Process a system transaction with the given code.

Prefer calling process_checked_system_transaction or process_unchecked_system_transaction depending on whether missing code or an execution error should cause the block to be rejected.

Parameters

block_env : The block scoped environment. target_address : Address of the contract to call. system_contract_code : Code of the contract to call. data : Data to pass to the contract.

Returns

system_tx_output : MessageCallOutput Output of processing the system transaction.

def process_system_transaction(block_env: ethereum.forks.bpo5.vm.BlockEnvironment, ​​target_address: Address, ​​system_contract_code: Bytes, ​​data: Bytes) -> MessageCallOutput:
597
    """
598
    Process a system transaction with the given code.
599
600
    Prefer calling `process_checked_system_transaction` or
601
    `process_unchecked_system_transaction` depending on whether missing code or
602
    an execution error should cause the block to be rejected.
603
604
    Parameters
605
    ----------
606
    block_env :
607
        The block scoped environment.
608
    target_address :
609
        Address of the contract to call.
610
    system_contract_code :
611
        Code of the contract to call.
612
    data :
613
        Data to pass to the contract.
614
615
    Returns
616
    -------
617
    system_tx_output : `MessageCallOutput`
618
        Output of processing the system transaction.
619
620
    """
621
    tx_env = vm.TransactionEnvironment(
622
        origin=SYSTEM_ADDRESS,
623
        gas_price=block_env.base_fee_per_gas,
624
        gas=SYSTEM_TRANSACTION_GAS,
625
        access_list_addresses=set(),
626
        access_list_storage_keys=set(),
627
        transient_storage=TransientStorage(),
628
        blob_versioned_hashes=(),
629
        authorizations=(),
630
        index_in_block=None,
631
        tx_hash=None,
632
    )
633
634
    system_tx_message = Message(
635
        block_env=block_env,
636
        tx_env=tx_env,
637
        caller=SYSTEM_ADDRESS,
638
        target=target_address,
639
        gas=SYSTEM_TRANSACTION_GAS,
640
        value=U256(0),
641
        data=data,
642
        code=system_contract_code,
643
        depth=Uint(0),
644
        current_target=target_address,
645
        code_address=target_address,
646
        should_transfer_value=False,
647
        is_static=False,
648
        accessed_addresses=set(),
649
        accessed_storage_keys=set(),
650
        disable_precompiles=False,
651
        parent_evm=None,
652
    )
653
654
    system_tx_output = process_message_call(system_tx_message)
655
656
    return system_tx_output

process_checked_system_transaction

Process a system transaction and raise an error if the contract does not contain code or if the transaction fails.

Parameters

block_env : The block scoped environment. target_address : Address of the contract to call. data : Data to pass to the contract.

Returns

system_tx_output : MessageCallOutput Output of processing the system transaction.

def process_checked_system_transaction(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​target_address: Address, ​​data: Bytes) -> MessageCallOutput:
681
    """
682
    Process a system transaction and raise an error if the contract does not
683
    contain code or if the transaction fails.
684
685
    Parameters
686
    ----------
687
    block_env :
688
        The block scoped environment.
689
    target_address :
690
        Address of the contract to call.
691
    data :
692
        Data to pass to the contract.
693
694
    Returns
695
    -------
696
    system_tx_output : `MessageCallOutput`
697
        Output of processing the system transaction.
698
699
    """
683
    system_contract_code = get_code(
684
        block_env.state,
685
        get_account(block_env.state, target_address).code_hash,
700
    # Read through BlockState (not pre-state) so that a system contract
701
    # deployed by an earlier transaction in the same block is visible.
702
    # See EIP-7002 and EIP-7251 for this edge case.
703
    #
704
    # This read is not recorded in the state tracker.
705
    # However, this is fine because `process_unchecked_system_transaction`
706
    # does its own get_account on the TransactionState that we do incorporate
707
    # into BlockState.
708
    untracked_state = TransactionState(parent=block_env.state)
709
    system_contract_code = get_code(
710
        untracked_state,
711
        get_account(untracked_state, target_address).code_hash,
712
    )
713
714
    if len(system_contract_code) == 0:
715
        raise InvalidBlock(
716
            f"System contract address {target_address.hex()} does not "
717
            "contain code"
718
        )
719
694
    system_tx_output = process_system_transaction(
720
    system_tx_output = process_unchecked_system_transaction(
721
        block_env,
722
        target_address,
697
        system_contract_code,
723
        data,
724
    )
725
726
    if system_tx_output.error:
727
        raise InvalidBlock(
728
            f"System contract ({target_address.hex()}) call failed: "
729
            f"{system_tx_output.error}"
730
        )
731
732
    return system_tx_output

process_unchecked_system_transaction

Process a system transaction without checking if the contract contains codeProcess a system transaction without checking if the contract contains or if the transaction fails.code or if the transaction fails.

Parameters

block_env : The block scoped environment. target_address : Address of the contract to call. data : Data to pass to the contract.

Returns

system_tx_output : MessageCallOutput Output of processing the system transaction.

def process_unchecked_system_transaction(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​target_address: Address, ​​data: Bytes) -> MessageCallOutput:
740
    """
716
    Process a system transaction without checking if the contract contains code
717
    or if the transaction fails.
741
    Process a system transaction without checking if the contract contains
742
    code or if the transaction fails.
743
744
    Parameters
745
    ----------
746
    block_env :
747
        The block scoped environment.
748
    target_address :
749
        Address of the contract to call.
750
    data :
751
        Data to pass to the contract.
752
753
    Returns
754
    -------
755
    system_tx_output : `MessageCallOutput`
756
        Output of processing the system transaction.
757
758
    """
734
    system_contract_code = get_code(
735
        block_env.state,
736
        get_account(block_env.state, target_address).code_hash,
759
    system_tx_state = TransactionState(parent=block_env.state)
760
    system_contract_code = get_code(
761
        system_tx_state,
762
        get_account(system_tx_state, target_address).code_hash,
763
    )
738
    return process_system_transaction(
739
        block_env,
740
        target_address,
741
        system_contract_code,
742
        data,
743
    )
764
765
    tx_env = vm.TransactionEnvironment(
766
        origin=SYSTEM_ADDRESS,
767
        gas_price=block_env.base_fee_per_gas,
768
        gas=SYSTEM_TRANSACTION_GAS,
769
        access_list_addresses=set(),
770
        access_list_storage_keys=set(),
771
        state=system_tx_state,
772
        blob_versioned_hashes=(),
773
        authorizations=(),
774
        index_in_block=None,
775
        tx_hash=None,
776
    )
777
778
    system_tx_message = Message(
779
        block_env=block_env,
780
        tx_env=tx_env,
781
        caller=SYSTEM_ADDRESS,
782
        target=target_address,
783
        gas=SYSTEM_TRANSACTION_GAS,
784
        value=U256(0),
785
        data=data,
786
        code=system_contract_code,
787
        depth=Uint(0),
788
        current_target=target_address,
789
        code_address=target_address,
790
        should_transfer_value=False,
791
        is_static=False,
792
        accessed_addresses=set(),
793
        accessed_storage_keys=set(),
794
        disable_precompiles=False,
795
        parent_evm=None,
796
        is_create=False,
797
    )
798
799
    system_tx_output = process_message_call(system_tx_message)
800
801
    incorporate_tx_into_block(
802
        system_tx_state, block_env.block_access_list_builder
803
    )
804
805
    return system_tx_output

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

block_env : The block scoped environment. transactions : Transactions included in the block. withdrawals : Withdrawals to be processed in the current block.

Returns

block_output : The block output for the current block.

def apply_body(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​transactions: Tuple[LegacyTransaction | Bytes, ...], ​​withdrawals: Tuple[Withdrawal, ...]) -> ethereum.forks.bpo5.vm.BlockOutputethereum.forks.amsterdam.vm.BlockOutput:
813
    """
814
    Executes a block.
815
816
    Many of the contents of a block are stored in data structures called
817
    tries. There is a transactions trie which is similar to a ledger of the
818
    transactions stored in the current block. There is also a receipts trie
819
    which stores the results of executing a transaction, like the post state
820
    and gas used. This function creates and executes the block that is to be
821
    added to the chain.
822
823
    Parameters
824
    ----------
825
    block_env :
826
        The block scoped environment.
827
    transactions :
828
        Transactions included in the block.
829
    withdrawals :
830
        Withdrawals to be processed in the current block.
831
832
    Returns
833
    -------
834
    block_output :
835
        The block output for the current block.
836
837
    """
838
    block_output = vm.BlockOutput()
839
840
    process_unchecked_system_transaction(
841
        block_env=block_env,
842
        target_address=BEACON_ROOTS_ADDRESS,
843
        data=block_env.parent_beacon_block_root,
844
    )
845
846
    process_unchecked_system_transaction(
847
        block_env=block_env,
848
        target_address=HISTORY_STORAGE_ADDRESS,
849
        data=block_env.block_hashes[-1],  # The parent hash
850
    )
851
852
    for i, tx in enumerate(map(decode_transaction, transactions)):
853
        process_transaction(block_env, block_output, tx, Uint(i))
854
855
    # EIP-7928: Post-execution operations use index N+1
856
    block_env.block_access_list_builder.block_access_index = BlockAccessIndex(
857
        Uint(len(transactions)) + Uint(1)
858
    )
859
860
    process_withdrawals(block_env, block_output, withdrawals)
861
862
    process_general_purpose_requests(
863
        block_env=block_env,
864
        block_output=block_output,
865
    )
866
867
    block_output.block_access_list = build_block_access_list(
868
        block_env.block_access_list_builder, block_env.state
869
    )
870
871
    # Validate block access list gas limit constraint (EIP-7928)
872
    validate_block_access_list_gas_limit(
873
        block_access_list=block_output.block_access_list,
874
        block_gas_limit=block_env.block_gas_limit,
875
    )
876
877
    return block_output

process_general_purpose_requests

Process all the requests in the block.

Parameters

block_env : The execution environment for the Block. block_output : The block output for the current block.

def process_general_purpose_requests(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​block_output: ethereum.forks.bpo5.vm.BlockOutputethereum.forks.amsterdam.vm.BlockOutput) -> None:
884
    """
885
    Process all the requests in the block.
886
887
    Parameters
888
    ----------
889
    block_env :
890
        The execution environment for the Block.
891
    block_output :
892
        The block output for the current block.
893
894
    """
895
    # Requests are to be in ascending order of request type
896
    deposit_requests = parse_deposit_requests(block_output)
897
    requests_from_execution = block_output.requests
898
    if len(deposit_requests) > 0:
899
        requests_from_execution.append(DEPOSIT_REQUEST_TYPE + deposit_requests)
900
901
    system_withdrawal_tx_output = process_checked_system_transaction(
902
        block_env=block_env,
903
        target_address=WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS,
904
        data=b"",
905
    )
906
907
    if len(system_withdrawal_tx_output.return_data) > 0:
908
        requests_from_execution.append(
909
            WITHDRAWAL_REQUEST_TYPE + system_withdrawal_tx_output.return_data
910
        )
911
912
    system_consolidation_tx_output = process_checked_system_transaction(
913
        block_env=block_env,
914
        target_address=CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS,
915
        data=b"",
916
    )
917
918
    if len(system_consolidation_tx_output.return_data) > 0:
919
        requests_from_execution.append(
920
            CONSOLIDATION_REQUEST_TYPE
921
            + system_consolidation_tx_output.return_data
922
        )

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 balance 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

block_env : Environment for the Ethereum Virtual Machine. block_output : The block output for the current block. tx : Transaction to execute. index: Index of the transaction in the block.

def process_transaction(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​block_output: ethereum.forks.bpo5.vm.BlockOutputethereum.forks.amsterdam.vm.BlockOutput, ​​tx: Transaction, ​​index: Uint) -> None:
931
    """
932
    Execute a transaction against the provided environment.
933
934
    This function processes the actions needed to execute a transaction.
935
    It decrements the sender's account balance after calculating the gas fee
936
    and refunds them the proper amount after execution. Calling contracts,
937
    deploying code, and incrementing nonces are all examples of actions that
938
    happen within this function or from a call made within this function.
939
940
    Accounts that are marked for deletion are processed and destroyed after
941
    execution.
942
943
    Parameters
944
    ----------
945
    block_env :
946
        Environment for the Ethereum Virtual Machine.
947
    block_output :
948
        The block output for the current block.
949
    tx :
950
        Transaction to execute.
951
    index:
952
        Index of the transaction in the block.
953
954
    """
955
    block_env.block_access_list_builder.block_access_index = BlockAccessIndex(
956
        index + Uint(1)
957
    )
958
    tx_state = TransactionState(parent=block_env.state)
959
960
    trie_set(
961
        block_output.transactions_trie,
962
        rlp.encode(index),
963
        encode_transaction(tx),
964
    )
965
966
    intrinsic_gas, calldata_floor_gas_cost = validate_transaction(tx)
967
968
    (
969
        sender,
970
        effective_gas_price,
971
        blob_versioned_hashes,
972
        tx_blob_gas_used,
973
    ) = check_transaction(
974
        block_env=block_env,
975
        block_output=block_output,
976
        tx=tx,
977
        tx_state=tx_state,
978
    )
979
897
    sender_account = get_account(block_env.state, sender)
980
    sender_account = get_account(tx_state, sender)
981
982
    if isinstance(tx, BlobTransaction):
983
        blob_gas_fee = calculate_data_fee(block_env.excess_blob_gas, tx)
984
    else:
985
        blob_gas_fee = Uint(0)
986
987
    effective_gas_fee = tx.gas * effective_gas_price
988
989
    gas = tx.gas - intrinsic_gas
907
    increment_nonce(block_env.state, sender)
990
991
    increment_nonce(tx_state, sender)
992
993
    sender_balance_after_gas_fee = (
994
        Uint(sender_account.balance) - effective_gas_fee - blob_gas_fee
995
    )
912
    set_account_balance(
913
        block_env.state, sender, U256(sender_balance_after_gas_fee)
914
    )
996
    set_account_balance(tx_state, sender, U256(sender_balance_after_gas_fee))
997
998
    access_list_addresses = set()
999
    access_list_storage_keys = set()
1000
    access_list_addresses.add(block_env.coinbase)
1001
    if isinstance(
1002
        tx,
1003
        (
1004
            AccessListTransaction,
1005
            FeeMarketTransaction,
1006
            BlobTransaction,
1007
            SetCodeTransaction,
1008
        ),
1009
    ):
1010
        for access in tx.access_list:
1011
            access_list_addresses.add(access.account)
1012
            for slot in access.slots:
1013
                access_list_storage_keys.add((access.account, slot))
1014
1015
    authorizations: Tuple[Authorization, ...] = ()
1016
    if isinstance(tx, SetCodeTransaction):
1017
        authorizations = tx.authorizations
1018
1019
    tx_env = vm.TransactionEnvironment(
1020
        origin=sender,
1021
        gas_price=effective_gas_price,
1022
        gas=gas,
1023
        access_list_addresses=access_list_addresses,
1024
        access_list_storage_keys=access_list_storage_keys,
943
        transient_storage=TransientStorage(),
1025
        state=tx_state,
1026
        blob_versioned_hashes=blob_versioned_hashes,
1027
        authorizations=authorizations,
1028
        index_in_block=index,
1029
        tx_hash=get_transaction_hash(encode_transaction(tx)),
1030
    )
1031
950
    message = prepare_message(block_env, tx_env, tx)
1032
    message = prepare_message(
1033
        block_env,
1034
        tx_env,
1035
        tx,
1036
    )
1037
1038
    tx_output = process_message_call(message)
1039
1040
    # For EIP-7623 we first calculate the execution_gas_used, which includes
1041
    # the execution gas refund.
1042
    tx_gas_used_before_refund = tx.gas - tx_output.gas_left
1043
    tx_gas_refund = min(
1044
        tx_gas_used_before_refund // Uint(5), Uint(tx_output.refund_counter)
1045
    )
1046
    tx_gas_used_after_refund = tx_gas_used_before_refund - tx_gas_refund
1047
1048
    # Transactions with less execution_gas_used than the floor pay at the
1049
    # floor cost.
1050
    tx_gas_used_after_refund = max(
1051
        tx_gas_used_after_refund, calldata_floor_gas_cost
1052
    )
1053
1054
    tx_gas_left = tx.gas - tx_gas_used_after_refund
1055
    gas_refund_amount = tx_gas_left * effective_gas_price
1056
1057
    # For non-1559 transactions effective_gas_price == tx.gas_price
1058
    priority_fee_per_gas = effective_gas_price - block_env.base_fee_per_gas
1059
    transaction_fee = tx_gas_used_after_refund * priority_fee_per_gas
1060
1061
    # refund gas
976
    sender_balance_after_refund = get_account(
977
        block_env.state, sender
978
    ).balance + U256(gas_refund_amount)
979
    set_account_balance(block_env.state, sender, sender_balance_after_refund)
1062
    sender_balance_after_refund = get_account(tx_state, sender).balance + U256(
1063
        gas_refund_amount
1064
    )
1065
    set_account_balance(tx_state, sender, sender_balance_after_refund)
1066
981
    # transfer miner fees
982
    coinbase_balance_after_mining_fee = get_account(
983
        block_env.state, block_env.coinbase
1067
    coinbase_balance_after_mining_fee = get_account(
1068
        tx_state, block_env.coinbase
1069
    ).balance + U256(transaction_fee)
985
    set_account_balance(
986
        block_env.state,
987
        block_env.coinbase,
988
        coinbase_balance_after_mining_fee,
1070
1071
    set_account_balance(
1072
        tx_state, block_env.coinbase, coinbase_balance_after_mining_fee
1073
    )
1074
991
    for address in tx_output.accounts_to_delete:
992
        destroy_account(block_env.state, address)
1075
    if coinbase_balance_after_mining_fee == 0 and account_exists_and_is_empty(
1076
        tx_state, block_env.coinbase
1077
    ):
1078
        destroy_account(tx_state, block_env.coinbase)
1079
1080
    block_output.block_gas_used += tx_gas_used_after_refund
1081
    block_output.blob_gas_used += tx_blob_gas_used
1082
1083
    receipt = make_receipt(
1084
        tx, tx_output.error, block_output.block_gas_used, tx_output.logs
1085
    )
1086
1087
    receipt_key = rlp.encode(Uint(index))
1088
    block_output.receipt_keys += (receipt_key,)
1089
1090
    trie_set(
1091
        block_output.receipts_trie,
1092
        receipt_key,
1093
        receipt,
1094
    )
1095
1010
    block_output.block_logs += tx_output.logs
1096
    block_output.block_logs += tx_output.logs
1097
1098
    for address in tx_output.accounts_to_delete:
1099
        destroy_account(tx_state, address)
1100
1101
    incorporate_tx_into_block(tx_state, block_env.block_access_list_builder)

process_withdrawals

Increase the balance of the withdrawing account.

def process_withdrawals(block_env: ethereum.forks.bpo5.vm.BlockEnvironmentethereum.forks.amsterdam.vm.BlockEnvironment, ​​block_output: ethereum.forks.bpo5.vm.BlockOutputethereum.forks.amsterdam.vm.BlockOutput, ​​withdrawals: Tuple[Withdrawal, ...]) -> None:
1109
    """
1110
    Increase the balance of the withdrawing account.
1111
    """
1021
1022
    def increase_recipient_balance(recipient: Account) -> None:
1023
        recipient.balance += wd.amount * U256(10**9)
1112
    wd_state = TransactionState(parent=block_env.state)
1113
1114
    for i, wd in enumerate(withdrawals):
1115
        trie_set(
1116
            block_output.withdrawals_trie,
1117
            rlp.encode(Uint(i)),
1118
            rlp.encode(wd),
1119
        )
1120
1032
        modify_state(block_env.state, wd.address, increase_recipient_balance)
1121
        current_balance = get_account(wd_state, wd.address).balance
1122
        new_balance = current_balance + wd.amount * GWEI_TO_WEI
1123
        set_account_balance(wd_state, wd.address, new_balance)
1124
1125
    incorporate_tx_into_block(wd_state, block_env.block_access_list_builder)

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:
1129
    """
1130
    Validates the gas limit for a block.
1131
1132
    The bounds of the gas limit, ``max_adjustment_delta``, is set as the
1133
    quotient of the parent block's gas limit and the
1134
    ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is
1135
    passed through as a parameter is greater than or equal to the *sum* of
1136
    the parent's gas and the adjustment delta then the limit for gas is too
1137
    high and fails this function's check. Similarly, if the limit is less
1138
    than or equal to the *difference* of the parent's gas and the adjustment
1139
    delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's
1140
    check fails because the gas limit doesn't allow for a sufficient or
1141
    reasonable amount of gas to be used on a block.
1142
1143
    Parameters
1144
    ----------
1145
    gas_limit :
1146
        Gas limit to validate.
1147
1148
    parent_gas_limit :
1149
        Gas limit of the parent block.
1150
1151
    Returns
1152
    -------
1153
    check : `bool`
1154
        True if gas limit constraints are satisfied, False otherwise.
1155
1156
    """
1157
    max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR
1158
    if gas_limit >= parent_gas_limit + max_adjustment_delta:
1159
        return False
1160
    if gas_limit <= parent_gas_limit - max_adjustment_delta:
1161
        return False
1162
    if gas_limit < GAS_LIMIT_MINIMUM:
1163
        return False
1164
1165
    return True