-
Notifications
You must be signed in to change notification settings - Fork 143
feat(grandpa): implement neighbor tracker and message handling #4230
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
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
947a0f4
wip/neighborMsg handling
jimjbrettj 3b01286
wip/catch up request flow
jimjbrettj 035646c
wip
jimjbrettj 8f8c066
wip/impl neighbor tracking
jimjbrettj fef75bb
neighbor message tracker
jimjbrettj fd0ffc2
remove changes not needed
jimjbrettj 97cbd31
remove minor diff
jimjbrettj 0c694bb
wip/feedback
jimjbrettj 41a3c76
respond to feedback
jimjbrettj f23987b
add unit tests
jimjbrettj 532afc1
use const for ticker period
jimjbrettj 3c0d6c6
feedback and lint
jimjbrettj 76836a5
remove return err from handleNeighbourMSg
jimjbrettj 8451a4c
fix lint and license
jimjbrettj 566b228
test for broadcast neighbour msg
jimjbrettj 39d2b22
test to update peer while running
jimjbrettj 3d1d0b7
fix TestHandleNetworkMessage
jimjbrettj 998d8cc
fix grandpa integration test
jimjbrettj 9f8e0dd
fix linting
jimjbrettj a137cba
fix race conditions
jimjbrettj 4689316
respond to most of feedback
jimjbrettj 7d67f80
add wait group to neighbor tracker
jimjbrettj 3dbb1db
move wg.Done() into a defer
jimjbrettj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// Copyright 2024 ChainSafe Systems (ON) | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
package grandpa | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/ChainSafe/gossamer/dot/types" | ||
"github.com/libp2p/go-libp2p/core/peer" | ||
) | ||
|
||
// How often neighbour messages should be rebroadcast in the case where no new packets are created | ||
const neighbourBroadcastPeriod = time.Minute * 2 | ||
|
||
type neighborData struct { | ||
peer peer.ID | ||
neighborMsg *NeighbourPacketV1 | ||
} | ||
|
||
type neighborState struct { | ||
setID uint64 | ||
round uint64 | ||
highestFinalized uint32 | ||
} | ||
|
||
type neighborTracker struct { | ||
sync.Mutex | ||
grandpa *Service | ||
|
||
peerview map[peer.ID]neighborState | ||
currentSetID uint64 | ||
currentRound uint64 | ||
highestFinalized uint32 | ||
|
||
finalizationCha chan *types.FinalisationInfo | ||
neighborMsgChan chan neighborData | ||
stoppedNeighbor chan struct{} | ||
wg sync.WaitGroup | ||
} | ||
|
||
func newNeighborTracker(grandpa *Service, neighborChan chan neighborData) *neighborTracker { | ||
return &neighborTracker{ | ||
grandpa: grandpa, | ||
peerview: make(map[peer.ID]neighborState), | ||
finalizationCha: grandpa.blockState.GetFinalisedNotifierChannel(), | ||
neighborMsgChan: neighborChan, | ||
stoppedNeighbor: make(chan struct{}), | ||
} | ||
} | ||
|
||
func (nt *neighborTracker) Start() { | ||
nt.wg.Add(1) | ||
go nt.run() | ||
} | ||
|
||
func (nt *neighborTracker) Stop() { | ||
nt.grandpa.blockState.FreeFinalisedNotifierChannel(nt.finalizationCha) | ||
close(nt.stoppedNeighbor) | ||
|
||
nt.wg.Wait() | ||
} | ||
|
||
func (nt *neighborTracker) run() { | ||
logger.Info("starting neighbour tracker") | ||
ticker := time.NewTicker(neighbourBroadcastPeriod) | ||
defer func() { | ||
ticker.Stop() | ||
nt.wg.Done() | ||
}() | ||
|
||
for { | ||
select { | ||
case <-ticker.C: | ||
logger.Debugf("neighbour message broadcast triggered by ticker") | ||
err := nt.BroadcastNeighborMsg() | ||
if err != nil { | ||
logger.Errorf("broadcasting neighbour message: %v", err) | ||
} | ||
|
||
case block := <-nt.finalizationCha: | ||
if block != nil { | ||
nt.updateState(block.SetID, block.Round, uint32(block.Header.Number)) //nolint | ||
err := nt.BroadcastNeighborMsg() | ||
if err != nil { | ||
logger.Errorf("broadcasting neighbour message: %v", err) | ||
} | ||
ticker.Reset(neighbourBroadcastPeriod) | ||
} | ||
case neighborData := <-nt.neighborMsgChan: | ||
if neighborData.neighborMsg.Number > nt.peerview[neighborData.peer].highestFinalized { | ||
nt.updatePeer( | ||
neighborData.peer, | ||
neighborData.neighborMsg.SetID, | ||
neighborData.neighborMsg.Round, | ||
neighborData.neighborMsg.Number, | ||
) | ||
} | ||
case <-nt.stoppedNeighbor: | ||
logger.Info("stopping neighbour tracker") | ||
return | ||
} | ||
} | ||
} | ||
|
||
func (nt *neighborTracker) updateState(setID uint64, round uint64, highestFinalized uint32) { | ||
nt.Lock() | ||
defer nt.Unlock() | ||
|
||
nt.currentSetID = setID | ||
nt.currentRound = round | ||
nt.highestFinalized = highestFinalized | ||
} | ||
|
||
func (nt *neighborTracker) updatePeer(p peer.ID, setID uint64, round uint64, highestFinalized uint32) { | ||
nt.Lock() | ||
defer nt.Unlock() | ||
peerState := neighborState{setID, round, highestFinalized} | ||
nt.peerview[p] = peerState | ||
} | ||
|
||
func (nt *neighborTracker) getPeer(p peer.ID) neighborState { | ||
nt.Lock() | ||
defer nt.Unlock() | ||
return nt.peerview[p] | ||
} | ||
|
||
func (nt *neighborTracker) BroadcastNeighborMsg() error { | ||
packet := NeighbourPacketV1{ | ||
Round: nt.currentRound, | ||
SetID: nt.currentSetID, | ||
Number: nt.highestFinalized, | ||
} | ||
|
||
cm, err := packet.ToConsensusMessage() | ||
if err != nil { | ||
return fmt.Errorf("converting NeighbourPacketV1 to network message: %w", err) | ||
} | ||
for id, peerState := range nt.peerview { | ||
if peerState.round >= nt.currentRound && peerState.setID >= nt.currentSetID { | ||
haikoschol marked this conversation as resolved.
Show resolved
Hide resolved
|
||
err = nt.grandpa.network.SendMessage(id, cm) | ||
if err != nil { | ||
return fmt.Errorf("sending message to peer: %v", id) | ||
} | ||
} | ||
} | ||
return nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.