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): implements GetBackableCandidates #4374

Open
wants to merge 14 commits into
base: eclesio/fragment-chain-impl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 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
87 changes: 86 additions & 1 deletion dot/parachain/prospective-parachains/prospective-parachains.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,23 @@

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

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

type ProspectiveParachains struct {
SubsystemToOverseer chan<- any
View *View
}

type View struct {
ActiveLeaves map[common.Hash]bool
PerRelayParent map[common.Hash]*RelayParentData
}

type RelayParentData struct {
FragmentChains map[parachaintypes.ParaID]*fragmentChain
DanielDDHM marked this conversation as resolved.
Show resolved Hide resolved
}

// Name returns the name of the subsystem
Expand Down Expand Up @@ -57,7 +68,7 @@
case CandidateBacked:
panic("not implemented yet: see issue #4309")
case GetBackableCandidates:
panic("not implemented yet: see issue #4310")
go pp.getBackableCandidates(msg)
DanielDDHM marked this conversation as resolved.
Show resolved Hide resolved
case GetHypotheticalMembership:
panic("not implemented yet: see issue #4311")
case GetMinimumRelayParents:
Expand All @@ -80,3 +91,77 @@
// NOTE: this subsystem does not process block finalized signal
return nil
}

func (pp *ProspectiveParachains) getBackableCandidates(
msg GetBackableCandidates,
) {
// Extract details from the message
relayParentHash := msg.RelayParentHash
paraId := msg.ParaId
requestedQty := msg.RequestedQty
ancestors := msg.Ancestors
responseChan := msg.Response

// Check if the relay parent is active
if _, exists := pp.View.ActiveLeaves[relayParentHash]; !exists {
logger.Debugf(
"Requested backable candidates for inactive relay-parent. "+
"RelayParentHash: %v, ParaId: %v",
relayParentHash, paraId,
)
responseChan <- []parachaintypes.CandidateHashAndRelayParent{}
return
}

// Retrieve data for the relay parent
data, ok := pp.View.PerRelayParent[relayParentHash]
if !ok {
logger.Debugf(
"Requested backable candidates for nonexistent relay-parent. "+
"RelayParentHash: %v, ParaId: %v",
relayParentHash, paraId,
)
responseChan <- []parachaintypes.CandidateHashAndRelayParent{}
return
}

// Retrieve the fragment chain for the ParaID
chain, ok := data.FragmentChains[paraId]
if !ok {
logger.Debugf(
"Requested backable candidates for inactive ParaID. "+
"RelayParentHash: %v, ParaId: %v",
relayParentHash, paraId,
)
responseChan <- []parachaintypes.CandidateHashAndRelayParent{}
return
}

// Retrieve backable candidates from the fragment chain
backableCandidates := chain.FindBackableChain(ancestors, requestedQty)

Check failure on line 141 in dot/parachain/prospective-parachains/prospective-parachains.go

View workflow job for this annotation

GitHub Actions / linting

chain.FindBackableChain undefined (type *fragmentChain has no field or method FindBackableChain, but does have method findBackableChain)) (typecheck)

Check failure on line 141 in dot/parachain/prospective-parachains/prospective-parachains.go

View workflow job for this annotation

GitHub Actions / linting

chain.FindBackableChain undefined (type *fragmentChain has no field or method FindBackableChain, but does have method findBackableChain) (typecheck)

Check failure on line 141 in dot/parachain/prospective-parachains/prospective-parachains.go

View workflow job for this annotation

GitHub Actions / integration-tests (github.com/ChainSafe/gossamer/dot)

chain.FindBackableChain undefined (type *fragmentChain has no field or method FindBackableChain, but does have method findBackableChain)

Check failure on line 141 in dot/parachain/prospective-parachains/prospective-parachains.go

View workflow job for this annotation

GitHub Actions / zombienet-tests

chain.FindBackableChain undefined (type *fragmentChain has no field or method FindBackableChain, but does have method findBackableChain)

Check failure on line 141 in dot/parachain/prospective-parachains/prospective-parachains.go

View workflow job for this annotation

GitHub Actions / unit-tests

chain.FindBackableChain undefined (type *fragmentChain has no field or method FindBackableChain, but does have method findBackableChain)
if len(backableCandidates) == 0 {
logger.Tracef(
DanielDDHM marked this conversation as resolved.
Show resolved Hide resolved
"No backable candidates found. RelayParentHash: %v, ParaId: %v, Ancestors: %v",
relayParentHash, paraId, ancestors,
)
responseChan <- []parachaintypes.CandidateHashAndRelayParent{}
return
}

logger.Tracef(
"Found backable candidates: %v. RelayParentHash: %v, ParaId: %v, Ancestors: %v",
backableCandidates, relayParentHash, paraId, ancestors,
)

// Convert backable candidates to the expected response format
candidateHashes := make([]parachaintypes.CandidateHashAndRelayParent, len(backableCandidates))
for i, candidate := range backableCandidates {
candidateHashes[i] = parachaintypes.CandidateHashAndRelayParent{
CandidateHash: candidate.candidateHash,
CandidateRelayParent: candidate.realyParentHash,
}
}

// Send the result through the response channel
responseChan <- candidateHashes
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package prospectiveparachains

import (
"testing"

parachaintypes "github.com/ChainSafe/gossamer/dot/parachain/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/stretchr/testify/assert"
)

type MockFragmentChain struct {
fragmentChain
}

func (m *MockFragmentChain) FindBackableChain(
ancestors Ancestors,
qty uint32,
) []parachaintypes.CandidateHashAndRelayParent {
return []parachaintypes.CandidateHashAndRelayParent{
{
CandidateHash: parachaintypes.CandidateHash{
Value: common.Hash{0x10},
},
CandidateRelayParent: common.Hash{0x20},
},
{
CandidateHash: parachaintypes.CandidateHash{
Value: common.Hash{0x11},
},
CandidateRelayParent: common.Hash{0x21},
},
}
}

func TestGetBackableCandidates(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add more tests to cover the various cases that result in an empty response.

You probably want to use a generated mock for that. Here is an example for how to do that.

Copy link
Author

Choose a reason for hiding this comment

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

@haikoschol i trying to refactor these tests and i will let you know

relayParentHash := common.Hash{0x01}
paraId := parachaintypes.ParaID(1)
requestedQty := uint32(2)
ancestors := Ancestors{
parachaintypes.CandidateHash{Value: common.Hash{0x02}}: {},
parachaintypes.CandidateHash{Value: common.Hash{0x03}}: {},
}
responseChan := make(chan []parachaintypes.CandidateHashAndRelayParent, 1)

mockFragmentChain := &MockFragmentChain{}

pp := &ProspectiveParachains{
View: &View{
ActiveLeaves: map[common.Hash]bool{
relayParentHash: true,
},
PerRelayParent: map[common.Hash]*RelayParentData{
relayParentHash: {
FragmentChains: map[parachaintypes.ParaID]*fragmentChain{
paraId: &mockFragmentChain.fragmentChain,
},
},
},
},
}

// Create the test message
msg := GetBackableCandidates{
RelayParentHash: relayParentHash,
ParaId: paraId,
RequestedQty: requestedQty,
Ancestors: ancestors,
Response: responseChan,
}

// Run the method in a goroutine
go pp.getBackableCandidates(msg)

// Collect the response
result := <-responseChan

// Assertions
assert.NotNil(t, result, "Result should not be nil")
assert.Len(t, result, 2, "Should return 2 backable candidates")
assert.Equal(t, result[0].CandidateHash.Value, common.Hash{0x10}, "First candidate hash mismatch")
assert.Equal(t, result[0].CandidateRelayParent, common.Hash{0x20}, "First candidate relay parent mismatch")
assert.Equal(t, result[1].CandidateHash.Value, common.Hash{0x11}, "Second candidate hash mismatch")
assert.Equal(t, result[1].CandidateRelayParent, common.Hash{0x21}, "Second candidate relay parent mismatch")
}
Loading