Skip to content
Open
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
3 changes: 0 additions & 3 deletions pysetup/spec_builders/gloas.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ def deprecate_functions(cls) -> set[str]:
"retrieve_column_sidecars",
"upgrade_to_fulu",
"verify_partial_data_column_header_inclusion_proof",
# TODO(jtraglia): Temporarily deprecate these until we update them for Gloas.
"validate_data_column_sidecar_gossip",
"validate_partial_data_column_sidecar_gossip",
}

@classmethod
Expand Down
4 changes: 1 addition & 3 deletions specs/fulu/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,12 @@ def validate_beacon_block_gossip(
state: BeaconState,
signed_beacon_block: SignedBeaconBlock,
current_time_ms: uint64,
block_payload_statuses: Optional[Dict[Root, PayloadValidationStatus]] = None,
block_payload_statuses: Dict[Root, PayloadValidationStatus],
) -> None:
"""
Validate a SignedBeaconBlock for gossip propagation.
Raises GossipIgnore or GossipReject on validation failure.
"""
if block_payload_statuses is None:
block_payload_statuses = {}
block = signed_beacon_block.message
execution_payload = block.body.execution_payload

Expand Down
75 changes: 44 additions & 31 deletions specs/fulu/partial-columns/p2p-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

- [Introduction](#introduction)
- [Containers](#containers)
- [`PartialDataColumnSidecar`](#partialdatacolumnsidecar)
- [`PartialDataColumnPartsMetadata`](#partialdatacolumnpartsmetadata)
- [`PartialDataColumnHeader`](#partialdatacolumnheader)
- [New `PartialDataColumnSidecar`](#new-partialdatacolumnsidecar)
- [New `PartialDataColumnPartsMetadata`](#new-partialdatacolumnpartsmetadata)
- [New `PartialDataColumnHeader`](#new-partialdatacolumnheader)
- [New `PartialDataColumnGroupID`](#new-partialdatacolumngroupid)
- [Helpers](#helpers)
- [`verify_partial_data_column_header_inclusion_proof`](#verify_partial_data_column_header_inclusion_proof)
- [`verify_partial_data_column_sidecar_kzg_proofs`](#verify_partial_data_column_sidecar_kzg_proofs)
- [New `verify_partial_data_column_header_inclusion_proof`](#new-verify_partial_data_column_header_inclusion_proof)
- [New `verify_partial_data_column_sidecar_kzg_proofs`](#new-verify_partial_data_column_sidecar_kzg_proofs)
- [The gossip domain: gossipsub](#the-gossip-domain-gossipsub)
- [Partial Messages on `data_column_sidecar_{subnet_id}`](#partial-messages-on-data_column_sidecar_subnet_id)
- [New `data_column_sidecar_{subnet_id}` (partial messages)](#new-data_column_sidecar_subnet_id-partial-messages)
- [Partial columns for Cell Dissemination](#partial-columns-for-cell-dissemination)
- [Partial message group ID](#partial-message-group-id)
- [Parts metadata](#parts-metadata)
Expand Down Expand Up @@ -40,7 +41,7 @@ particular, this document builds on the

## Containers

### `PartialDataColumnSidecar`
### New `PartialDataColumnSidecar`

The `PartialDataColumnSidecar` is similar to the `DataColumnSidecar` container,
except that only the cells and proofs identified by the bitmap are present.
Expand All @@ -56,7 +57,7 @@ class PartialDataColumnSidecar(Container):
header: List[PartialDataColumnHeader, 1]
```

### `PartialDataColumnPartsMetadata`
### New `PartialDataColumnPartsMetadata`

Peers communicate the cells available with a bitmap. A set bit (`1`) at index
`i` means that the peer has the cell at index `i`. Peers explicitly request
Expand Down Expand Up @@ -86,7 +87,7 @@ bit from the requests bit.
Having a cell but not willing to provide it is functionally the same as not
having the cell and not wanting it, so it does not need a separate state.

### `PartialDataColumnHeader`
### New `PartialDataColumnHeader`

The `PartialDataColumnHeader` is the header that is common to all columns for a
given block. It lets a peer identify which blobs are included in a block, as
Expand All @@ -101,9 +102,16 @@ class PartialDataColumnHeader(Container):
kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH]
```

### New `PartialDataColumnGroupID`

```python
class PartialDataColumnGroupID(Container):
block_root: Root
```

## Helpers

### `verify_partial_data_column_header_inclusion_proof`
### New `verify_partial_data_column_header_inclusion_proof`

```python
def verify_partial_data_column_header_inclusion_proof(header: PartialDataColumnHeader) -> bool:
Expand All @@ -119,7 +127,7 @@ def verify_partial_data_column_header_inclusion_proof(header: PartialDataColumnH
)
```

### `verify_partial_data_column_sidecar_kzg_proofs`
### New `verify_partial_data_column_sidecar_kzg_proofs`

```python
def verify_partial_data_column_sidecar_kzg_proofs(
Expand Down Expand Up @@ -147,7 +155,7 @@ def verify_partial_data_column_sidecar_kzg_proofs(

## The gossip domain: gossipsub

### Partial Messages on `data_column_sidecar_{subnet_id}`
### New `data_column_sidecar_{subnet_id}` (partial messages)

*Note*: Validating partial messages happens in two parts. First, the
`PartialDataColumnHeader` needs to be validated, then the cell and proof data.
Expand All @@ -156,15 +164,24 @@ subnet (gossipsub topic), it can be used for all subnets. Due to the nature of
partial messages, it is possible to get the `PartialDataColumnHeader` with no
cells, and get cells in a future response.

*Note*: The Partial Message Group ID is the SSZ encoded
`PartialDataColumnGroupID` prefixed with the version byte `0x00`.
Implementations MUST ignore unknown versions.

*Note*: The optional check "for cells the receiver already has, the sidecar's
cell and proof data are equal to the local copy" is not encoded above. The
sender MUST always send valid cell and proof data; receivers MAY perform this
equality check against their local copy as an additional safeguard.

```python
def validate_partial_data_column_sidecar_gossip(
seen: Seen,
store: Store,
state: BeaconState,
sidecar: PartialDataColumnSidecar,
block_root: Root,
column_index: ColumnIndex,
current_time_ms: uint64,
group_id: PartialDataColumnGroupID,
column_index: ColumnIndex,
) -> None:
"""
Validate a PartialDataColumnSidecar for gossip propagation on a subnet.
Expand All @@ -178,11 +195,11 @@ def validate_partial_data_column_sidecar_gossip(
if not (has_header or has_cells):
raise GossipReject("partial message is semantically empty")

# [REJECT] The cell count equals the number of bits set in cells_present_bitmap
# [REJECT] The cell count equals the number of set bits in the bitmap
if len(sidecar.partial_column) != num_cells_present:
raise GossipReject("number of cells does not match number of set bits")

# [REJECT] The proof count equals the number of bits set in cells_present_bitmap
# [REJECT] The proof count equals the number of set bits in the bitmap
if len(sidecar.kzg_proofs) != num_cells_present:
raise GossipReject("number of proofs does not match number of set bits")

Expand All @@ -191,13 +208,13 @@ def validate_partial_data_column_sidecar_gossip(
block_header = header.signed_block_header.message

# [REJECT] The received header MUST equal any previously validated header for this block
prior_header = seen.partial_data_column_headers.get(block_root)
prior_header = seen.partial_data_column_headers.get(group_id.block_root)
if prior_header is not None and prior_header != header:
raise GossipReject("header differs from previously validated header")

# [REJECT] The signed_block_header hash matches the partial message's group id
if hash_tree_root(block_header) != block_root:
raise GossipReject("header's block root does not match partial message group id")
if hash_tree_root(block_header) != group_id.block_root:
raise GossipReject("header's block root does not match group id's block root")

# [REJECT] The header's kzg_commitments list is non-empty
if len(header.kzg_commitments) == 0:
Expand Down Expand Up @@ -257,11 +274,11 @@ def validate_partial_data_column_sidecar_gossip(
raise GossipReject("header proposer_index does not match expected proposer")

# Mark this header as seen
seen.partial_data_column_headers[block_root] = header
seen.partial_data_column_headers[group_id.block_root] = header

if has_cells:
# [IGNORE] A valid corresponding PartialDataColumnHeader has been seen
header = seen.partial_data_column_headers.get(block_root)
header = seen.partial_data_column_headers.get(group_id.block_root)
if header is None:
raise GossipIgnore("valid corresponding header has not been seen")

Expand All @@ -279,22 +296,17 @@ def validate_partial_data_column_sidecar_gossip(
"corresponding header is not from a slot greater than the latest finalized slot"
)

# [REJECT] The cells_present_bitmap length equals the number of header kzg_commitments
# [REJECT] The cells present bitmap length equals the number of bid commitments
if len(sidecar.cells_present_bitmap) != len(header.kzg_commitments):
raise GossipReject("bitmap length does not match commitments length")

# [REJECT] The sidecar's cell and proof data is valid
# [REJECT] The sidecar's cell and proof data passes KZG verification
if not verify_partial_data_column_sidecar_kzg_proofs(
sidecar, header.kzg_commitments, column_index
):
raise GossipReject("invalid sidecar kzg proofs")
```

*Note*: The optional check "for cells the receiver already has, the sidecar's
cell and proof data are equal to the local copy" is not encoded above. The
sender MUST always send valid cell and proof data; receivers MAY perform this
equality check against their local copy as an additional safeguard.

### Partial columns for Cell Dissemination

Gossipsub's
Expand All @@ -305,9 +317,10 @@ cells along with their proofs.

#### Partial message group ID

When sending a partial message, the gossipsub group ID MUST be the block root
prefixed by a single byte used for versioning. The version byte MUST be zero.
Other versions may be defined later.
When sending a partial message, the gossipsub group ID MUST be the SSZ encoded
`PartialDataColumnGroupID` prefixed with a single version byte. The version byte
MUST be `0x00`. Implementations MUST ignore unknown versions. Other versions may
be defined later.

#### Parts metadata

Expand Down
Loading