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

feat(prospective-parachains): create subsystem skeleton #4325

Merged
merged 5 commits into from
Nov 26, 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
7 changes: 1 addition & 6 deletions dot/parachain/backing/candidate_backing.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,10 @@ func (v validator) sign(keystore keystore.Keystore, payload parachaintypes.State
// GetBackableCandidatesMessage is a message received from overseer that requests a set of backable
// candidates that could be backed in a child of the given relay-parent.
type GetBackableCandidatesMessage struct {
Candidates []*CandidateHashAndRelayParent
Candidates []*parachaintypes.CandidateHashAndRelayParent
ResCh chan []*parachaintypes.BackedCandidate
}

type CandidateHashAndRelayParent struct {
CandidateHash parachaintypes.CandidateHash
CandidateRelayParent common.Hash
}

// CanSecondMessage is a request made to the candidate backing subsystem to determine whether it is permissible
// to second a given candidate.
// The rule for seconding candidates is: Collations must either be built on top of the root of a fragment tree
Expand Down
2 changes: 1 addition & 1 deletion dot/parachain/backing/get_backed_candidates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestHandleGetBackedCandidatesMessage(t *testing.T) {
defer close(resCh)

requestedCandidates := GetBackableCandidatesMessage{
Candidates: []*CandidateHashAndRelayParent{
Candidates: []*parachaintypes.CandidateHashAndRelayParent{
{
CandidateHash: dummyCandidateHash(t),
CandidateRelayParent: getDummyHash(t, 2),
Expand Down
6 changes: 3 additions & 3 deletions dot/parachain/backing/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ func TestCandidateReachesQuorum(t *testing.T) {
time.Sleep(1 * time.Second)

getBackable := backing.GetBackableCandidatesMessage{
Candidates: []*backing.CandidateHashAndRelayParent{
Candidates: []*parachaintypes.CandidateHashAndRelayParent{
{
CandidateHash: candidateHash,
CandidateRelayParent: relayParent,
Expand Down Expand Up @@ -607,7 +607,7 @@ func TestCandidateReachesQuorum(t *testing.T) {
time.Sleep(1 * time.Second)

getBackable = backing.GetBackableCandidatesMessage{
Candidates: []*backing.CandidateHashAndRelayParent{
Candidates: []*parachaintypes.CandidateHashAndRelayParent{
{
CandidateHash: candidateHash,
CandidateRelayParent: relayParent,
Expand Down Expand Up @@ -753,7 +753,7 @@ func TestValidationFailDoesNotStopSubsystem(t *testing.T) {
require.NoError(t, err)

getBackable := backing.GetBackableCandidatesMessage{
Candidates: []*backing.CandidateHashAndRelayParent{
Candidates: []*parachaintypes.CandidateHashAndRelayParent{
{
CandidateHash: candidateHash,
CandidateRelayParent: relayParent,
Expand Down
167 changes: 167 additions & 0 deletions dot/parachain/prospective-parachains/messages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package prospectiveparachains

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

// ProspectiveParachainsMessage Messages sent to the Prospective Parachains subsystem.
type ProspectiveParachainsMessage interface {
isProspectiveParachainsMessage()
}

// IntroduceSecondedCandidate Inform the Prospective Parachains Subsystem of a new seconded candidate.
// The response is false if the candidate was rejected by prospective parachains,
// true otherwise (if it was accepted or already present)
type IntroduceSecondedCandidate struct {
axaysagathiya marked this conversation as resolved.
Show resolved Hide resolved
IntroduceSecondedCandidateRequest
Response chan bool
}

func (IntroduceSecondedCandidate) isProspectiveParachainsMessage() {}

// IntroduceSecondedCandidateRequest Request introduction of a seconded candidate into the prospective parachains
// subsystem.
type IntroduceSecondedCandidateRequest struct {
// The para-id of the candidate.
CandidateParaID parachaintypes.ParaID
// The candidate receipt itself.
CandidateReceipt parachaintypes.CommittedCandidateReceipt
// The persisted validation data of the candidate.
PersistedValidationData parachaintypes.PersistedValidationData
}

// CandidateBacked Inform the Prospective Parachains Subsystem that a previously introduced candidate
// has been backed. This requires that the candidate was successfully introduced in
// the past.
type CandidateBacked struct {
ParaId parachaintypes.ParaID
CandidateHash parachaintypes.CandidateHash
}

func (CandidateBacked) isProspectiveParachainsMessage() {}

// GetBackableCandidates Try getting requested quantity of backable candidate hashes along with their relay parents
// for the given parachain, under the given relay-parent hash, which is a descendant of the given ancestors.
// Timed out ancestors should not be included in the collection.
// RequestedQty should represent the number of scheduled cores of this ParaId.
// A timed out ancestor frees the cores of all of its descendants, so if there's a hole in the
// supplied ancestor path, we'll get candidates that backfill those timed out slots first. It
// may also return less/no candidates, if there aren't enough backable candidates recorded.
type GetBackableCandidates struct {
RelayParentHash common.Hash
ParaId parachaintypes.ParaID
RequestedQty uint32
Ancestors Ancestors
edwardmack marked this conversation as resolved.
Show resolved Hide resolved
Response chan []parachaintypes.CandidateHashAndRelayParent
}

func (GetBackableCandidates) isProspectiveParachainsMessage() {}

// Ancestors A collection of ancestor candidates of a parachain.
type Ancestors map[parachaintypes.CandidateHash]struct{}

// GetHypotheticalMembership Get the hypothetical or actual membership of candidates with the given properties
// under the specified active leave's fragment chain.
//
// For each candidate, we return a vector of leaves where the candidate is present or could be
// added. "Could be added" either means that the candidate can be added to the chain right now
// or could be added in the future (we may not have its ancestors yet).
// Note that even if we think it could be added in the future, we may find out that it was
// invalid, as time passes.
// If an active leaf is not in the vector, it means that there's no
// chance this candidate will become valid under that leaf in the future.
//
// If `RragmentChainRelayParent` in the request is not `nil`, the return vector can only
// contain this relay parent (or none).
type GetHypotheticalMembership struct {
HypotheticalMembershipRequest HypotheticalMembershipRequest
Response chan []HypotheticalMembershipResponseItem
}

func (GetHypotheticalMembership) isProspectiveParachainsMessage() {}

type HypotheticalMembershipResponseItem struct {
HypotheticalCandidate parachaintypes.HypotheticalCandidate
HypotheticalMembership HypotheticalMembership
}

// HypotheticalMembershipRequest Request specifying which candidates are either already included
// or might become included in fragment chain under a given active leaf (or any active leaf if
// `FragmentChainRelayParent` is `nil`).
type HypotheticalMembershipRequest struct {
// Candidates, in arbitrary order, which should be checked for
// hypothetical/actual membership in fragment chains.
Candidates []parachaintypes.HypotheticalCandidate
// Either a specific fragment chain to check, otherwise all.
FragmentChainRelayParent *common.Hash
}

// HypotheticalMembership Indicates the relay-parents whose fragment chain a candidate
// is present in or can be added in (right now or in the future).
type HypotheticalMembership []common.Hash

// GetMinimumRelayParents Get the minimum accepted relay-parent number for each para in the fragment chain
// for the given relay-chain block hash.
//
// That is, if the block hash is known and is an active leaf, this returns the
// minimum relay-parent block number in the same branch of the relay chain which
// is accepted in the fragment chain for each para-id.
//
// If the block hash is not an active leaf, this will return an empty vector.
//
// Para-IDs which are omitted from this list can be assumed to have no
// valid candidate relay-parents under the given relay-chain block hash.
//
// Para-IDs are returned in no particular order.
type GetMinimumRelayParents struct {
RelayChainBlockHash common.Hash
Sender chan []ParaIDBlockNumber
}

type ParaIDBlockNumber struct {
ParaId parachaintypes.ParaID
BlockNumber parachaintypes.BlockNumber
}

func (GetMinimumRelayParents) isProspectiveParachainsMessage() {}

// GetProspectiveValidationData Get the validation data of some prospective candidate. The candidate doesn't need
// to be part of any fragment chain, but this only succeeds if the parent head-data and
// relay-parent are part of the `CandidateStorage` (meaning that it's a candidate which is
// part of some fragment chain or which prospective-parachains predicted will become part of
// some fragment chain).
type GetProspectiveValidationData struct {
ProspectiveValidationDataRequest
Sender chan parachaintypes.PersistedValidationData
}

// ProspectiveValidationDataRequest A request for the persisted validation data stored in the prospective
// parachains subsystem.
type ProspectiveValidationDataRequest struct {
// The para-id of the candidate.
ParaId parachaintypes.ParaID
// The relay-parent of the candidate.
CandidateRelayParent common.Hash
// The parent head-data.
ParentHeadData ParentHeadData
}

// ParentHeadData The parent head-data hash with optional data itself.
type ParentHeadData interface {
isParentHeadData()
}

// ParentHeadDataHash Parent head-data hash.
type ParentHeadDataHash common.Hash

func (ParentHeadDataHash) isParentHeadData() {}

type ParentHeadDataWithHash struct {
// This will be provided for collations with elastic scaling enabled.
Data parachaintypes.HeadData
// Parent head-data hash.
Hash ParentHeadDataHash
}

func (ParentHeadDataWithHash) isParentHeadData() {}
82 changes: 82 additions & 0 deletions dot/parachain/prospective-parachains/prospective-parachains.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package prospectiveparachains

import (
"context"
"errors"

parachaintypes "github.com/ChainSafe/gossamer/dot/parachain/types"
"github.com/ChainSafe/gossamer/internal/log"
)

var logger = log.NewFromGlobal(log.AddContext("pkg", "prospective_parachains"), log.SetLevel(log.Debug))

type ProspectiveParachains struct {
SubsystemToOverseer chan<- any
}

// Name returns the name of the subsystem
func (*ProspectiveParachains) Name() parachaintypes.SubSystemName {
return parachaintypes.ProspectiveParachains
}

// NewProspectiveParachains creates a new ProspectiveParachain subsystem
func NewProspectiveParachains(overseerChan chan<- any) *ProspectiveParachains {
prospectiveParachain := ProspectiveParachains{
SubsystemToOverseer: overseerChan,
}
return &prospectiveParachain
}

// Run starts the ProspectiveParachains subsystem
func (pp *ProspectiveParachains) Run(ctx context.Context, overseerToSubsystem <-chan any) {
for {
select {
case msg := <-overseerToSubsystem:
pp.processMessage(msg)
case <-ctx.Done():
if err := ctx.Err(); err != nil && !errors.Is(err, context.Canceled) {
logger.Errorf("ctx error: %s\n", err)
}
return
}
}
}

func (*ProspectiveParachains) Stop() {}

func (pp *ProspectiveParachains) processMessage(msg any) {
switch msg := msg.(type) {
case parachaintypes.Conclude:
pp.Stop()
case parachaintypes.ActiveLeavesUpdateSignal:
_ = pp.ProcessActiveLeavesUpdateSignal(msg)
case parachaintypes.BlockFinalizedSignal:
_ = pp.ProcessBlockFinalizedSignal(msg)
case IntroduceSecondedCandidate:
panic("not implemented yet: see issue #4308")
case CandidateBacked:
panic("not implemented yet: see issue #4309")
case GetBackableCandidates:
panic("not implemented yet: see issue #4310")
case GetHypotheticalMembership:
panic("not implemented yet: see issue #4311")
case GetMinimumRelayParents:
panic("not implemented yet: see issue #4312")
case GetProspectiveValidationData:
panic("not implemented yet: see issue #4313")
default:
logger.Errorf("%w: %T", parachaintypes.ErrUnknownOverseerMessage, msg)
}

}

// ProcessActiveLeavesUpdateSignal processes active leaves update signal
func (pp *ProspectiveParachains) ProcessActiveLeavesUpdateSignal(parachaintypes.ActiveLeavesUpdateSignal) error {
panic("not implemented yet: see issue #4305")
}

// ProcessBlockFinalizedSignal processes block finalized signal
func (*ProspectiveParachains) ProcessBlockFinalizedSignal(parachaintypes.BlockFinalizedSignal) error {
// NOTE: this subsystem does not process block finalized signal
return nil
}
14 changes: 9 additions & 5 deletions dot/parachain/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import (
"time"

"github.com/ChainSafe/gossamer/dot/network"
availability_store "github.com/ChainSafe/gossamer/dot/parachain/availability-store"
availabilitystore "github.com/ChainSafe/gossamer/dot/parachain/availability-store"
"github.com/ChainSafe/gossamer/dot/parachain/backing"
candidatevalidation "github.com/ChainSafe/gossamer/dot/parachain/candidate-validation"
collatorprotocol "github.com/ChainSafe/gossamer/dot/parachain/collator-protocol"
collatorprotocolmessages "github.com/ChainSafe/gossamer/dot/parachain/collator-protocol/messages"
networkbridge "github.com/ChainSafe/gossamer/dot/parachain/network-bridge"
validationprotocol "github.com/ChainSafe/gossamer/dot/parachain/validation-protocol"

candidatevalidation "github.com/ChainSafe/gossamer/dot/parachain/candidate-validation"
"github.com/ChainSafe/gossamer/dot/parachain/overseer"
prospectiveparachains "github.com/ChainSafe/gossamer/dot/parachain/prospective-parachains"
parachaintypes "github.com/ChainSafe/gossamer/dot/parachain/types"
validationprotocol "github.com/ChainSafe/gossamer/dot/parachain/validation-protocol"
"github.com/ChainSafe/gossamer/dot/peerset"
"github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/internal/log"
Expand Down Expand Up @@ -68,7 +68,7 @@ func NewService(net Network, forkID string, st *state.Service, ks keystore.Keyst
}
overseer.RegisterSubsystem(networkBridgeReceiver)

availabilityStore, err := availability_store.Register(overseer.GetSubsystemToOverseerChannel(), st.DB(), nil)
availabilityStore, err := availabilitystore.Register(overseer.GetSubsystemToOverseerChannel(), st.DB(), nil)
if err != nil {
return nil, fmt.Errorf("registering availability store: %w", err)
}
Expand All @@ -85,6 +85,10 @@ func NewService(net Network, forkID string, st *state.Service, ks keystore.Keyst

overseer.RegisterSubsystem(candidateValidationSubsystem)

// register prospective parachains subsystem
prospectiveParachainsSubsystem := prospectiveparachains.NewProspectiveParachains(overseer.SubsystemsToOverseer)
overseer.RegisterSubsystem(prospectiveParachainsSubsystem)

parachainService := &Service{
Network: net,
overseer: overseer,
Expand Down
3 changes: 3 additions & 0 deletions dot/parachain/types/overseer_signals.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ type BlockFinalizedSignal struct {
Hash common.Hash
BlockNumber uint32
}

// Conclude the work of the `Overseer` and all `Subsystem`s.
type Conclude struct{}
1 change: 1 addition & 0 deletions dot/parachain/types/subsystems.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
CandidateValidation SubSystemName = "CandidateValidation"
Provisioner SubSystemName = "Provisioner"
StatementDistribution SubSystemName = "StatementDistribution"
ProspectiveParachains SubSystemName = "ProspectiveParachains"
)

var SubsystemRequestTimeout = 1 * time.Second
Expand Down
6 changes: 6 additions & 0 deletions dot/parachain/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -739,3 +739,9 @@ type Subsystem interface {
ProcessBlockFinalizedSignal(BlockFinalizedSignal) error
Stop()
}

// CandidateHashAndRelayParent is a pair of candidate hash and relay parent hash
type CandidateHashAndRelayParent struct {
CandidateHash CandidateHash
CandidateRelayParent common.Hash
}
Loading