mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
Merge branch 'swarm-network-rewrite' into stream-test-rpc-unsubscribe-deadlock
This commit is contained in:
commit
9075ffdba2
17 changed files with 775 additions and 96 deletions
|
|
@ -274,7 +274,7 @@ func (self *SimNode) Start(snapshots map[string][]byte) error {
|
||||||
for _, name := range self.config.Services {
|
for _, name := range self.config.Services {
|
||||||
if err := self.node.Register(newService(name)); err != nil {
|
if err := self.node.Register(newService(name)); err != nil {
|
||||||
regErr = err
|
regErr = err
|
||||||
return
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,10 @@ func (self *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error)
|
||||||
if conf.Reachable == nil {
|
if conf.Reachable == nil {
|
||||||
conf.Reachable = func(otherID discover.NodeID) bool {
|
conf.Reachable = func(otherID discover.NodeID) bool {
|
||||||
_, err := self.InitConn(conf.ID, otherID)
|
_, err := self.InitConn(conf.ID, otherID)
|
||||||
return err == nil
|
if err != nil && bytes.Compare(conf.ID.Bytes(), otherID.Bytes()) < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -448,9 +451,11 @@ func (self *Network) getConn(oneID, otherID discover.NodeID) *Conn {
|
||||||
// this is cheating as the simulation is used as an oracle and know about
|
// this is cheating as the simulation is used as an oracle and know about
|
||||||
// remote peers attempt to connect to a node which will then not initiate the connection
|
// remote peers attempt to connect to a node which will then not initiate the connection
|
||||||
func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
|
func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
|
||||||
|
log.Debug(fmt.Sprintf("InitConn(oneID: %v, otherID: %v)", oneID, otherID))
|
||||||
self.lock.Lock()
|
self.lock.Lock()
|
||||||
defer self.lock.Unlock()
|
defer self.lock.Unlock()
|
||||||
if oneID == otherID {
|
if oneID == otherID {
|
||||||
|
log.Trace(fmt.Sprintf("refusing to connect to self %v", oneID))
|
||||||
return nil, fmt.Errorf("refusing to connect to self %v", oneID)
|
return nil, fmt.Errorf("refusing to connect to self %v", oneID)
|
||||||
}
|
}
|
||||||
conn, err := self.getOrCreateConn(oneID, otherID)
|
conn, err := self.getOrCreateConn(oneID, otherID)
|
||||||
|
|
@ -458,15 +463,19 @@ func (self *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if time.Since(conn.initiated) < dialBanTimeout {
|
if time.Since(conn.initiated) < dialBanTimeout {
|
||||||
|
log.Trace(fmt.Sprintf("connection between %v and %v recently attempted", oneID, otherID))
|
||||||
return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
|
return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
|
||||||
}
|
}
|
||||||
if conn.Up {
|
if conn.Up {
|
||||||
|
log.Trace(fmt.Sprintf("%v and %v already connected", oneID, otherID))
|
||||||
return nil, fmt.Errorf("%v and %v already connected", oneID, otherID)
|
return nil, fmt.Errorf("%v and %v already connected", oneID, otherID)
|
||||||
}
|
}
|
||||||
err = conn.nodesUp()
|
err = conn.nodesUp()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Trace(fmt.Sprintf("nodes not up: %v", err))
|
||||||
return nil, fmt.Errorf("nodes not up: %v", err)
|
return nil, fmt.Errorf("nodes not up: %v", err)
|
||||||
}
|
}
|
||||||
|
log.Debug("InitConn - connection initiated")
|
||||||
conn.initiated = time.Now()
|
conn.initiated = time.Now()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -71,7 +70,7 @@ func NewHiveParams() *HiveParams {
|
||||||
Discovery: true,
|
Discovery: true,
|
||||||
PeersBroadcastSetSize: 3,
|
PeersBroadcastSetSize: 3,
|
||||||
MaxPeersPerRequest: 5,
|
MaxPeersPerRequest: 5,
|
||||||
KeepAliveInterval: 1000 * time.Millisecond,
|
KeepAliveInterval: 500 * time.Millisecond,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,10 +101,12 @@ func NewHive(params *HiveParams, overlay Overlay, store state.Store) *Hive {
|
||||||
// server is used to connect to a peer based on its NodeID or enode URL
|
// server is used to connect to a peer based on its NodeID or enode URL
|
||||||
// these are called on the p2p.Server which runs on the node
|
// these are called on the p2p.Server which runs on the node
|
||||||
func (h *Hive) Start(server *p2p.Server) error {
|
func (h *Hive) Start(server *p2p.Server) error {
|
||||||
log.Trace(fmt.Sprintf("%08x hive starting", h.BaseAddr()[:4]))
|
log.Info(fmt.Sprintf("%08x hive starting", h.BaseAddr()[:4]))
|
||||||
// if state store is specified, load peers to prepopulate the overlay address book
|
// if state store is specified, load peers to prepopulate the overlay address book
|
||||||
if h.Store != nil {
|
if h.Store != nil {
|
||||||
|
log.Info("detected an existing store. trying to load peers")
|
||||||
if err := h.loadPeers(); err != nil {
|
if err := h.loadPeers(); err != nil {
|
||||||
|
log.Error(fmt.Sprintf("%08x hive encoutered an error trying to load peers", h.BaseAddr()[:4]))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +124,12 @@ func (h *Hive) Stop() error {
|
||||||
log.Info(fmt.Sprintf("%08x hive stopping, saving peers", h.BaseAddr()[:4]))
|
log.Info(fmt.Sprintf("%08x hive stopping, saving peers", h.BaseAddr()[:4]))
|
||||||
h.ticker.Stop()
|
h.ticker.Stop()
|
||||||
if h.Store != nil {
|
if h.Store != nil {
|
||||||
return h.savePeers()
|
if err := h.savePeers(); err != nil {
|
||||||
|
return fmt.Errorf("could not save peers to persistence store: %v", err)
|
||||||
|
}
|
||||||
|
if err := h.Store.Close(); err != nil {
|
||||||
|
return fmt.Errorf("could not close file handle to persistence store: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Info(fmt.Sprintf("%08x hive stopped, dropping peers", h.BaseAddr()[:4]))
|
log.Info(fmt.Sprintf("%08x hive stopped, dropping peers", h.BaseAddr()[:4]))
|
||||||
h.EachConn(nil, 255, func(p OverlayConn, _ int, _ bool) bool {
|
h.EachConn(nil, 255, func(p OverlayConn, _ int, _ bool) bool {
|
||||||
|
|
@ -139,8 +145,9 @@ func (h *Hive) Stop() error {
|
||||||
// at each iteration, ask the overlay driver to suggest the most preferred peer to connect to
|
// at each iteration, ask the overlay driver to suggest the most preferred peer to connect to
|
||||||
// as well as advertises saturation depth if needed
|
// as well as advertises saturation depth if needed
|
||||||
func (h *Hive) connect() {
|
func (h *Hive) connect() {
|
||||||
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
|
|
||||||
for range h.ticker.C {
|
for range h.ticker.C {
|
||||||
|
log.Trace(fmt.Sprintf("%08x hive connect()", h.BaseAddr()[:4]))
|
||||||
|
|
||||||
addr, depth, changed := h.SuggestPeer()
|
addr, depth, changed := h.SuggestPeer()
|
||||||
if h.Discovery && changed {
|
if h.Discovery && changed {
|
||||||
NotifyDepth(uint8(depth), h)
|
NotifyDepth(uint8(depth), h)
|
||||||
|
|
@ -203,14 +210,16 @@ func ToAddr(pa OverlayPeer) *BzzAddr {
|
||||||
// loadPeers, savePeer implement persistence callback/
|
// loadPeers, savePeer implement persistence callback/
|
||||||
func (h *Hive) loadPeers() error {
|
func (h *Hive) loadPeers() error {
|
||||||
var as []*BzzAddr
|
var as []*BzzAddr
|
||||||
|
|
||||||
err := h.Store.Get("peers", &as)
|
err := h.Store.Get("peers", &as)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == state.ErrNotFound {
|
if err == state.ErrNotFound {
|
||||||
|
log.Info(fmt.Sprintf("hive %08x: no persisted peers found", h.BaseAddr()[:4]))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
log.Info(fmt.Sprintf("hive %08x: peers loaded", h.BaseAddr()[:4]))
|
||||||
|
|
||||||
return h.Register(toOverlayAddrs(as...))
|
return h.Register(toOverlayAddrs(as...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
|
||||||
"github.com/ethereum/go-ethereum/pot"
|
"github.com/ethereum/go-ethereum/pot"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -263,11 +263,14 @@ func (k *Kademlia) SuggestPeer() (a OverlayAddr, o int, want bool) {
|
||||||
if po >= depth {
|
if po >= depth {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
f(func(val pot.Val, _ int) bool {
|
ok := f(func(val pot.Val, _ int) bool {
|
||||||
a = k.callable(val)
|
a = k.callable(val)
|
||||||
return a == nil
|
return a == nil
|
||||||
})
|
})
|
||||||
return false
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
})
|
})
|
||||||
// found a candidate
|
// found a candidate
|
||||||
if a != nil {
|
if a != nil {
|
||||||
|
|
@ -616,16 +619,17 @@ type PeerPot struct {
|
||||||
EmptyBins []int
|
EmptyBins []int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPeerPot just creates a new pot record OverlayAddr
|
// NewPeerPotMap creates a map of pot record of OverlayAddr with keys
|
||||||
func NewPeerPot(kadMinProxSize int, ids []discover.NodeID, addrs [][]byte) map[discover.NodeID]*PeerPot {
|
// as hexadecimal representations of the address.
|
||||||
|
func NewPeerPotMap(kadMinProxSize int, addrs [][]byte) map[string]*PeerPot {
|
||||||
// create a table of all nodes for health check
|
// create a table of all nodes for health check
|
||||||
np := pot.NewPot(nil, 0)
|
np := pot.NewPot(nil, 0)
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
np, _, _ = pot.Add(np, addr, pof)
|
np, _, _ = pot.Add(np, addr, pof)
|
||||||
}
|
}
|
||||||
ppmap := make(map[discover.NodeID]*PeerPot)
|
ppmap := make(map[string]*PeerPot)
|
||||||
|
|
||||||
for i, id := range ids {
|
for i, a := range addrs {
|
||||||
pl := 256
|
pl := 256
|
||||||
prev := 256
|
prev := 256
|
||||||
var emptyBins []int
|
var emptyBins []int
|
||||||
|
|
@ -654,7 +658,7 @@ func NewPeerPot(kadMinProxSize int, ids []discover.NodeID, addrs [][]byte) map[d
|
||||||
emptyBins = append(emptyBins, j)
|
emptyBins = append(emptyBins, j)
|
||||||
}
|
}
|
||||||
log.Trace(fmt.Sprintf("%x NNS: %s", addrs[i][:4], logNNS(nns)))
|
log.Trace(fmt.Sprintf("%x NNS: %s", addrs[i][:4], logNNS(nns)))
|
||||||
ppmap[id] = &PeerPot{nns, emptyBins}
|
ppmap[common.Bytes2Hex(a)] = &PeerPot{nns, emptyBins}
|
||||||
}
|
}
|
||||||
return ppmap
|
return ppmap
|
||||||
}
|
}
|
||||||
|
|
@ -674,23 +678,38 @@ func (k *Kademlia) saturation(n int) int {
|
||||||
return prev
|
return prev
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// full returns true if all required bins have connected peers.
|
||||||
|
// It is used in Healthy function.
|
||||||
func (k *Kademlia) full(emptyBins []int) (full bool) {
|
func (k *Kademlia) full(emptyBins []int) (full bool) {
|
||||||
prev := 0
|
prev := 0
|
||||||
e := len(emptyBins)
|
e := len(emptyBins)
|
||||||
|
ok := true
|
||||||
|
depth := k.neighbourhoodDepth()
|
||||||
k.conns.EachBin(k.base, pof, 0, func(po, _ int, _ func(func(val pot.Val, i int) bool) bool) bool {
|
k.conns.EachBin(k.base, pof, 0, func(po, _ int, _ func(func(val pot.Val, i int) bool) bool) bool {
|
||||||
for i := prev; e > 0 && i < po; i++ {
|
if prev == depth+1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for i := prev; i < po; i++ {
|
||||||
e--
|
e--
|
||||||
|
if e < 0 {
|
||||||
|
ok = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
if emptyBins[e] != i {
|
if emptyBins[e] != i {
|
||||||
log.Trace(fmt.Sprintf("%08x po: %d, i: %d, e: %d, emptybins: %v", k.BaseAddr()[:4], po, i, e, logEmptyBins(emptyBins)))
|
log.Trace(fmt.Sprintf("%08x po: %d, i: %d, e: %d, emptybins: %v", k.BaseAddr()[:4], po, i, e, logEmptyBins(emptyBins)))
|
||||||
if emptyBins[e] < i {
|
if emptyBins[e] < i {
|
||||||
panic("incorrect peerpot")
|
panic("incorrect peerpot")
|
||||||
}
|
}
|
||||||
|
ok = false
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev = po + 1
|
prev = po + 1
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return e == 0
|
return e == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,13 @@
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/pot"
|
"github.com/ethereum/go-ethereum/pot"
|
||||||
)
|
)
|
||||||
|
|
@ -228,19 +230,18 @@ func TestSuggestPeerFindPeers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
k.Register("01000001")
|
k.Register("01000001")
|
||||||
err = testSuggestPeer(t, k, "<nil>", 0, false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
k.On("10000001")
|
|
||||||
log.Trace("Kad:\n%v", k.String())
|
|
||||||
err = testSuggestPeer(t, k, "01000001", 0, false)
|
err = testSuggestPeer(t, k, "01000001", 0, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err.Error())
|
t.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
k.On("10000001")
|
k.On("10000001")
|
||||||
|
log.Trace(fmt.Sprintf("Kad:\n%v", k.String()))
|
||||||
|
err = testSuggestPeer(t, k, "<nil>", 1, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
k.On("01000001")
|
k.On("01000001")
|
||||||
err = testSuggestPeer(t, k, "<nil>", 0, false)
|
err = testSuggestPeer(t, k, "<nil>", 0, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -283,7 +284,7 @@ func TestSuggestPeerFindPeers(t *testing.T) {
|
||||||
func TestSuggestPeerRetries(t *testing.T) {
|
func TestSuggestPeerRetries(t *testing.T) {
|
||||||
// 2 row gap, unsaturated proxbin, no callables -> want PO 0
|
// 2 row gap, unsaturated proxbin, no callables -> want PO 0
|
||||||
k := newTestKademlia("00000000")
|
k := newTestKademlia("00000000")
|
||||||
k.RetryInterval = int64(time.Second) // cycle
|
k.RetryInterval = int64(100 * time.Millisecond) // cycle
|
||||||
k.MaxRetries = 50
|
k.MaxRetries = 50
|
||||||
k.RetryExponent = 2
|
k.RetryExponent = 2
|
||||||
sleep := func(n int) {
|
sleep := func(n int) {
|
||||||
|
|
@ -405,3 +406,266 @@ func TestKademliaHiveString(t *testing.T) {
|
||||||
t.Fatalf("incorrect hive output. expected %v, got %v", expH, h)
|
t.Fatalf("incorrect hive output. expected %v, got %v", expH, h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testKademliaCase constructs the kademlia and PeerPot map to validate
|
||||||
|
// the SuggestPeer and Healthy methods for provided hex-encoded addresses.
|
||||||
|
// Argument pivotAddr is the address of the kademlia.
|
||||||
|
func testKademliaCase(t *testing.T, pivotAddr string, addrs ...string) {
|
||||||
|
addr := common.FromHex(pivotAddr)
|
||||||
|
addrs = append(addrs, pivotAddr)
|
||||||
|
|
||||||
|
k := NewKademlia(addr, NewKadParams())
|
||||||
|
|
||||||
|
as := make([][]byte, len(addrs))
|
||||||
|
for i, a := range addrs {
|
||||||
|
as[i] = common.FromHex(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range as {
|
||||||
|
if bytes.Equal(a, addr) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p := &BzzAddr{OAddr: a, UAddr: a}
|
||||||
|
if err := k.Register([]OverlayAddr{p}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ppmap := NewPeerPotMap(2, as)
|
||||||
|
|
||||||
|
pp := ppmap[pivotAddr]
|
||||||
|
|
||||||
|
for {
|
||||||
|
a, _, _ := k.SuggestPeer()
|
||||||
|
if a == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
k.On(&BzzPeer{BzzAddr: a.(*BzzAddr)})
|
||||||
|
}
|
||||||
|
|
||||||
|
h := k.Healthy(pp)
|
||||||
|
if !(h.GotNN && h.KnowNN && h.Full) {
|
||||||
|
t.Error("not healthy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The regression test for the following invalid kademlia edge case.
|
||||||
|
|
||||||
|
Addresses used in this test are discovered as part of the simulation network
|
||||||
|
in higher level tests for streaming. They were generated randomly.
|
||||||
|
|
||||||
|
=========================================================================
|
||||||
|
Mon Apr 9 12:18:24 UTC 2018 KΛÐΞMLIΛ hive: queen's address: 7efef1
|
||||||
|
population: 9 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
|
||||||
|
000 2 d7e5 ec56 | 18 ec56 (0) d7e5 (0) d9e0 (0) c735 (0)
|
||||||
|
001 2 18f1 3176 | 14 18f1 (0) 10bb (0) 10d1 (0) 0421 (0)
|
||||||
|
002 2 52aa 47cd | 11 52aa (0) 51d9 (0) 5161 (0) 5130 (0)
|
||||||
|
003 1 646e | 1 646e (0)
|
||||||
|
004 0 | 3 769c (0) 76d1 (0) 7656 (0)
|
||||||
|
============ DEPTH: 5 ==========================================
|
||||||
|
005 1 7a48 | 1 7a48 (0)
|
||||||
|
006 1 7cbd | 1 7cbd (0)
|
||||||
|
007 0 | 0
|
||||||
|
008 0 | 0
|
||||||
|
009 0 | 0
|
||||||
|
010 0 | 0
|
||||||
|
011 0 | 0
|
||||||
|
012 0 | 0
|
||||||
|
013 0 | 0
|
||||||
|
014 0 | 0
|
||||||
|
015 0 | 0
|
||||||
|
=========================================================================
|
||||||
|
*/
|
||||||
|
func TestKademliaCase1(t *testing.T) {
|
||||||
|
testKademliaCase(t,
|
||||||
|
"7efef1c41d77f843ad167be95f6660567eb8a4a59f39240000cce2e0d65baf8e",
|
||||||
|
"ec560e6a4806aa37f147ee83687f3cf044d9953e61eedb8c34b6d50d9e2c5623",
|
||||||
|
"646e9540c84f6a2f9cf6585d45a4c219573b4fd1b64a3c9a1386fc5cf98c0d4d",
|
||||||
|
"18f13c5fba653781019025ab10e8d2fdc916d6448729268afe9e928ffcdbb8e8",
|
||||||
|
"317617acf99b4ffddda8a736f8fc6c6ede0bf690bc23d834123823e6d03e2f69",
|
||||||
|
"d7e52d9647a5d1c27a68c3ee65d543be3947ae4b68537b236d71ef9cb15fb9ab",
|
||||||
|
"7a48f75f8ca60487ae42d6f92b785581b40b91f2da551ae73d5eae46640e02e8",
|
||||||
|
"7cbd42350bde8e18ae5b955b5450f8e2cef3419f92fbf5598160c60fd78619f0",
|
||||||
|
"52aa3ddec61f4d48dd505a2385403c634f6ad06ee1d99c5c90a5ba6006f9af9c",
|
||||||
|
"47cdb6fa93eeb8bc91a417ff4e3b14a9c2ea85137462e2f575fae97f0c4be60d",
|
||||||
|
"5161943eb42e2a03e715fe8afa1009ff5200060c870ead6ab103f63f26cb107f",
|
||||||
|
"a38eaa1255f76bf883ca0830c86e8c4bb7eed259a8348aae9b03f21f90105bee",
|
||||||
|
"b2522bdf1ab26f324e75424fdf6e493b47e8a27687fe76347607b344fc010075",
|
||||||
|
"5bd7213964efb2580b91d02ac31ef126838abeba342f5dbdbe8d4d03562671a2",
|
||||||
|
"0b531adb82744768b694d7f94f73d4f0c9de591266108daeb8c74066bfc9c9ca",
|
||||||
|
"28501f59f70e888d399570145ed884353e017443c675aa12731ada7c87ea14f7",
|
||||||
|
"4a45f1fc63e1a9cb9dfa44c98da2f3d20c2923e5d75ff60b2db9d1bdb0c54d51",
|
||||||
|
"b193431ee35cd32de95805e7c1c749450c47486595aae7195ea6b6019a64fd61",
|
||||||
|
"baebf36a1e35a7ed834e1c72faf44ba16c159fa47d3289ceb3ca35fefa8739b5",
|
||||||
|
"a3659bd32e05fa36c8d20dbaaed8362bf1a8a7bd116aed62d8a43a2efbdf513f",
|
||||||
|
"10d1b50881a4770ebebdd0a75589dabb931e6716747b0f65fd6b080b88c4fdb6",
|
||||||
|
"3c76b8ca5c7ce6a03320646826213f59229626bf5b9d25da0c3ec0662dcb8ff3",
|
||||||
|
"4d72a04ddeb851a68cd197ef9a92a3e2ff01fbbff638e64929dd1a9c2e150112",
|
||||||
|
"c7353d320987956075b5bc1668571c7a36c800d5598fdc4832ec6569561e15d1",
|
||||||
|
"d9e0c7c90878c20ab7639d5954756f54775404b3483407fe1b483635182734f6",
|
||||||
|
"8fca67216b7939c0824fb06c5279901a94da41da9482b000f56df9906736ee75",
|
||||||
|
"460719d7f7aa7d7438f0eaf30333484fa3bd0f233632c10ba89e6e46dd3604be",
|
||||||
|
"0421d92c8a1c79ed5d01305a3d25aaf22a8f5f9e3d4bc80da47ee16ce20465fe",
|
||||||
|
"3441d9d9c0f05820a1bb6459fc7d8ef266a1bd929e7db939a10f544efe8261ea",
|
||||||
|
"ab198a66c293586746758468c610e5d3914d4ce629147eff6dd55a31f863ff8f",
|
||||||
|
"3a1c8c16b0763f3d2c35269f454ff779d1255e954d2deaf6c040fb3f0bcdc945",
|
||||||
|
"5561c0ea3b203e173b11e6aa9d0e621a4e10b1d8b178b8fe375220806557b823",
|
||||||
|
"7656caccdc79cd8d7ce66d415cc96a718e8271c62fb35746bfc2b49faf3eebf3",
|
||||||
|
"5130594fd54c1652cf2debde2c4204573ed76555d1e26757fe345b409af1544a",
|
||||||
|
"76d1e83c71ca246d042e37ff1db181f2776265fbcfdc890ce230bfa617c9c2f0",
|
||||||
|
"89580231962624c53968c1b0095b4a2732b2a2640a19fdd7d21fd064fcc0a5ef",
|
||||||
|
"3d10d001fff44680c7417dd66ecf2e984f0baa20a9bbcea348583ba5ff210c4f",
|
||||||
|
"43754e323f0f3a1155b1852bd6edd55da86b8c4cfe3df8b33733fca50fc202b8",
|
||||||
|
"a9e7b1bb763ae6452ddcacd174993f82977d81a85206bb2ae3c842e2d8e19b4c",
|
||||||
|
"10bb07da7bc7c7757f74149eff167d528a94a253cdc694a863f4d50054c00b6d",
|
||||||
|
"28f0bc1b44658548d6e05dd16d4c2fe77f1da5d48b6774bc4263b045725d0c19",
|
||||||
|
"835fbbf1d16ba7347b6e2fc552d6e982148d29c624ea20383850df3c810fa8fc",
|
||||||
|
"8e236c56a77d7f46e41e80f7092b1a68cd8e92f6156365f41813ad1ca2c6b6f3",
|
||||||
|
"51d9c857e9238c49186e37b4eccf17a82de3d5739f026f6043798ab531456e73",
|
||||||
|
"bbddf7db6a682225301f36a9fd5b0d0121d2951753e1681295f3465352ad511f",
|
||||||
|
"2690a910c33ee37b91eb6c4e0731d1d345e2dc3b46d308503a6e85bbc242c69e",
|
||||||
|
"769ce86aa90b518b7ed382f9fdacfbed93574e18dc98fe6c342e4f9f409c2d5a",
|
||||||
|
"ba3bebec689ce51d3e12776c45f80d25164fdfb694a8122d908081aaa2e7122c",
|
||||||
|
"3a51f4146ea90a815d0d283d1ceb20b928d8b4d45875e892696986a3c0d8fb9b",
|
||||||
|
"81968a2d8fb39114342ee1da85254ec51e0608d7f0f6997c2a8354c260a71009",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The regression test for the following invalid kademlia edge case.
|
||||||
|
|
||||||
|
Addresses used in this test are discovered as part of the simulation network
|
||||||
|
in higher level tests for streaming. They were generated randomly.
|
||||||
|
|
||||||
|
=========================================================================
|
||||||
|
Mon Apr 9 18:43:48 UTC 2018 KΛÐΞMLIΛ hive: queen's address: bc7f3b
|
||||||
|
population: 9 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
|
||||||
|
000 2 0f49 67ff | 28 0f49 (0) 0211 (0) 07b2 (0) 0703 (0)
|
||||||
|
001 2 e84b f3a4 | 13 f3a4 (0) e84b (0) e58b (0) e60b (0)
|
||||||
|
002 1 8dba | 1 8dba (0)
|
||||||
|
003 2 a008 ad72 | 2 ad72 (0) a008 (0)
|
||||||
|
004 0 | 3 b61f (0) b27f (0) b027 (0)
|
||||||
|
============ DEPTH: 5 ==========================================
|
||||||
|
005 1 ba19 | 1 ba19 (0)
|
||||||
|
006 0 | 0
|
||||||
|
007 1 bdd6 | 1 bdd6 (0)
|
||||||
|
008 0 | 0
|
||||||
|
009 0 | 0
|
||||||
|
010 0 | 0
|
||||||
|
011 0 | 0
|
||||||
|
012 0 | 0
|
||||||
|
013 0 | 0
|
||||||
|
014 0 | 0
|
||||||
|
015 0 | 0
|
||||||
|
=========================================================================
|
||||||
|
*/
|
||||||
|
func TestKademliaCase2(t *testing.T) {
|
||||||
|
testKademliaCase(t,
|
||||||
|
"bc7f3b6a4a7e3c91b100ca6680b6c06ff407972b88956324ca853295893e0237", "67ffb61d3aa27449d277016188f35f19e2321fbda5008c68cf6303faa080534f", "600cd54c842eadac1729c04abfc369bc244572ca76117105b9dd910283b82730", "d955a05409650de151218557425105a8aa2867bb6a0e0462fa1cf90abcf87ad6", "7a6b726de45abdf7bb3e5fd9fb0dc8932270ca4dedef92238c80c05bcdb570e3", "263e99424ebfdb652adb4e3dcd27d59e11bb7ae1c057b3ef6f390d0228006254", "ba195d1a53aafde68e661c64d39db8c2a73505bf336125c15c3560de3b48b7ed", "3458c762169937115f67cabc35a6c384ed70293a8aec37b077a6c1b8e02d510e", "4ef4dc2e28ac6efdba57e134ac24dd4e0be68b9d54f7006515eb9509105f700c", "2a8782b79b0c24b9714dfd2c8ff1932bebc08aa6520b4eaeaa59ff781238890c", "625d02e960506f4524e9cdeac85b33faf3ea437fceadbd478b62b78720cf24fc", "e051a36a8c8637f520ba259c9ed3fadaf740dadc6a04c3f0e21778ebd4cd6ac4", "e34bc014fa2504f707bb3d904872b56c2fa250bee3cb19a147a0418541f1bd90", "28036dc79add95799916893890add5d8972f3b95325a509d6ded3d448f4dc652", "1b013c407794fa2e4c955d8f51cbc6bd78588a174b6548246b291281304b5409", "34f71b68698e1534095ff23ee9c35bf64c7f12b8463e7c6f6b19c25cf03928b4", "c712c6e9bbb7076832972a95890e340b94ed735935c3c0bb788e61f011b59479", "a008d5becdcda4b9dbfdaafc3cec586cf61dcf2d4b713b6168fff02e3b9f0b08", "29de15555cdbebaab214009e416ee92f947dcec5dab9894129f50f1b17138f34", "5df9449f700bd4b5a23688b68b293f2e92fa6ca524c93bc6bb9936efba9d9ada", "3ab0168a5f87fedc6a39b53c628256ac87a98670d8691bbdaaecec22418d13a2", "1ee299b2d2a74a568494130e6869e66d57982d345c482a0e0eeb285ac219ae3b", "e0e0e3b860cea9b7a74cf1b0675cc632dc64e80a02f20bbc5e96e2e8bb670606", "dc1ba6f169b0fcdcca021dcebaf39fe5d4875e7e69b854fad65687c1d7719ec0", "d321f73e42fcfb1d3a303eddf018ca5dffdcfd5567cd5ec1212f045f6a07e47d", "070320c3da7b542e5ca8aaf6a0a53d2bb5113ed264ab1db2dceee17c729edcb1", "17d314d65fdd136b50d182d2c8f5edf16e7838c2be8cf2c00abe4b406dbcd1d8", "e60b99e0a06f7d2d99d84085f67cdf8cc22a9ae22c339365d80f90289834a2b4", "02115771e18932e1f67a45f11f5bf743c5dae97fbc477d34d35c996012420eac", "3102a40eb2e5060353dd19bf61eeec8782dd1bebfcb57f4c796912252b591827", "8dbaf231062f2dc7ddaba5f9c7761b0c21292be51bf8c2ef503f31d4a2f63f79", "b02787b713c83a9f9183216310f04251994e04c2763a9024731562e8978e7cc4", "b27fe6cd33989e10909ce794c4b0b88feae286b614a59d49a3444c1a7b51ea82", "07b2d2c94fdc6fd148fe23be2ed9eff54f5e12548f29ed8416e6860fc894466f", "e58bf9f451ef62ac44ff0a9bb0610ec0fd14d423235954f0d3695e83017cbfc4", "bdd600b91bb79d1ee0053b854de308cfaa7e2abce575ea6815a0a7b3449609c2", "0f49c93c1edc7999920b21977cedd51a763940dac32e319feb9c1df2da0f3071", "7cbf0297cd41acf655cd6f960d7aaf61479edb4189d5c001cbc730861f0deb41", "79265193778d87ad626a5f59397bc075872d7302a12634ce2451a767d0a82da2", "2fe7d705f7c370b9243dbaafe007d555ff58d218822fca49d347b12a0282457c", "e84bc0c83d05e55a0080eed41dda5a795da4b9313a4da697142e69a65834cbb3", "cc4d278bd9aa0e9fb3cd8d2e0d68fb791aab5de4b120b845c409effbed47a180", "1a2317a8646cd4b6d3c4aa4cc25f676533abb689cf180787db216880a1239ad8", "cbafd6568cf8e99076208e6b6843f5808a7087897c67aad0c54694669398f889", "7b7c8357255fc37b4dae0e1af61589035fd39ff627e0938c6b3da8b4e4ec5d23", "2b8d782c1f5bac46c922cf439f6aa79f91e9ba5ffc0020d58455188a2075b334", "b61f45af2306705740742e76197a119235584ced01ef3f7cf3d4370f6c557cd1", "2775612e7cdae2780bf494c370bdcbe69c55e4a1363b1dc79ea0135e61221cce", "f3a49bb22f40885e961299abfa697a7df690a79f067bf3a4847a3ad48d826c9f", "ad724ac218dc133c0aadf4618eae21fdd0c2f3787af279846b49e2b4f97ff167",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The regression test for the following invalid kademlia edge case.
|
||||||
|
|
||||||
|
Addresses used in this test are discovered as part of the simulation network
|
||||||
|
in higher level tests for streaming. They were generated randomly.
|
||||||
|
|
||||||
|
=========================================================================
|
||||||
|
Mon Apr 9 19:04:35 UTC 2018 KΛÐΞMLIΛ hive: queen's address: b4822e
|
||||||
|
population: 8 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
|
||||||
|
000 2 786c 774b | 29 774b (0) 786c (0) 7a79 (0) 7d2f (0)
|
||||||
|
001 2 d9de cf19 | 10 cf19 (0) d9de (0) d2ff (0) d2a2 (0)
|
||||||
|
002 2 8ca1 8d74 | 5 8d74 (0) 8ca1 (0) 9793 (0) 9f51 (0)
|
||||||
|
003 0 | 0
|
||||||
|
004 0 | 3 bfac (0) bcbb (0) bde9 (0)
|
||||||
|
005 0 | 0
|
||||||
|
============ DEPTH: 6 ==========================================
|
||||||
|
006 1 b660 | 1 b660 (0)
|
||||||
|
007 0 | 0
|
||||||
|
008 1 b450 | 1 b450 (0)
|
||||||
|
009 0 | 0
|
||||||
|
010 0 | 0
|
||||||
|
011 0 | 0
|
||||||
|
012 0 | 0
|
||||||
|
013 0 | 0
|
||||||
|
014 0 | 0
|
||||||
|
015 0 | 0
|
||||||
|
=========================================================================
|
||||||
|
*/
|
||||||
|
func TestKademliaCase3(t *testing.T) {
|
||||||
|
testKademliaCase(t,
|
||||||
|
"b4822e874a01b94ac3a35c821e6db131e785c2fcbb3556e84b36102caf09b091", "2ecf54ea38d58f9cfc3862e54e5854a7c506fbc640e0b38e46d7d45a19794999", "442374092be50fc7392e8dd3f6fab3158ff7f14f26ff98060aed9b2eecf0b97d", "b450a4a67fcfa3b976cf023d8f1f15052b727f712198ce901630efe2f95db191", "9a7291638eb1c989a6dd6661a42c735b23ac6605b5d3e428aa5ffe650e892c85", "67f62eeab9804cfcac02b25ebeab9113d1b9d03dd5200b1c5a324cc0163e722f", "2e4a0e4b53bca4a9d7e2734150e9f579f29a255ade18a268461b20d026c9ee90", "30dd79c5fcdaa1b106f6960c45c9fde7c046aa3d931088d98c52ab759d0b2ac4", "97936fb5a581e59753c54fa5feec493714f2218245f61f97a62eafd4699433e4", "3a2899b6e129e3e193f6e2aefb82589c948c246d2ec1d4272af32ef3b2660f44", "f0e2a8aa88e67269e9952431ef12e5b29b7f41a1871fbfc38567fad95655d607", "7fa12b3f3c5f8383bfc644b958f72a486969733fa097d8952b3eb4f7b4f73192", "360c167aad5fc992656d6010ec45fdce5bcd492ad9608bc515e2be70d4e430c1", "fe21bc969b3d8e5a64a6484a829c1e04208f26f3cd4de6afcbc172a5bd17f1f1", "b660a1f40141d7ccd282fe5bd9838744119bd1cb3780498b5173578cc5ad308f", "44dcb3370e76680e2fba8cd986ad45ff0b77ca45680ee8d950e47922c4af6226", "8ca126923d17fccb689647307b89f38aa14e2a7b9ebcf3c1e31ccf3d2291a3bc", "f0ae19ae9ce6329327cbf42baf090e084c196b0877d8c7b69997e0123be23ef8", "d2a2a217385158e3e1e348883a14bc423e57daa12077e8c49797d16121ea0810", "f5467ccd85bb4ebe768527db520a210459969a5f1fae6e07b43f519799f0b224", "68be5fd9f9d142a5099e3609011fe3bab7bb992c595999e31e0b3d1668dfb3cf", "4d49a8a476e4934afc6b5c36db9bece3ed1804f20b952da5a21b2b0de766aa73", "ea7155745ef3fb2d099513887a2ba279333ced65c65facbd890ce58bd3fce772", "cf19f51f4e848053d289ac95a9138cdd23fc3077ae913cd58cda8cc7a521b2e1", "590b1cd41c7e6144e76b5cd515a3a4d0a4317624620a3f1685f43ae68bdcd890", "d2ffe0626b5f94a7e00fa0b506e7455a3d9399c15800db108d5e715ef5f6e346", "69630878c50a91f6c2edd23a706bfa0b50bd5661672a37d67bab38e6bca3b698", "445e9067079899bb5faafaca915ae6c0f6b1b730a5a628835dd827636f7feb1e", "6461c77491f1c4825958949f23c153e6e1759a5be53abbcee17c9da3867f3141", "23a235f4083771ccc207771daceda700b525a59ab586788d4f6892e69e34a6e2", "bde99f79ef41a81607ddcf92b9f95dcbc6c3537e91e8bf740e193dc73b19485e", "177957c0e5f0fbd12b88022a91768095d193830986caec8d888097d3ff4310b8", "bcbbdbaa4cdf8352422072f332e05111b732354a35c4d7c617ce1fc3b8b42a5a", "774b6717fdfb0d1629fb9d4c04a9ca40079ae2955d7f82e897477055ed017abb", "16443bf625be6d39ecaa6f114e5d2c1d47a64bfd3c13808d94b55b6b6acef2ee", "8d7495d9008066505ed00ce8198af82bfa5a6b4c08768b4c9fb3aa4eb0b0cca2", "15800849a53349508cb382959527f6c3cf1a46158ff1e6e2316b7dea7967e35f", "7a792f0f4a2b731781d1b244b2a57947f1a2e32900a1c0793449f9f7ae18a7b7", "5e517c2832c9deaa7df77c7bad4d20fd6eda2b7815e155e68bc48238fac1416f", "9f51a14f0019c72bd1d472706d8c80a18c1873c6a0663e754b60eae8094483d7", "7d2fabb565122521d22ba99fed9e5be6a458fbc93156d54db27d97a00b8c3a97", "786c9e412a7db4ec278891fa534caa9a1d1a028c631c6f3aeb9c4d96ad895c36", "3bd6341d40641c2632a5a0cd7a63553a04e251efd7195897a1d27e02a7a8bfde", "31efd1f5fb57b8cff0318d77a1a9e8d67e1d1c8d18ce90f99c3a240dff48cdc8", "d9de3e1156ce1380150948acbcfecd99c96e7f4b0bc97745f4681593d017f74f", "427a2201e09f9583cd990c03b81b58148c297d474a3b50f498d83b1c7a9414cd", "bfaca11596d3dec406a9fcf5d97536516dfe7f0e3b12078428a7e1700e25218a", "351c4770a097248a650008152d0cab5825d048bef770da7f3364f59d1e721bc0", "ee00f205d1486b2be7381d962bd2867263758e880529e4e2bfedfa613bbc0e71", "6aa3b6418d89e3348e4859c823ef4d6d7cd46aa7f7e77aba586c4214d760d8f8",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The regression test for the following invalid kademlia edge case.
|
||||||
|
|
||||||
|
Addresses used in this test are discovered as part of the simulation network
|
||||||
|
in higher level tests for streaming. They were generated randomly.
|
||||||
|
|
||||||
|
=========================================================================
|
||||||
|
Mon Apr 9 19:16:25 UTC 2018 KΛÐΞMLIΛ hive: queen's address: 9a90fe
|
||||||
|
population: 8 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
|
||||||
|
000 2 72ef 4e6c | 24 0b1e (0) 0d66 (0) 17f5 (0) 17e8 (0)
|
||||||
|
001 2 fc2b fa47 | 13 fa47 (0) fc2b (0) fffd (0) ecef (0)
|
||||||
|
002 2 b847 afa8 | 6 afa8 (0) ad77 (0) bb7c (0) b847 (0)
|
||||||
|
003 0 | 0
|
||||||
|
004 0 | 4 91fc (0) 957d (0) 9482 (0) 949a (0)
|
||||||
|
============ DEPTH: 5 ==========================================
|
||||||
|
005 1 9ccf | 1 9ccf (0)
|
||||||
|
006 0 | 0
|
||||||
|
007 1 9bb2 | 1 9bb2 (0)
|
||||||
|
008 0 | 0
|
||||||
|
009 0 | 0
|
||||||
|
010 0 | 0
|
||||||
|
011 0 | 0
|
||||||
|
012 0 | 0
|
||||||
|
013 0 | 0
|
||||||
|
014 0 | 0
|
||||||
|
015 0 | 0
|
||||||
|
=========================================================================
|
||||||
|
*/
|
||||||
|
func TestKademliaCase4(t *testing.T) {
|
||||||
|
testKademliaCase(t,
|
||||||
|
"9a90fe3506277244549064b8c3276abb06284a199d9063a97331947f2b7da7f4",
|
||||||
|
"c19359eddef24b7be1a833b4475f212cd944263627a53f9ef4837d106c247730", "fc2b6fef99ef947f7e57c3df376891769e2a2fd83d2b8e634e0fc1e91eaa080c", "ecefc0e1a8ea7bb4b48c469e077401fce175dd75294255b96c4e54f6a2950a55", "bb7ce598efc056bba343cc2614aa3f67a575557561290b44c73a63f8f433f9f7", "55fbee6ca52dfd7f0be0db969ee8e524b654ab4f0cce7c05d83887d7d2a15460", "afa852b6b319998c6a283cc0c82d2f5b8e9410075d7700f3012761f1cfbd0f76", "36c370cfb63f2087971ba6e58d7585b04e16b8f0da335efb91554c2dd8fe191c", "6be41e029985edebc901fb77fc4fb65516b6d85086e2a98bfa3159c99391e585", "dd3cfc72ea553e7d2b28f0037a65646b30955b929d29ba4c40f4a2a811248e77", "da3a8f18e09c7b0ca235c4e33e1441a5188f1df023138bf207753ee63e768f7d", "de9e3ab4dc572d54a2d4b878329fd832bb51a149f4ce167316eeb177b61e7e01", "4e6c1ecde6ed917706257fe020a1d02d2e9d87fca4c85f0f7b132491008c5032", "72ef04b77a070e13463b3529dd312bcacfb7a12d20dc597f5ec3de0501e9b834", "3fef57186675d524ab8bb1f54ba8cb68610babca1247c0c46dbb60aed003c69d", "1d8e6b71f7a052865d6558d4ba44ad5fab7b908cc1badf5766822e1c20d0d823", "6be2f2b4ffa173014d4ec7df157d289744a2bda54bb876b264ccfa898a0da315", "b0ba3fff8643f9985c744327b0c4c869763509fd5da2de9a80a4a0a082021255", "9ccf40b9406ba2e6567101fb9b4e5334a9ec74263eff47267da266ba45e6c158", "d7347f02c180a448e60f73931845062ce00048750b584790278e9c93ef31ad81", "b68c6359a22b3bee6fecb8804311cfd816648ea31d530c9fb48e477e029d707a", "0d668a18ad7c2820214df6df95a6c855ce19fb1cb765f8ca620e45db76686d37", "3fbd2663bff65533246f1fabb9f38086854c6218aeb3dc9ac6ac73d4f0988f91", "949aa5719ca846052bfaa1b38c97b6eca3df3e24c0e0630042c6bccafbb4cdb5", "77b8a2b917bef5d54f3792183b014cca7798f713ff14fe0b2ac79b4c9f6f996d", "17e853cbd8dc00cba3cd9ffeb36f26a9f41a0eb92f80b62c2cda16771c935388", "5f682ed7a8cf2f98387c3def7c97f9f05ae39e39d393eeca3cf621268d6347f8", "ad77487eaf11fd8084ba4517a51766eb0e5b77dd3492dfa79aa3a2802fb29d20", "d247cfcacf9a8200ebaddf639f8c926ab0a001abe682f40df3785e80ed124e91", "195589442e11907eede1ee6524157f1125f68399f3170c835ff81c603b069f6c", "5b5ca0a67f3c54e7d3a6a862ef56168ec9ed1f4945e6c24de6d336b2be2e6f8c", "56430e4caa253015f1f998dce4a48a88af1953f68e94eca14f53074ae9c3e467", "0b1eed6a5bf612d1d8e08f5c546f3d12e838568fd3aa43ed4c537f10c65545d6", "7058db19a56dfff01988ac4a62e1310597f9c8d7ebde6890dadabf047d722d39", "b847380d6888ff7cd11402d086b19eccc40950b52c9d67e73cb4f8462f5df078", "df6c048419a2290ab546d527e9eeba349e7f7e1759bafe4adac507ce60ef9670", "91fc5b4b24fc3fbfea7f9a3d0f0437cb5733c0c2345d8bdffd7048d6e3b8a37b", "957d8ea51b37523952b6f5ae95462fcd4aed1483ef32cc80b69580aaeee03606", "efa82e4e91ad9ab781977400e9ac0bb9de7389aaedebdae979b73d1d3b8d72b0", "7400c9f3f3fc0cc6fe8cc37ab24b9771f44e9f78be913f73cd35fc4be030d6bd", "9bb28f4122d61f7bb56fe27ef706159fb802fef0f5de9dfa32c9c5b3183235f1", "40a8de6e98953498b806614532ea4abf8b99ad7f9719fb68203a6eae2efa5b2a", "412de0b218b8f7dcacc9205cd16ffb4eca5b838f46a2f4f9f534026061a47308", "17f56ecad51075080680ad9faa0fd8946b824d3296ddb20be07f9809fe8d1c5a", "fffd4e7ae885a41948a342b6647955a7ec8a8039039f510cff467ef597675457", "35e78e11b5ac46a29dd04ab0043136c3291f4ca56cb949ace33111ed56395463", "94824fc80230af82077c83bfc01dc9675b1f9d3d538b1e5f41c21ac753598691", "fa470ae314ca3fce493f21b423eef2a49522e09126f6f2326fa3c9cac0b344f7", "7078860b5b621b21ac7b95f9fc4739c8235ce5066a8b9bd7d938146a34fa88ec", "eea53560f0428bfd2eca4f86a5ce9dec5ff1309129a975d73465c1c9e9da71d1",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The regression test for the following invalid kademlia edge case.
|
||||||
|
|
||||||
|
Addresses used in this test are discovered as part of the simulation network
|
||||||
|
in higher level tests for streaming. They were generated randomly.
|
||||||
|
|
||||||
|
=========================================================================
|
||||||
|
Mon Apr 9 19:25:18 UTC 2018 KΛÐΞMLIΛ hive: queen's address: 5dd5c7
|
||||||
|
population: 13 (49), MinProxBinSize: 2, MinBinSize: 2, MaxBinSize: 4
|
||||||
|
000 2 e528 fad0 | 22 fad0 (0) e528 (0) e3bb (0) ed13 (0)
|
||||||
|
001 3 3f30 18e0 1dd3 | 7 3f30 (0) 23db (0) 10b6 (0) 18e0 (0)
|
||||||
|
002 4 7c54 7804 61e4 60f9 | 10 61e4 (0) 60f9 (0) 636c (0) 7186 (0)
|
||||||
|
003 2 40ae 4bae | 5 4bae (0) 4d5c (0) 403a (0) 40ae (0)
|
||||||
|
004 0 | 0
|
||||||
|
005 0 | 3 5808 (0) 5a0e (0) 5bdb (0)
|
||||||
|
============ DEPTH: 6 ==========================================
|
||||||
|
006 2 5f14 5f61 | 2 5f14 (0) 5f61 (0)
|
||||||
|
007 0 | 0
|
||||||
|
008 0 | 0
|
||||||
|
009 0 | 0
|
||||||
|
010 0 | 0
|
||||||
|
011 0 | 0
|
||||||
|
012 0 | 0
|
||||||
|
013 0 | 0
|
||||||
|
014 0 | 0
|
||||||
|
015 0 | 0
|
||||||
|
=========================================================================
|
||||||
|
*/
|
||||||
|
func TestKademliaCase5(t *testing.T) {
|
||||||
|
testKademliaCase(t,
|
||||||
|
"5dd5c77dd9006a800478fcebb02d48d4036389e7d3c8f6a83b97dbad13f4c0a9",
|
||||||
|
"78fafa0809929a1279ece089a51d12457c2d8416dff859aeb2ccc24bb50df5ec", "1dd39b1257e745f147cbbc3cadd609ccd6207c41056dbc4254bba5d2527d3ee5", "5f61dd66d4d94aec8fcc3ce0e7885c7edf30c43143fa730e2841c5d28e3cd081", "8aa8b0472cb351d967e575ad05c4b9f393e76c4b01ef4b3a54aac5283b78abc9", "4502f385152a915b438a6726ce3ea9342e7a6db91a23c2f6bee83a885ed7eb82", "718677a504249db47525e959ef1784bed167e1c46f1e0275b9c7b588e28a3758", "7c54c6ed1f8376323896ed3a4e048866410de189e9599dd89bf312ca4adb96b5", "18e03bd3378126c09e799a497150da5c24c895aedc84b6f0dbae41fc4bac081a", "23db76ac9e6e58d9f5395ca78252513a7b4118b4155f8462d3d5eec62486cadc", "40ae0e8f065e96c7adb7fa39505136401f01780481e678d718b7f6dbb2c906ec", "c1539998b8bae19d339d6bbb691f4e9daeb0e86847545229e80fe0dffe716e92", "ed139d73a2699e205574c08722ca9f030ad2d866c662f1112a276b91421c3cb9", "5bdb19584b7a36d09ca689422ef7e6bb681b8f2558a6b2177a8f7c812f631022", "636c9de7fe234ffc15d67a504c69702c719f626c17461d3f2918e924cd9d69e2", "de4455413ff9335c440d52458c6544191bd58a16d85f700c1de53b62773064ea", "de1963310849527acabc7885b6e345a56406a8f23e35e436b6d9725e69a79a83", "a80a50a467f561210a114cba6c7fb1489ed43a14d61a9edd70e2eb15c31f074d", "7804f12b8d8e6e4b375b242058242068a3809385e05df0e64973cde805cf729c", "60f9aa320c02c6f2e6370aa740cf7cea38083fa95fca8c99552cda52935c1520", "d8da963602390f6c002c00ce62a84b514edfce9ebde035b277a957264bb54d21", "8463d93256e026fe436abad44697152b9a56ac8e06a0583d318e9571b83d073c", "9a3f78fcefb9a05e40a23de55f6153d7a8b9d973ede43a380bf46bb3b3847de1", "e3bb576f4b3760b9ca6bff59326f4ebfc4a669d263fb7d67ab9797adea54ed13", "4d5cdbd6dcca5bdf819a0fe8d175dc55cc96f088d37462acd5ea14bc6296bdbe", "5a0ed28de7b5258c727cb85447071c74c00a5fbba9e6bc0393bc51944d04ab2a", "61e4ddb479c283c638f4edec24353b6cc7a3a13b930824aad016b0996ca93c47", "7e3610868acf714836cafaaa7b8c009a9ac6e3a6d443e5586cf661530a204ee2", "d74b244d4345d2c86e30a097105e4fb133d53c578320285132a952cdaa64416e", "cfeed57d0f935bfab89e3f630a7c97e0b1605f0724d85a008bbfb92cb47863a8", "580837af95055670e20d494978f60c7f1458dc4b9e389fc7aa4982b2aca3bce3", "df55c0c49e6c8a83d82dfa1c307d3bf6a20e18721c80d8ec4f1f68dc0a137ced", "5f149c51ce581ba32a285439a806c063ced01ccd4211cd024e6a615b8f216f95", "1eb76b00aeb127b10dd1b7cd4c3edeb4d812b5a658f0feb13e85c4d2b7c6fe06", "7a56ba7c3fb7cbfb5561a46a75d95d7722096b45771ec16e6fa7bbfab0b35dfe", "4bae85ad88c28470f0015246d530adc0cd1778bdd5145c3c6b538ee50c4e04bd", "afd1892e2a7145c99ec0ebe9ded0d3fec21089b277a68d47f45961ec5e39e7e0", "953138885d7b36b0ef79e46030f8e61fd7037fbe5ce9e0a94d728e8c8d7eab86", "de761613ef305e4f628cb6bf97d7b7dc69a9d513dc233630792de97bcda777a6", "3f3087280063d09504c084bbf7fdf984347a72b50d097fd5b086ffabb5b3fb4c", "7d18a94bb1ebfdef4d3e454d2db8cb772f30ca57920dd1e402184a9e598581a0", "a7d6fbdc9126d9f10d10617f49fb9f5474ffe1b229f76b7dd27cebba30eccb5d", "fad0246303618353d1387ec10c09ee991eb6180697ed3470ed9a6b377695203d", "1cf66e09ea51ee5c23df26615a9e7420be2ac8063f28f60a3bc86020e94fe6f3", "8269cdaa153da7c358b0b940791af74d7c651cd4d3f5ed13acfe6d0f2c539e7f", "90d52eaaa60e74bf1c79106113f2599471a902d7b1c39ac1f55b20604f453c09", "9788fd0c09190a3f3d0541f68073a2f44c2fcc45bb97558a7c319f36c25a75b3", "10b68fc44157ecfdae238ee6c1ce0333f906ad04d1a4cb1505c8e35c3c87fbb0", "e5284117fdf3757920475c786e0004cb00ba0932163659a89b36651a01e57394", "403ad51d911e113dcd5f9ff58c94f6d278886a2a4da64c3ceca2083282c92de3",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,13 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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"
|
||||||
|
|
@ -20,6 +23,7 @@ import (
|
||||||
"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/swarm/network"
|
"github.com/ethereum/go-ethereum/swarm/network"
|
||||||
|
"github.com/ethereum/go-ethereum/swarm/state"
|
||||||
colorable "github.com/mattn/go-colorable"
|
colorable "github.com/mattn/go-colorable"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -27,13 +31,46 @@ import (
|
||||||
// service to execute
|
// service to execute
|
||||||
const serviceName = "discovery"
|
const serviceName = "discovery"
|
||||||
const testMinProxBinSize = 2
|
const testMinProxBinSize = 2
|
||||||
|
const discoveryPersistenceDatadir = "discovery_persistence_test_store"
|
||||||
|
|
||||||
|
var discoveryPersistencePath = path.Join(os.TempDir(), discoveryPersistenceDatadir)
|
||||||
|
var discoveryEnabled = true
|
||||||
|
var persistenceEnabled = false
|
||||||
|
|
||||||
var services = adapters.Services{
|
var services = adapters.Services{
|
||||||
serviceName: newService,
|
serviceName: newService,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cleanDbStores() error {
|
||||||
|
entries, err := ioutil.ReadDir(os.TempDir())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range entries {
|
||||||
|
if strings.HasPrefix(f.Name(), discoveryPersistenceDatadir) {
|
||||||
|
os.RemoveAll(path.Join(os.TempDir(), f.Name()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDbStore(nodeID string) (*state.DBStore, error) {
|
||||||
|
if _, err := os.Stat(discoveryPersistencePath + "_" + nodeID); os.IsNotExist(err) {
|
||||||
|
log.Info(fmt.Sprintf("directory for nodeID %s does not exist. creating...", nodeID))
|
||||||
|
ioutil.TempDir("", discoveryPersistencePath+"_"+nodeID)
|
||||||
|
}
|
||||||
|
log.Info(fmt.Sprintf("opening storage directory for nodeID %s", nodeID))
|
||||||
|
store, err := state.NewDBStore(discoveryPersistencePath + "_" + nodeID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return store, nil
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
nodeCount = flag.Int("nodes", 16, "number of nodes to create (default 10)")
|
nodeCount = flag.Int("nodes", 10, "number of nodes to create (default 10)")
|
||||||
initCount = flag.Int("conns", 1, "number of originally connected peers (default 1)")
|
initCount = flag.Int("conns", 1, "number of originally connected peers (default 1)")
|
||||||
snapshotFile = flag.String("snapshot", "", "create snapshot")
|
snapshotFile = flag.String("snapshot", "", "create snapshot")
|
||||||
loglevel = flag.Int("loglevel", 3, "verbosity of logs")
|
loglevel = flag.Int("loglevel", 3, "verbosity of logs")
|
||||||
|
|
@ -109,6 +146,14 @@ func TestDiscoverySimulationSimAdapter(t *testing.T) {
|
||||||
testDiscoverySimulationSimAdapter(t, *nodeCount, *initCount)
|
testDiscoverySimulationSimAdapter(t, *nodeCount, *initCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDiscoveryPersistenceSimulationSimAdapter(t *testing.T) {
|
||||||
|
testDiscoveryPersistenceSimulationSimAdapter(t, *nodeCount, *initCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDiscoveryPersistenceSimulationSimAdapter(t *testing.T, nodes, conns int) {
|
||||||
|
testDiscoveryPersistenceSimulation(t, nodes, conns, adapters.NewSimAdapter(services))
|
||||||
|
}
|
||||||
|
|
||||||
func testDiscoverySimulationSimAdapter(t *testing.T, nodes, conns int) {
|
func testDiscoverySimulationSimAdapter(t *testing.T, nodes, conns int) {
|
||||||
testDiscoverySimulation(t, nodes, conns, adapters.NewSimAdapter(services))
|
testDiscoverySimulation(t, nodes, conns, adapters.NewSimAdapter(services))
|
||||||
}
|
}
|
||||||
|
|
@ -144,6 +189,26 @@ func testDiscoverySimulation(t *testing.T, nodes, conns int, adapter adapters.No
|
||||||
t.Logf("Setup: %s, shutdown: %s", result.StartedAt.Sub(startedAt), finishedAt.Sub(result.FinishedAt))
|
t.Logf("Setup: %s, shutdown: %s", result.StartedAt.Sub(startedAt), finishedAt.Sub(result.FinishedAt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testDiscoveryPersistenceSimulation(t *testing.T, nodes, conns int, adapter adapters.NodeAdapter) map[int][]byte {
|
||||||
|
persistenceEnabled = true
|
||||||
|
discoveryEnabled = true
|
||||||
|
|
||||||
|
result, err := discoveryPersistenceSimulation(nodes, conns, adapter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Setting up simulation failed: %v", err)
|
||||||
|
}
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Fatalf("Simulation failed: %s", result.Error)
|
||||||
|
}
|
||||||
|
t.Logf("Simulation with %d nodes passed in %s", nodes, result.FinishedAt.Sub(result.StartedAt))
|
||||||
|
// set the discovery and persistence flags again to default so other
|
||||||
|
// tests will not be affected
|
||||||
|
discoveryEnabled = true
|
||||||
|
persistenceEnabled = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func benchmarkDiscovery(b *testing.B, nodes, conns int) {
|
func benchmarkDiscovery(b *testing.B, nodes, conns int) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
result, err := discoverySimulation(nodes, conns, adapters.NewSimAdapter(services))
|
result, err := discoverySimulation(nodes, conns, adapters.NewSimAdapter(services))
|
||||||
|
|
@ -207,7 +272,7 @@ func discoverySimulation(nodes, conns int, adapter adapters.NodeAdapter) (*simul
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
log.Debug(fmt.Sprintf("nodes: %v", len(addrs)))
|
log.Debug(fmt.Sprintf("nodes: %v", len(addrs)))
|
||||||
// construct the peer pot, so that kademlia health can be checked
|
// construct the peer pot, so that kademlia health can be checked
|
||||||
ppmap := network.NewPeerPot(testMinProxBinSize, ids, addrs)
|
ppmap := network.NewPeerPotMap(testMinProxBinSize, addrs)
|
||||||
check := func(ctx context.Context, id discover.NodeID) (bool, error) {
|
check := func(ctx context.Context, id discover.NodeID) (bool, error) {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|
@ -224,7 +289,8 @@ func discoverySimulation(nodes, conns int, adapter adapters.NodeAdapter) (*simul
|
||||||
return false, fmt.Errorf("error getting node client: %s", err)
|
return false, fmt.Errorf("error getting node client: %s", err)
|
||||||
}
|
}
|
||||||
healthy := &network.Health{}
|
healthy := &network.Health{}
|
||||||
if err := client.Call(&healthy, "hive_healthy", ppmap[id]); err != nil {
|
addr := common.Bytes2Hex(network.ToOverlayAddr(id.Bytes()))
|
||||||
|
if err := client.Call(&healthy, "hive_healthy", ppmap[addr]); err != nil {
|
||||||
return false, fmt.Errorf("error getting node health: %s", err)
|
return false, fmt.Errorf("error getting node health: %s", err)
|
||||||
}
|
}
|
||||||
log.Debug(fmt.Sprintf("node %4s healthy: got nearest neighbours: %v, know nearest neighbours: %v, saturated: %v\n%v", id, healthy.GotNN, healthy.KnowNN, healthy.Full, healthy.Hive))
|
log.Debug(fmt.Sprintf("node %4s healthy: got nearest neighbours: %v, know nearest neighbours: %v, saturated: %v\n%v", id, healthy.GotNN, healthy.KnowNN, healthy.Full, healthy.Hive))
|
||||||
|
|
@ -266,6 +332,172 @@ func discoverySimulation(nodes, conns int, adapter adapters.NodeAdapter) (*simul
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func discoveryPersistenceSimulation(nodes, conns int, adapter adapters.NodeAdapter) (*simulations.StepResult, error) {
|
||||||
|
cleanDbStores()
|
||||||
|
defer cleanDbStores()
|
||||||
|
|
||||||
|
// create network
|
||||||
|
net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{
|
||||||
|
ID: "0",
|
||||||
|
DefaultService: serviceName,
|
||||||
|
})
|
||||||
|
defer net.Shutdown()
|
||||||
|
trigger := make(chan discover.NodeID)
|
||||||
|
ids := make([]discover.NodeID, nodes)
|
||||||
|
var addrs [][]byte
|
||||||
|
|
||||||
|
for i := 0; i < nodes; i++ {
|
||||||
|
conf := adapters.RandomNodeConfig()
|
||||||
|
node, err := net.NewNodeWithConfig(conf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error starting node: %s", err)
|
||||||
|
}
|
||||||
|
if err := net.Start(node.ID()); err != nil {
|
||||||
|
return nil, fmt.Errorf("error starting node %s: %s", node.ID().TerminalString(), err)
|
||||||
|
}
|
||||||
|
if err := triggerChecks(trigger, net, node.ID()); err != nil {
|
||||||
|
return nil, fmt.Errorf("error triggering checks for node %s: %s", node.ID().TerminalString(), err)
|
||||||
|
}
|
||||||
|
ids[i] = node.ID()
|
||||||
|
a := network.ToOverlayAddr(ids[i].Bytes())
|
||||||
|
|
||||||
|
addrs = append(addrs, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
// run a simulation which connects the 10 nodes in a ring and waits
|
||||||
|
// for full peer discovery
|
||||||
|
ppmap := network.NewPeerPotMap(testMinProxBinSize, addrs)
|
||||||
|
|
||||||
|
var restartTime time.Time
|
||||||
|
|
||||||
|
action := func(ctx context.Context) error {
|
||||||
|
ticker := time.NewTicker(500 * time.Millisecond)
|
||||||
|
|
||||||
|
for range ticker.C {
|
||||||
|
isHealthy := true
|
||||||
|
for _, id := range ids {
|
||||||
|
//call Healthy RPC
|
||||||
|
node := net.GetNode(id)
|
||||||
|
if node == nil {
|
||||||
|
return fmt.Errorf("unknown node: %s", id)
|
||||||
|
}
|
||||||
|
client, err := node.Client()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting node client: %s", err)
|
||||||
|
}
|
||||||
|
healthy := &network.Health{}
|
||||||
|
addr := common.Bytes2Hex(network.ToOverlayAddr(id.Bytes()))
|
||||||
|
if err := client.Call(&healthy, "hive_healthy", ppmap[addr]); err != nil {
|
||||||
|
return fmt.Errorf("error getting node health: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info(fmt.Sprintf("NODE: %s, IS HEALTHY: %t", id.String(), healthy.GotNN && healthy.KnowNN && healthy.Full))
|
||||||
|
if !healthy.GotNN || !healthy.Full {
|
||||||
|
isHealthy = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isHealthy {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ticker.Stop()
|
||||||
|
|
||||||
|
log.Info("reached healthy kademlia. starting to shutdown nodes.")
|
||||||
|
shutdownStarted := time.Now()
|
||||||
|
// stop all ids, then start them again
|
||||||
|
for _, id := range ids {
|
||||||
|
node := net.GetNode(id)
|
||||||
|
|
||||||
|
if err := net.Stop(node.ID()); err != nil {
|
||||||
|
return fmt.Errorf("error stopping node %s: %s", node.ID().TerminalString(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Info(fmt.Sprintf("shutting down nodes took: %s", time.Now().Sub(shutdownStarted)))
|
||||||
|
persistenceEnabled = true
|
||||||
|
discoveryEnabled = false
|
||||||
|
restartTime = time.Now()
|
||||||
|
for _, id := range ids {
|
||||||
|
node := net.GetNode(id)
|
||||||
|
if err := net.Start(node.ID()); err != nil {
|
||||||
|
return fmt.Errorf("error starting node %s: %s", node.ID().TerminalString(), err)
|
||||||
|
}
|
||||||
|
if err := triggerChecks(trigger, net, node.ID()); err != nil {
|
||||||
|
return fmt.Errorf("error triggering checks for node %s: %s", node.ID().TerminalString(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info(fmt.Sprintf("restarting nodes took: %s", time.Now().Sub(restartTime)))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
//connects in a chain
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
//connects in a ring
|
||||||
|
for i := range ids {
|
||||||
|
for j := 1; j <= conns; j++ {
|
||||||
|
k := (i + j) % len(ids)
|
||||||
|
if k == i {
|
||||||
|
k = (k + 1) % len(ids)
|
||||||
|
}
|
||||||
|
wg.Add(1)
|
||||||
|
go func(i, k int) {
|
||||||
|
defer wg.Done()
|
||||||
|
net.Connect(ids[i], ids[k])
|
||||||
|
}(i, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
log.Debug(fmt.Sprintf("nodes: %v", len(addrs)))
|
||||||
|
// construct the peer pot, so that kademlia health can be checked
|
||||||
|
check := func(ctx context.Context, id discover.NodeID) (bool, error) {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return false, ctx.Err()
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
node := net.GetNode(id)
|
||||||
|
if node == nil {
|
||||||
|
return false, fmt.Errorf("unknown node: %s", id)
|
||||||
|
}
|
||||||
|
client, err := node.Client()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error getting node client: %s", err)
|
||||||
|
}
|
||||||
|
healthy := &network.Health{}
|
||||||
|
addr := common.Bytes2Hex(network.ToOverlayAddr(id.Bytes()))
|
||||||
|
if err := client.Call(&healthy, "hive_healthy", ppmap[addr]); err != nil {
|
||||||
|
return false, fmt.Errorf("error getting node health: %s", err)
|
||||||
|
}
|
||||||
|
log.Info(fmt.Sprintf("node %4s healthy: got nearest neighbours: %v, know nearest neighbours: %v, saturated: %v", id, healthy.GotNN, healthy.KnowNN, healthy.Full))
|
||||||
|
|
||||||
|
return healthy.KnowNN && healthy.GotNN && healthy.Full, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 64 nodes ~ 1min
|
||||||
|
// 128 nodes ~
|
||||||
|
timeout := 300 * time.Second
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
defer cancel()
|
||||||
|
result := simulations.NewSimulation(net).Run(ctx, &simulations.Step{
|
||||||
|
Action: action,
|
||||||
|
Trigger: trigger,
|
||||||
|
Expect: &simulations.Expectation{
|
||||||
|
Nodes: ids,
|
||||||
|
Check: check,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// triggerChecks triggers a simulation step check whenever a peer is added or
|
// triggerChecks triggers a simulation step check whenever a peer is added or
|
||||||
// removed from the given node, and also every second to avoid a race between
|
// removed from the given node, and also every second to avoid a race between
|
||||||
// peer events and kademlia becoming healthy
|
// peer events and kademlia becoming healthy
|
||||||
|
|
@ -313,11 +545,6 @@ func newService(ctx *adapters.ServiceContext) (node.Service, error) {
|
||||||
|
|
||||||
kp := network.NewKadParams()
|
kp := network.NewKadParams()
|
||||||
kp.MinProxBinSize = testMinProxBinSize
|
kp.MinProxBinSize = testMinProxBinSize
|
||||||
kp.MaxBinSize = 3
|
|
||||||
kp.MinBinSize = 1
|
|
||||||
kp.MaxRetries = 1000
|
|
||||||
kp.RetryExponent = 2
|
|
||||||
kp.RetryInterval = 50000000
|
|
||||||
|
|
||||||
if ctx.Config.Reachable != nil {
|
if ctx.Config.Reachable != nil {
|
||||||
kp.Reachable = func(o network.OverlayAddr) bool {
|
kp.Reachable = func(o network.OverlayAddr) bool {
|
||||||
|
|
@ -325,9 +552,11 @@ func newService(ctx *adapters.ServiceContext) (node.Service, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kad := network.NewKademlia(addr.Over(), kp)
|
kad := network.NewKademlia(addr.Over(), kp)
|
||||||
|
|
||||||
hp := network.NewHiveParams()
|
hp := network.NewHiveParams()
|
||||||
hp.KeepAliveInterval = 200 * time.Millisecond
|
hp.KeepAliveInterval = time.Duration(200) * time.Millisecond
|
||||||
|
hp.Discovery = discoveryEnabled
|
||||||
|
|
||||||
|
log.Info(fmt.Sprintf("discovery for nodeID %s is %t", ctx.Config.ID.String(), hp.Discovery))
|
||||||
|
|
||||||
config := &network.BzzConfig{
|
config := &network.BzzConfig{
|
||||||
OverlayAddr: addr.Over(),
|
OverlayAddr: addr.Over(),
|
||||||
|
|
@ -335,5 +564,14 @@ func newService(ctx *adapters.ServiceContext) (node.Service, error) {
|
||||||
HiveParams: hp,
|
HiveParams: hp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if persistenceEnabled {
|
||||||
|
log.Info(fmt.Sprintf("persistence enabled for nodeID %s", ctx.Config.ID.String()))
|
||||||
|
store, err := getDbStore(ctx.Config.ID.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return network.NewBzz(config, kad, store, nil, nil), nil
|
||||||
|
}
|
||||||
|
|
||||||
return network.NewBzz(config, kad, nil, nil, nil), nil
|
return network.NewBzz(config, kad, nil, nil, nil), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
|
|
@ -51,7 +52,7 @@ var (
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
ids []discover.NodeID
|
ids []discover.NodeID
|
||||||
datadirs map[discover.NodeID]string
|
datadirs map[discover.NodeID]string
|
||||||
ppmap map[discover.NodeID]*network.PeerPot
|
ppmap map[string]*network.PeerPot
|
||||||
|
|
||||||
globalWg sync.WaitGroup
|
globalWg sync.WaitGroup
|
||||||
|
|
||||||
|
|
@ -240,7 +241,7 @@ func runSyncTest(chunkCount int, nodeCount int, live bool, history bool) error {
|
||||||
log.Info("Test config successfully initialized")
|
log.Info("Test config successfully initialized")
|
||||||
|
|
||||||
//only needed for healthy call when debugging
|
//only needed for healthy call when debugging
|
||||||
ppmap = network.NewPeerPot(testMinProxBinSize, ids, conf.addrs)
|
ppmap = network.NewPeerPotMap(testMinProxBinSize, conf.addrs)
|
||||||
|
|
||||||
//define the action to be performed before the test checks: start syncing
|
//define the action to be performed before the test checks: start syncing
|
||||||
action := func(ctx context.Context) error {
|
action := func(ctx context.Context) error {
|
||||||
|
|
@ -251,7 +252,8 @@ func runSyncTest(chunkCount int, nodeCount int, live bool, history bool) error {
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
r := registries[id]
|
r := registries[id]
|
||||||
//PeerPot for this node
|
//PeerPot for this node
|
||||||
pp := ppmap[id]
|
addr := common.Bytes2Hex(network.ToOverlayAddr(id.Bytes()))
|
||||||
|
pp := ppmap[addr]
|
||||||
//call Healthy RPC
|
//call Healthy RPC
|
||||||
h := r.delivery.overlay.Healthy(pp)
|
h := r.delivery.overlay.Healthy(pp)
|
||||||
//print info
|
//print info
|
||||||
|
|
@ -342,11 +344,9 @@ func runSyncTest(chunkCount int, nodeCount int, live bool, history bool) error {
|
||||||
errc <- nil
|
errc <- nil
|
||||||
}()
|
}()
|
||||||
|
|
||||||
select {
|
err := <-errc
|
||||||
case err := <-errc:
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log.Info("Stream subscriptions successfully requested")
|
log.Info("Stream subscriptions successfully requested")
|
||||||
if live {
|
if live {
|
||||||
|
|
@ -447,10 +447,9 @@ func (r *TestRegistry) StartSyncing(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if log.Lvl(*loglevel) == log.LvlDebug {
|
if log.Lvl(*loglevel) == log.LvlDebug {
|
||||||
//address of registry
|
|
||||||
add := r.addr.ID()
|
|
||||||
//PeerPot for this node
|
//PeerPot for this node
|
||||||
pp := ppmap[add]
|
addr := common.Bytes2Hex(r.addr.OAddr)
|
||||||
|
pp := ppmap[addr]
|
||||||
//call Healthy RPC
|
//call Healthy RPC
|
||||||
h := r.delivery.overlay.Healthy(pp)
|
h := r.delivery.overlay.Healthy(pp)
|
||||||
//print info
|
//print info
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -2,6 +2,7 @@ package pss
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
|
@ -122,7 +123,11 @@ func (pssapi *API) GetAsymmetricAddressHint(topic Topic, pubkeyid string) (PssAd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pssapi *API) StringToTopic(topicstring string) (Topic, error) {
|
func (pssapi *API) StringToTopic(topicstring string) (Topic, error) {
|
||||||
return BytesToTopic([]byte(topicstring)), nil
|
topicbytes := BytesToTopic([]byte(topicstring))
|
||||||
|
if topicbytes == rawTopic {
|
||||||
|
return rawTopic, errors.New("Topic string hashes to 0x00000000 and cannot be used")
|
||||||
|
}
|
||||||
|
return topicbytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pssapi *API) SendAsym(pubkeyhex string, topic Topic, msg hexutil.Bytes) error {
|
func (pssapi *API) SendAsym(pubkeyhex string, topic Topic, msg hexutil.Bytes) error {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ func testProtocol(t *testing.T) {
|
||||||
|
|
||||||
topic := PingTopic.String()
|
topic := PingTopic.String()
|
||||||
|
|
||||||
clients, err := setupNetwork(2)
|
clients, err := setupNetwork(2, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -32,7 +33,7 @@ const (
|
||||||
defaultMaxMsgSize = 1024 * 1024
|
defaultMaxMsgSize = 1024 * 1024
|
||||||
defaultCleanInterval = time.Second * 60 * 10
|
defaultCleanInterval = time.Second * 60 * 10
|
||||||
defaultDequeueInterval = time.Millisecond * 10
|
defaultDequeueInterval = time.Millisecond * 10
|
||||||
defaultOutboxQueueSize = 10000
|
defaultOutboxCapacity = 10000
|
||||||
pssProtocolName = "pss"
|
pssProtocolName = "pss"
|
||||||
pssVersion = 1
|
pssVersion = 1
|
||||||
hasherCount = 8
|
hasherCount = 8
|
||||||
|
|
@ -71,6 +72,7 @@ type PssParams struct {
|
||||||
CacheTTL time.Duration
|
CacheTTL time.Duration
|
||||||
privateKey *ecdsa.PrivateKey
|
privateKey *ecdsa.PrivateKey
|
||||||
SymKeyCacheCapacity int
|
SymKeyCacheCapacity int
|
||||||
|
AllowRaw bool // If true, enables sending and receiving messages without builtin pss encryption
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sane defaults for Pss
|
// Sane defaults for Pss
|
||||||
|
|
@ -115,6 +117,7 @@ type Pss struct {
|
||||||
// message handling
|
// message handling
|
||||||
handlers map[Topic]map[*Handler]bool // topic and version based pss payload handlers. See pss.Handle()
|
handlers map[Topic]map[*Handler]bool // topic and version based pss payload handlers. See pss.Handle()
|
||||||
handlersMu sync.RWMutex
|
handlersMu sync.RWMutex
|
||||||
|
allowRaw bool
|
||||||
hashPool sync.Pool
|
hashPool sync.Pool
|
||||||
|
|
||||||
// process
|
// process
|
||||||
|
|
@ -146,7 +149,7 @@ func NewPss(k network.Overlay, params *PssParams) *Pss {
|
||||||
msgTTL: params.MsgTTL,
|
msgTTL: params.MsgTTL,
|
||||||
paddingByteSize: defaultPaddingByteSize,
|
paddingByteSize: defaultPaddingByteSize,
|
||||||
capstring: cap.String(),
|
capstring: cap.String(),
|
||||||
outbox: make(chan *PssMsg, defaultOutboxQueueSize),
|
outbox: make(chan *PssMsg, defaultOutboxCapacity),
|
||||||
|
|
||||||
pubKeyPool: make(map[string]map[Topic]*pssPeer),
|
pubKeyPool: make(map[string]map[Topic]*pssPeer),
|
||||||
symKeyPool: make(map[string]map[Topic]*pssPeer),
|
symKeyPool: make(map[string]map[Topic]*pssPeer),
|
||||||
|
|
@ -154,6 +157,7 @@ func NewPss(k network.Overlay, params *PssParams) *Pss {
|
||||||
symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity,
|
symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity,
|
||||||
|
|
||||||
handlers: make(map[Topic]map[*Handler]bool),
|
handlers: make(map[Topic]map[*Handler]bool),
|
||||||
|
allowRaw: params.AllowRaw,
|
||||||
hashPool: sync.Pool{
|
hashPool: sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return storage.MakeHashFunc(storage.SHA3Hash)()
|
return storage.MakeHashFunc(storage.SHA3Hash)()
|
||||||
|
|
@ -324,12 +328,17 @@ func (self *Pss) handlePssMsg(msg interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
if !self.isSelfPossibleRecipient(pssmsg) {
|
if !self.isSelfPossibleRecipient(pssmsg) {
|
||||||
log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(self.BaseAddr()))
|
log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(self.BaseAddr()))
|
||||||
self.outbox <- pssmsg
|
if err := self.enqueue(pssmsg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(self.BaseAddr()))
|
log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(self.BaseAddr()))
|
||||||
|
|
||||||
if !self.process(pssmsg) {
|
if err := self.process(pssmsg); err != nil {
|
||||||
self.outbox <- pssmsg
|
qerr := self.enqueue(pssmsg)
|
||||||
|
if qerr != nil {
|
||||||
|
err = fmt.Errorf("%s + %s", err, qerr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +349,7 @@ func (self *Pss) handlePssMsg(msg interface{}) error {
|
||||||
// Entry point to processing a message for which the current node can be the intended recipient.
|
// Entry point to processing a message for which the current node can be the intended recipient.
|
||||||
// Attempts symmetric and asymmetric decryption with stored keys.
|
// Attempts symmetric and asymmetric decryption with stored keys.
|
||||||
// Dispatches message to all handlers matching the message topic
|
// Dispatches message to all handlers matching the message topic
|
||||||
func (self *Pss) process(pssmsg *PssMsg) bool {
|
func (self *Pss) process(pssmsg *PssMsg) error {
|
||||||
var err error
|
var err error
|
||||||
var recvmsg *whisper.ReceivedMessage
|
var recvmsg *whisper.ReceivedMessage
|
||||||
var from *PssAddress
|
var from *PssAddress
|
||||||
|
|
@ -350,6 +359,10 @@ func (self *Pss) process(pssmsg *PssMsg) bool {
|
||||||
|
|
||||||
envelope := pssmsg.Payload
|
envelope := pssmsg.Payload
|
||||||
psstopic := Topic(envelope.Topic)
|
psstopic := Topic(envelope.Topic)
|
||||||
|
if self.allowRaw && psstopic == rawTopic {
|
||||||
|
self.executeHandlers(rawTopic, envelope.Data, nil, false, "")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if len(envelope.AESNonce) > 0 { // detect symkey msg according to whisperv5/envelope.go:OpenSymmetric
|
if len(envelope.AESNonce) > 0 { // detect symkey msg according to whisperv5/envelope.go:OpenSymmetric
|
||||||
keyFunc = self.processSym
|
keyFunc = self.processSym
|
||||||
|
|
@ -359,26 +372,30 @@ func (self *Pss) process(pssmsg *PssMsg) bool {
|
||||||
}
|
}
|
||||||
recvmsg, keyid, from, err = keyFunc(envelope)
|
recvmsg, keyid, from, err = keyFunc(envelope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("decrypt message fail", "err", err, "asym", asymmetric, "pss", common.ToHex(self.BaseAddr()))
|
return errors.New("Decryption failed")
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pssmsg.To) < addressLength {
|
if len(pssmsg.To) < addressLength {
|
||||||
go func() {
|
if err := self.enqueue(pssmsg); err != nil {
|
||||||
self.outbox <- pssmsg
|
return err
|
||||||
}()
|
}
|
||||||
}
|
}
|
||||||
handlers := self.getHandlers(psstopic)
|
self.executeHandlers(psstopic, recvmsg.Payload, from, asymmetric, keyid)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, asymmetric bool, keyid string) {
|
||||||
|
handlers := self.getHandlers(topic)
|
||||||
nid, _ := discover.HexID("0x00") // this hack is needed to satisfy the p2p method
|
nid, _ := discover.HexID("0x00") // this hack is needed to satisfy the p2p method
|
||||||
p := p2p.NewPeer(nid, fmt.Sprintf("%x", from), []p2p.Cap{})
|
p := p2p.NewPeer(nid, fmt.Sprintf("%x", from), []p2p.Cap{})
|
||||||
for f := range handlers {
|
for f := range handlers {
|
||||||
err := (*f)(recvmsg.Payload, p, asymmetric, keyid)
|
err := (*f)(payload, p, asymmetric, keyid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Pss handler %p failed: %v", f, err)
|
log.Warn("Pss handler %p failed: %v", f, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// will return false if using partial address
|
// will return false if using partial address
|
||||||
|
|
@ -586,6 +603,35 @@ func (self *Pss) cleanKeys() (count int) {
|
||||||
// SECTION: Message sending
|
// SECTION: Message sending
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
func (self *Pss) enqueue(msg *PssMsg) error {
|
||||||
|
select {
|
||||||
|
case self.outbox <- msg:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("outbox full")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a raw message (any encryption is responsibility of calling client)
|
||||||
|
//
|
||||||
|
// Will fail if raw messages are disallowed
|
||||||
|
func (self *Pss) SendRaw(msg []byte, address PssAddress) error {
|
||||||
|
if !self.allowRaw {
|
||||||
|
return errors.New("Raw messages not enabled")
|
||||||
|
}
|
||||||
|
pssmsg := &PssMsg{
|
||||||
|
To: address,
|
||||||
|
Expire: uint32(time.Now().Add(self.msgTTL).Unix()),
|
||||||
|
Payload: &whisper.Envelope{
|
||||||
|
Data: msg,
|
||||||
|
Topic: whisper.TopicType(rawTopic),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
self.addFwdCache(pssmsg)
|
||||||
|
return self.enqueue(pssmsg)
|
||||||
|
}
|
||||||
|
|
||||||
// Send a message using symmetric encryption
|
// Send a message using symmetric encryption
|
||||||
//
|
//
|
||||||
// Fails if the key id does not match any of the stored symmetric keys
|
// Fails if the key id does not match any of the stored symmetric keys
|
||||||
|
|
@ -676,14 +722,13 @@ func (self *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key [
|
||||||
Expire: uint32(time.Now().Add(self.msgTTL).Unix()),
|
Expire: uint32(time.Now().Add(self.msgTTL).Unix()),
|
||||||
Payload: envelope,
|
Payload: envelope,
|
||||||
}
|
}
|
||||||
self.outbox <- pssmsg
|
return self.enqueue(pssmsg)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forwards a pss message to the peer(s) closest to the to recipient address in the PssMsg struct
|
// Forwards a pss message to the peer(s) closest to the to recipient address in the PssMsg struct
|
||||||
// The recipient address can be of any length, and the byte slice will be matched to the MSB slice
|
// The recipient address can be of any length, and the byte slice will be matched to the MSB slice
|
||||||
// of the peer address of the equivalent length.
|
// of the peer address of the equivalent length.
|
||||||
func (self *Pss) forward(msg *PssMsg) {
|
func (self *Pss) forward(msg *PssMsg) error {
|
||||||
to := make([]byte, addressLength)
|
to := make([]byte, addressLength)
|
||||||
copy(to[:len(msg.To)], msg.To)
|
copy(to[:len(msg.To)], msg.To)
|
||||||
|
|
||||||
|
|
@ -748,11 +793,14 @@ func (self *Pss) forward(msg *PssMsg) {
|
||||||
if sent == 0 {
|
if sent == 0 {
|
||||||
log.Debug("unable to forward to any peers")
|
log.Debug("unable to forward to any peers")
|
||||||
time.Sleep(time.Millisecond)
|
time.Sleep(time.Millisecond)
|
||||||
self.outbox <- msg
|
if err := self.enqueue(msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache the message
|
// cache the message
|
||||||
self.addFwdCache(msg)
|
self.addFwdCache(msg)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
|
|
||||||
adapters.RegisterServices(newServices())
|
adapters.RegisterServices(newServices(false))
|
||||||
initTest()
|
initTest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,14 +419,96 @@ func TestMismatch(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send symmetrically encrypted message between two directly connected peers
|
func TestSendRaw(t *testing.T) {
|
||||||
func TestSymSend(t *testing.T) {
|
t.Run("32", testSendRaw)
|
||||||
t.Run("32", testSymSend)
|
t.Run("8", testSendRaw)
|
||||||
t.Run("8", testSymSend)
|
t.Run("0", testSendRaw)
|
||||||
t.Run("0", testSymSend)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSymSend(t *testing.T) {
|
func testSendRaw(t *testing.T) {
|
||||||
|
|
||||||
|
var addrsize int64
|
||||||
|
var err error
|
||||||
|
|
||||||
|
paramstring := strings.Split(t.Name(), "/")
|
||||||
|
|
||||||
|
addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
|
||||||
|
log.Info("raw send test", "addrsize", addrsize)
|
||||||
|
|
||||||
|
clients, err := setupNetwork(2, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
topic := "0x00000000"
|
||||||
|
|
||||||
|
var loaddrhex string
|
||||||
|
err = clients[0].Call(&loaddrhex, "pss_baseAddr")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("rpc get node 1 baseaddr fail: %v", err)
|
||||||
|
}
|
||||||
|
loaddrhex = loaddrhex[:2+(addrsize*2)]
|
||||||
|
var roaddrhex string
|
||||||
|
err = clients[1].Call(&roaddrhex, "pss_baseAddr")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("rpc get node 2 baseaddr fail: %v", err)
|
||||||
|
}
|
||||||
|
roaddrhex = roaddrhex[:2+(addrsize*2)]
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 500)
|
||||||
|
|
||||||
|
// at this point we've verified that symkeys are saved and match on each peer
|
||||||
|
// now try sending symmetrically encrypted message, both directions
|
||||||
|
lmsgC := make(chan APIMsg)
|
||||||
|
lctx, lcancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||||
|
defer lcancel()
|
||||||
|
lsub, err := clients[0].Subscribe(lctx, "pss", lmsgC, "receive", topic)
|
||||||
|
log.Trace("lsub", "id", lsub)
|
||||||
|
defer lsub.Unsubscribe()
|
||||||
|
rmsgC := make(chan APIMsg)
|
||||||
|
rctx, rcancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||||
|
defer rcancel()
|
||||||
|
rsub, err := clients[1].Subscribe(rctx, "pss", rmsgC, "receive", topic)
|
||||||
|
log.Trace("rsub", "id", rsub)
|
||||||
|
defer rsub.Unsubscribe()
|
||||||
|
|
||||||
|
// send and verify delivery
|
||||||
|
lmsg := []byte("plugh")
|
||||||
|
err = clients[1].Call(nil, "pss_sendRaw", lmsg, loaddrhex)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case recvmsg := <-lmsgC:
|
||||||
|
if !bytes.Equal(recvmsg.Msg, lmsg) {
|
||||||
|
t.Fatalf("node 1 received payload mismatch: expected %v, got %v", lmsg, recvmsg)
|
||||||
|
}
|
||||||
|
case cerr := <-lctx.Done():
|
||||||
|
t.Fatalf("test message (left) timed out: %v", cerr)
|
||||||
|
}
|
||||||
|
rmsg := []byte("xyzzy")
|
||||||
|
err = clients[0].Call(nil, "pss_sendRaw", rmsg, roaddrhex)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case recvmsg := <-rmsgC:
|
||||||
|
if !bytes.Equal(recvmsg.Msg, rmsg) {
|
||||||
|
t.Fatalf("node 2 received payload mismatch: expected %x, got %v", rmsg, recvmsg.Msg)
|
||||||
|
}
|
||||||
|
case cerr := <-rctx.Done():
|
||||||
|
t.Fatalf("test message (right) timed out: %v", cerr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send symmetrically encrypted message between two directly connected peers
|
||||||
|
func TestSendSym(t *testing.T) {
|
||||||
|
t.Run("32", testSendSym)
|
||||||
|
t.Run("8", testSendSym)
|
||||||
|
t.Run("0", testSendSym)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSendSym(t *testing.T) {
|
||||||
|
|
||||||
// address hint size
|
// address hint size
|
||||||
var addrsize int64
|
var addrsize int64
|
||||||
|
|
@ -435,7 +517,7 @@ func testSymSend(t *testing.T) {
|
||||||
addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
|
addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
|
||||||
log.Info("sym send test", "addrsize", addrsize)
|
log.Info("sym send test", "addrsize", addrsize)
|
||||||
|
|
||||||
clients, err := setupNetwork(2)
|
clients, err := setupNetwork(2, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -535,13 +617,13 @@ func testSymSend(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// send asymmetrically encrypted message between two directly connected peers
|
// send asymmetrically encrypted message between two directly connected peers
|
||||||
func TestAsymSend(t *testing.T) {
|
func TestSendAsym(t *testing.T) {
|
||||||
t.Run("32", testAsymSend)
|
t.Run("32", testSendAsym)
|
||||||
t.Run("8", testAsymSend)
|
t.Run("8", testSendAsym)
|
||||||
t.Run("0", testAsymSend)
|
t.Run("0", testSendAsym)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAsymSend(t *testing.T) {
|
func testSendAsym(t *testing.T) {
|
||||||
|
|
||||||
// address hint size
|
// address hint size
|
||||||
var addrsize int64
|
var addrsize int64
|
||||||
|
|
@ -550,7 +632,7 @@ func testAsymSend(t *testing.T) {
|
||||||
addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
|
addrsize, _ = strconv.ParseInt(paramstring[1], 10, 0)
|
||||||
log.Info("asym send test", "addrsize", addrsize)
|
log.Info("asym send test", "addrsize", addrsize)
|
||||||
|
|
||||||
clients, err := setupNetwork(2)
|
clients, err := setupNetwork(2, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -710,11 +792,11 @@ func testNetwork(t *testing.T) {
|
||||||
}
|
}
|
||||||
a = adapters.NewExecAdapter(dirname)
|
a = adapters.NewExecAdapter(dirname)
|
||||||
} else if adapter == "sock" {
|
} else if adapter == "sock" {
|
||||||
a = adapters.NewSocketAdapter(newServices())
|
a = adapters.NewSocketAdapter(newServices(false))
|
||||||
} else if adapter == "tcp" {
|
} else if adapter == "tcp" {
|
||||||
a = adapters.NewTCPAdapter(newServices())
|
a = adapters.NewTCPAdapter(newServices(false))
|
||||||
} else if adapter == "sim" {
|
} else if adapter == "sim" {
|
||||||
a = adapters.NewSimAdapter(newServices())
|
a = adapters.NewSimAdapter(newServices(false))
|
||||||
}
|
}
|
||||||
net := simulations.NewNetwork(a, &simulations.NetworkConfig{
|
net := simulations.NewNetwork(a, &simulations.NetworkConfig{
|
||||||
ID: "0",
|
ID: "0",
|
||||||
|
|
@ -864,10 +946,12 @@ outer:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check that in a network of a -> b -> c -> a
|
||||||
|
// a doesn't receive a sent message twice
|
||||||
func TestDeduplication(t *testing.T) {
|
func TestDeduplication(t *testing.T) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
clients, err := setupNetwork(3)
|
clients, err := setupNetwork(3, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1108,7 +1192,7 @@ func benchmarkSymkeyBruteforceChangeaddr(b *testing.B) {
|
||||||
}
|
}
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if !ps.process(pssmsgs[len(pssmsgs)-(i%len(pssmsgs))-1]) {
|
if err := ps.process(pssmsgs[len(pssmsgs)-(i%len(pssmsgs))-1]); err != nil {
|
||||||
b.Fatalf("pss processing failed: %v", err)
|
b.Fatalf("pss processing failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1190,20 +1274,22 @@ func benchmarkSymkeyBruteforceSameaddr(b *testing.B) {
|
||||||
Payload: env,
|
Payload: env,
|
||||||
}
|
}
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if !ps.process(pssmsg) {
|
if err := ps.process(pssmsg); err != nil {
|
||||||
b.Fatalf("pss processing failed: %v", err)
|
b.Fatalf("pss processing failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup simulated network and connect nodes in circle
|
// setup simulated network with bzz/discovery and pss services.
|
||||||
func setupNetwork(numnodes int) (clients []*rpc.Client, err error) {
|
// connects nodes in a circle
|
||||||
|
// if allowRaw is set, omission of builtin pss encryption is enabled (see PssParams)
|
||||||
|
func setupNetwork(numnodes int, allowRaw bool) (clients []*rpc.Client, err error) {
|
||||||
nodes := make([]*simulations.Node, numnodes)
|
nodes := make([]*simulations.Node, numnodes)
|
||||||
clients = make([]*rpc.Client, numnodes)
|
clients = make([]*rpc.Client, numnodes)
|
||||||
if numnodes < 2 {
|
if numnodes < 2 {
|
||||||
return nil, fmt.Errorf("Minimum two nodes in network")
|
return nil, fmt.Errorf("Minimum two nodes in network")
|
||||||
}
|
}
|
||||||
adapter := adapters.NewSimAdapter(newServices())
|
adapter := adapters.NewSimAdapter(newServices(allowRaw))
|
||||||
net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{
|
net := simulations.NewNetwork(adapter, &simulations.NetworkConfig{
|
||||||
ID: "0",
|
ID: "0",
|
||||||
DefaultService: "bzz",
|
DefaultService: "bzz",
|
||||||
|
|
@ -1239,7 +1325,7 @@ func setupNetwork(numnodes int) (clients []*rpc.Client, err error) {
|
||||||
return clients, nil
|
return clients, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newServices() adapters.Services {
|
func newServices(allowRaw bool) adapters.Services {
|
||||||
stateStore := state.NewMemStore()
|
stateStore := state.NewMemStore()
|
||||||
kademlias := make(map[discover.NodeID]*network.Kademlia)
|
kademlias := make(map[discover.NodeID]*network.Kademlia)
|
||||||
kademlia := func(id discover.NodeID) *network.Kademlia {
|
kademlia := func(id discover.NodeID) *network.Kademlia {
|
||||||
|
|
@ -1268,6 +1354,7 @@ func newServices() adapters.Services {
|
||||||
privkey, err := w.GetPrivateKey(keys)
|
privkey, err := w.GetPrivateKey(keys)
|
||||||
pssp := NewPssParams(privkey)
|
pssp := NewPssParams(privkey)
|
||||||
pssp.MsgTTL = time.Second * 30
|
pssp.MsgTTL = time.Second * 30
|
||||||
|
pssp.AllowRaw = allowRaw
|
||||||
pskad := kademlia(ctx.Config.ID)
|
pskad := kademlia(ctx.Config.ID)
|
||||||
ps := NewPss(pskad, pssp)
|
ps := NewPss(pskad, pssp)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ const (
|
||||||
var (
|
var (
|
||||||
topicHashMutex = sync.Mutex{}
|
topicHashMutex = sync.Mutex{}
|
||||||
topicHashFunc = storage.MakeHashFunc("SHA256")()
|
topicHashFunc = storage.MakeHashFunc("SHA256")()
|
||||||
|
rawTopic = Topic{}
|
||||||
)
|
)
|
||||||
|
|
||||||
type Topic whisper.TopicType
|
type Topic whisper.TopicType
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue