mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
swarm/network: Kademlia fixes
This commit is contained in:
parent
a03781dfb0
commit
5307e1ea77
5 changed files with 76 additions and 93 deletions
|
|
@ -120,9 +120,8 @@ func (self *discPeer) handleSubPeersMsg(msg *subPeersMsg) error {
|
||||||
if uint8(po) < self.depth {
|
if uint8(po) < self.depth {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
log.Warn(fmt.Sprintf("peer %#v depth %v", p, self.depth))
|
|
||||||
if !self.seen(p) {
|
if !self.seen(p) {
|
||||||
peers = append(peers, ToAddr(p))
|
peers = append(peers, ToAddr(p.Off()))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
@ -147,13 +146,15 @@ func (self *discPeer) handlePeersMsg(msg *peersMsg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var c chan OverlayAddr
|
c := make(chan OverlayAddr)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(c)
|
||||||
for _, a := range msg.Peers {
|
for _, a := range msg.Peers {
|
||||||
self.seen(a)
|
self.seen(a)
|
||||||
c <- a
|
c <- a
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
log.Info("discovery overlay register")
|
||||||
return self.overlay.Register(c)
|
return self.overlay.Register(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +169,7 @@ func (self *discPeer) handleGetPeersMsg(msg *getPeersMsg) error {
|
||||||
self.overlay.EachConn(self.Over(), int(msg.Order), func(p OverlayConn, po int, isproxbin bool) bool {
|
self.overlay.EachConn(self.Over(), int(msg.Order), func(p OverlayConn, po int, isproxbin bool) bool {
|
||||||
i++
|
i++
|
||||||
// only send peers we have not sent before in this session
|
// only send peers we have not sent before in this session
|
||||||
a := ToAddr(p)
|
a := ToAddr(p.Off())
|
||||||
if self.seen(a) {
|
if self.seen(a) {
|
||||||
peers = append(peers, a)
|
peers = append(peers, a)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,8 @@ func (self *Hive) Start(server *p2p.Server) error {
|
||||||
// to attempt to write to more (remove Peer when shutting down)
|
// to attempt to write to more (remove Peer when shutting down)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Trace("hive delegate to overlay driver: suggest addr to connect to")
|
log.Debug("hive delegate to overlay driver: suggest addr to connect to")
|
||||||
|
// log.Trace("hive delegate to overlay driver: suggest addr to connect to")
|
||||||
addr, order, want := self.SuggestPeer()
|
addr, order, want := self.SuggestPeer()
|
||||||
|
|
||||||
if addr != nil {
|
if addr != nil {
|
||||||
|
|
@ -143,16 +144,17 @@ func (self *Hive) Start(server *p2p.Server) error {
|
||||||
|
|
||||||
want = want && self.Discovery
|
want = want && self.Discovery
|
||||||
if want {
|
if want {
|
||||||
|
log.Debug(fmt.Sprintf("========> request peers nearest %v", addr))
|
||||||
RequestOrder(self.Overlay, uint8(order), self.PeersBroadcastSetSize, self.MaxPeersPerRequest)
|
RequestOrder(self.Overlay, uint8(order), self.PeersBroadcastSetSize, self.MaxPeersPerRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info(fmt.Sprintf("%v", self))
|
||||||
select {
|
select {
|
||||||
case self.toggle <- want:
|
case self.toggle <- want:
|
||||||
log.Trace(fmt.Sprintf("keep hive alive: %v", want))
|
log.Trace(fmt.Sprintf("keep hive alive: %v", want))
|
||||||
case <-self.quit:
|
case <-self.quit:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// log.Info(fmt.Sprintf("%v", self))
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -177,13 +179,6 @@ func (self *Hive) Run(p *bzzPeer) error {
|
||||||
return p.Run(dp.HandleMsg)
|
return p.Run(dp.HandleMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove called after peer is disconnected
|
|
||||||
// func (self *Hive) Remove(p *bzzPeer) {
|
|
||||||
// defer self.wake()
|
|
||||||
// log.Debug(fmt.Sprintf("remove bee %v", p))
|
|
||||||
// self.Off(p)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// NodeInfo function is used by the p2p.server RPC interface to display
|
// NodeInfo function is used by the p2p.server RPC interface to display
|
||||||
// protocol specific node information
|
// protocol specific node information
|
||||||
func (self *Hive) NodeInfo() interface{} {
|
func (self *Hive) NodeInfo() interface{} {
|
||||||
|
|
@ -229,6 +224,9 @@ func ToAddr(pa OverlayPeer) *bzzAddr {
|
||||||
if addr, ok := pa.(*bzzAddr); ok {
|
if addr, ok := pa.(*bzzAddr); ok {
|
||||||
return addr
|
return addr
|
||||||
}
|
}
|
||||||
|
if p, ok := pa.(*discPeer); ok {
|
||||||
|
return p.bzzAddr
|
||||||
|
}
|
||||||
return pa.(*bzzPeer).bzzAddr
|
return pa.(*bzzPeer).bzzAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -262,7 +260,7 @@ func (self *Hive) keepAlive() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-tick:
|
case <-tick:
|
||||||
log.Trace("wake up: make hive alive")
|
log.Debug("wake up: make hive alive")
|
||||||
self.wake()
|
self.wake()
|
||||||
case need := <-self.toggle:
|
case need := <-self.toggle:
|
||||||
if ticker == nil && need {
|
if ticker == nil && need {
|
||||||
|
|
@ -295,9 +293,9 @@ func (self *Hive) loadPeers() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var c chan OverlayAddr
|
c := make(chan OverlayAddr)
|
||||||
defer close(c)
|
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(c)
|
||||||
for _, a := range as {
|
for _, a := range as {
|
||||||
c <- a
|
c <- a
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,10 +162,11 @@ func (self *Kademlia) Register(peers chan OverlayAddr) error {
|
||||||
if bytes.Equal(p.Address(), self.base) {
|
if bytes.Equal(p.Address(), self.base) {
|
||||||
return fmt.Errorf("add peers: %x is self", self.base)
|
return fmt.Errorf("add peers: %x is self", self.base)
|
||||||
}
|
}
|
||||||
np, _, _ = pot.Add(np, pot.PotVal(newEntry(p)))
|
np, _, _ = pot.Add(np, newEntry(p))
|
||||||
}
|
}
|
||||||
com := self.addrs.Merge(np)
|
com := self.addrs.Merge(np)
|
||||||
log.Trace(fmt.Sprintf("merged %v peers, %v known", np.Size(), com))
|
log.Debug(fmt.Sprintf("merged %v peers, %v known, total: %v", np.Size(), com, self.addrs.Size()))
|
||||||
|
// log.Trace(fmt.Sprintf("merged %v peers, %v known", np.Size(), com))
|
||||||
|
|
||||||
// TODO: remove this check
|
// TODO: remove this check
|
||||||
m := make(map[string]bool)
|
m := make(map[string]bool)
|
||||||
|
|
@ -189,7 +190,8 @@ func (self *Kademlia) SuggestPeer() (a OverlayAddr, o int, want bool) {
|
||||||
depth := self.Depth()
|
depth := self.Depth()
|
||||||
// if there is a callable neighbour within the current proxBin, connect
|
// if there is a callable neighbour within the current proxBin, connect
|
||||||
// this makes sure nearest neighbour set is fully connected
|
// this makes sure nearest neighbour set is fully connected
|
||||||
log.Trace(fmt.Sprintf("candidate prox peer checking above PO %v", depth))
|
log.Debug(fmt.Sprintf("candidate prox peer checking above PO %v", depth))
|
||||||
|
// log.Trace(fmt.Sprintf("candidate prox peer checking above PO %v", depth))
|
||||||
var ppo int
|
var ppo int
|
||||||
ba := pot.NewBytesVal(self.base, nil)
|
ba := pot.NewBytesVal(self.base, nil)
|
||||||
self.addrs.EachNeighbour(ba, func(val pot.PotVal, po int) bool {
|
self.addrs.EachNeighbour(ba, func(val pot.PotVal, po int) bool {
|
||||||
|
|
@ -266,12 +268,10 @@ func (self *Kademlia) On(p OverlayConn) {
|
||||||
return v
|
return v
|
||||||
})
|
})
|
||||||
|
|
||||||
log.Trace(fmt.Sprintf("Notifier:%#v", p))
|
|
||||||
np, ok := p.(Notifier)
|
np, ok := p.(Notifier)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Trace(fmt.Sprintf("notify:%v", p))
|
|
||||||
|
|
||||||
depth := uint8(self.Depth())
|
depth := uint8(self.Depth())
|
||||||
if depth != self.depth {
|
if depth != self.depth {
|
||||||
|
|
@ -284,10 +284,12 @@ func (self *Kademlia) On(p OverlayConn) {
|
||||||
f := func(val pot.PotVal, po int) {
|
f := func(val pot.PotVal, po int) {
|
||||||
dp := val.(*entry).OverlayPeer.(Notifier)
|
dp := val.(*entry).OverlayPeer.(Notifier)
|
||||||
dp.NotifyPeer(p.Off(), uint8(po))
|
dp.NotifyPeer(p.Off(), uint8(po))
|
||||||
log.Trace(fmt.Sprintf("peer %v notified of %v (%v)", dp, p, po))
|
// log.Trace(fmt.Sprintf("peer %v notified of %v (%v)", dp, p, po))
|
||||||
|
log.Debug(fmt.Sprintf("peer %v notified of %v (%v)", dp, p, po))
|
||||||
if depth > 0 {
|
if depth > 0 {
|
||||||
dp.NotifyDepth(depth)
|
dp.NotifyDepth(depth)
|
||||||
log.Trace("peer %v notified of new depth %v", dp, depth)
|
log.Debug(fmt.Sprintf("peer %v notified of new depth %v", dp, depth))
|
||||||
|
// log.Trace(fmt.Sprintf("peer %v notified of new depth %v", dp, depth))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.conns.EachNeighbourAsync(e, 1024, 255, f, false)
|
self.conns.EachNeighbourAsync(e, 1024, 255, f, false)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -185,6 +186,7 @@ func (b *Bzz) Stop() error {
|
||||||
|
|
||||||
func (b *Bzz) runHandshake(p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
func (b *Bzz) runHandshake(p *p2p.Peer, rw p2p.MsgReadWriter) error {
|
||||||
handshake := b.getHandshake(p.ID())
|
handshake := b.getHandshake(p.ID())
|
||||||
|
defer b.removeHandshake(p.ID())
|
||||||
|
|
||||||
if err := handshake.Perform(p, rw); err != nil {
|
if err := handshake.Perform(p, rw); err != nil {
|
||||||
log.Error("handshake failed", "peer", p.ID(), "err", err)
|
log.Error("handshake failed", "peer", p.ID(), "err", err)
|
||||||
|
|
@ -218,6 +220,12 @@ func (b *Bzz) runProtocol(spec *protocols.Spec, run func(*bzzPeer) error) func(*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bzz) removeHandshake(peerID discover.NodeID) {
|
||||||
|
b.mtx.Lock()
|
||||||
|
defer b.mtx.Unlock()
|
||||||
|
delete(b.handshakes, peerID)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bzz) getHandshake(peerID discover.NodeID) *bzzHandshake {
|
func (b *Bzz) getHandshake(peerID discover.NodeID) *bzzHandshake {
|
||||||
b.mtx.Lock()
|
b.mtx.Lock()
|
||||||
defer b.mtx.Unlock()
|
defer b.mtx.Unlock()
|
||||||
|
|
@ -370,5 +378,8 @@ func NewNodeIdFromAddr(addr Addr) *adapters.NodeId {
|
||||||
// the overlay address is derived as the hash of the nodeId
|
// the overlay address is derived as the hash of the nodeId
|
||||||
func NewAddrFromNodeId(n *adapters.NodeId) *bzzAddr {
|
func NewAddrFromNodeId(n *adapters.NodeId) *bzzAddr {
|
||||||
id := n.NodeID
|
id := n.NodeID
|
||||||
return &bzzAddr{crypto.Keccak256(id[:]), id[:]}
|
return &bzzAddr{
|
||||||
|
OAddr: crypto.Keccak256(id[:]),
|
||||||
|
UAddr: []byte(discover.NewNode(id, net.IP{127, 0, 0, 1}, 30303, 30303).String()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,66 +11,57 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/simulations"
|
"github.com/ethereum/go-ethereum/p2p/simulations"
|
||||||
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
|
||||||
"github.com/ethereum/go-ethereum/swarm/network"
|
"github.com/ethereum/go-ethereum/swarm/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SimNode is the adapter used by Swarm simulations.
|
type simStore struct {
|
||||||
type SimNode struct {
|
|
||||||
id *adapters.NodeId
|
|
||||||
rw network.ReadWriter
|
|
||||||
hive *network.Hive
|
|
||||||
protocol *p2p.Protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
type simReadWriter struct {
|
|
||||||
m map[string][]byte
|
m map[string][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *simReadWriter) ReadAll(s string) ([]byte, error) {
|
func (self *simStore) Load(s string) ([]byte, error) {
|
||||||
return self.m[s], nil
|
return self.m[s], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *simReadWriter) WriteAll(s string, data []byte) error {
|
func (self *simStore) Save(s string, data []byte) error {
|
||||||
self.m[s] = data
|
self.m[s] = data
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSimReadWriter() *simReadWriter {
|
func NewSimStore() *simStore {
|
||||||
return &simReadWriter{
|
return &simStore{
|
||||||
make(map[string][]byte),
|
make(map[string][]byte),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SimNode) Protocols() []p2p.Protocol {
|
type Simulation struct {
|
||||||
return []p2p.Protocol{*s.protocol}
|
mtx sync.Mutex
|
||||||
|
stores map[discover.NodeID]*simStore
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SimNode) APIs() []rpc.API {
|
func NewSimulation() *Simulation {
|
||||||
return nil
|
return &Simulation{
|
||||||
|
stores: make(map[discover.NodeID]*simStore),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the hive update ticker for hive
|
func (s *Simulation) NewService(id *adapters.NodeId, snapshot []byte) node.Service {
|
||||||
func af() <-chan time.Time {
|
s.mtx.Lock()
|
||||||
return time.NewTicker(1 * time.Second).C
|
store, ok := s.stores[id.NodeID]
|
||||||
}
|
if !ok {
|
||||||
|
store = NewSimStore()
|
||||||
|
s.stores[id.NodeID] = store
|
||||||
|
}
|
||||||
|
s.mtx.Unlock()
|
||||||
|
|
||||||
// Start() starts up the hive
|
addr := network.NewAddrFromNodeId(id)
|
||||||
// makes SimNode implement node.Service
|
|
||||||
func (self *SimNode) Start(server *p2p.Server) error {
|
|
||||||
self.init()
|
|
||||||
return self.hive.Start(server, af, self.rw)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SimNode) init() {
|
|
||||||
addr := network.NewPeerAddrFromNodeId(self.id)
|
|
||||||
kp := network.NewKadParams()
|
kp := network.NewKadParams()
|
||||||
|
|
||||||
kp.MinProxBinSize = 2
|
kp.MinProxBinSize = 2
|
||||||
|
|
@ -80,42 +71,16 @@ func (self *SimNode) init() {
|
||||||
kp.RetryExponent = 2
|
kp.RetryExponent = 2
|
||||||
kp.RetryInterval = 1000000
|
kp.RetryInterval = 1000000
|
||||||
|
|
||||||
to := network.NewKademlia(addr.OverlayAddr(), kp) // overlay topology driver
|
|
||||||
hp := network.NewHiveParams()
|
hp := network.NewHiveParams()
|
||||||
hp.CallInterval = 5000
|
hp.KeepAliveInterval = 5 * time.Second
|
||||||
pp := network.NewHive(hp, to) // hive
|
config := &network.BzzConfig{
|
||||||
|
OverlayAddr: addr.Over(),
|
||||||
services := func(p network.Peer) error {
|
UnderlayAddr: addr.Under(),
|
||||||
dp := network.NewDiscovery(p, to)
|
KadParams: kp,
|
||||||
pp.Add(dp)
|
HiveParams: hp,
|
||||||
log.Trace(fmt.Sprintf("kademlia on %v", dp))
|
Store: store,
|
||||||
p.DisconnectHook(func(err error) {
|
|
||||||
pp.Remove(dp)
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return network.NewBzz(config)
|
||||||
ct := network.BzzCodeMap(network.DiscoveryMsgs...) // bzz protocol code map
|
|
||||||
nodeInfo := func() interface{} { return pp.String() }
|
|
||||||
self.hive = pp
|
|
||||||
self.protocol = network.Bzz(addr.OverlayAddr(), addr.UnderlayAddr(), ct, services, nil, nodeInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop() shuts down the hive
|
|
||||||
// makes SimNode implement node.Service
|
|
||||||
func (self *SimNode) Stop() error {
|
|
||||||
self.hive.Stop()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSimNode creates adapters for nodes in the simulation.
|
|
||||||
func NewSimNode(id *adapters.NodeId, snapshot []byte) node.Service {
|
|
||||||
s := &SimNode{
|
|
||||||
id: id,
|
|
||||||
rw: NewSimReadWriter(),
|
|
||||||
}
|
|
||||||
s.init()
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMockers() map[string]*simulations.MockerConfig {
|
func createMockers() map[string]*simulations.MockerConfig {
|
||||||
|
|
@ -171,7 +136,12 @@ func setupMocker(net *simulations.Network) []*adapters.NodeId {
|
||||||
} else {
|
} else {
|
||||||
peerId = ids[i-1]
|
peerId = ids[i-1]
|
||||||
}
|
}
|
||||||
if err := net.Connect(id, peerId); err != nil {
|
ch := make(chan network.OverlayAddr)
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
ch <- network.NewAddrFromNodeId(peerId)
|
||||||
|
}()
|
||||||
|
if err := net.GetNode(id).Node.(*adapters.SimNode).Service().(*network.Bzz).Hive.Register(ch); err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -243,10 +213,11 @@ func startStopMocker(net *simulations.Network) {
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
||||||
|
|
||||||
|
s := NewSimulation()
|
||||||
services := adapters.Services{
|
services := adapters.Services{
|
||||||
"overlay": NewSimNode,
|
"overlay": s.NewService,
|
||||||
}
|
}
|
||||||
adapters.RegisterServices(services)
|
adapters.RegisterServices(services)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue