diff --git a/Bootstrap.go b/Bootstrap.go index d5e3327..0abd4a6 100644 --- a/Bootstrap.go +++ b/Bootstrap.go @@ -98,7 +98,7 @@ func (peer *rootPeer) contact() { contactArbitraryPeer(peer.publicKey, peer.addresses) } -// bootstrap connects to the initial set of peers. It will also start the routine for ongoing sending of multicast/broadcast messages. +// bootstrap connects to the initial set of peers. func bootstrap() { if len(rootPeers) == 0 { log.Printf("bootstrap warning: Empty list of root peers. Connectivity relies on local peer discovery and incoming connections.\n") diff --git a/Kademlia.go b/Kademlia.go index 92e2353..1e34970 100644 --- a/Kademlia.go +++ b/Kademlia.go @@ -56,20 +56,43 @@ func initKademlia() { node.Info.(*PeerInfo).sendAnnouncementFindValue(request) } } +} - // Refresh buckets every 5 minutes to meet the alpha nodes per bucket target. Force full refresh every hour. - go func() { - for minute := 5; ; minute += 5 { - time.Sleep(time.Minute * 5) +// autoBucketRefresh refreshes buckets every 5 minutes to meet the alpha nodes per bucket target. Force full refresh every hour. +func autoBucketRefresh() { + for minute := 5; ; minute += 5 { + time.Sleep(time.Minute * 5) - target := alpha - if minute%60 == 0 { - target = 0 - } - - nodesDHT.RefreshBuckets(target) + target := alpha + if minute%60 == 0 { + target = 0 } - }() + + nodesDHT.RefreshBuckets(target) + } +} + +// bootstrapKademlia bootstraps the Kademlia bucket list +func bootstrapKademlia() { + monitor := make(chan *PeerInfo) + registerPeerMonitor(monitor) + + // Wait until there are at least 2 peers connected. + for { + <-monitor + if nodesDHT.NumNodes() >= 2 { + break + } + } + + unregisterPeerMonitor(monitor) + + // Refresh every 10 seconds 3 times + for n := 0; n < 3; n++ { + nodesDHT.RefreshBuckets(alpha) + + time.Sleep(time.Second) + } } // Future sendAnnouncementX: If it detects that announcements are sent out to the same peer within 50ms it should activate a wait-and-group scheme. diff --git a/Peer ID.go b/Peer ID.go index c337e1e..7488d8b 100644 --- a/Peer ID.go +++ b/Peer ID.go @@ -113,6 +113,14 @@ func PeerlistAdd(PublicKey *btcec.PublicKey, connections ...*Connection) (peer * // add to Kademlia nodesDHT.AddNode(&dht.Node{ID: peer.NodeID, Info: peer}) + // send to all channels non-blocking + for _, monitor := range peerMonitor { + select { + case monitor <- peer: + default: + } + } + return peer, true } @@ -201,3 +209,30 @@ func selfPeerRecord(network *Network) (result PeerRecord) { LastContact: 0, } } + +var peerMonitor []chan<- *PeerInfo + +// registerPeerMonitor registers a channel to receive all new peers +func registerPeerMonitor(channel chan<- *PeerInfo) { + peerlistMutex.Lock() + defer peerlistMutex.Unlock() + + peerMonitor = append(peerMonitor, channel) +} + +// unregisterPeerMonitor unregisters a channel +func unregisterPeerMonitor(channel chan<- *PeerInfo) { + peerlistMutex.Lock() + defer peerlistMutex.Unlock() + + for n, channel2 := range peerMonitor { + if channel == channel2 { + peerMonitorNew := peerMonitor[:n] + if n < len(peerMonitor)-1 { + peerMonitorNew = append(peerMonitorNew, peerMonitor[n+1:]...) + } + peerMonitor = peerMonitorNew + break + } + } +} diff --git a/Peernet.go b/Peernet.go index 0793ffd..2154057 100644 --- a/Peernet.go +++ b/Peernet.go @@ -20,8 +20,10 @@ func Init() { // Connect starts bootstrapping and local peer discovery. func Connect() { + go bootstrapKademlia() go bootstrap() go autoMulticastBroadcast() go autoPingAll() go networkChangeMonitor() + go autoBucketRefresh() } diff --git a/README.md b/README.md index 427a557..c756a79 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ The Private Key is required to make any changes to the user's blockchain, includ * Check every 10 seconds for new/removed network interfaces and for new/removed IPs. * Automatically listen on any newly detected network interfaces and IPs. * Start a full Kademlia bucket refresh in case of a new network interface or IP. +* Kademlia bootstrap: + * As soon as there are at least 2 peers, keep refreshing buckets (target number is alpha) every 10 seconds 3 times. ### Ping diff --git a/go.mod b/go.mod index b899e5d..bd2c872 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/PeernetOfficial/core go 1.16 require ( - github.com/PeernetOfficial/core/dht v0.0.0-20210424204239-6693d442a6e2 + github.com/PeernetOfficial/core/dht v0.0.0-20210425014452-611dfa3b1ce9 github.com/btcsuite/btcd v0.21.0-beta.0.20210401013323-36a96f6a0025 github.com/pkg/errors v0.9.1 golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc diff --git a/go.sum b/go.sum index d85365e..8c33674 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/PeernetOfficial/core/dht v0.0.0-20210424204239-6693d442a6e2 h1:h4EP52078qatwYoW1DztuQhg5Y8i9wwDbkdO92usM+o= -github.com/PeernetOfficial/core/dht v0.0.0-20210424204239-6693d442a6e2/go.mod h1:sb2H21VIVTohCXVrDFo/Skl2tN8Yzba+MXSS6NgCYXw= +github.com/PeernetOfficial/core/dht v0.0.0-20210425014452-611dfa3b1ce9 h1:kcjoWZl9GZ9uSajS6t0tiKDpaatUQ64tl3OqXPc+YsY= +github.com/PeernetOfficial/core/dht v0.0.0-20210425014452-611dfa3b1ce9/go.mod h1:sb2H21VIVTohCXVrDFo/Skl2tN8Yzba+MXSS6NgCYXw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta.0.20210401013323-36a96f6a0025 h1:aoVqvZk4mLyF3WZbqEVPq+vXnwL2wekZg4P4mjYJNLs=