Skip to content

Commit

Permalink
make requests opaque
Browse files Browse the repository at this point in the history
This PR incorporates the following updates to the Prague EIPs

EIP-7002: add logging to system contract Update EIP-7002: add logging to system contract EIPs#8890
EIP-7251: max eb, change request to flat encoding Update EIP-7251: change request to flat encoding EIPs#8857
EIP-6110: deposits, change request to flat encoding Update EIP-6110: change request to flat encoding EIPs#8856
EIP-7002: withdrawals, change request to flat encoding Update EIP-7002: change request to flat encoding EIPs#8855
EIP-7685: change requests hash to flat hash Update EIP-7685: change requests hash to flat hash EIPs#8854
  • Loading branch information
gurukamath committed Sep 27, 2024
1 parent 2875a73 commit 0248192
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 233 deletions.
4 changes: 2 additions & 2 deletions src/ethereum/genesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ def add_genesis_block(
if has_field(hardfork.Header, "parent_beacon_block_root"):
fields["parent_beacon_block_root"] = Hash32(b"\0" * 32)

if has_field(hardfork.Header, "requests_root"):
fields["requests_root"] = hardfork.root(hardfork.Trie(False, None))
if has_field(hardfork.Header, "requests_hash"):
fields["requests_hash"] = Hash32(b"\0" * 32)

genesis_header = hardfork.Header(**fields)

Expand Down
2 changes: 1 addition & 1 deletion src/ethereum/prague/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class Header:
blob_gas_used: U64
excess_blob_gas: U64
parent_beacon_block_root: Root
requests_root: Root
requests_hash: Hash32


@slotted_freezable
Expand Down
20 changes: 8 additions & 12 deletions src/ethereum/prague/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@
"0x0aae40965e6800cd9b1f4b05ff21581047e3f91e"
)
WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS = hex_to_address(
"0x00A3ca265EBcb825B45F985A16CEFB49958cE017"
"0x05F27129610CB42103b665629CB5c8C00296AaAa"
)
CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS = hex_to_address(
"0x00b42dbf2194e931e80326d950320f7d9dbeac02"
"0x00706203067988Ab3E2A2ab626EdCD6f28bDBbbb"
)
SYSTEM_TRANSACTION_GAS = Uint(30000000)
MAX_BLOB_GAS_PER_BLOCK = 786432
Expand Down Expand Up @@ -236,7 +236,7 @@ def state_transition(chain: BlockChain, block: Block) -> None:
raise InvalidBlock
if apply_body_output.blob_gas_used != block.header.blob_gas_used:
raise InvalidBlock
if apply_body_output.requests_root != block.header.requests_root:
if apply_body_output.requests_hash != block.header.requests_hash:
raise InvalidBlock

chain.blocks.append(block)
Expand Down Expand Up @@ -522,8 +522,8 @@ class ApplyBodyOutput:
Trie root of all the withdrawals in the block.
blob_gas_used : `ethereum.base_types.Uint`
Total blob gas used in the block.
requests_root : `ethereum.fork_types.Root`
Trie root of all the requests in the block.
requests_hash : `ethereum.fork_types.Root`
Hash of all the requests in the block.
"""

block_gas_used: Uint
Expand All @@ -533,7 +533,7 @@ class ApplyBodyOutput:
state_root: Root
withdrawals_root: Root
blob_gas_used: Uint
requests_root: Root
requests_hash: Hash32


def process_system_transaction(
Expand Down Expand Up @@ -715,9 +715,6 @@ def apply_body(
withdrawals_trie: Trie[Bytes, Optional[Union[Bytes, Withdrawal]]] = Trie(
secured=False, default=None
)
requests_trie: Trie[Bytes, Optional[Bytes]] = Trie(
secured=False, default=None
)
block_logs: Tuple[Log, ...] = ()
requests_from_execution: Tuple[Bytes, ...] = ()

Expand Down Expand Up @@ -867,8 +864,7 @@ def apply_body(
if requests_from_execution != requests:
raise InvalidBlock

for i, request in enumerate(requests_from_execution):
trie_set(requests_trie, rlp.encode(Uint(i)), request)
requests_hash = keccak256(rlp.encode(requests_from_execution))

return ApplyBodyOutput(
block_gas_used,
Expand All @@ -878,7 +874,7 @@ def apply_body(
state_root(state),
root(withdrawals_trie),
blob_gas_used,
root(requests_trie),
requests_hash,
)


Expand Down
145 changes: 18 additions & 127 deletions src/ethereum/prague/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,10 @@
[EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685
"""

from dataclasses import dataclass
from typing import Tuple, Union

from .. import rlp
from ..base_types import (
U64,
Bytes,
Bytes32,
Bytes48,
Bytes96,
slotted_freezable,
)
from ..base_types import Bytes
from .blocks import Receipt, decode_receipt
from .fork_types import Address
from .utils.hexadecimal import hex_to_address

DEPOSIT_CONTRACT_ADDRESS = hex_to_address(
Expand All @@ -34,94 +24,17 @@
CONSOLIDATION_REQUEST_LENGTH = 116


@slotted_freezable
@dataclass
class DepositRequest:
"""
Requests for validator deposits on chain (See [EIP-6110]).
[EIP-6110]: https://eips.ethereum.org/EIPS/eip-6110
"""

public_key: Bytes48
withdrawal_credentials: Bytes32
amount: U64
signature: Bytes96
index: U64


@slotted_freezable
@dataclass
class WithdrawalRequest:
"""
Requests for execution layer withdrawals (See [EIP-7002]).
[EIP-7002]: https://eips.ethereum.org/EIPS/eip-7002
"""

source_address: Address
validator_public_key: Bytes48
amount: U64


@slotted_freezable
@dataclass
class ConsolidationRequest:
"""
Requests for validator consolidation (See [EIP-7251]).
[EIP-7251]: https://eips.ethereum.org/EIPS/eip-7251
"""

source_address: Address
source_public_key: Bytes48
target_public_key: Bytes48


Request = Union[DepositRequest, WithdrawalRequest, ConsolidationRequest]


def encode_request(req: Request) -> Bytes:
"""
Serialize a `Request` into a byte sequence.
`Request`s are encoded as a type byte followed by the RLP encoding
of the request.
"""
if isinstance(req, DepositRequest):
return DEPOSIT_REQUEST_TYPE + rlp.encode(req)
elif isinstance(req, WithdrawalRequest):
return WITHDRAWAL_REQUEST_TYPE + rlp.encode(req)
elif isinstance(req, ConsolidationRequest):
return CONSOLIDATION_REQUEST_TYPE + rlp.encode(req)
else:
raise Exception("Unknown request type")


def decode_request(data: Bytes) -> Request:
"""
Decode a request.
"""
if data.startswith(DEPOSIT_REQUEST_TYPE):
return rlp.decode_to(DepositRequest, data[1:])
elif data.startswith(WITHDRAWAL_REQUEST_TYPE):
return rlp.decode_to(WithdrawalRequest, data[1:])
elif data.startswith(CONSOLIDATION_REQUEST_TYPE):
return rlp.decode_to(ConsolidationRequest, data[1:])
else:
raise Exception("Unknown request type")


def parse_deposit_data(data: Bytes) -> DepositRequest:
def parse_deposit_data(data: Bytes) -> Bytes:
"""
Parses Deposit Request from the DepositContract.DepositEvent data.
"""
return DepositRequest(
public_key=Bytes48(data[192:240]),
withdrawal_credentials=Bytes32(data[288:320]),
amount=U64.from_le_bytes(data[352:360]),
signature=Bytes96(data[416:512]),
index=U64.from_le_bytes(data[544:552]),
return (
DEPOSIT_REQUEST_TYPE
+ data[192:240] # public_key
+ data[288:320] # withdrawal_credentials
+ data[352:360] # amount
+ data[416:512] # signature
+ data[544:552] # index
)


Expand All @@ -136,23 +49,11 @@ def parse_deposit_requests_from_receipt(
for log in decoded_receipt.logs:
if log.address == DEPOSIT_CONTRACT_ADDRESS:
deposit_request = parse_deposit_data(log.data)
deposit_requests += (encode_request(deposit_request),)
deposit_requests += (deposit_request,)

return deposit_requests


def parse_withdrawal_data(data: Bytes) -> WithdrawalRequest:
"""
Parses Withdrawal Request from the data.
"""
assert len(data) == WITHDRAWAL_REQUEST_LENGTH
return WithdrawalRequest(
source_address=Address(data[:20]),
validator_public_key=Bytes48(data[20:68]),
amount=U64.from_be_bytes(data[68:76]),
)


def parse_withdrawal_requests_from_system_tx(
evm_call_output: Bytes,
) -> Tuple[Bytes, ...]:
Expand All @@ -166,26 +67,15 @@ def parse_withdrawal_requests_from_system_tx(
withdrawal_requests: Tuple[Bytes, ...] = ()
for i in range(count_withdrawal_requests):
start = i * WITHDRAWAL_REQUEST_LENGTH
withdrawal_request = parse_withdrawal_data(
evm_call_output[start : start + WITHDRAWAL_REQUEST_LENGTH]
withdrawal_request = (
WITHDRAWAL_REQUEST_TYPE
+ evm_call_output[start : start + WITHDRAWAL_REQUEST_LENGTH]
)
withdrawal_requests += (encode_request(withdrawal_request),)
withdrawal_requests += (withdrawal_request,)

return withdrawal_requests


def parse_consolidation_data(data: Bytes) -> ConsolidationRequest:
"""
Parses Consolidation Request from the data.
"""
assert len(data) == CONSOLIDATION_REQUEST_LENGTH
return ConsolidationRequest(
source_address=Address(data[:20]),
source_public_key=Bytes48(data[20:68]),
target_public_key=Bytes48(data[68:116]),
)


def parse_consolidation_requests_from_system_tx(
evm_call_output: Bytes,
) -> Tuple[Bytes, ...]:
Expand All @@ -199,9 +89,10 @@ def parse_consolidation_requests_from_system_tx(
consolidation_requests: Tuple[Bytes, ...] = ()
for i in range(count_consolidation_requests):
start = i * CONSOLIDATION_REQUEST_LENGTH
consolidation_request = parse_consolidation_data(
evm_call_output[start : start + CONSOLIDATION_REQUEST_LENGTH]
consolidation_request = (
CONSOLIDATION_REQUEST_TYPE
+ evm_call_output[start : start + CONSOLIDATION_REQUEST_LENGTH]
)
consolidation_requests += (encode_request(consolidation_request),)
consolidation_requests += (consolidation_request,)

return consolidation_requests
6 changes: 3 additions & 3 deletions src/ethereum_spec_tools/evm_tools/loaders/fixture_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ def json_to_header(self, raw: Any) -> Any:
)
parameters.append(parent_beacon_block_root)

if "requestsRoot" in raw:
requests_root = self.fork.hex_to_root(raw.get("requestsRoot"))
parameters.append(requests_root)
if "requestsHash" in raw:
requests_hash = hex_to_bytes32(raw.get("requestsHash"))
parameters.append(requests_hash)

return self.fork.Header(*parameters)
20 changes: 0 additions & 20 deletions src/ethereum_spec_tools/evm_tools/loaders/fork_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,26 +172,6 @@ def Block(self) -> Any:
"""Block class of the fork"""
return self._module("blocks").Block

@property
def DepositRequest(self) -> Any:
"""Deposit request of the fork"""
return self._module("requests").DepositRequest

@property
def WithdrawalRequest(self) -> Any:
"""Withdrawal request of the fork"""
return self._module("requests").WithdrawalRequest

@property
def ConsolidationRequest(self) -> Any:
"""Consolidation request of the fork"""
return self._module("requests").ConsolidationRequest

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

@property
def parse_withdrawal_requests_from_system_tx(self) -> Any:
"""parse_withdrawal_requests_from_system_tx function of the fork"""
Expand Down
24 changes: 4 additions & 20 deletions src/ethereum_spec_tools/evm_tools/t8n/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,18 +289,6 @@ def restore_state(self) -> None:
state = self.alloc.state
state._main_trie, state._storage_tries = self.alloc.state_backup

def decode_request(self, decoded_requests: Any, request: Any) -> Any:
"""Decode a request."""
req = self.fork.decode_request(request)
if isinstance(req, self.fork.DepositRequest):
decoded_requests.append(("depositRequests", req))
elif isinstance(req, self.fork.WithdrawalRequest):
decoded_requests.append(("withdrawalRequests", req))
elif isinstance(req, self.fork.ConsolidationRequest):
decoded_requests.append(("consolidationRequests", req))
else:
raise Exception("Unknown request type")

def apply_body(self) -> None:
"""
The apply body function is seen as the entry point of
Expand All @@ -320,7 +308,6 @@ def apply_body(self) -> None:
self.fork.is_after_fork("ethereum.prague")
and not self.options.state_test
):
requests_trie = self.fork.Trie(secured=False, default=None)
requests_from_execution: Tuple[Bytes, ...] = ()

self.fork.process_system_transaction(
Expand Down Expand Up @@ -501,11 +488,6 @@ def apply_body(self) -> None:

requests_from_execution += consolidation_requests

decoded_requests: Any = []
for i, request in enumerate(requests_from_execution):
self.fork.trie_set(requests_trie, rlp.encode(Uint(i)), request)
self.decode_request(decoded_requests, request)

self.result.state_root = self.fork.state_root(self.alloc.state)
self.result.tx_root = self.fork.root(transactions_trie)
self.result.receipt_root = self.fork.root(receipts_trie)
Expand All @@ -519,8 +501,10 @@ def apply_body(self) -> None:
self.fork.is_after_fork("ethereum.prague")
and not self.options.state_test
):
self.result.requests_root = self.fork.root(requests_trie)
self.result.requests = decoded_requests
self.result.requests_hash = keccak256(
rlp.encode(requests_from_execution)
)
self.result.requests = requests_from_execution

def run(self) -> int:
"""Run the transition and provide the relevant outputs"""
Expand Down
Loading

0 comments on commit 0248192

Please sign in to comment.