The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
woop/p2p/stream/protocols/sync/protocol.go

261 lines
6.5 KiB

package sync
import (
"context"
"strconv"
"time"
"github.com/ethereum/go-ethereum/event"
"github.com/harmony-one/harmony/consensus/engine"
nodeconfig "github.com/harmony-one/harmony/internal/configs/node"
shardingconfig "github.com/harmony-one/harmony/internal/configs/sharding"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p/discovery"
"github.com/harmony-one/harmony/p2p/stream/common/ratelimiter"
"github.com/harmony-one/harmony/p2p/stream/common/requestmanager"
"github.com/harmony-one/harmony/p2p/stream/common/streammanager"
sttypes "github.com/harmony-one/harmony/p2p/stream/types"
"github.com/hashicorp/go-version"
Release Candidate: dev -> main (#4319) * Rebase dev branch to current main branch (#4318) * add openssl compatibility on m2 chips using darwin (#4302) Adds support for OpenSSL on MacOS Ventura using m2 chips. * [dumpdb] ensure each cross link is dumped (#4311) * bump libp2p to version 0.24.0 and update its dependencies and relevant tests (#4315) * Removed legacy syncing peer provider. (#4260) * Removed legacy syncing peer provider. * Fix localnet. * Fix migrate version. * Rebased on main. * Fix formatting. * Remove blockchain dependency from engine. (#4310) * Consensus doesn't require anymore `Node` as a circular dependency. * Rebased upon main. * Removed engine beacon chain dependency. * Fixed nil error. * Fixed error. * bump libp2p to version 0.24.0 and update its dependencies and relevant tests * fix format, remove wrongly added configs * add back wrongly deleted comment * fix travis go checker Co-authored-by: Konstantin <355847+Frozen@users.noreply.github.com> Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * bump libp2p to version 0.24.0 and update its dependencies and relevant tests (#4315) * Removed legacy syncing peer provider. (#4260) * Removed legacy syncing peer provider. * Fix localnet. * Fix migrate version. * Rebased on main. * Fix formatting. * Remove blockchain dependency from engine. (#4310) * Consensus doesn't require anymore `Node` as a circular dependency. * Rebased upon main. * Removed engine beacon chain dependency. * Fixed nil error. * Fixed error. * bump libp2p to version 0.24.0 and update its dependencies and relevant tests * fix format, remove wrongly added configs * add back wrongly deleted comment * fix travis go checker Co-authored-by: Konstantin <355847+Frozen@users.noreply.github.com> Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * Fix for consensus stuck. (#4307) * Added check for block validity. * Starts new view change if block invalid. * Revert "Starts new view change if block invalid." This reverts commit e889fa5da2e0780f087ab7dae5106b96287706db. * staged dns sync v1.0 (#4316) * staged dns sync v1.0 * enabled stream downloader for localnet * fix code review issues * remove extra lock Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * add description for closing client and change randomize process to ma… (#4276) * add description for closing client and change randomize process to make sure only online nodes are added to sync config * fix sync test * fix legacy limitNumPeers test * add WaitForEachPeerToConnect to node configs to make parallel peer connection optional Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * Small fixes and code cleanup for network stack. (#4320) * staged dns sync v1.0 * enabled stream downloader for localnet * fix code review issues * remove extra lock * staged dns sync v1.0 * Fixed, code clean up and other. * Fixed, code clean up and other. * Fixed, code clean up and other. * Fix config. Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> * Fix not disable cache in archival mode (#4322) * Feature registry (#4324) * Registry for services. * Test. * Reverted comment. * Fix. * Slash fix (#4284) * Implementation of new slashing rate calculation * Write tests for then new slashing rate calculation * Add engine.applySlashing tests * fix #4059 Co-authored-by: Alex Brezas <abresas@gmail.com> Co-authored-by: Dimitris Lamprinos <pkakelas@gmail.com> * Bump github.com/aws/aws-sdk-go from 1.30.1 to 1.33.0 (#4325) (#4328) Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.30.1 to 1.33.0. - [Release notes](https://github.com/aws/aws-sdk-go/releases) - [Changelog](https://github.com/aws/aws-sdk-go/blob/v1.33.0/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-go/compare/v1.30.1...v1.33.0) --- updated-dependencies: - dependency-name: github.com/aws/aws-sdk-go dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/btcsuite/btcd from 0.21.0-beta to 0.23.2 (#4327) (#4329) Bumps [github.com/btcsuite/btcd](https://github.com/btcsuite/btcd) from 0.21.0-beta to 0.23.2. - [Release notes](https://github.com/btcsuite/btcd/releases) - [Changelog](https://github.com/btcsuite/btcd/blob/master/CHANGES) - [Commits](https://github.com/btcsuite/btcd/compare/v0.21.0-beta...v0.23.2) --- updated-dependencies: - dependency-name: github.com/btcsuite/btcd dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Max <82761650+MaxMustermann2@users.noreply.github.com> Co-authored-by: Gheis <36589218+GheisMohammadi@users.noreply.github.com> Co-authored-by: Konstantin <355847+Frozen@users.noreply.github.com> Co-authored-by: “GheisMohammadi” <“Gheis.Mohammadi@gmail.com”> Co-authored-by: Danny Willis <102543677+dannyposi@users.noreply.github.com> Co-authored-by: PeekPI <894646171@QQ.COM> Co-authored-by: Alex Brezas <abresas@gmail.com> Co-authored-by: Dimitris Lamprinos <pkakelas@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2 years ago
libp2p_host "github.com/libp2p/go-libp2p/core/host"
libp2p_network "github.com/libp2p/go-libp2p/core/network"
"github.com/rs/zerolog"
)
const (
// serviceSpecifier is the specifier for the service.
serviceSpecifier = "sync"
)
var (
version100, _ = version.NewVersion("1.0.0")
// MyVersion is the version of sync protocol of the local node
MyVersion = version100
// MinVersion is the minimum version for matching function
MinVersion = version100
)
type (
// Protocol is the protocol for sync streaming
Protocol struct {
chain engine.ChainReader // provide SYNC data
schedule shardingconfig.Schedule // provide schedule information
rl ratelimiter.RateLimiter // limit the incoming request rate
sm streammanager.StreamManager // stream management
rm requestmanager.RequestManager // deliver the response from stream
disc discovery.Discovery
config Config
logger zerolog.Logger
ctx context.Context
cancel func()
closeC chan struct{}
}
// Config is the sync protocol config
Config struct {
Chain engine.ChainReader
Host libp2p_host.Host
Discovery discovery.Discovery
ShardID nodeconfig.ShardID
Network nodeconfig.NetworkType
// stream manager config
SmSoftLowCap int
SmHardLowCap int
SmHiCap int
DiscBatch int
}
)
// NewProtocol creates a new sync protocol
func NewProtocol(config Config) *Protocol {
ctx, cancel := context.WithCancel(context.Background())
sp := &Protocol{
chain: config.Chain,
disc: config.Discovery,
config: config,
ctx: ctx,
cancel: cancel,
closeC: make(chan struct{}),
}
smConfig := streammanager.Config{
SoftLoCap: config.SmSoftLowCap,
HardLoCap: config.SmHardLowCap,
HiCap: config.SmHiCap,
DiscBatch: config.DiscBatch,
}
sp.sm = streammanager.NewStreamManager(sp.ProtoID(), config.Host, config.Discovery,
sp.HandleStream, smConfig)
sp.rl = ratelimiter.NewRateLimiter(sp.sm, rateLimiterGlobalRequestPerSecond, rateLimiterSingleRequestsPerSecond)
sp.rm = requestmanager.NewRequestManager(sp.sm)
sp.logger = utils.Logger().With().Str("Protocol", string(sp.ProtoID())).Logger()
return sp
}
// Start starts the sync protocol
func (p *Protocol) Start() {
p.sm.Start()
p.rm.Start()
p.rl.Start()
go p.advertiseLoop()
}
// Close close the protocol
func (p *Protocol) Close() {
p.rl.Close()
p.rm.Close()
p.sm.Close()
p.cancel()
close(p.closeC)
}
// Specifier return the specifier for the protocol
func (p *Protocol) Specifier() string {
return serviceSpecifier + "/" + strconv.Itoa(int(p.config.ShardID))
}
// ProtoID return the ProtoID of the sync protocol
func (p *Protocol) ProtoID() sttypes.ProtoID {
return p.protoIDByVersion(MyVersion)
}
// Version returns the sync protocol version
func (p *Protocol) Version() *version.Version {
return MyVersion
}
// Match checks the compatibility to the target protocol ID.
func (p *Protocol) Match(targetID string) bool {
target, err := sttypes.ProtoIDToProtoSpec(sttypes.ProtoID(targetID))
if err != nil {
return false
}
if target.Service != serviceSpecifier {
return false
}
if target.NetworkType != p.config.Network {
return false
}
if target.ShardID != p.config.ShardID {
return false
}
if target.Version.LessThan(MinVersion) {
return false
}
return true
}
// HandleStream is the stream handle function being registered to libp2p.
func (p *Protocol) HandleStream(raw libp2p_network.Stream) {
p.logger.Info().Str("stream", raw.ID()).Msg("handle new sync stream")
st := p.wrapStream(raw)
if err := p.sm.NewStream(st); err != nil {
// Possibly we have reach the hard limit of the stream
p.logger.Warn().Err(err).Str("stream ID", string(st.ID())).
Msg("failed to add new stream")
return
}
st.run()
}
func (p *Protocol) advertiseLoop() {
for {
sleep := p.advertise()
select {
case <-time.After(sleep):
case <-p.closeC:
return
}
}
}
// advertise will advertise all compatible protocol versions for helping nodes running low
// version
func (p *Protocol) advertise() time.Duration {
var nextWait time.Duration
pids := p.supportedProtoIDs()
for _, pid := range pids {
w, e := p.disc.Advertise(p.ctx, string(pid))
if e != nil {
p.logger.Warn().Err(e).Str("protocol", string(pid)).
Msg("cannot advertise sync protocol")
continue
}
if nextWait == 0 || nextWait > w {
nextWait = w
}
}
if nextWait < minAdvertiseInterval {
nextWait = minAdvertiseInterval
}
return nextWait
}
func (p *Protocol) supportedProtoIDs() []sttypes.ProtoID {
vs := p.supportedVersions()
pids := make([]sttypes.ProtoID, 0, len(vs))
for _, v := range vs {
pids = append(pids, p.protoIDByVersion(v))
}
return pids
}
func (p *Protocol) supportedVersions() []*version.Version {
return []*version.Version{version100}
}
func (p *Protocol) protoIDByVersion(v *version.Version) sttypes.ProtoID {
spec := sttypes.ProtoSpec{
Service: serviceSpecifier,
NetworkType: p.config.Network,
ShardID: p.config.ShardID,
Version: v,
}
return spec.ToProtoID()
}
// RemoveStream removes the stream of the given stream ID
func (p *Protocol) RemoveStream(stID sttypes.StreamID) {
if stID == "" {
return
}
st, exist := p.sm.GetStreamByID(stID)
if exist && st != nil {
st.Close()
}
}
// NumStreams return the streams with minimum version.
// Note: nodes with sync version smaller than minVersion is not counted.
func (p *Protocol) NumStreams() int {
res := 0
sts := p.sm.GetStreams()
for _, st := range sts {
ps, _ := st.ProtoSpec()
if ps.Version.GreaterThanOrEqual(MinVersion) {
res++
}
}
return res
}
// GetStreamManager get the underlying stream manager for upper level stream operations
func (p *Protocol) GetStreamManager() streammanager.StreamManager {
return p.sm
}
// SubscribeAddStreamEvent subscribe the stream add event
func (p *Protocol) SubscribeAddStreamEvent(ch chan<- streammanager.EvtStreamAdded) event.Subscription {
return p.sm.SubscribeAddStreamEvent(ch)
}