Skip to content

Commit

Permalink
Implement EIP-4788
Browse files Browse the repository at this point in the history
  • Loading branch information
gurukamath committed Dec 10, 2023
1 parent fcf2cd6 commit 5cdcc25
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/ethereum/cancun/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
state_root,
)
from .trie import Trie, root, trie_set
from .utils.hexadecimal import hex_to_address
from .utils.message import prepare_message
from .vm import Message
from .vm.gas import init_code_cost
from .vm.interpreter import MAX_CODE_SIZE, process_message_call

Expand All @@ -67,6 +69,11 @@
GAS_LIMIT_ADJUSTMENT_FACTOR = 1024
GAS_LIMIT_MINIMUM = 5000
EMPTY_OMMER_HASH = keccak256(rlp.encode([]))
SYSTEM_ADDRESS = hex_to_address("0xfffffffffffffffffffffffffffffffffffffffe")
BEACON_ROOTS_ADDRESS = hex_to_address(
"0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"
)
SYSTEM_TRANSACTION_GAS = 30000000


@dataclass
Expand Down Expand Up @@ -186,6 +193,7 @@ def state_transition(chain: BlockChain, block: Block) -> None:
block.transactions,
chain.chain_id,
block.withdrawals,
block.header.parent_beacon_block_root,
)
ensure(gas_used == block.header.gas_used, InvalidBlock)
ensure(transactions_root == block.header.transactions_root, InvalidBlock)
Expand Down Expand Up @@ -411,6 +419,7 @@ def apply_body(
transactions: Tuple[Union[LegacyTransaction, Bytes], ...],
chain_id: U64,
withdrawals: Tuple[Withdrawal, ...],
parent_beacon_block_root: Root,
) -> Tuple[Uint, Root, Root, Bloom, State, Root]:
"""
Executes a block.
Expand Down Expand Up @@ -450,6 +459,8 @@ def apply_body(
ID of the executing chain.
withdrawals :
Withdrawals to be processed in the current block.
parent_beacon_block_root :
The root of the beacon block from the parent block.
Returns
-------
Expand Down Expand Up @@ -477,6 +488,45 @@ def apply_body(
)
block_logs: Tuple[Log, ...] = ()

beacon_block_roots_contract_code = get_account(
state, BEACON_ROOTS_ADDRESS
).code

system_tx_message = Message(
caller=SYSTEM_ADDRESS,
target=BEACON_ROOTS_ADDRESS,
gas=Uint(SYSTEM_TRANSACTION_GAS),
value=U256(0),
data=parent_beacon_block_root,
code=beacon_block_roots_contract_code,
depth=Uint(0),
current_target=BEACON_ROOTS_ADDRESS,
code_address=BEACON_ROOTS_ADDRESS,
should_transfer_value=False,
is_static=False,
accessed_addresses=set(),
accessed_storage_keys=set(),
parent_evm=None,
)

system_tx_env = vm.Environment(
caller=SYSTEM_ADDRESS,
origin=SYSTEM_ADDRESS,
block_hashes=block_hashes,
coinbase=coinbase,
number=block_number,
gas_limit=block_gas_limit,
base_fee_per_gas=base_fee_per_gas,
gas_price=base_fee_per_gas,
time=block_time,
prev_randao=prev_randao,
state=state,
chain_id=chain_id,
traces=[],
)

process_message_call(system_tx_message, system_tx_env)

for i, tx in enumerate(map(decode_transaction, transactions)):
trie_set(
transactions_trie, rlp.encode(Uint(i)), encode_transaction(tx)
Expand Down
1 change: 1 addition & 0 deletions src/ethereum/cancun/fork_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ class Header:
nonce: Bytes8
base_fee_per_gas: Uint
withdrawals_root: Root
parent_beacon_block_root: Root


@slotted_freezable
Expand Down
5 changes: 5 additions & 0 deletions src/ethereum_spec_tools/evm_tools/fixture_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ def State(self) -> Any:
"""State class of the fork"""
return self._module("state").State

@property
def get_account(self) -> Any:
"""get_account function of the fork"""
return self._module("state").get_account

@property
def set_account(self) -> Any:
"""set_account function of the fork"""
Expand Down
56 changes: 56 additions & 0 deletions src/ethereum_spec_tools/evm_tools/t8n/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ def __init__(self, options: Any) -> None:
self.env.block_difficulty, self.env.base_fee_per_gas
)

if self.is_after_fork("ethereum.cancun"):
self.SYSTEM_ADDRESS = self.hex_to_address(
"0xfffffffffffffffffffffffffffffffffffffffe"
)
self.BEACON_ROOTS_ADDRESS = self.hex_to_address(
"0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"
)
self.SYSTEM_TRANSACTION_GAS = 30000000

@property
def fork(self) -> Any:
"""The fork module of the given fork."""
Expand Down Expand Up @@ -146,6 +155,11 @@ def vm(self) -> Any:
"""The vm module of the given fork."""
return self._module("vm")

@property
def interpreter(self) -> Any:
"""The interpreter module of the given fork."""
return self._module("vm.interpreter")

@property
def BLOCK_REWARD(self) -> Any:
"""
Expand Down Expand Up @@ -320,6 +334,48 @@ def apply_body(self) -> None:
receipts_trie = self.trie.Trie(secured=False, default=None)
block_logs = ()

if self.is_after_fork("ethereum.cancun"):
beacon_block_roots_contract_code = self.get_account(
self.alloc.state, self.BEACON_ROOTS_ADDRESS
).code

system_tx_message = self.vm.Message(
caller=self.SYSTEM_ADDRESS,
target=self.BEACON_ROOTS_ADDRESS,
gas=Uint(self.SYSTEM_TRANSACTION_GAS),
value=U256(0),
data=self.env.parent_beacon_block_root,
code=beacon_block_roots_contract_code,
depth=Uint(0),
current_target=self.BEACON_ROOTS_ADDRESS,
code_address=self.BEACON_ROOTS_ADDRESS,
should_transfer_value=False,
is_static=False,
accessed_addresses=set(),
accessed_storage_keys=set(),
parent_evm=None,
)

system_tx_env = self.vm.Environment(
caller=self.SYSTEM_ADDRESS,
origin=self.SYSTEM_ADDRESS,
block_hashes=self.env.block_hashes,
coinbase=self.env.coinbase,
number=self.env.block_number,
gas_limit=self.env.block_gas_limit,
base_fee_per_gas=self.env.base_fee_per_gas,
gas_price=self.env.base_fee_per_gas,
time=self.env.block_timestamp,
prev_randao=self.env.prev_randao,
state=self.alloc.state,
chain_id=self.chain_id,
traces=[],
)

self.interpreter.process_message_call(
system_tx_message, system_tx_env
)

for i, (tx_idx, tx) in enumerate(self.txs.transactions):
# i is the index among valid transactions
# tx_idx is the index among all transactions. tx_idx is only used
Expand Down
8 changes: 8 additions & 0 deletions src/ethereum_spec_tools/evm_tools/t8n/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Env:
block_hashes: Optional[List[Any]]
parent_ommers_hash: Optional[Hash32]
ommers: Any
parent_beacon_block_root: Optional[Hash32]

def __init__(self, t8n: Any, stdin: Optional[Dict] = None):
if t8n.options.input_env == "stdin":
Expand All @@ -64,6 +65,13 @@ def __init__(self, t8n: Any, stdin: Optional[Dict] = None):
self.read_ommers(data, t8n)
self.read_withdrawals(data, t8n)

if t8n.is_after_fork("ethereum.cancun"):
self.parent_beacon_block_root = Bytes32(
hex_to_bytes(data["parentBeaconBlockRoot"])
)
else:
self.parent_beacon_block_root = None

def read_base_fee_per_gas(self, data: Any, t8n: Any) -> None:
"""
Read the base_fee_per_gas from the data. If the base fee is
Expand Down
1 change: 1 addition & 0 deletions tests/cancun/test_rlp.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
nonce=Bytes8(b"12345678"),
base_fee_per_gas=Uint(6),
withdrawals_root=hash6,
parent_beacon_block_root=Bytes32(b"1234567890abcdef1234567890abcdef"),
)

block = Block(
Expand Down

0 comments on commit 5cdcc25

Please sign in to comment.