Bitfield Signing Subsystem¶
The bitfield signing subsystem is responsible for producing signed availability bitfields and passing them to the bitfield distribution subsystem. 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¶
package parachaintypes
import "github.com/ChainSafe/gossamer/lib/common"
type DistributeBitfield struct {
RelayParent common.Hash
Bitfield UncheckedSignedAvailabilityBitfield
}
As mentioned in bitfield distribution, it makes sense to duplicate the type
UncheckedSignedAvailabilityBitfield
as CheckedSignedAvailabilityBitfield
or just SignedAvailabilityBitfield
and
use it in DistributeBitfield
.
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.
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
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:
-
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.
-
Query the set of availability cores for the given leaf from the runtime.
-
For each core, concurrently check whether the core is occupied and if so, query the availability store using
QueryChunkAvailability
. -
Collect the results of the queries into a bitfield, sign it and send a
DistributeBitfield
message to the overseer.