From ce05f6c68ec08ae0c7b5d4d2218bde363bcc8661 Mon Sep 17 00:00:00 2001 From: Milos Stankovic <82043364+morph-dev@users.noreply.github.com> Date: Thu, 4 Sep 2025 22:53:19 +0300 Subject: [PATCH 1/2] feat: add support for EIP-7782 (6 sec slots) --- src/ethereum/osaka/fork.py | 42 ++++++++++++++++++------------------ src/ethereum/osaka/vm/gas.py | 7 +++--- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/ethereum/osaka/fork.py b/src/ethereum/osaka/fork.py index 03d2955f2a..ecf1bde781 100644 --- a/src/ethereum/osaka/fork.py +++ b/src/ethereum/osaka/fork.py @@ -29,7 +29,7 @@ NonceMismatchError, ) -from . import vm +from . import FORK_CRITERIA, vm from .blocks import Block, Header, Log, Receipt, Withdrawal, encode_receipt from .bloom import logs_bloom from .exceptions import ( @@ -81,6 +81,7 @@ from .vm import Message from .vm.eoa_delegation import is_valid_delegation from .vm.gas import ( + MAX_BLOB_GAS_PER_BLOCK, calculate_blob_gas_price, calculate_data_fee, calculate_excess_blob_gas, @@ -88,17 +89,16 @@ ) from .vm.interpreter import MessageCallOutput, process_message_call -BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(8) +BASE_FEE_MAX_CHANGE_DENOMINATOR = Uint(16) # Doubled for EIP-7782 (was 8) ELASTICITY_MULTIPLIER = Uint(2) -GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(1024) -GAS_LIMIT_MINIMUM = Uint(5000) +GAS_LIMIT_ADJUSTMENT_FACTOR = Uint(2048) # Doubled for EIP-7782 (was 1024) +GAS_LIMIT_MINIMUM = Uint(2500) # Halved for EIP-7782 (was 5000) EMPTY_OMMER_HASH = keccak256(rlp.encode([])) SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe") BEACON_ROOTS_ADDRESS = hex_to_address( "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02" ) SYSTEM_TRANSACTION_GAS = Uint(30000000) -MAX_BLOB_GAS_PER_BLOCK = U64(1179648) VERSIONED_HASH_VERSION_KZG = b"\x01" WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address( @@ -110,11 +110,10 @@ HISTORY_STORAGE_ADDRESS = hex_to_address( "0x0000F90827F1C53a10cb7A02335B175320002935" ) -MAX_BLOCK_SIZE = 10_485_760 -SAFETY_MARGIN = 2_097_152 +MAX_BLOCK_SIZE = 5_242_880 # Halved for EIP-7782 (was 10_485_760) +SAFETY_MARGIN = 1_048_576 # Halved for EIP-7782 (was 2_097_152) MAX_RLP_BLOCK_SIZE = MAX_BLOCK_SIZE - SAFETY_MARGIN -BLOB_COUNT_LIMIT = 6 - +BLOB_COUNT_LIMIT = 3 # Halved for EIP-7782 (was 6) @dataclass class BlockChain: @@ -271,7 +270,6 @@ def state_transition(chain: BlockChain, block: Block) -> None: def calculate_base_fee_per_gas( - block_gas_limit: Uint, parent_gas_limit: Uint, parent_gas_used: Uint, parent_base_fee_per_gas: Uint, @@ -296,8 +294,6 @@ def calculate_base_fee_per_gas( Base fee per gas for the block. """ parent_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER - if not check_gas_limit(block_gas_limit, parent_gas_limit): - raise InvalidBlock if parent_gas_used == parent_gas_target: expected_base_fee_per_gas = parent_base_fee_per_gas @@ -361,13 +357,11 @@ def validate_header(chain: BlockChain, header: Header) -> None: if header.gas_used > header.gas_limit: raise InvalidBlock + + if not check_gas_limit(header.gas_limit, parent_header): + raise InvalidBlock - expected_base_fee_per_gas = calculate_base_fee_per_gas( - header.gas_limit, - parent_header.gas_limit, - parent_header.gas_used, - parent_header.base_fee_per_gas, - ) + expected_base_fee_per_gas = calculate_base_fee_per_gas(parent_header) if expected_base_fee_per_gas != header.base_fee_per_gas: raise InvalidBlock if header.timestamp <= parent_header.timestamp: @@ -1014,7 +1008,7 @@ def increase_recipient_balance(recipient: Account) -> None: destroy_account(block_env.state, wd.address) -def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: +def check_gas_limit(gas_limit: Uint, parent: Header) -> bool: """ Validates the gas limit for a block. @@ -1034,14 +1028,20 @@ def check_gas_limit(gas_limit: Uint, parent_gas_limit: Uint) -> bool: gas_limit : Gas limit to validate. - parent_gas_limit : - Gas limit of the parent block. + parent : + The parent block of the current block. Returns ------- check : `bool` True if gas limit constraints are satisfied, False otherwise. """ + parent_gas_limit = parent.gas_limit + + # If this is a fork block, use half of parent's gas limit (EIP-7782) + if not FORK_CRITERIA.check(parent.number, parent.timestamp): + parent_gas_limit /= 2 + max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: return False diff --git a/src/ethereum/osaka/vm/gas.py b/src/ethereum/osaka/vm/gas.py index e570fac5fc..8a01a4aba9 100644 --- a/src/ethereum/osaka/vm/gas.py +++ b/src/ethereum/osaka/vm/gas.py @@ -70,12 +70,13 @@ GAS_POINT_EVALUATION = Uint(50000) GAS_PER_BLOB = U64(2**17) -BLOB_SCHEDULE_TARGET = U64(6) +BLOB_SCHEDULE_TARGET = U64(3) # Halved for EIP-7782 (was 6) TARGET_BLOB_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET BLOB_BASE_COST = Uint(2**13) -BLOB_SCHEDULE_MAX = U64(9) +BLOB_SCHEDULE_MAX = U64(4) # Halved for EIP-7782 (was 9) +MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB MIN_BLOB_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716) +BLOB_BASE_FEE_UPDATE_FRACTION = Uint(10015432) # Doubled for EIP-7782 (was 5007716) GAS_BLS_G1_ADD = Uint(375) GAS_BLS_G1_MUL = Uint(12000) From b2625ee42cdc1e9061c0aff91f3938d42a87b756 Mon Sep 17 00:00:00 2001 From: Milos Stankovic <82043364+morph-dev@users.noreply.github.com> Date: Thu, 4 Sep 2025 23:24:46 +0300 Subject: [PATCH 2/2] fix: static checks --- src/ethereum/osaka/fork.py | 10 +++++++--- src/ethereum/osaka/vm/gas.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ethereum/osaka/fork.py b/src/ethereum/osaka/fork.py index ecf1bde781..17201accb2 100644 --- a/src/ethereum/osaka/fork.py +++ b/src/ethereum/osaka/fork.py @@ -357,11 +357,15 @@ def validate_header(chain: BlockChain, header: Header) -> None: if header.gas_used > header.gas_limit: raise InvalidBlock - + if not check_gas_limit(header.gas_limit, parent_header): raise InvalidBlock - expected_base_fee_per_gas = calculate_base_fee_per_gas(parent_header) + expected_base_fee_per_gas = calculate_base_fee_per_gas( + parent_header.gas_limit, + parent_header.gas_used, + parent_header.base_fee_per_gas, + ) if expected_base_fee_per_gas != header.base_fee_per_gas: raise InvalidBlock if header.timestamp <= parent_header.timestamp: @@ -1040,7 +1044,7 @@ def check_gas_limit(gas_limit: Uint, parent: Header) -> bool: # If this is a fork block, use half of parent's gas limit (EIP-7782) if not FORK_CRITERIA.check(parent.number, parent.timestamp): - parent_gas_limit /= 2 + parent_gas_limit //= Uint(2) max_adjustment_delta = parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR if gas_limit >= parent_gas_limit + max_adjustment_delta: diff --git a/src/ethereum/osaka/vm/gas.py b/src/ethereum/osaka/vm/gas.py index 8a01a4aba9..34003da22a 100644 --- a/src/ethereum/osaka/vm/gas.py +++ b/src/ethereum/osaka/vm/gas.py @@ -76,7 +76,7 @@ BLOB_SCHEDULE_MAX = U64(4) # Halved for EIP-7782 (was 9) MAX_BLOB_GAS_PER_BLOCK = BLOB_SCHEDULE_MAX * GAS_PER_BLOB MIN_BLOB_GASPRICE = Uint(1) -BLOB_BASE_FEE_UPDATE_FRACTION = Uint(10015432) # Doubled for EIP-7782 (was 5007716) +BLOB_BASE_FEE_UPDATE_FRACTION = Uint(10015432) # Doubled for EIP-7782 GAS_BLS_G1_ADD = Uint(375) GAS_BLS_G1_MUL = Uint(12000)