Skip to content

Commit 90774ea

Browse files
committed
fix gas_used
1 parent b912261 commit 90774ea

File tree

1 file changed

+67
-158
lines changed

1 file changed

+67
-158
lines changed

src/ethereum/prague/fork.py

Lines changed: 67 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
Log,
3030
Receipt,
3131
Withdrawal,
32-
encode_receipt,
33-
parse_deposit_requests_from_receipt,
34-
parse_withdrawal_requests_from_system_tx,
32+
validate_deposit_requests,
33+
validate_requests,
3534
)
3635
from .bloom import logs_bloom
3736
from .fork_types import Address, Bloom, Root, VersionedHash
@@ -74,11 +73,7 @@
7473
calculate_total_blob_gas,
7574
init_code_cost,
7675
)
77-
from .vm.interpreter import (
78-
MAX_CODE_SIZE,
79-
MessageCallOutput,
80-
process_message_call,
81-
)
76+
from .vm.interpreter import MAX_CODE_SIZE, process_message_call
8277

8378
BASE_FEE_MAX_CHANGE_DENOMINATOR = 8
8479
ELASTICITY_MULTIPLIER = 2
@@ -92,9 +87,6 @@
9287
HISTORY_STORAGE_ADDRESS = hex_to_address(
9388
"0x25a219378dad9b3503c8268c9ca836a52427a4fb"
9489
)
95-
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address(
96-
"0x00A3ca265EBcb825B45F985A16CEFB49958cE017"
97-
)
9890
SYSTEM_TRANSACTION_GAS = Uint(30000000)
9991
MAX_BLOB_GAS_PER_BLOCK = 786432
10092
VERSIONED_HASH_VERSION_KZG = b"\x01"
@@ -220,8 +212,6 @@ def state_transition(chain: BlockChain, block: Block) -> None:
220212
raise InvalidBlock
221213
if apply_body_output.blob_gas_used != block.header.blob_gas_used:
222214
raise InvalidBlock
223-
if apply_body_output.requests_root != block.header.requests_root:
224-
raise InvalidBlock
225215

226216
chain.blocks.append(block)
227217
if len(chain.blocks) > 255:
@@ -469,7 +459,14 @@ def make_receipt(
469459
logs=logs,
470460
)
471461

472-
return encode_receipt(tx, receipt)
462+
if isinstance(tx, AccessListTransaction):
463+
return b"\x01" + rlp.encode(receipt)
464+
elif isinstance(tx, FeeMarketTransaction):
465+
return b"\x02" + rlp.encode(receipt)
466+
elif isinstance(tx, BlobTransaction):
467+
return b"\x03" + rlp.encode(receipt)
468+
else:
469+
return receipt
473470

474471

475472
@dataclass
@@ -508,103 +505,6 @@ class ApplyBodyOutput:
508505
requests_root: Root
509506

510507

511-
def process_system_transaction(
512-
target_address: Address,
513-
data: Bytes,
514-
coinbase: Address,
515-
block_number: Uint,
516-
base_fee_per_gas: Uint,
517-
block_gas_limit: Uint,
518-
block_time: U256,
519-
prev_randao: Bytes32,
520-
state: State,
521-
chain_id: U64,
522-
excess_blob_gas: U64,
523-
) -> MessageCallOutput:
524-
"""
525-
Process a system transaction.
526-
527-
Parameters
528-
----------
529-
target_address :
530-
Address of the contract to call.
531-
data :
532-
Data to pass to the contract.
533-
coinbase :
534-
Address of the block's coinbase.
535-
block_number :
536-
Block number.
537-
base_fee_per_gas :
538-
Base fee per gas.
539-
block_gas_limit :
540-
Gas limit of the block.
541-
block_time :
542-
Time the block was produced.
543-
prev_randao :
544-
Previous randao value.
545-
state :
546-
Current state.
547-
chain_id :
548-
ID of the chain.
549-
excess_blob_gas :
550-
Excess blob gas.
551-
552-
Returns
553-
-------
554-
system_tx_output : `MessageCallOutput`
555-
Output of processing the system transaction.
556-
"""
557-
system_contract_code = get_account(state, target_address).code
558-
559-
system_tx_message = Message(
560-
caller=SYSTEM_ADDRESS,
561-
target=target_address,
562-
gas=SYSTEM_TRANSACTION_GAS,
563-
value=U256(0),
564-
data=data,
565-
code=system_contract_code,
566-
depth=Uint(0),
567-
current_target=target_address,
568-
code_address=target_address,
569-
should_transfer_value=False,
570-
is_static=False,
571-
accessed_addresses=set(),
572-
accessed_storage_keys=set(),
573-
parent_evm=None,
574-
)
575-
576-
system_tx_env = vm.Environment(
577-
caller=SYSTEM_ADDRESS,
578-
origin=SYSTEM_ADDRESS,
579-
coinbase=coinbase,
580-
number=block_number,
581-
gas_limit=block_gas_limit,
582-
base_fee_per_gas=base_fee_per_gas,
583-
gas_price=base_fee_per_gas,
584-
time=block_time,
585-
prev_randao=prev_randao,
586-
state=state,
587-
chain_id=chain_id,
588-
traces=[],
589-
excess_blob_gas=excess_blob_gas,
590-
blob_versioned_hashes=(),
591-
transient_storage=TransientStorage(),
592-
)
593-
594-
system_tx_output = process_message_call(system_tx_message, system_tx_env)
595-
596-
# TODO: Empty accounts in post-merge forks are impossible
597-
# see Ethereum Improvement Proposal 7523.
598-
# This line is only included to support invalid tests in the test suite
599-
# and will have to be removed in the future.
600-
# See https://github.com/ethereum/execution-specs/issues/955
601-
destroy_touched_empty_accounts(
602-
system_tx_env.state, system_tx_output.touched_accounts
603-
)
604-
605-
return system_tx_output
606-
607-
608508
def apply_body(
609509
state: State,
610510
coinbase: Address,
@@ -682,20 +582,51 @@ def apply_body(
682582
secured=False, default=None
683583
)
684584
block_logs: Tuple[Log, ...] = ()
685-
requests_from_execution: Tuple[Bytes, ...] = ()
686-
687-
process_system_transaction(
688-
BEACON_ROOTS_ADDRESS,
689-
parent_beacon_block_root,
690-
coinbase,
691-
block_number,
692-
base_fee_per_gas,
693-
block_gas_limit,
694-
block_time,
695-
prev_randao,
696-
state,
697-
chain_id,
698-
excess_blob_gas,
585+
receipts: Tuple[Receipt, ...] = ()
586+
587+
beacon_block_roots_contract_code = get_account(
588+
state, BEACON_ROOTS_ADDRESS
589+
).code
590+
591+
system_tx_message = Message(
592+
caller=SYSTEM_ADDRESS,
593+
target=BEACON_ROOTS_ADDRESS,
594+
gas=SYSTEM_TRANSACTION_GAS,
595+
value=U256(0),
596+
data=parent_beacon_block_root,
597+
code=beacon_block_roots_contract_code,
598+
depth=Uint(0),
599+
current_target=BEACON_ROOTS_ADDRESS,
600+
code_address=BEACON_ROOTS_ADDRESS,
601+
should_transfer_value=False,
602+
is_static=False,
603+
accessed_addresses=set(),
604+
accessed_storage_keys=set(),
605+
parent_evm=None,
606+
)
607+
608+
system_tx_env = vm.Environment(
609+
caller=SYSTEM_ADDRESS,
610+
origin=SYSTEM_ADDRESS,
611+
coinbase=coinbase,
612+
number=block_number,
613+
gas_limit=block_gas_limit,
614+
base_fee_per_gas=base_fee_per_gas,
615+
gas_price=base_fee_per_gas,
616+
time=block_time,
617+
prev_randao=prev_randao,
618+
state=state,
619+
chain_id=chain_id,
620+
traces=[],
621+
excess_blob_gas=excess_blob_gas,
622+
blob_versioned_hashes=(),
623+
transient_storage=TransientStorage(),
624+
)
625+
626+
system_tx_output = process_message_call(system_tx_message, system_tx_env)
627+
628+
destroy_touched_empty_accounts(
629+
system_tx_env.state, system_tx_output.touched_accounts
699630
)
700631

701632
for i, tx in enumerate(map(decode_transaction, transactions)):
@@ -746,9 +677,8 @@ def apply_body(
746677
rlp.encode(Uint(i)),
747678
receipt,
748679
)
749-
750-
deposit_requests = parse_deposit_requests_from_receipt(receipt)
751-
requests_from_execution += deposit_requests
680+
if isinstance(receipt, Receipt):
681+
receipts += (receipt,)
752682

753683
block_logs += logs
754684
blob_gas_used += calculate_total_blob_gas(tx)
@@ -767,31 +697,10 @@ def apply_body(
767697
destroy_account(state, wd.address)
768698

769699
# Requests are to be in ascending order of request type
700+
validate_requests(requests)
770701

771-
system_withdrawal_tx_output = process_system_transaction(
772-
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS,
773-
b"",
774-
coinbase,
775-
block_number,
776-
base_fee_per_gas,
777-
block_gas_limit,
778-
block_time,
779-
prev_randao,
780-
state,
781-
chain_id,
782-
excess_blob_gas,
783-
)
784-
785-
withdrawal_requests = parse_withdrawal_requests_from_system_tx(
786-
system_withdrawal_tx_output.return_data
787-
)
788-
789-
requests_from_execution += withdrawal_requests
790-
791-
if requests_from_execution != requests:
792-
raise InvalidBlock
793-
794-
for i, request in enumerate(requests_from_execution):
702+
validate_deposit_requests(receipts, requests)
703+
for i, request in enumerate(requests):
795704
trie_set(requests_trie, rlp.encode(Uint(i)), request)
796705

797706
return ApplyBodyOutput(
@@ -878,15 +787,15 @@ def process_transaction(
878787

879788
output = process_message_call(message, env)
880789

881-
floor = Uint(tokens_in_calldata * COST_FLOOR_PER_CALLDATA_TOKEN + TX_BASE_COST)
882-
883-
legacy_cost = Uint(gas_used + tokens_in_calldata * LEGACY_TOKEN_COST)
790+
gas_used = tx.gas - output.gas_left
884791

792+
floor = Uint(tokens_in_calldata * COST_FLOOR_PER_CALLDATA_TOKEN + TX_BASE_COST)
793+
794+
legacy_cost = Uint(gas_used - tokens_in_calldata * (COST_FLOOR_PER_CALLDATA_TOKEN - LEGACY_TOKEN_COST))
795+
885796
if legacy_cost < floor:
886797
output.gas_left -= floor - gas_used
887798
gas_used = floor
888-
else:
889-
gas_used = tx.gas - output.gas_left
890799

891800
gas_refund = min(gas_used // 5, output.refund_counter)
892801
gas_refund_amount = (output.gas_left + gas_refund) * env.gas_price
@@ -946,7 +855,7 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
946855
-------
947856
verified : `ethereum.base_types.Uint`
948857
The intrinsic cost of the transaction.
949-
verified : `ethereum.base_types.Uint`
858+
tokens_in_calldata : `ethereum.base_types.Uint`
950859
The eip-7623 calldata tokens used by the transaction.
951860
"""
952861
data_cost = 0

0 commit comments

Comments
 (0)