-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Add ExecutionPayloadHeader
to LC data
#3151
Changes from 30 commits
0fb0b26
14fd937
364d106
08a2080
c1a6b12
9ab22b3
2e97af2
7e6a990
2df8a55
11d2a59
d6da56c
5028a80
4df8663
e67ca3d
8ad6810
dc05a3f
700bef7
a8dabc0
af78506
3bfac0e
f24365f
02abdc3
b047151
e5cda17
ce7fd41
3754360
53a95f0
82d6267
b720581
ca32fe8
a580f82
514d443
ffd047c
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 |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Capella Light Client -- Fork Logic | ||
|
||
## Table of contents | ||
|
||
<!-- TOC --> | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
- [Introduction](#introduction) | ||
- [Upgrading light client data](#upgrading-light-client-data) | ||
- [Upgrading the store](#upgrading-the-store) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- /TOC --> | ||
|
||
## Introduction | ||
|
||
This document describes how to upgrade existing light client objects based on the [Altair specification](../../altair/light-client/sync-protocol.md) to Capella. This is necessary when processing pre-Capella data with a post-Capella `LightClientStore`. Note that the data being exchanged over the network protocols uses the original format. | ||
|
||
### Upgrading light client data | ||
|
||
A Capella `LightClientStore` can still process earlier light client data. In order to do so, that pre-Capella data needs to be locally upgraded to Capella before processing. | ||
|
||
```python | ||
def upgrade_lc_header_to_capella(pre: BeaconBlockHeader) -> LightClientHeader: | ||
return LightClientHeader( | ||
beacon=pre, | ||
) | ||
``` | ||
|
||
```python | ||
def upgrade_lc_bootstrap_to_capella(pre: altair.LightClientBootstrap) -> LightClientBootstrap: | ||
return LightClientBootstrap( | ||
header=upgrade_lc_header_to_capella(pre.header), | ||
current_sync_committee=pre.current_sync_committee, | ||
current_sync_committee_branch=pre.current_sync_committee_branch, | ||
) | ||
``` | ||
|
||
```python | ||
def upgrade_lc_update_to_capella(pre: altair.LightClientUpdate) -> LightClientUpdate: | ||
return LightClientUpdate( | ||
attested_header=upgrade_lc_header_to_capella(pre.attested_header), | ||
next_sync_committee=pre.next_sync_committee, | ||
next_sync_committee_branch=pre.next_sync_committee_branch, | ||
finalized_header=upgrade_lc_header_to_capella(pre.finalized_header), | ||
finality_branch=pre.finality_branch, | ||
sync_aggregate=pre.sync_aggregate, | ||
signature_slot=pre.signature_slot, | ||
) | ||
``` | ||
|
||
```python | ||
def upgrade_lc_finality_update_to_capella(pre: altair.LightClientFinalityUpdate) -> LightClientFinalityUpdate: | ||
return LightClientFinalityUpdate( | ||
attested_header=upgrade_lc_header_to_capella(pre.attested_header), | ||
finalized_header=upgrade_lc_header_to_capella(pre.finalized_header), | ||
finality_branch=pre.finality_branch, | ||
sync_aggregate=pre.sync_aggregate, | ||
signature_slot=pre.signature_slot, | ||
) | ||
``` | ||
|
||
```python | ||
def upgrade_lc_optimistic_update_to_capella(pre: altair.LightClientOptimisticUpdate) -> LightClientOptimisticUpdate: | ||
return LightClientOptimisticUpdate( | ||
attested_header=upgrade_lc_header_to_capella(pre.attested_header), | ||
sync_aggregate=pre.sync_aggregate, | ||
signature_slot=pre.signature_slot, | ||
) | ||
``` | ||
|
||
### Upgrading the store | ||
|
||
Existing `LightClientStore` objects based on Altair MUST be upgraded to Capella before Capella based light client data can be processed. The `LightClientStore` upgrade MAY be performed before `CAPELLA_FORK_EPOCH`. | ||
|
||
```python | ||
def upgrade_lc_store_to_capella(pre: altair.LightClientStore) -> LightClientStore: | ||
if pre.best_valid_update is None: | ||
best_valid_update = None | ||
else: | ||
best_valid_update = upgrade_lc_update_to_capella(pre.best_valid_update) | ||
return LightClientStore( | ||
finalized_header=upgrade_lc_header_to_capella(pre.finalized_header), | ||
current_sync_committee=pre.current_sync_committee, | ||
next_sync_committee=pre.next_sync_committee, | ||
best_valid_update=best_valid_update, | ||
optimistic_header=upgrade_lc_header_to_capella(pre.optimistic_header), | ||
previous_max_active_participants=pre.previous_max_active_participants, | ||
current_max_active_participants=pre.current_max_active_participants, | ||
) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# Capella Light Client -- Full Node | ||
|
||
**Notice**: This document is a work-in-progress for researchers and implementers. | ||
|
||
## Table of contents | ||
|
||
<!-- TOC --> | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
- [Introduction](#introduction) | ||
- [Helper functions](#helper-functions) | ||
- [`compute_merkle_proof_for_block_body`](#compute_merkle_proof_for_block_body) | ||
- [Modified `block_to_light_client_header`](#modified-block_to_light_client_header) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- /TOC --> | ||
|
||
## Introduction | ||
|
||
This upgrade adds information about the execution payload to light client data as part of the Capella upgrade. | ||
|
||
## Helper functions | ||
|
||
### `compute_merkle_proof_for_block_body` | ||
|
||
```python | ||
def compute_merkle_proof_for_block_body(body: BeaconBlockBody, | ||
index: GeneralizedIndex) -> Sequence[Bytes32]: | ||
... | ||
``` | ||
|
||
### Modified `block_to_light_client_header` | ||
|
||
```python | ||
def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: | ||
epoch = compute_epoch_at_slot(block.message.slot) | ||
|
||
if epoch >= CAPELLA_FORK_EPOCH: | ||
Comment on lines
+36
to
+39
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. Is it because 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, exactly (or, in theory, even all the way back to Altair or Phase0, if bellatrix / altair never finalized, and finalized header is still back in those ancient forks). Added a comment to clarify that. |
||
payload = block.message.body.execution_payload | ||
execution_header = ExecutionPayloadHeader( | ||
parent_hash=payload.parent_hash, | ||
fee_recipient=payload.fee_recipient, | ||
state_root=payload.state_root, | ||
receipts_root=payload.receipts_root, | ||
logs_bloom=payload.logs_bloom, | ||
prev_randao=payload.prev_randao, | ||
block_number=payload.block_number, | ||
gas_limit=payload.gas_limit, | ||
gas_used=payload.gas_used, | ||
timestamp=payload.timestamp, | ||
extra_data=payload.extra_data, | ||
base_fee_per_gas=payload.base_fee_per_gas, | ||
block_hash=payload.block_hash, | ||
transactions_root=hash_tree_root(payload.transactions), | ||
withdrawals_root=hash_tree_root(payload.withdrawals), | ||
) | ||
execution_branch = compute_merkle_proof_for_block_body(block.message.body, EXECUTION_PAYLOAD_INDEX) | ||
else: | ||
# Note that during fork transitions, `finalized_header` may still point to earlier forks. | ||
# While Bellatrix blocks also contain an `ExecutionPayload` (minus `withdrawals_root`), | ||
# it was not included in the corresponding light client data. To ensure compatibility | ||
# with legacy data going through `upgrade_lc_header_to_capella`, leave out execution data. | ||
execution_header = ExecutionPayloadHeader() | ||
execution_branch = [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))] | ||
|
||
return LightClientHeader( | ||
beacon=BeaconBlockHeader( | ||
slot=block.message.slot, | ||
proposer_index=block.message.proposer_index, | ||
parent_root=block.message.parent_root, | ||
state_root=block.message.state_root, | ||
body_root=hash_tree_root(block.message.body), | ||
), | ||
execution=execution_header, | ||
execution_branch=execution_branch, | ||
) | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Capella Light Client -- Networking | ||
|
||
**Notice**: This document is a work-in-progress for researchers and implementers. | ||
|
||
## Table of contents | ||
|
||
<!-- TOC --> | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
- [Networking](#networking) | ||
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub) | ||
- [Topics and messages](#topics-and-messages) | ||
- [Global topics](#global-topics) | ||
- [`light_client_finality_update`](#light_client_finality_update) | ||
- [`light_client_optimistic_update`](#light_client_optimistic_update) | ||
- [The Req/Resp domain](#the-reqresp-domain) | ||
- [Messages](#messages) | ||
- [GetLightClientBootstrap](#getlightclientbootstrap) | ||
- [LightClientUpdatesByRange](#lightclientupdatesbyrange) | ||
- [GetLightClientFinalityUpdate](#getlightclientfinalityupdate) | ||
- [GetLightClientOptimisticUpdate](#getlightclientoptimisticupdate) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- /TOC --> | ||
|
||
## Networking | ||
|
||
The [Altair light client networking specification](../../altair/light-client/p2p-interface.md) is extended to exchange [Capella light client data](./sync-protocol.md). | ||
|
||
### The gossip domain: gossipsub | ||
|
||
#### Topics and messages | ||
|
||
##### Global topics | ||
|
||
###### `light_client_finality_update` | ||
|
||
[0]: # (eth2spec: skip) | ||
|
||
| `fork_version` | Message SSZ type | | ||
| ------------------------------------------------------ | ------------------------------------- | | ||
| `GENESIS_FORK_VERSION` | n/a | | ||
| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientFinalityUpdate` | | ||
| `CAPELLA_FORK_VERSION` and later | `capella.LightClientFinalityUpdate` | | ||
|
||
###### `light_client_optimistic_update` | ||
|
||
[0]: # (eth2spec: skip) | ||
|
||
| `fork_version` | Message SSZ type | | ||
| ------------------------------------------------------ | ------------------------------------- | | ||
| `GENESIS_FORK_VERSION` | n/a | | ||
| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientOptimisticUpdate` | | ||
| `CAPELLA_FORK_VERSION` and later | `capella.LightClientOptimisticUpdate` | | ||
|
||
### The Req/Resp domain | ||
|
||
#### Messages | ||
|
||
##### GetLightClientBootstrap | ||
|
||
[0]: # (eth2spec: skip) | ||
|
||
| `fork_version` | Response SSZ type | | ||
| ------------------------------------------------------ | ------------------------------------- | | ||
| `GENESIS_FORK_VERSION` | n/a | | ||
| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientBootstrap` | | ||
| `CAPELLA_FORK_VERSION` and later | `capella.LightClientBootstrap` | | ||
|
||
##### LightClientUpdatesByRange | ||
|
||
[0]: # (eth2spec: skip) | ||
|
||
| `fork_version` | Response chunk SSZ type | | ||
| ------------------------------------------------------ | ------------------------------------- | | ||
| `GENESIS_FORK_VERSION` | n/a | | ||
| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientUpdate` | | ||
| `CAPELLA_FORK_VERSION` and later | `capella.LightClientUpdate` | | ||
|
||
##### GetLightClientFinalityUpdate | ||
|
||
[0]: # (eth2spec: skip) | ||
|
||
| `fork_version` | Response SSZ type | | ||
| ------------------------------------------------------ | ------------------------------------- | | ||
| `GENESIS_FORK_VERSION` | n/a | | ||
| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientFinalityUpdate` | | ||
| `CAPELLA_FORK_VERSION` and later | `capella.LightClientFinalityUpdate` | | ||
|
||
##### GetLightClientOptimisticUpdate | ||
|
||
[0]: # (eth2spec: skip) | ||
|
||
| `fork_version` | Response SSZ type | | ||
| ------------------------------------------------------ | ------------------------------------- | | ||
| `GENESIS_FORK_VERSION` | n/a | | ||
| `ALTAIR_FORK_VERSION` through `BELLATRIX_FORK_VERSION` | `altair.LightClientOptimisticUpdate` | | ||
| `CAPELLA_FORK_VERSION` and later | `capella.LightClientOptimisticUpdate` | |
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.
Although
altair.LightClientBootstrap
SSZ fields are identicalbellatrix.LightClientBootstrap
, I still think it should bebellatrix.LightClientBootstrap
here for the fork transition. That is, we needbellatrix/light-client/fork.md
andupgrade_*_to_bellatrix
helpers.Moreover, should we make
bellatrix.LightClientHeader
includeExecutionPayloadHeader
and the Merkle proof? It seems more natural since theExecutionPayloadHeader
field was first introduced in Bellatrix. However, (1) it's less useful since Capella is coming soon, and (2) we are still discussing #3078. So I'd say it's fine to keepbellatrix.LightClientHeader
as simple asaltair.LightClientHeader
.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.
Hmm, not sure about the nop
upgrade_*_to_bellatrix
— this would then be required for any future fork, regardless of whether there are any real updates.Kinda like it with
altair
for readability (in practice, implementations will reuse the Altair definition for Bellatrix and not duplicate all the code with every fork). Agree though, that it is a bit hacky as proposed.Anyhow, if you insist, can update it (it works well as-is in pytests though).
About changing Bellatrix data: that one is already being cached in DBs and gossiped without the
ExecutionPayloadHeader
. Changing that would be quite tricky (and in case of gossip may even need a version bump on those topics to avoid disconnecting peers on the previous version). Would therefore leave Bellatrix as is, also considering Capella is in the near future.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.
About
upgrade_*_to_bellatrix
, those are actually not needed. Theseupgrade
helpers are only used when obtaining Altair formatted data and trying to feed it to an already-upgradedLightClientStore
.In the
p2p-interface.md
files you can see that it is not possible to obtain abellatrix.LightClient*
object.fork_version
GENESIS_FORK_VERSION
ALTAIR_FORK_VERSION
throughBELLATRIX_FORK_VERSION
altair.LightClientUpdate
CAPELLA_FORK_VERSION
capella.LightClientUpdate
EIP4844_FORK_VERSION
and latereip4844.LightClientUpdate
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.
And, with this, it is actually correct to have the upgrade convert directly from
altair.LightClient*
tocapella.LightClient*
.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.
(as in, there is no way to actually obtain a
bellatrix.LightClientUpdate
in practice, so no upgrade facility is needed).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.
Now I agree on no need to implement
upgrade_*_to_bellatrix
and the wholebellatrix/light-client/fork.md
file. 👍But I still think it's good to use the "previous fork" (bellatrix) in
upgrade_*_to_capella
in specs.bellatrix.X
means the class/method version we have in Bellatrix.bellatrix.LightClientUpdate
exists in pyspec usage, although it is just as same asaltair.LightClientUpdate
definition.If client implementations actually skip the "unchanged-phase" objects, it's also acceptable since the results are the same.
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.
Sounds good, will change the function signature to
bellatrix.X
but omit theupgrade_*_to_bellatrix
stub.