Skip to content
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

docs(parachain): add design doc for bitfield signing subsystem #4408

Merged
merged 7 commits into from
Dec 16, 2024
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
2 changes: 1 addition & 1 deletion docs/docs/design/availability-subsystems.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Availability is handled by these subsystems:
- Requests chunks from backing validators to put them in their local Availability Store.
- Validator with index i gets chunk with the same index.

## Bitfield Signing subsystem
## [Bitfield Signing subsystem](./bitfield-signing.md)

- For each fresh leaf, wait a fixed period of time for availability distribution to make candidate available.
- Validator with index i gets a chunk with the same index.
Expand Down
9 changes: 3 additions & 6 deletions docs/docs/design/bitfield-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,13 @@ network message as part of the message handling code.
subsystem.)

```go
package bitfielddistribution
package parachaintypes

import (
parachaintypes "github.com/ChainSafe/gossamer/dot/parachain/types"
"github.com/ChainSafe/gossamer/lib/common"
)
import "github.com/ChainSafe/gossamer/lib/common"

type DistributeBitfield struct {
RelayParent common.Hash
Bitfield parachaintypes.UncheckedSignedAvailabilityBitfield
Bitfield UncheckedSignedAvailabilityBitfield
}
```

Expand Down
100 changes: 100 additions & 0 deletions docs/docs/design/bitfield-signing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
layout: default
title: Bitfield Signing Subsystem
permalink: /design/bitfield-signing/
---

# Bitfield Signing Subsystem

[The bitfield signing subsystem](https://paritytech.github.io/polkadot-sdk/book/node/availability/bitfield-signing.html)
is responsible for producing signed availability bitfields and passing them to
[the bitfield distribution subsystem](./bitfield-distribution.md). It only does that when running on a validator.

## Subsystem Structure

The implementation must conform to the `Subsystem` interface defined in the `parachaintypes` package. It should live in
a package named `bitfieldsigning` under `dot/parachain/bitfield-signing`.

### Messages Received

The subsystem must be registered with the overseer. It only handles `parachaintypes.ActiveLeavesUpdateSignal`. The
overseer must be modified to forward this message to the subsystem.

### Messages Sent

1. [`DistributeBitfield`](https://github.com/paritytech/polkadot-sdk/blob/1e3b8e1639c1cf784eabf0a9afcab1f3987e0ca4/polkadot/node/subsystem-types/src/messages.rs#L522)

```go
package parachaintypes

import "github.com/ChainSafe/gossamer/lib/common"

type DistributeBitfield struct {
RelayParent common.Hash
Bitfield UncheckedSignedAvailabilityBitfield
}
```

As mentioned in [bitfield distribution](./bitfield-distribution.md), it makes sense to duplicate the type
`UncheckedSignedAvailabilityBitfield` as `CheckedSignedAvailabilityBitfield` or just `SignedAvailabilityBitfield` and
use it in `DistributeBitfield`.

2. [`AvailabilityStore::QueryChunkAvailability(CandidateHash, ValidatorIndex, response_channel)`](https://github.com/paritytech/polkadot-sdk/blob/1e3b8e1639c1cf784eabf0a9afcab1f3987e0ca4/polkadot/node/subsystem-types/src/messages.rs#L556)
haikoschol marked this conversation as resolved.
Show resolved Hide resolved

This message is sent once for each occupied core, whenever the subsystem is notified of a new active leaf.

The type is already defined as `availabilitystore.QueryChunkAvailability` in
`dot/parachain/availability-store/messages.go`.

## Subsystem State

The subsystem needs access to the parachain session keys for signing bitfields. The appropriate `Keystore` should be
passed to the subsystem constructor as a dependency to facilitate testing. Since each new active leave results in a
goroutine being spawned, the subsystem needs to maintain state to receive data from them and to cancel them when
appropriate.

```go
package bitfieldsigning

import (
"context"

"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/keystore"
)

type signingTask struct {
ctx context.Context
response <-chan parachaintypes.UncheckedSignedAvailabilityBitfield
}

type BitfieldSigning struct {
keystore keystore.Keystore
haikoschol marked this conversation as resolved.
Show resolved Hide resolved
tasks map[common.Hash]*signingTask
}
```

Ideally the implementation should avoid lock contention around the keystore. Since the signing key remains the same for
the duration of the signing task, the subsystem could pass in the key pair or just the private key. The implementer
should double-check that this approach is thread-safe.

Again, this should probably use a (to be created) type `CheckedSignedAvailabilityBitfield`.

## Message Handling Logic

### `parachaintypes.ActiveLeavesUpdateSignal`

For all leaves that have been deactivated, cancel the signing tasks associated with them.

For all activated leaves, spawn a new signing task. The task needs to perform the following steps:

1. Wait a while to let the availability store get populated with information about erasure chunks. In the Parity node,
this delay is currently set to [1500ms](https://github.com/paritytech/polkadot-sdk/blob/1e3b8e1639c1cf784eabf0a9afcab1f3987e0ca4/polkadot/node/core/bitfield-signing/src/lib.rs#L49).

2. Query the set of [availability cores](https://paritytech.github.io/polkadot-sdk/book/runtime-api/availability-cores.html)
for the given leaf from the runtime.

3. For each core, concurrently check whether the core is occupied and if so, query the availability store using
`QueryChunkAvailability`.

4. Collect the results of the queries into a bitfield, sign it and send a `DistributeBitfield` message to the overseer.
Loading