Skip to content

Commit 363df20

Browse files
felix314159marioevz
authored andcommitted
refactor(specs): Add count_tokens_in_data helper
fix: 7976 and 7981 devnet merger fix, extract count_tokens_in_data and restructure floor calc refactor: 8037+7981 harmonization, add zero-valued access list token scaffolding fix: add comment
1 parent 6fe032f commit 363df20

1 file changed

Lines changed: 32 additions & 12 deletions

File tree

src/ethereum/forks/amsterdam/transactions.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -581,8 +581,8 @@ def validate_transaction(tx: Transaction) -> Tuple[Uint, Uint]:
581581
"""
582582
from .vm.interpreter import MAX_INIT_CODE_SIZE
583583

584-
intrinsic_gas, calldata_floor_gas_cost = calculate_intrinsic_cost(tx)
585-
if max(intrinsic_gas, calldata_floor_gas_cost) > tx.gas:
584+
intrinsic_gas, data_floor_gas_cost = calculate_intrinsic_cost(tx)
585+
if max(intrinsic_gas, data_floor_gas_cost) > tx.gas:
586586
raise InsufficientTransactionGasError("Insufficient gas")
587587
if U256(tx.nonce) >= U256(U64.MAX_VALUE):
588588
raise NonceOverflowError("Nonce too high")
@@ -591,7 +591,7 @@ def validate_transaction(tx: Transaction) -> Tuple[Uint, Uint]:
591591
if tx.gas > TX_MAX_GAS_LIMIT:
592592
raise TransactionGasLimitExceededError("Gas limit too high")
593593

594-
return intrinsic_gas, calldata_floor_gas_cost
594+
return intrinsic_gas, data_floor_gas_cost
595595

596596

597597
def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
@@ -622,14 +622,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
622622
from .vm.eoa_delegation import GAS_AUTH_PER_EMPTY_ACCOUNT
623623
from .vm.gas import init_code_cost
624624

625-
num_zeros = Uint(tx.data.count(0))
626-
num_non_zeros = ulen(tx.data) - num_zeros
627-
628-
tokens_in_calldata = num_zeros + num_non_zeros * Uint(4)
629-
# EIP-7623 floor price (note: no EVM costs)
630-
calldata_floor_gas_cost = (
631-
tokens_in_calldata * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE
632-
)
625+
tokens_in_calldata = count_tokens_in_data(tx.data)
633626

634627
data_cost = tokens_in_calldata * GAS_TX_DATA_TOKEN_STANDARD
635628

@@ -639,17 +632,32 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
639632
create_cost = Uint(0)
640633

641634
access_list_cost = Uint(0)
635+
tokens_in_access_list = Uint(0)
642636
if has_access_list(tx):
643637
for access in tx.access_list:
644638
access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS
645639
access_list_cost += (
646640
ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY
647641
)
648642

643+
# Data token floor cost for access list bytes.
644+
access_list_cost += tokens_in_access_list * GAS_TX_DATA_TOKEN_FLOOR
645+
649646
auth_cost = Uint(0)
650647
if isinstance(tx, SetCodeTransaction):
651648
auth_cost += Uint(GAS_AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations))
652649

650+
# Floor tokens from calldata.
651+
floor_tokens_in_calldata = tokens_in_calldata
652+
653+
# Total floor tokens.
654+
total_floor_tokens = floor_tokens_in_calldata + tokens_in_access_list
655+
656+
# Floor gas cost (EIP-7623: minimum gas for data-heavy transactions).
657+
data_floor_gas_cost = (
658+
total_floor_tokens * GAS_TX_DATA_TOKEN_FLOOR + GAS_TX_BASE
659+
)
660+
653661
return (
654662
Uint(
655663
GAS_TX_BASE
@@ -658,10 +666,22 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
658666
+ access_list_cost
659667
+ auth_cost
660668
),
661-
calldata_floor_gas_cost,
669+
data_floor_gas_cost,
662670
)
663671

664672

673+
def count_tokens_in_data(data: bytes) -> Uint:
674+
"""
675+
Count the data tokens in arbitrary input bytes.
676+
677+
Zero bytes count as 1 token; non-zero bytes count as 4 tokens.
678+
"""
679+
num_zeros = Uint(data.count(0))
680+
num_non_zeros = ulen(data) - num_zeros
681+
682+
return num_zeros + num_non_zeros * Uint(4)
683+
684+
665685
def recover_sender(chain_id: U64, tx: Transaction) -> Address:
666686
"""
667687
Extracts the sender address from a transaction.

0 commit comments

Comments
 (0)