-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Update EIP-6110: Spec parse_deposit_data
#9460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
232872a
8e67988
9b687a3
4f912ac
3c96c46
9bef0b9
eb150ed
01e54fc
194f66e
43cf243
b1e69fd
31641e8
6b0eb53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,11 +76,26 @@ Beginning with the `FORK_BLOCK`, each deposit accumulated in the block **MUST** | |
in the order they appear in the logs. To illustrate: | ||
|
||
```python | ||
def parse_deposit_data(deposit_event_data) -> bytes[]: | ||
""" | ||
Parses deposit data from DepositContract.DepositEvent data | ||
""" | ||
pass | ||
def parse_deposit_data(deposit_event_data): | ||
""" | ||
Parses deposit data from DepositContract.DepositEvent data. | ||
""" | ||
|
||
# TODO: verify byte length of deposit_event_data? Should be 576. Should this be part of the spec? | ||
|
||
PUBKEY_OFFSET = 192 | ||
WITHDRAWAL_OFFSET = 288 | ||
AMOUNT_OFFSET = 352 | ||
SIGNATURE_OFFSET = 416 | ||
INDEX_OFFSET = 544 | ||
|
||
pubkey = deposit_event_data[PUBKEY_OFFSET:PUBKEY_OFFSET + 48] | ||
withdrawal_credentials = deposit_event_data[WITHDRAWAL_OFFSET:WITHDRAWAL_OFFSET + 32] | ||
amount = deposit_event_data[AMOUNT_OFFSET:AMOUNT_OFFSET + 8] | ||
signature = deposit_event_data[SIGNATURE_OFFSET:SIGNATURE_OFFSET + 96] | ||
index = deposit_event_data[INDEX_OFFSET:INDEX_OFFSET + 8] | ||
|
||
return [pubkey, withdrawal_credentials, amount, signature, index] | ||
|
||
def event_data_to_deposit_request(deposit_event_data) -> bytes: | ||
deposit_data = parse_deposit_data(deposit_event_data) | ||
|
@@ -97,7 +112,7 @@ def get_deposit_request_data(receipts) | |
deposit_requests = [] | ||
for receipt in receipts: | ||
for log in receipt.logs: | ||
is_deposit_event = (len(log.topics) > 0 and log.topics[0] == DEPOSIT_EVENT_SIGNATURE_HASH) | ||
is_deposit_event = (len(log.topics) > 0 and log.topics[0] == DEPOSIT_EVENT_SIGNATURE_HASH and len(log.data) === 576) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens when its the correct contract, correct signature but There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It skips the log. Note that the current spec tells us how to encode the request (no changes to it in this PR):
Note that if these value lengths are ABI encoded you would still end up with the 576 length event, because:
So, in total (5+5) * 32 + 64 + 32 + 32 + 96 + 32 = 576 bytes. If we would take, for instance, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The spec does not specify lengths and offsets, it specifies that the input values are variable https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md#staking-deposit-contract
and also that the logs are variable
The L1 smart contract also specify that the types are variable https://etherscan.io/address/0x00000000219ab540356cbb839cbe05303d7705fa#code function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) override external payable { and in the log event DepositEvent(
bytes pubkey,
bytes withdrawal_credentials,
bytes amount,
bytes signature,
bytes index
); Where is it specified that they are fixed sized buffers of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I should have been more clear, I was not referring to the solidity spec, but to the encoding spec of the actual request (so the request which gets in the block header) of this EIP. See: https://eips.ethereum.org/EIPS/eip-6110#execution-layer and then to the "Deposit request" part: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok but those are post parsing the log data? i.e. Before that where is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There technically is none, but, the deposit event hash is now hardcoded in clients to filter out non- So this is given: event DepositEvent(
bytes pubkey,
bytes withdrawal_credentials,
bytes amount,
bytes signature,
bytes index
); Note: By ABI encoding as mentioned here: #9460 (comment) if we keep the way how requests are encoded, then if more data would get added to one of these parameters, it would not fit in the requests data (and we thus need to edit how the request itself gets encoded in the header) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Side-note, this extra check is taken from Geth's code: https://github.com/ethereum/go-ethereum/blob/cd78b65cdaa9e00866962e38685c4f93ac9e8444/core/types/deposit.go#L28 Note that on mainnet the deposit event length should be 576 bytes always (implied by the solidity implementation, did not check bytecode) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes and The L1 code does have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. e.g. if the contract accepted 1ETH deposits However the log would also fail the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What the mainnet contract does is no guarantee of what ABI compliant contracts that follow the spec do; or Sepolia wouldn't have broken. What is in all prior specs is that these are all variable length fields; that the size is 576 is an implementation detail of the mainnet contract, however it is not guaranteed in any spec; which in fact specify they are variable length fields. Mainnet output in |
||
if log.address == DEPOSIT_CONTRACT_ADDRESS and is_deposit_event: | ||
deposit_request = event_data_to_deposit_request(log.data) | ||
deposit_requests.append(deposit_request) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it has to be. The simplest is to require the length of the log data to be exactly this (otherwise, no request is noted).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops forgot to remove this TODO. It is currently at line 115
is_deposit_event = (len(log.topics) > 0 and log.topics[0] == DEPOSIT_EVENT_SIGNATURE_HASH and len(log.data) === 576)
. I'll remove the TODO :)