Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 10 additions & 23 deletions specs/gloas/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,21 +142,20 @@ and broadcasts it on the `execution_payload_header` global gossip topic.

#### Modified `get_data_column_sidecars`

*Note*: The function `get_data_column_sidecars` is modified to use the updated
blob KZG commitments inclusion proof type with a different length.
*Note*: The function `get_data_column_sidecars` is modified to remove
`signed_block_header` and `kzg_commitments_inclusion_proof` parameters as header
and inclusion proof verifications are no longer required in ePBS.

```python
def get_data_column_sidecars(
signed_block_header: SignedBeaconBlockHeader,
beacon_block_root: Root,
kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK],
# [Modified in Gloas:EIP7732]
kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH_GLOAS],
cells_and_kzg_proofs: Sequence[
Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]]
],
) -> Sequence[DataColumnSidecar]:
"""
Given a signed block header and the commitments, inclusion proof, cells/proofs associated with
Given a beacon block root and the commitments, cells/proofs associated with
each blob in the block, assemble the sidecars which can be distributed to peers.
"""
assert len(cells_and_kzg_proofs) == len(kzg_commitments)
Expand All @@ -173,8 +172,7 @@ def get_data_column_sidecars(
column=column_cells,
kzg_commitments=kzg_commitments,
kzg_proofs=column_proofs,
signed_block_header=signed_block_header,
kzg_commitments_inclusion_proof=kzg_commitments_inclusion_proof,
beacon_block_root=beacon_block_root,
)
)
return sidecars
Expand All @@ -183,8 +181,8 @@ def get_data_column_sidecars(
#### Modified `get_data_column_sidecars_from_block`

*Note*: The function `get_data_column_sidecars_from_block` is modified to
include the list of blob KZG commitments and to compute the blob KZG commitments
inclusion proof given that these are in the `ExecutionPayloadEnvelope` now.
include the list of blob KZG commitments and to use `beacon_block_root` instead
of header and inclusion proof computations.

```python
def get_data_column_sidecars_from_block(
Expand All @@ -199,21 +197,10 @@ def get_data_column_sidecars_from_block(
Given a signed block and the cells/proofs associated with each blob in the
block, assemble the sidecars which can be distributed to peers.
"""
signed_block_header = compute_signed_block_header(signed_block)
# [Modified in Gloas:EIP7732]
kzg_commitments_inclusion_proof = compute_merkle_proof(
signed_block.message.body,
get_generalized_index(
BeaconBlockBody,
"signed_execution_payload_header",
"message",
"blob_kzg_commitments_root",
),
)
beacon_block_root = hash_tree_root(signed_block.message)
return get_data_column_sidecars(
signed_block_header,
beacon_block_root,
blob_kzg_commitments,
kzg_commitments_inclusion_proof,
cells_and_kzg_proofs,
)
```
Expand Down
113 changes: 66 additions & 47 deletions specs/gloas/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@
- [Modification in Gloas](#modification-in-gloas)
- [Helper functions](#helper-functions)
- [Modified `compute_fork_version`](#modified-compute_fork_version)
- [Preset](#preset)
- [Configuration](#configuration)
- [Containers](#containers)
- [Modified `DataColumnSidecar`](#modified-datacolumnsidecar)
- [Helpers](#helpers)
- [Modified `verify_data_column_sidecar_inclusion_proof`](#modified-verify_data_column_sidecar_inclusion_proof)
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
- [Topics and messages](#topics-and-messages)
- [Global topics](#global-topics)
Expand All @@ -22,6 +19,8 @@
- [`execution_payload`](#execution_payload)
- [`payload_attestation_message`](#payload_attestation_message)
- [`execution_payload_header`](#execution_payload_header)
- [Blob subnets](#blob-subnets)
- [`data_column_sidecar_{subnet_id}`](#data_column_sidecar_subnet_id)
- [Attestation subnets](#attestation-subnets)
- [`beacon_attestation_{subnet_id}`](#beacon_attestation_subnet_id)
- [The Req/Resp domain](#the-reqresp-domain)
Expand Down Expand Up @@ -68,14 +67,6 @@ def compute_fork_version(epoch: Epoch) -> Version:
return GENESIS_FORK_VERSION
```

### Preset

*[Modified in Gloas:EIP7732]*

| Name | Value | Description |
| --------------------------------------------- | ----- | ----------------------------------------------------------- |
| `KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH_GLOAS` | `9` | Merkle proof depth for the `blob_kzg_commitments` list item |

### Configuration

*[New in Gloas:EIP7732]*
Expand All @@ -88,49 +79,19 @@ def compute_fork_version(epoch: Epoch) -> Version:

#### Modified `DataColumnSidecar`

*Note*: The `DataColumnSidecar` container is modified indirectly because the
constant `KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH` is modified.
*Note*: The `signed_block_header` and `kzg_commitments_inclusion_proof` fields
have been removed from `DataColumnSidecar` in Gloas as header and inclusion
proof verifications are no longer required in ePBS. Instead, sidecars are
validated by checking that the hash of `kzg_commitments` matches what's
committed in the builder's bid for the corresponding `beacon_block_root`.

```python
class DataColumnSidecar(Container):
index: ColumnIndex
column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK]
kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK]
signed_block_header: SignedBeaconBlockHeader
# [Modified in Gloas:EIP7732]
kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH_GLOAS]
```

#### Helpers

##### Modified `verify_data_column_sidecar_inclusion_proof`

`verify_data_column_sidecar_inclusion_proof` is modified in Gloas to account for
the fact that the KZG commitments are included in the `ExecutionPayloadEnvelope`
and no longer in the beacon block body.

```python
def verify_data_column_sidecar_inclusion_proof(sidecar: DataColumnSidecar) -> bool:
"""
Verify if the given KZG commitments included in the given beacon block.
"""
return is_valid_merkle_branch(
leaf=hash_tree_root(sidecar.kzg_commitments),
branch=sidecar.kzg_commitments_inclusion_proof,
# [Modified in Gloas:EIP7732]
depth=KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH_GLOAS,
# [Modified in Gloas:EIP7732]
index=get_subtree_index(
get_generalized_index(
BeaconBlockBody,
"signed_execution_payload_header",
"message",
"blob_kzg_commitments_root",
)
),
root=sidecar.signed_block_header.message.body_root,
)
beacon_block_root: Root
```

### The gossip domain: gossipsub
Expand Down Expand Up @@ -293,6 +254,64 @@ The following validations MUST pass before forwarding the
- _[REJECT]_ `signed_execution_payload_header.signature` is valid with respect
to the `header.builder_index`.

##### Blob subnets

###### `data_column_sidecar_{subnet_id}`

*[Modified in Gloas:EIP7732]*

This topic is used to propagate column sidecars, where each column maps to some
`subnet_id`.

The *type* of the payload of this topic is `DataColumnSidecar`.

The following validations MUST pass before forwarding the
`sidecar: DataColumnSidecar` on the network:

**Modified from Fulu:**

- _[IGNORE]_ The sidecar is the first sidecar for the tuple
`(sidecar.beacon_block_root, sidecar.index)` with valid kzg proof.

**Added in Gloas:**

- _[IGNORE]_ The sidecar's `beacon_block_root` has been seen via a valid signed
execution payload header (builder's bid).
- _[REJECT]_ The hash of the sidecar's `kzg_commitments` matches the
`blob_kzg_commitments_root` in the corresponding builder's bid for
`sidecar.beacon_block_root`.

**Removed from Fulu:**

- _[IGNORE]_ The sidecar is not from a future slot (with a
`MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. validate that
`block_header.slot <= current_slot` (a client MAY queue future sidecars for
processing at the appropriate slot).
- _[IGNORE]_ The sidecar is from a slot greater than the latest finalized slot
-- i.e. validate that
`block_header.slot > compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)`
- _[REJECT]_ The proposer signature of `sidecar.signed_block_header`, is valid
with respect to the `block_header.proposer_index` pubkey.
- _[IGNORE]_ The sidecar's block's parent (defined by
`block_header.parent_root`) has been seen (via gossip or non-gossip sources)
(a client MAY queue sidecars for processing once the parent block is
retrieved).
- _[REJECT]_ The sidecar's block's parent (defined by
`block_header.parent_root`) passes validation.
- _[REJECT]_ The sidecar is from a higher slot than the sidecar's block's parent
(defined by `block_header.parent_root`).
- _[REJECT]_ The current finalized_checkpoint is an ancestor of the sidecar's
block -- i.e.
`get_checkpoint_block(store, block_header.parent_root, store.finalized_checkpoint.epoch) == store.finalized_checkpoint.root`.
- _[REJECT]_ The sidecar's `kzg_commitments` field inclusion proof is valid as
verified by `verify_data_column_sidecar_inclusion_proof(sidecar)`.
- _[REJECT]_ The sidecar is proposed by the expected `proposer_index` for the
block's slot in the context of the current shuffling (defined by
`block_header.parent_root`/`block_header.slot`). If the `proposer_index`
cannot immediately be verified against the expected shuffling, the sidecar MAY
be queued for later processing while proposers for the block's branch are
calculated -- in such a case _do not_ `REJECT`, instead `IGNORE` this message.

##### Attestation subnets

###### `beacon_attestation_{subnet_id}`
Expand Down
28 changes: 28 additions & 0 deletions specs/gloas/validator.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
- [Constructing a payload attestation](#constructing-a-payload-attestation)
- [Modified functions](#modified-functions)
- [Modified `prepare_execution_payload`](#modified-prepare_execution_payload)
- [Data column sidecars](#data-column-sidecars)
- [Modified `get_data_column_sidecars_from_column_sidecar`](#modified-get_data_column_sidecars_from_column_sidecar)

<!-- mdformat-toc end -->

Expand Down Expand Up @@ -253,3 +255,29 @@ def prepare_execution_payload(
payload_attributes=payload_attributes,
)
```

## Data column sidecars

*[Modified in Gloas]*

### Modified `get_data_column_sidecars_from_column_sidecar`

```python
def get_data_column_sidecars_from_column_sidecar(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

help needed: I had to add this to get the lint to pass and I dont know why

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What did you had to add?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had to add this function because we changed the definition of get_data_column_sidecars which it calls. Without the tests which use it would call that function with the wrong arguments. This seems fine to me.

sidecar: DataColumnSidecar,
cells_and_kzg_proofs: Sequence[
Tuple[Vector[Cell, CELLS_PER_EXT_BLOB], Vector[KZGProof, CELLS_PER_EXT_BLOB]]
],
) -> Sequence[DataColumnSidecar]:
"""
Given a DataColumnSidecar and the cells/proofs associated with each blob corresponding
to the commitments it contains, assemble all sidecars for distribution to peers.
"""
assert len(cells_and_kzg_proofs) == len(sidecar.kzg_commitments)

return get_data_column_sidecars(
sidecar.signed_block_header.message.body_root,
sidecar.kzg_commitments,
cells_and_kzg_proofs,
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -62,33 +62,26 @@ def _run_blob_kzg_commitments_merkle_proof_test(spec, state, rng=None, blob_coun
column_sidcar = column_sidcars[0]

yield "object", block.body
kzg_commitments_inclusion_proof = column_sidcar.kzg_commitments_inclusion_proof
if is_post_gloas(spec):
gindex = spec.get_generalized_index(
spec.BeaconBlockBody,
"signed_execution_payload_header",
"message",
"blob_kzg_commitments_root",
)
else:
if not is_post_gloas(spec):
kzg_commitments_inclusion_proof = column_sidcar.kzg_commitments_inclusion_proof
gindex = spec.get_generalized_index(spec.BeaconBlockBody, "blob_kzg_commitments")
yield (
"proof",
{
"leaf": "0x" + column_sidcar.kzg_commitments.hash_tree_root().hex(),
"leaf_index": gindex,
"branch": ["0x" + root.hex() for root in kzg_commitments_inclusion_proof],
},
)
assert spec.is_valid_merkle_branch(
leaf=column_sidcar.kzg_commitments.hash_tree_root(),
branch=column_sidcar.kzg_commitments_inclusion_proof,
depth=spec.floorlog2(gindex),
index=spec.get_subtree_index(gindex),
root=column_sidcar.signed_block_header.message.body_root,
)
yield (
"proof",
{
"leaf": "0x" + column_sidcar.kzg_commitments.hash_tree_root().hex(),
"leaf_index": gindex,
"branch": ["0x" + root.hex() for root in kzg_commitments_inclusion_proof],
},
)
assert spec.is_valid_merkle_branch(
leaf=column_sidcar.kzg_commitments.hash_tree_root(),
branch=column_sidcar.kzg_commitments_inclusion_proof,
depth=spec.floorlog2(gindex),
index=spec.get_subtree_index(gindex),
root=column_sidcar.signed_block_header.message.body_root,
)
assert spec.verify_data_column_sidecar_inclusion_proof(column_sidcar)
assert spec.verify_data_column_sidecar_kzg_proofs(column_sidcar)
assert spec.verify_data_column_sidecar_inclusion_proof(column_sidcar)


@with_test_suite_name("BeaconBlockBody")
Expand Down
27 changes: 21 additions & 6 deletions tests/core/pyspec/eth2spec/test/fulu/unittests/das/test_das.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
get_sample_blob,
)
from eth2spec.test.helpers.fork_choice import BlobData, with_blob_data
from eth2spec.test.helpers.forks import (
is_post_gloas,
)


def chunks(lst, n):
Expand Down Expand Up @@ -101,12 +104,19 @@ def test_get_data_column_sidecars(spec, state):
spec, state, rng=rng, blob_count=2
)

sidecars_result = spec.get_data_column_sidecars(
signed_block_header=spec.compute_signed_block_header(signed_block),
kzg_commitments=sidecars[0].kzg_commitments,
kzg_commitments_inclusion_proof=sidecars[0].kzg_commitments_inclusion_proof,
cells_and_kzg_proofs=[spec.compute_cells_and_kzg_proofs(blob) for blob in blobs],
)
if is_post_gloas(spec):
sidecars_result = spec.get_data_column_sidecars_from_block(
signed_block,
sidecars[0].kzg_commitments,
[spec.compute_cells_and_kzg_proofs(blob) for blob in blobs],
)
else:
sidecars_result = spec.get_data_column_sidecars(
signed_block_header=spec.compute_signed_block_header(signed_block),
kzg_commitments=sidecars[0].kzg_commitments,
kzg_commitments_inclusion_proof=sidecars[0].kzg_commitments_inclusion_proof,
cells_and_kzg_proofs=[spec.compute_cells_and_kzg_proofs(blob) for blob in blobs],
)

assert len(sidecars_result) == len(sidecars), (
"Should return the same number of sidecars as input"
Expand All @@ -117,6 +127,11 @@ def test_get_data_column_sidecars(spec, state):
@with_fulu_and_later
@spec_state_test
def test_get_data_column_sidecars_from_column_sidecar(spec, state):
if is_post_gloas(spec):
# Skip this test for Gloas as the function hasn't been updated yet
# to work without signed_block_header and kzg_commitments_inclusion_proof
return

rng = random.Random(1234)
_, blobs, _, _, sidecars = get_block_with_blob_and_sidecars(spec, state, rng=rng, blob_count=2)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ def test_verify_data_column_sidecar_kzg_proofs__invalid_wrong_proof(spec, state)
@spec_state_test
@single_phase
def test_verify_data_column_sidecar_inclusion_proof__valid(spec, state):
if is_post_gloas(spec):
# Skip for Gloas as inclusion proof fields were removed
return
sidecar = compute_data_column_sidecar(spec, state)
assert spec.verify_data_column_sidecar_inclusion_proof(sidecar)

Expand All @@ -169,6 +172,9 @@ def test_verify_data_column_sidecar_inclusion_proof__valid(spec, state):
@spec_state_test
@single_phase
def test_verify_data_column_sidecar_inclusion_proof__invalid_missing_commitment(spec, state):
if is_post_gloas(spec):
# Skip for Gloas as inclusion proof fields were removed
return
sidecar = compute_data_column_sidecar(spec, state)
sidecar.kzg_commitments = sidecar.kzg_commitments[1:]
assert not spec.verify_data_column_sidecar_inclusion_proof(sidecar)
Expand All @@ -178,6 +184,9 @@ def test_verify_data_column_sidecar_inclusion_proof__invalid_missing_commitment(
@spec_state_test
@single_phase
def test_verify_data_column_sidecar_inclusion_proof__invalid_duplicate_commitment(spec, state):
if is_post_gloas(spec):
# Skip for Gloas as inclusion proof fields were removed
return
sidecar = compute_data_column_sidecar(spec, state)
sidecar.kzg_commitments = sidecar.kzg_commitments + [sidecar.kzg_commitments[0]]
assert not spec.verify_data_column_sidecar_inclusion_proof(sidecar)
Expand Down
Loading