Skip to content

Commit

Permalink
Merge branch 'feat/parachain' into ed/prospective-parachains/skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardmack authored Nov 13, 2024
2 parents 7f641a0 + 075322c commit f88ed19
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 118 deletions.
26 changes: 13 additions & 13 deletions dot/parachain/collator-protocol/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func TestHandleCollationMessageDeclare(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down Expand Up @@ -268,7 +268,7 @@ func TestHandleCollationMessageDeclare(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Connected,
},
Expand All @@ -285,7 +285,7 @@ func TestHandleCollationMessageDeclare(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Connected,
},
Expand All @@ -312,7 +312,7 @@ func TestHandleCollationMessageDeclare(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Connected,
},
Expand Down Expand Up @@ -342,7 +342,7 @@ func TestHandleCollationMessageDeclare(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Connected,
},
Expand Down Expand Up @@ -449,7 +449,7 @@ func TestHandleCollationMessageAdvertiseCollation(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Connected,
},
Expand All @@ -475,7 +475,7 @@ func TestHandleCollationMessageAdvertiseCollation(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down Expand Up @@ -510,7 +510,7 @@ func TestHandleCollationMessageAdvertiseCollation(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand All @@ -536,7 +536,7 @@ func TestHandleCollationMessageAdvertiseCollation(t *testing.T) {
},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down Expand Up @@ -616,7 +616,7 @@ func TestInsertAdvertisement(t *testing.T) {
{
description: "fail with undeclared collator",
peerData: PeerData{
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Connected,
},
Expand All @@ -626,7 +626,7 @@ func TestInsertAdvertisement(t *testing.T) {
{
description: "fail with error out of view",
peerData: PeerData{
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
},
Expand All @@ -639,7 +639,7 @@ func TestInsertAdvertisement(t *testing.T) {
{
description: "fail with error duplicate advertisement",
peerData: PeerData{
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand All @@ -662,7 +662,7 @@ func TestInsertAdvertisement(t *testing.T) {
{
description: "success case",
peerData: PeerData{
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down
79 changes: 34 additions & 45 deletions dot/parachain/collator-protocol/validator_side.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/ChainSafe/gossamer/dot/network"
collatorprotocolmessages "github.com/ChainSafe/gossamer/dot/parachain/collator-protocol/messages"
"github.com/ChainSafe/gossamer/dot/parachain/network-bridge/events"
networkbridgeevents "github.com/ChainSafe/gossamer/dot/parachain/network-bridge/events"
networkbridgemessages "github.com/ChainSafe/gossamer/dot/parachain/network-bridge/messages"
parachaintypes "github.com/ChainSafe/gossamer/dot/parachain/types"
Expand Down Expand Up @@ -123,7 +122,7 @@ func (cpvs *CollatorProtocolValidatorSide) ProcessActiveLeavesUpdateSignal(
return nil
}

func (cpvs *CollatorProtocolValidatorSide) handleOurViewChange(view events.View) error {
func (cpvs *CollatorProtocolValidatorSide) handleOurViewChange(view parachaintypes.View) error {
// 1. Find out removed leaves (hashes) and newly added leaves
// 2. Go over each new leaves,
// - check if perspective parachain mode is enabled
Expand Down Expand Up @@ -400,7 +399,7 @@ type PendingCollation struct {
}

type PeerData struct {
view View
view parachaintypes.View
state PeerStateInfo
}

Expand Down Expand Up @@ -495,6 +494,31 @@ func (peerData *PeerData) InsertAdvertisement(
return true, nil
}

// UpdateView updates the view clearing all advertisements that are no longer in the current view.
func (peerData *PeerData) UpdateView(implicitView ImplicitView,
activeLeaves map[common.Hash]parachaintypes.ProspectiveParachainsMode, perRelayParent map[common.Hash]PerRelayParent,
newView parachaintypes.View) {

oldView := peerData.view
if peerData.state.PeerState == Collating {
// remove relay parent advertisement if it went out of implicit view
diff := oldView.Difference(newView)
for _, relayParent := range diff {
_, ok := perRelayParent[relayParent]
if !ok {
delete(peerData.state.CollatingPeerState.advertisements, relayParent)
}

keep := IsRelayParentInImplicitView(relayParent, perRelayParent[relayParent].prospectiveParachainMode,
implicitView, activeLeaves, peerData.state.CollatingPeerState.ParaID)

if !keep {
delete(peerData.state.CollatingPeerState.advertisements, relayParent)
}
}
}
}

type PeerStateInfo struct {
PeerState PeerState
// instant at which peer got connected
Expand All @@ -521,47 +545,6 @@ const (
// We use the same limit to compute the view sent to peers locally.
const MaxViewHeads uint8 = 5

// A succinct representation of a peer's view. This consists of a bounded amount of chain heads
// and the highest known finalized block number.
//
// Up to `N` (5?) chain heads.
type View struct {
// a bounded amount of chain heads
heads []common.Hash
// the highest known finalized number
finalizedNumber uint32
}

type SortableHeads []common.Hash

func (s SortableHeads) Len() int {
return len(s)
}

func (s SortableHeads) Less(i, j int) bool {
return s[i].String() > s[j].String()
}

func (s SortableHeads) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}

func ConstructView(liveHeads map[common.Hash]struct{}, finalizedNumber uint32) View {
heads := make([]common.Hash, 0, len(liveHeads))
for head := range liveHeads {
heads = append(heads, head)
}

if len(heads) >= 5 {
heads = heads[:5]
}

return View{
heads: heads,
finalizedNumber: finalizedNumber,
}
}

// Network is the interface required by parachain service for the network
type Network interface {
GossipMessage(msg network.NotificationsMessage)
Expand Down Expand Up @@ -743,7 +726,13 @@ func (cpvs CollatorProtocolValidatorSide) handleNetworkBridgeEvents(msg any) err
case networkbridgeevents.NewGossipTopology:
// NOTE: This won't happen
case networkbridgeevents.PeerViewChange:
// TODO #4155
// - advertisements by this peer that are no longer relevant have to be removed
peerData, ok := cpvs.peerData[msg.PeerID]
if ok {
peerData.UpdateView(cpvs.implicitView, cpvs.activeLeaves, cpvs.perRelayParent, msg.View)
cpvs.peerData[msg.PeerID] = peerData
}

case networkbridgeevents.OurViewChange:
return cpvs.handleOurViewChange(msg.View)
case networkbridgeevents.UpdatedAuthorityIDs:
Expand Down
56 changes: 53 additions & 3 deletions dot/parachain/collator-protocol/validator_side_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/parachain/backing"
collatorprotocolmessages "github.com/ChainSafe/gossamer/dot/parachain/collator-protocol/messages"
networkbridgeevents "github.com/ChainSafe/gossamer/dot/parachain/network-bridge/events"
networkbridgemessages "github.com/ChainSafe/gossamer/dot/parachain/network-bridge/messages"
"github.com/ChainSafe/gossamer/dot/parachain/overseer"
parachaintypes "github.com/ChainSafe/gossamer/dot/parachain/types"
Expand Down Expand Up @@ -104,7 +105,7 @@ func TestProcessOverseerMessage(t *testing.T) {
}},
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down Expand Up @@ -168,7 +169,7 @@ func TestProcessOverseerMessage(t *testing.T) {
}(),
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down Expand Up @@ -250,7 +251,7 @@ func TestProcessOverseerMessage(t *testing.T) {
}(),
peerData: map[peer.ID]PeerData{
peerID: {
view: View{},
view: parachaintypes.View{},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
Expand Down Expand Up @@ -460,3 +461,52 @@ func TestProcessBackedOverseerMessage(t *testing.T) {
})
}
}

func TestPeerViewChange(t *testing.T) {
t.Parallel()

// test that relay parent advertisement gets removed if it went out of implicit view

cpvs := CollatorProtocolValidatorSide{
activeLeaves: map[common.Hash]parachaintypes.ProspectiveParachainsMode{},
perRelayParent: map[common.Hash]PerRelayParent{
{0x01}: {
prospectiveParachainMode: parachaintypes.ProspectiveParachainsMode{
IsEnabled: false,
},
},
},
peerData: map[peer.ID]PeerData{
peer.ID("peer1"): {
// this shows our current view of peer1
view: parachaintypes.View{
Heads: []common.Hash{{0x01}},
},
state: PeerStateInfo{
PeerState: Collating,
CollatingPeerState: CollatingPeerState{
advertisements: map[common.Hash][]parachaintypes.CandidateHash{
{0x01}: {},
},
},
},
},
},
}

msg := networkbridgeevents.PeerViewChange{
PeerID: peer.ID("peer1"),
// this shows the new view of peer1, since the new view does not contain relay parent {0x01},
// we will remove the advertisement for that relay parent
View: parachaintypes.View{
Heads: []common.Hash{{0x02}},
},
}

err := cpvs.handleNetworkBridgeEvents(msg)
require.NoError(t, err)

// advertisement for relay parent {0x01} should be removed
_, ok := cpvs.peerData[peer.ID("peer1")].state.CollatingPeerState.advertisements[common.Hash{0x01}]
require.False(t, ok)
}
15 changes: 2 additions & 13 deletions dot/parachain/network-bridge/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,11 @@ type NewGossipTopology struct {

type PeerViewChange struct {
PeerID peer.ID
View View
}

// View is a succinct representation of a peer's view. This consists of a bounded amount of chain heads
// and the highest known finalized block number.
//
// Up to `N` (5?) chain heads.
type View struct {
// a bounded amount of chain heads
Heads []common.Hash
// the highest known finalized number
FinalizedNumber uint32
View parachaintypes.View
}

type OurViewChange struct {
View View
View parachaintypes.View
}

type PeerMessage[Message collationprotocol.CollationProtocol | validationprotocol.ValidationProtocol] struct {
Expand Down
Loading

0 comments on commit f88ed19

Please sign in to comment.