diff --git a/src/ethereum/forks/amsterdam/fork.py b/src/ethereum/forks/amsterdam/fork.py index 1f2771c4c49..11cb557f1e4 100644 --- a/src/ethereum/forks/amsterdam/fork.py +++ b/src/ethereum/forks/amsterdam/fork.py @@ -59,7 +59,13 @@ TransactionTypeContractCreationError, WrongChainIdError, ) -from .fork_types import Authorization, BlockAccessIndex, VersionedHash +from .fork_types import ( + Authorization, + BlockAccessIndex, + RegularGas, + StateGas, + VersionedHash, +) from .requests import ( BUILDER_DEPOSIT_REQUEST_TYPE, BUILDER_EXIT_REQUEST_TYPE, @@ -795,8 +801,8 @@ def process_unchecked_system_transaction( recipient=target_address, value=U256(0), gas_price=block_env.base_fee_per_gas, - gas=SYSTEM_TRANSACTION_GAS, - state_gas_reservoir=( + gas=RegularGas(SYSTEM_TRANSACTION_GAS), + state_gas_reservoir=StateGas( StateGasCosts.STORAGE_SET * SYSTEM_MAX_SSTORES_PER_CALL ), access_list_addresses=set(), @@ -806,8 +812,8 @@ def process_unchecked_system_transaction( authorizations=(), index_in_block=None, tx_hash=None, - intrinsic_regular_gas=Uint(0), - intrinsic_state_gas=Uint(0), + intrinsic_regular_gas=RegularGas(Uint(0)), + intrinsic_state_gas=StateGas(Uint(0)), ) system_tx_message = Message( @@ -815,8 +821,8 @@ def process_unchecked_system_transaction( tx_env=tx_env, caller=SYSTEM_ADDRESS, target=target_address, - gas=SYSTEM_TRANSACTION_GAS, - state_gas_reservoir=( + gas=RegularGas(SYSTEM_TRANSACTION_GAS), + state_gas_reservoir=StateGas( StateGasCosts.STORAGE_SET * SYSTEM_MAX_SSTORES_PER_CALL ), value=U256(0), @@ -1061,8 +1067,8 @@ def process_transaction( # budget) and state_gas_reservoir. execution_gas = tx.gas - intrinsic_gas regular_gas_budget = TX_MAX_GAS_LIMIT - intrinsic.regular - gas = min(regular_gas_budget, execution_gas) - state_gas_reservoir = Uint(execution_gas - gas) + gas = RegularGas(min(regular_gas_budget, execution_gas)) + state_gas_reservoir = StateGas(execution_gas - gas) increment_nonce(tx_state, sender) diff --git a/src/ethereum/forks/amsterdam/vm/__init__.py b/src/ethereum/forks/amsterdam/vm/__init__.py index 0b9dae40e86..943a1936f2d 100644 --- a/src/ethereum/forks/amsterdam/vm/__init__.py +++ b/src/ethereum/forks/amsterdam/vm/__init__.py @@ -26,7 +26,7 @@ from ..block_access_lists import BlockAccessList, BlockAccessListBuilder from ..blocks import Log, Receipt, Withdrawal -from ..fork_types import Authorization, StateGas, VersionedHash +from ..fork_types import Authorization, RegularGas, StateGas, VersionedHash from ..state_tracker import BlockState, TransactionState from ..transactions import LegacyTransaction @@ -123,8 +123,8 @@ class TransactionEnvironment: recipient: Bytes0 | Address value: U256 gas_price: Uint - gas: Uint - state_gas_reservoir: Uint + gas: RegularGas + state_gas_reservoir: StateGas access_list_addresses: Set[Address] access_list_storage_keys: Set[Tuple[Address, Bytes32]] state: TransactionState @@ -132,8 +132,8 @@ class TransactionEnvironment: authorizations: Tuple[Authorization, ...] index_in_block: Optional[Uint] tx_hash: Optional[Hash32] - intrinsic_regular_gas: Uint - intrinsic_state_gas: Uint + intrinsic_regular_gas: RegularGas + intrinsic_state_gas: StateGas @final @@ -148,8 +148,8 @@ class Message: caller: Address target: Bytes0 | Address current_target: Address - gas: Uint - state_gas_reservoir: Uint + gas: RegularGas + state_gas_reservoir: StateGas value: U256 data: Bytes code_address: Optional[Address] @@ -172,8 +172,8 @@ class Evm: stack: List[U256] memory: bytearray code: Bytes - gas_left: Uint - state_gas_left: Uint + gas_left: RegularGas + state_gas_left: StateGas valid_jump_destinations: Set[Uint] logs: Tuple[Log, ...] refund_counter: int @@ -185,8 +185,8 @@ class Evm: error: Optional[EthereumException] accessed_addresses: Set[Address] accessed_storage_keys: Set[Tuple[Address, Bytes32]] - regular_gas_used: Uint = Uint(0) - state_gas_spilled: Uint = Uint(0) + regular_gas_used: RegularGas = RegularGas(Uint(0)) + state_gas_spilled: StateGas = StateGas(Uint(0)) def credit_state_gas_refund(evm: Evm, amount: StateGas) -> None: @@ -206,10 +206,10 @@ def credit_state_gas_refund(evm: Evm, amount: StateGas) -> None: The refund amount to credit. """ - from_gas_left = min(amount, evm.state_gas_spilled) - evm.gas_left += from_gas_left - evm.state_gas_spilled -= from_gas_left - evm.state_gas_left += amount - from_gas_left + from_gas_left = StateGas(min(amount, evm.state_gas_spilled)) + evm.gas_left = RegularGas(evm.gas_left + Uint(from_gas_left)) + evm.state_gas_spilled = StateGas(evm.state_gas_spilled - from_gas_left) + evm.state_gas_left = StateGas(evm.state_gas_left + amount - from_gas_left) def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: @@ -224,15 +224,21 @@ def incorporate_child_on_success(evm: Evm, child_evm: Evm) -> None: The child evm to incorporate. """ - evm.gas_left += child_evm.gas_left - evm.state_gas_left += child_evm.state_gas_left - evm.state_gas_spilled += child_evm.state_gas_spilled + evm.gas_left = RegularGas(evm.gas_left + child_evm.gas_left) + evm.state_gas_left = StateGas( + evm.state_gas_left + child_evm.state_gas_left + ) + evm.state_gas_spilled = StateGas( + evm.state_gas_spilled + child_evm.state_gas_spilled + ) evm.logs += child_evm.logs evm.refund_counter += child_evm.refund_counter evm.accounts_to_delete.update(child_evm.accounts_to_delete) evm.accessed_addresses.update(child_evm.accessed_addresses) evm.accessed_storage_keys.update(child_evm.accessed_storage_keys) - evm.regular_gas_used += child_evm.regular_gas_used + evm.regular_gas_used = RegularGas( + evm.regular_gas_used + child_evm.regular_gas_used + ) def refill_frame_state_gas(evm: Evm) -> None: @@ -249,9 +255,9 @@ def refill_frame_state_gas(evm: Evm) -> None: The frame whose state gas is rolled back. """ - evm.gas_left += evm.state_gas_spilled + evm.gas_left = RegularGas(evm.gas_left + Uint(evm.state_gas_spilled)) evm.state_gas_left = evm.message.state_gas_reservoir - evm.state_gas_spilled = Uint(0) + evm.state_gas_spilled = StateGas(Uint(0)) def frame_state_gas_used(evm: Evm) -> int: @@ -298,9 +304,13 @@ def incorporate_child_on_error( The child evm to incorporate. """ - evm.gas_left += child_evm.gas_left - evm.state_gas_left += child_evm.state_gas_left - evm.regular_gas_used += child_evm.regular_gas_used + evm.gas_left = RegularGas(evm.gas_left + child_evm.gas_left) + evm.state_gas_left = StateGas( + evm.state_gas_left + child_evm.state_gas_left + ) + evm.regular_gas_used = RegularGas( + evm.regular_gas_used + child_evm.regular_gas_used + ) def emit_transfer_log( diff --git a/src/ethereum/forks/amsterdam/vm/eoa_delegation.py b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py index 2060d5465d7..d1288af71ae 100644 --- a/src/ethereum/forks/amsterdam/vm/eoa_delegation.py +++ b/src/ethereum/forks/amsterdam/vm/eoa_delegation.py @@ -13,7 +13,7 @@ from ethereum.exceptions import InvalidBlock, InvalidSignatureError from ethereum.state import Address -from ..fork_types import Authorization, StateGas +from ..fork_types import Authorization, RegularGas, StateGas from ..state_tracker import ( account_exists, get_account, @@ -123,7 +123,7 @@ def recover_authority(authorization: Authorization) -> Address: def calculate_delegation_cost( evm: Evm, address: Address -) -> Tuple[bool, Address, Uint]: +) -> Tuple[bool, Address, RegularGas]: """ Get the delegation address and the cost of access from the address. @@ -136,7 +136,7 @@ def calculate_delegation_cost( Returns ------- - delegation : `Tuple[bool, Address, Uint]` + delegation : `Tuple[bool, Address, RegularGas]` The delegation address and access gas cost. """ @@ -145,7 +145,7 @@ def calculate_delegation_cost( code = get_code(tx_state, get_account(tx_state, address).code_hash) if not is_valid_delegation(code): - return False, address, Uint(0) + return False, address, RegularGas(Uint(0)) delegated_address = Address(code[EOA_DELEGATION_MARKER_LENGTH:]) diff --git a/src/ethereum/forks/amsterdam/vm/gas.py b/src/ethereum/forks/amsterdam/vm/gas.py index 91a5810b7d2..bd4dff0d302 100644 --- a/src/ethereum/forks/amsterdam/vm/gas.py +++ b/src/ethereum/forks/amsterdam/vm/gas.py @@ -21,7 +21,7 @@ from ethereum.utils.numeric import ceil32, taylor_exponential from ..blocks import Header -from ..fork_types import StateGas, StateGasPerByte +from ..fork_types import RegularGas, StateGas, StateGasPerByte from ..transactions import BlobTransaction, Transaction from . import Evm from .exceptions import OutOfGasError @@ -59,34 +59,37 @@ class GasCosts: """ # Tiers - BASE: Final[Uint] = Uint(2) - VERY_LOW: Final[Uint] = Uint(3) - LOW: Final[Uint] = Uint(5) - MID: Final[Uint] = Uint(8) - HIGH: Final[Uint] = Uint(10) + BASE: Final[RegularGas] = RegularGas(Uint(2)) + VERY_LOW: Final[RegularGas] = RegularGas(Uint(3)) + LOW: Final[RegularGas] = RegularGas(Uint(5)) + MID: Final[RegularGas] = RegularGas(Uint(8)) + HIGH: Final[RegularGas] = RegularGas(Uint(10)) # Access - WARM_ACCESS: Final[Uint] = Uint(100) - COLD_ACCOUNT_ACCESS: Final[Uint] = Uint(3000) - COLD_STORAGE_ACCESS: Final[Uint] = Uint(3000) + WARM_ACCESS: Final[RegularGas] = RegularGas(Uint(100)) + COLD_ACCOUNT_ACCESS: Final[RegularGas] = RegularGas(Uint(3000)) + COLD_STORAGE_ACCESS: Final[RegularGas] = RegularGas(Uint(3000)) # Storage - STORAGE_WRITE: Final[Uint] = Uint(10000) + STORAGE_WRITE: Final[RegularGas] = RegularGas(Uint(10000)) # Call - CALL_VALUE: Final[Uint] = Uint(10300) # ACCOUNT_WRITE + CALL_STIPEND - CALL_STIPEND: Final[Uint] = Uint(2300) - ACCOUNT_WRITE: Final[Uint] = Uint(8000) + # ACCOUNT_WRITE + CALL_STIPEND + CALL_VALUE: Final[RegularGas] = RegularGas(Uint(10300)) + CALL_STIPEND: Final[RegularGas] = RegularGas(Uint(2300)) + ACCOUNT_WRITE: Final[RegularGas] = RegularGas(Uint(8000)) # Contract Creation - CODE_DEPOSIT_PER_BYTE: Final[Uint] = Uint(200) - CODE_INIT_PER_WORD: Final[Uint] = Uint(2) - CREATE_ACCESS: Final[Uint] = ACCOUNT_WRITE + COLD_STORAGE_ACCESS + CODE_DEPOSIT_PER_BYTE: Final[RegularGas] = RegularGas(Uint(200)) + CODE_INIT_PER_WORD: Final[RegularGas] = RegularGas(Uint(2)) + CREATE_ACCESS: Final[RegularGas] = RegularGas( + ACCOUNT_WRITE + COLD_STORAGE_ACCESS + ) # Utility - ZERO: Final[Uint] = Uint(0) - MEMORY_PER_WORD: Final[Uint] = Uint(3) - FAST_STEP: Final[Uint] = Uint(5) + ZERO: Final[RegularGas] = RegularGas(Uint(0)) + MEMORY_PER_WORD: Final[RegularGas] = RegularGas(Uint(3)) + FAST_STEP: Final[RegularGas] = RegularGas(Uint(5)) # Refunds REFUND_STORAGE_CLEAR: Final[int] = int( @@ -94,26 +97,26 @@ class GasCosts: ) # Precompiles - PRECOMPILE_ECRECOVER: Final[Uint] = Uint(3000) - PRECOMPILE_P256VERIFY: Final[Uint] = Uint(6900) - PRECOMPILE_SHA256_BASE: Final[Uint] = Uint(60) - PRECOMPILE_SHA256_PER_WORD: Final[Uint] = Uint(12) - PRECOMPILE_RIPEMD160_BASE: Final[Uint] = Uint(600) - PRECOMPILE_RIPEMD160_PER_WORD: Final[Uint] = Uint(120) - PRECOMPILE_IDENTITY_BASE: Final[Uint] = Uint(15) - PRECOMPILE_IDENTITY_PER_WORD: Final[Uint] = Uint(3) - PRECOMPILE_BLAKE2F_PER_ROUND: Final[Uint] = Uint(1) - PRECOMPILE_POINT_EVALUATION: Final[Uint] = Uint(50000) - PRECOMPILE_BLS_G1ADD: Final[Uint] = Uint(375) - PRECOMPILE_BLS_G1MUL: Final[Uint] = Uint(12000) - PRECOMPILE_BLS_G1MAP: Final[Uint] = Uint(5500) - PRECOMPILE_BLS_G2ADD: Final[Uint] = Uint(600) - PRECOMPILE_BLS_G2MUL: Final[Uint] = Uint(22500) - PRECOMPILE_BLS_G2MAP: Final[Uint] = Uint(23800) - PRECOMPILE_ECADD: Final[Uint] = Uint(150) - PRECOMPILE_ECMUL: Final[Uint] = Uint(6000) - PRECOMPILE_ECPAIRING_BASE: Final[Uint] = Uint(45000) - PRECOMPILE_ECPAIRING_PER_POINT: Final[Uint] = Uint(34000) + PRECOMPILE_ECRECOVER: Final[RegularGas] = RegularGas(Uint(3000)) + PRECOMPILE_P256VERIFY: Final[RegularGas] = RegularGas(Uint(6900)) + PRECOMPILE_SHA256_BASE: Final[RegularGas] = RegularGas(Uint(60)) + PRECOMPILE_SHA256_PER_WORD: Final[RegularGas] = RegularGas(Uint(12)) + PRECOMPILE_RIPEMD160_BASE: Final[RegularGas] = RegularGas(Uint(600)) + PRECOMPILE_RIPEMD160_PER_WORD: Final[RegularGas] = RegularGas(Uint(120)) + PRECOMPILE_IDENTITY_BASE: Final[RegularGas] = RegularGas(Uint(15)) + PRECOMPILE_IDENTITY_PER_WORD: Final[RegularGas] = RegularGas(Uint(3)) + PRECOMPILE_BLAKE2F_PER_ROUND: Final[RegularGas] = RegularGas(Uint(1)) + PRECOMPILE_POINT_EVALUATION: Final[RegularGas] = RegularGas(Uint(50000)) + PRECOMPILE_BLS_G1ADD: Final[RegularGas] = RegularGas(Uint(375)) + PRECOMPILE_BLS_G1MUL: Final[RegularGas] = RegularGas(Uint(12000)) + PRECOMPILE_BLS_G1MAP: Final[RegularGas] = RegularGas(Uint(5500)) + PRECOMPILE_BLS_G2ADD: Final[RegularGas] = RegularGas(Uint(600)) + PRECOMPILE_BLS_G2MUL: Final[RegularGas] = RegularGas(Uint(22500)) + PRECOMPILE_BLS_G2MAP: Final[RegularGas] = RegularGas(Uint(23800)) + PRECOMPILE_ECADD: Final[RegularGas] = RegularGas(Uint(150)) + PRECOMPILE_ECMUL: Final[RegularGas] = RegularGas(Uint(6000)) + PRECOMPILE_ECPAIRING_BASE: Final[RegularGas] = RegularGas(Uint(45000)) + PRECOMPILE_ECPAIRING_PER_POINT: Final[RegularGas] = RegularGas(Uint(34000)) # Blobs PER_BLOB: Final[U64] = U64(2**17) @@ -125,21 +128,21 @@ class GasCosts: BLOB_BASE_FEE_UPDATE_FRACTION: Final[Uint] = Uint(11684671) # Block Access Lists - BLOCK_ACCESS_LIST_ITEM: Final[Uint] = Uint(2000) + BLOCK_ACCESS_LIST_ITEM: Final[RegularGas] = RegularGas(Uint(2000)) # Transactions - TX_BASE: Final[Uint] = Uint(12000) - TX_CREATE: Final[Uint] = Uint(32000) - TX_VALUE_COST: Final[Uint] = Uint(4244) - TRANSFER_LOG_COST: Final[Uint] = Uint(1756) - TX_DATA_TOKEN_STANDARD: Final[Uint] = Uint(4) - TX_DATA_TOKEN_FLOOR: Final[Uint] = Uint(16) - TX_ACCESS_LIST_ADDRESS: Final[Uint] = COLD_ACCOUNT_ACCESS - TX_ACCESS_LIST_STORAGE_KEY: Final[Uint] = COLD_STORAGE_ACCESS + TX_BASE: Final[RegularGas] = RegularGas(Uint(12000)) + TX_CREATE: Final[RegularGas] = RegularGas(Uint(32000)) + TX_VALUE_COST: Final[RegularGas] = RegularGas(Uint(4244)) + TRANSFER_LOG_COST: Final[RegularGas] = RegularGas(Uint(1756)) + TX_DATA_TOKEN_STANDARD: Final[RegularGas] = RegularGas(Uint(4)) + TX_DATA_TOKEN_FLOOR: Final[RegularGas] = RegularGas(Uint(16)) + TX_ACCESS_LIST_ADDRESS: Final[RegularGas] = COLD_ACCOUNT_ACCESS + TX_ACCESS_LIST_STORAGE_KEY: Final[RegularGas] = COLD_STORAGE_ACCESS # Authorization AUTH_TUPLE_BYTES: Final[Uint] = Uint(101) - REGULAR_PER_AUTH_BASE_COST: Final[Uint] = ( + REGULAR_PER_AUTH_BASE_COST: Final[RegularGas] = RegularGas( AUTH_TUPLE_BYTES * TX_DATA_TOKEN_FLOOR + PRECOMPILE_ECRECOVER + COLD_ACCOUNT_ACCESS @@ -151,86 +154,86 @@ class GasCosts: LIMIT_MINIMUM: Final[Uint] = Uint(5000) # Static Opcodes - OPCODE_ADD: Final[Uint] = VERY_LOW - OPCODE_SUB: Final[Uint] = VERY_LOW - OPCODE_MUL: Final[Uint] = LOW - OPCODE_DIV: Final[Uint] = LOW - OPCODE_SDIV: Final[Uint] = LOW - OPCODE_MOD: Final[Uint] = LOW - OPCODE_SMOD: Final[Uint] = LOW - OPCODE_ADDMOD: Final[Uint] = MID - OPCODE_MULMOD: Final[Uint] = MID - OPCODE_SIGNEXTEND: Final[Uint] = LOW - OPCODE_LT: Final[Uint] = VERY_LOW - OPCODE_GT: Final[Uint] = VERY_LOW - OPCODE_SLT: Final[Uint] = VERY_LOW - OPCODE_SGT: Final[Uint] = VERY_LOW - OPCODE_EQ: Final[Uint] = VERY_LOW - OPCODE_ISZERO: Final[Uint] = VERY_LOW - OPCODE_AND: Final[Uint] = VERY_LOW - OPCODE_OR: Final[Uint] = VERY_LOW - OPCODE_XOR: Final[Uint] = VERY_LOW - OPCODE_NOT: Final[Uint] = VERY_LOW - OPCODE_BYTE: Final[Uint] = VERY_LOW - OPCODE_SHL: Final[Uint] = VERY_LOW - OPCODE_SHR: Final[Uint] = VERY_LOW - OPCODE_SAR: Final[Uint] = VERY_LOW - OPCODE_CLZ: Final[Uint] = LOW - OPCODE_JUMP: Final[Uint] = MID - OPCODE_JUMPI: Final[Uint] = HIGH - OPCODE_JUMPDEST: Final[Uint] = Uint(1) - OPCODE_CALLDATALOAD: Final[Uint] = VERY_LOW - OPCODE_BLOCKHASH: Final[Uint] = Uint(20) - OPCODE_COINBASE: Final[Uint] = BASE - OPCODE_POP: Final[Uint] = BASE - OPCODE_MSIZE: Final[Uint] = BASE - OPCODE_PC: Final[Uint] = BASE - OPCODE_GAS: Final[Uint] = BASE - OPCODE_ADDRESS: Final[Uint] = BASE - OPCODE_ORIGIN: Final[Uint] = BASE - OPCODE_CALLER: Final[Uint] = BASE - OPCODE_CALLVALUE: Final[Uint] = BASE - OPCODE_CALLDATASIZE: Final[Uint] = BASE - OPCODE_CODESIZE: Final[Uint] = BASE - OPCODE_GASPRICE: Final[Uint] = BASE - OPCODE_TIMESTAMP: Final[Uint] = BASE - OPCODE_NUMBER: Final[Uint] = BASE - OPCODE_GASLIMIT: Final[Uint] = BASE - OPCODE_PREVRANDAO: Final[Uint] = BASE - OPCODE_RETURNDATASIZE: Final[Uint] = BASE - OPCODE_CHAINID: Final[Uint] = BASE - OPCODE_BASEFEE: Final[Uint] = BASE - OPCODE_BLOBBASEFEE: Final[Uint] = BASE - OPCODE_SLOTNUM: Final[Uint] = BASE - OPCODE_BLOBHASH: Final[Uint] = Uint(3) - OPCODE_PUSH: Final[Uint] = VERY_LOW - OPCODE_PUSH0: Final[Uint] = BASE - OPCODE_DUP: Final[Uint] = VERY_LOW - OPCODE_SWAP: Final[Uint] = VERY_LOW - OPCODE_DUPN: Final[Uint] = VERY_LOW - OPCODE_SWAPN: Final[Uint] = VERY_LOW - OPCODE_EXCHANGE: Final[Uint] = VERY_LOW - OPCODE_TLOAD: Final[Uint] = Uint(100) - OPCODE_TSTORE: Final[Uint] = Uint(100) + OPCODE_ADD: Final[RegularGas] = VERY_LOW + OPCODE_SUB: Final[RegularGas] = VERY_LOW + OPCODE_MUL: Final[RegularGas] = LOW + OPCODE_DIV: Final[RegularGas] = LOW + OPCODE_SDIV: Final[RegularGas] = LOW + OPCODE_MOD: Final[RegularGas] = LOW + OPCODE_SMOD: Final[RegularGas] = LOW + OPCODE_ADDMOD: Final[RegularGas] = MID + OPCODE_MULMOD: Final[RegularGas] = MID + OPCODE_SIGNEXTEND: Final[RegularGas] = LOW + OPCODE_LT: Final[RegularGas] = VERY_LOW + OPCODE_GT: Final[RegularGas] = VERY_LOW + OPCODE_SLT: Final[RegularGas] = VERY_LOW + OPCODE_SGT: Final[RegularGas] = VERY_LOW + OPCODE_EQ: Final[RegularGas] = VERY_LOW + OPCODE_ISZERO: Final[RegularGas] = VERY_LOW + OPCODE_AND: Final[RegularGas] = VERY_LOW + OPCODE_OR: Final[RegularGas] = VERY_LOW + OPCODE_XOR: Final[RegularGas] = VERY_LOW + OPCODE_NOT: Final[RegularGas] = VERY_LOW + OPCODE_BYTE: Final[RegularGas] = VERY_LOW + OPCODE_SHL: Final[RegularGas] = VERY_LOW + OPCODE_SHR: Final[RegularGas] = VERY_LOW + OPCODE_SAR: Final[RegularGas] = VERY_LOW + OPCODE_CLZ: Final[RegularGas] = LOW + OPCODE_JUMP: Final[RegularGas] = MID + OPCODE_JUMPI: Final[RegularGas] = HIGH + OPCODE_JUMPDEST: Final[RegularGas] = RegularGas(Uint(1)) + OPCODE_CALLDATALOAD: Final[RegularGas] = VERY_LOW + OPCODE_BLOCKHASH: Final[RegularGas] = RegularGas(Uint(20)) + OPCODE_COINBASE: Final[RegularGas] = BASE + OPCODE_POP: Final[RegularGas] = BASE + OPCODE_MSIZE: Final[RegularGas] = BASE + OPCODE_PC: Final[RegularGas] = BASE + OPCODE_GAS: Final[RegularGas] = BASE + OPCODE_ADDRESS: Final[RegularGas] = BASE + OPCODE_ORIGIN: Final[RegularGas] = BASE + OPCODE_CALLER: Final[RegularGas] = BASE + OPCODE_CALLVALUE: Final[RegularGas] = BASE + OPCODE_CALLDATASIZE: Final[RegularGas] = BASE + OPCODE_CODESIZE: Final[RegularGas] = BASE + OPCODE_GASPRICE: Final[RegularGas] = BASE + OPCODE_TIMESTAMP: Final[RegularGas] = BASE + OPCODE_NUMBER: Final[RegularGas] = BASE + OPCODE_GASLIMIT: Final[RegularGas] = BASE + OPCODE_PREVRANDAO: Final[RegularGas] = BASE + OPCODE_RETURNDATASIZE: Final[RegularGas] = BASE + OPCODE_CHAINID: Final[RegularGas] = BASE + OPCODE_BASEFEE: Final[RegularGas] = BASE + OPCODE_BLOBBASEFEE: Final[RegularGas] = BASE + OPCODE_SLOTNUM: Final[RegularGas] = BASE + OPCODE_BLOBHASH: Final[RegularGas] = RegularGas(Uint(3)) + OPCODE_PUSH: Final[RegularGas] = VERY_LOW + OPCODE_PUSH0: Final[RegularGas] = BASE + OPCODE_DUP: Final[RegularGas] = VERY_LOW + OPCODE_SWAP: Final[RegularGas] = VERY_LOW + OPCODE_DUPN: Final[RegularGas] = VERY_LOW + OPCODE_SWAPN: Final[RegularGas] = VERY_LOW + OPCODE_EXCHANGE: Final[RegularGas] = VERY_LOW + OPCODE_TLOAD: Final[RegularGas] = RegularGas(Uint(100)) + OPCODE_TSTORE: Final[RegularGas] = RegularGas(Uint(100)) # Dynamic Opcode Components - OPCODE_RETURNDATACOPY_BASE: Final[Uint] = VERY_LOW - OPCODE_RETURNDATACOPY_PER_WORD: Final[Uint] = Uint(3) - OPCODE_CALLDATACOPY_BASE: Final[Uint] = VERY_LOW - OPCODE_CODECOPY_BASE: Final[Uint] = VERY_LOW - OPCODE_MCOPY_BASE: Final[Uint] = VERY_LOW - OPCODE_MLOAD_BASE: Final[Uint] = VERY_LOW - OPCODE_MSTORE_BASE: Final[Uint] = VERY_LOW - OPCODE_MSTORE8_BASE: Final[Uint] = VERY_LOW - OPCODE_COPY_PER_WORD: Final[Uint] = Uint(3) - OPCODE_EXP_BASE: Final[Uint] = Uint(10) - OPCODE_EXP_PER_BYTE: Final[Uint] = Uint(50) - OPCODE_KECCAK256_BASE: Final[Uint] = Uint(30) - OPCODE_KECCAK256_PER_WORD: Final[Uint] = Uint(6) - OPCODE_LOG_BASE: Final[Uint] = Uint(375) - OPCODE_LOG_DATA_PER_BYTE: Final[Uint] = Uint(8) - OPCODE_LOG_TOPIC: Final[Uint] = Uint(375) - OPCODE_SELFDESTRUCT_BASE: Final[Uint] = Uint(5000) + OPCODE_RETURNDATACOPY_BASE: Final[RegularGas] = VERY_LOW + OPCODE_RETURNDATACOPY_PER_WORD: Final[RegularGas] = RegularGas(Uint(3)) + OPCODE_CALLDATACOPY_BASE: Final[RegularGas] = VERY_LOW + OPCODE_CODECOPY_BASE: Final[RegularGas] = VERY_LOW + OPCODE_MCOPY_BASE: Final[RegularGas] = VERY_LOW + OPCODE_MLOAD_BASE: Final[RegularGas] = VERY_LOW + OPCODE_MSTORE_BASE: Final[RegularGas] = VERY_LOW + OPCODE_MSTORE8_BASE: Final[RegularGas] = VERY_LOW + OPCODE_COPY_PER_WORD: Final[RegularGas] = RegularGas(Uint(3)) + OPCODE_EXP_BASE: Final[RegularGas] = RegularGas(Uint(10)) + OPCODE_EXP_PER_BYTE: Final[RegularGas] = RegularGas(Uint(50)) + OPCODE_KECCAK256_BASE: Final[RegularGas] = RegularGas(Uint(30)) + OPCODE_KECCAK256_PER_WORD: Final[RegularGas] = RegularGas(Uint(6)) + OPCODE_LOG_BASE: Final[RegularGas] = RegularGas(Uint(375)) + OPCODE_LOG_DATA_PER_BYTE: Final[RegularGas] = RegularGas(Uint(8)) + OPCODE_LOG_TOPIC: Final[RegularGas] = RegularGas(Uint(375)) + OPCODE_SELFDESTRUCT_BASE: Final[RegularGas] = RegularGas(Uint(5000)) @final @@ -245,7 +248,7 @@ class ExtendMemory: The size by which the memory will be extended """ - cost: Uint + cost: RegularGas expand_by: Uint @@ -264,8 +267,8 @@ class MessageCallGas: if not consumed. """ - cost: Uint - sub_call: Uint + cost: RegularGas + sub_call: RegularGas def check_gas(evm: Evm, amount: Uint) -> None: @@ -301,9 +304,9 @@ def charge_gas(evm: Evm, amount: Uint) -> None: if evm.gas_left < amount: raise OutOfGasError - evm.gas_left -= amount + evm.gas_left = RegularGas(evm.gas_left - amount) - evm.regular_gas_used += amount + evm.regular_gas_used = RegularGas(evm.regular_gas_used + amount) def charge_state_gas(evm: Evm, amount: StateGas) -> None: @@ -324,12 +327,12 @@ def charge_state_gas(evm: Evm, amount: StateGas) -> None: evm_trace(evm, StateGasAndRefund(int(amount))) if evm.state_gas_left >= amount: - evm.state_gas_left -= amount - elif evm.state_gas_left + evm.gas_left >= amount: - remainder = amount - evm.state_gas_left - evm.state_gas_left = Uint(0) - evm.gas_left -= remainder - evm.state_gas_spilled += remainder + evm.state_gas_left = StateGas(evm.state_gas_left - amount) + elif Uint(evm.state_gas_left) + Uint(evm.gas_left) >= Uint(amount): + remainder = StateGas(amount - evm.state_gas_left) + evm.state_gas_left = StateGas(Uint(0)) + evm.gas_left = RegularGas(evm.gas_left - Uint(remainder)) + evm.state_gas_spilled = StateGas(evm.state_gas_spilled + remainder) else: raise OutOfGasError @@ -398,7 +401,7 @@ def calculate_gas_extend_memory( current_size = after_size - return ExtendMemory(to_be_paid, size_to_extend) + return ExtendMemory(RegularGas(to_be_paid), size_to_extend) def calculate_message_call_gas( @@ -437,14 +440,21 @@ def calculate_message_call_gas( """ call_stipend = Uint(0) if value == 0 else call_stipend if gas_left < extra_gas + memory_cost: - return MessageCallGas(gas + extra_gas, gas + call_stipend) + return MessageCallGas( + RegularGas(gas + extra_gas), RegularGas(gas + call_stipend) + ) - gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) + gas = min( + gas, + max_message_call_gas(RegularGas(gas_left - memory_cost - extra_gas)), + ) - return MessageCallGas(gas + extra_gas, gas + call_stipend) + return MessageCallGas( + RegularGas(gas + extra_gas), RegularGas(gas + call_stipend) + ) -def max_message_call_gas(gas: Uint) -> Uint: +def max_message_call_gas(gas: RegularGas) -> RegularGas: """ Calculates the maximum gas that is allowed for making a message call. @@ -459,7 +469,7 @@ def max_message_call_gas(gas: Uint) -> Uint: The maximum gas allowed for making the message-call. """ - return gas - (gas // Uint(64)) + return RegularGas(gas - (gas // Uint(64))) def init_code_cost(init_code_length: Uint) -> Uint: diff --git a/src/ethereum/forks/amsterdam/vm/instructions/system.py b/src/ethereum/forks/amsterdam/vm/instructions/system.py index 9d4e4fa815d..81045dd919c 100644 --- a/src/ethereum/forks/amsterdam/vm/instructions/system.py +++ b/src/ethereum/forks/amsterdam/vm/instructions/system.py @@ -20,7 +20,7 @@ from ethereum.state import Address from ethereum.utils.numeric import ceil32 -from ...fork_types import StateGas +from ...fork_types import RegularGas, StateGas from ...state_tracker import ( account_deployable, get_account, @@ -94,13 +94,13 @@ def generic_create( evm.memory, memory_start_position, memory_size ) - create_message_gas = max_message_call_gas(Uint(evm.gas_left)) - evm.gas_left -= create_message_gas + create_message_gas = max_message_call_gas(evm.gas_left) + evm.gas_left = RegularGas(evm.gas_left - create_message_gas) # Move full reservoir to child (no 63/64 rule for state gas). Parent's # `state_gas_left` is zeroed and restored when the child returns. create_message_state_gas_reservoir = evm.state_gas_left - evm.state_gas_left = Uint(0) + evm.state_gas_left = StateGas(Uint(0)) evm.return_data = b"" @@ -112,8 +112,10 @@ def generic_create( or sender.nonce == Uint(2**64 - 1) or evm.message.depth + Uint(1) > STACK_DEPTH_LIMIT ): - evm.gas_left += create_message_gas - evm.state_gas_left += create_message_state_gas_reservoir + evm.gas_left = RegularGas(evm.gas_left + create_message_gas) + evm.state_gas_left = StateGas( + evm.state_gas_left + create_message_state_gas_reservoir + ) credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT) push(evm.stack, U256(0)) return @@ -122,8 +124,12 @@ def generic_create( if not account_deployable(tx_state, contract_address): increment_nonce(tx_state, evm.message.current_target) - evm.regular_gas_used += create_message_gas - evm.state_gas_left += create_message_state_gas_reservoir + evm.regular_gas_used = RegularGas( + evm.regular_gas_used + create_message_gas + ) + evm.state_gas_left = StateGas( + evm.state_gas_left + create_message_state_gas_reservoir + ) # Address collision — no account created, refund state gas. credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT) push(evm.stack, U256(0)) @@ -314,8 +320,8 @@ class GenericCall: Parameters for the core logic of the `CALL*` family of opcodes. """ - gas: Uint - state_gas_reservoir: Uint + gas: RegularGas + state_gas_reservoir: StateGas value: U256 caller: Address to: Address @@ -340,8 +346,10 @@ def generic_call(evm: Evm, params: GenericCall) -> None: evm.return_data = b"" if evm.message.depth + Uint(1) > STACK_DEPTH_LIMIT: - evm.gas_left += params.gas - evm.state_gas_left += params.state_gas_reservoir + evm.gas_left = RegularGas(evm.gas_left + params.gas) + evm.state_gas_left = StateGas( + evm.state_gas_left + params.state_gas_reservoir + ) if params.new_account_charged: credit_state_gas_refund(evm, StateGasCosts.NEW_ACCOUNT) push(evm.stack, U256(0)) @@ -485,7 +493,7 @@ def call(evm: Evm) -> None: # Pass full reservoir to child (no 63/64 rule for state gas) call_state_gas_reservoir = evm.state_gas_left - evm.state_gas_left = Uint(0) + evm.state_gas_left = StateGas(Uint(0)) sender_balance = get_account(tx_state, evm.message.current_target).balance if sender_balance < value: @@ -602,7 +610,7 @@ def callcode(evm: Evm) -> None: # Pass full reservoir to child (no 63/64 rule for state gas) call_state_gas_reservoir = evm.state_gas_left - evm.state_gas_left = Uint(0) + evm.state_gas_left = StateGas(Uint(0)) sender_balance = get_account(tx_state, evm.message.current_target).balance @@ -776,7 +784,7 @@ def delegatecall(evm: Evm) -> None: # Pass full reservoir to child (no 63/64 rule for state gas) call_state_gas_reservoir = evm.state_gas_left - evm.state_gas_left = Uint(0) + evm.state_gas_left = StateGas(Uint(0)) generic_call( evm, @@ -875,7 +883,7 @@ def staticcall(evm: Evm) -> None: # Pass full reservoir to child (no 63/64 rule for state gas) call_state_gas_reservoir = evm.state_gas_left - evm.state_gas_left = Uint(0) + evm.state_gas_left = StateGas(Uint(0)) generic_call( evm, diff --git a/src/ethereum/forks/amsterdam/vm/interpreter.py b/src/ethereum/forks/amsterdam/vm/interpreter.py index 921873a06bd..f798a48c5dc 100644 --- a/src/ethereum/forks/amsterdam/vm/interpreter.py +++ b/src/ethereum/forks/amsterdam/vm/interpreter.py @@ -32,6 +32,7 @@ from ethereum.utils.numeric import ceil32 from ..blocks import Log +from ..fork_types import RegularGas, StateGas from ..state_tracker import ( account_deployable, copy_tx_state, @@ -101,16 +102,16 @@ class MessageCallOutput: transaction targeted an already-existent account. """ - gas_left: Uint + gas_left: RegularGas refund_counter: U256 logs: Tuple[Log, ...] accounts_to_delete: Set[Address] error: Optional[EthereumException] return_data: Bytes - state_gas_left: Uint - regular_gas_used: Uint + state_gas_left: StateGas + regular_gas_used: RegularGas state_gas_used: int - state_refund: Uint + state_refund: StateGas created_target_alive: bool @@ -132,7 +133,7 @@ def process_message_call(message: Message) -> MessageCallOutput: """ tx_state = message.tx_env.state refund_counter = U256(0) - state_refund = Uint(0) + state_refund = StateGas(Uint(0)) target_alive = False if message.target == Bytes0(b""): if account_deployable(tx_state, message.current_target): @@ -140,7 +141,7 @@ def process_message_call(message: Message) -> MessageCallOutput: evm = process_create_message(message) else: return MessageCallOutput( - gas_left=Uint(0), + gas_left=RegularGas(Uint(0)), refund_counter=U256(0), logs=tuple(), accounts_to_delete=set(), @@ -149,13 +150,13 @@ def process_message_call(message: Message) -> MessageCallOutput: state_gas_left=message.state_gas_reservoir, regular_gas_used=message.gas, state_gas_used=0, - state_refund=Uint(0), + state_refund=StateGas(Uint(0)), created_target_alive=False, ) else: if message.tx_env.authorizations != (): auth_state_refund, auth_regular_refund = set_delegation(message) - state_refund += auth_state_refund + state_refund = StateGas(state_refund + auth_state_refund) refund_counter += U256(auth_regular_refund) delegated_address = get_delegated_code_address(message.code) @@ -257,7 +258,7 @@ def process_create_message(message: Message) -> Evm: restore_tx_state(tx_state, snapshot) refill_frame_state_gas(evm) evm.regular_gas_used += evm.gas_left - evm.gas_left = Uint(0) + evm.gas_left = RegularGas(Uint(0)) evm.output = b"" evm.error = error else: @@ -362,7 +363,7 @@ def process_message(message: Message) -> Evm: evm_trace(evm, OpException(error)) refill_frame_state_gas(evm) evm.regular_gas_used += evm.gas_left - evm.gas_left = Uint(0) + evm.gas_left = RegularGas(Uint(0)) evm.output = b"" evm.error = error except Revert as error: