Browse Source

Merge branch 'develop' of https://github.com/tendermint/tendermint into develop

pull/882/head
caffix 7 years ago
parent
commit
aeaf2d0b20
10 changed files with 179 additions and 129 deletions
  1. +0
    -1
      INSTALL.md
  2. +1
    -1
      docs/getting-started.rst
  3. +19
    -19
      glide.lock
  4. +1
    -1
      glide.yaml
  5. +88
    -68
      p2p/addrbook.go
  6. +39
    -0
      p2p/addrbook_test.go
  7. +6
    -3
      p2p/connection.go
  8. +19
    -33
      p2p/pex_reactor.go
  9. +6
    -3
      p2p/switch.go
  10. +0
    -0
      p2p/trust/trustmetric_test.go_

+ 0
- 1
INSTALL.md View File

@ -1 +0,0 @@
The installation guide has moved to the [docs directory](docs/guides/install-from-source.md) in order to easily be rendered by the website. Please update your links accordingly.

+ 1
- 1
docs/getting-started.rst View File

@ -5,7 +5,7 @@ As a general purpose blockchain engine, Tendermint is agnostic to the
application you want to run. So, to run a complete blockchain that does
something useful, you must start two programs: one is Tendermint Core,
the other is your application, which can be written in any programming
language. Recall from `the intro to ABCI <introduction.rst#ABCI-Overview>`__ that
language. Recall from `the intro to ABCI <introduction.html#ABCI-Overview>`__ that
Tendermint Core handles all the p2p and consensus stuff, and just
forwards transactions to the application when they need to be validated,
or when they're ready to be committed to a block.


+ 19
- 19
glide.lock View File

@ -1,5 +1,5 @@
hash: 0f9ba99fd411afaaf90993037b0067c5f9f873554f407a6ae9afa0e2548343c5
updated: 2017-10-27T22:34:38.187149434-04:00
hash: 223d8e42a118e7861cb673ea58a035e99d3a98c94e4b71fb52998d320f9c3b49
updated: 2017-11-22T07:33:50.996598926-08:00
imports:
- name: github.com/btcsuite/btcd
version: 8cea3866d0f7fb12d567a20744942c0d078c7d15
@ -10,7 +10,7 @@ imports:
- name: github.com/fsnotify/fsnotify
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
- name: github.com/go-kit/kit
version: e2b298466b32c7cd5579a9b9b07e968fc9d9452c
version: e3b2152e0063c5f05efea89ecbe297852af2a92d
subpackages:
- log
- log/level
@ -24,13 +24,13 @@ imports:
- name: github.com/go-playground/universal-translator
version: 71201497bace774495daed26a3874fd339e0b538
- name: github.com/go-stack/stack
version: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf
version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc
- name: github.com/gogo/protobuf
version: 342cbe0a04158f6dcb03ca0079991a51a4248c02
subpackages:
- proto
- name: github.com/golang/protobuf
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9
version: 1e59b77b52bf8e4b449a57e6f79f21226d571845
subpackages:
- proto
- ptypes
@ -59,7 +59,7 @@ imports:
- name: github.com/kr/logfmt
version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0
- name: github.com/magiconair/properties
version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a
version: 49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934
- name: github.com/mitchellh/mapstructure
version: 06020f85339e21b2478f756a78e295255ffa4d6a
- name: github.com/pelletier/go-toml
@ -69,7 +69,7 @@ imports:
- name: github.com/rcrowley/go-metrics
version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c
- name: github.com/spf13/afero
version: 5660eeed305fe5f69c8fc6cf899132a459a97064
version: 8d919cbe7e2627e417f3e45c3c0e489a5b7e2536
subpackages:
- mem
- name: github.com/spf13/cast
@ -79,11 +79,11 @@ imports:
- name: github.com/spf13/jwalterweatherman
version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
- name: github.com/spf13/pflag
version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea
- name: github.com/spf13/viper
version: 25b30aa063fc18e48662b86996252eabdcf2f0c7
- name: github.com/syndtr/goleveldb
version: b89cc31ef7977104127d34c1bd31ebd1a9db2199
version: adf24ef3f94bd13ec4163060b21a5678f22b429b
subpackages:
- leveldb
- leveldb/cache
@ -98,7 +98,7 @@ imports:
- leveldb/table
- leveldb/util
- name: github.com/tendermint/abci
version: dc33aad9b4e514a2322725ef68f27f72d955c537
version: 76ef8a0697c6179220a74c479b36c27a5b53008a
subpackages:
- client
- example/counter
@ -113,10 +113,11 @@ imports:
- name: github.com/tendermint/go-crypto
version: dd20358a264c772b4a83e477b0cfce4c88a7001d
- name: github.com/tendermint/go-wire
version: 2baffcb6b690057568bc90ef1d457efb150b979a
version: 7d50b38b3815efe313728de77e2995c8813ce13f
subpackages:
- data
- data/base58
- nowriter/tmencoding
- name: github.com/tendermint/iavl
version: 594cc0c062a7174475f0ab654384038d77067917
subpackages:
@ -130,7 +131,6 @@ imports:
- clist
- common
- db
- events
- flowrate
- log
- merkle
@ -138,7 +138,7 @@ imports:
- pubsub/query
- test
- name: golang.org/x/crypto
version: 2509b142fb2b797aa7587dad548f113b2c0f20ce
version: 9f005a07e0d31d45e6656d241bb5c0f2efd4bc94
subpackages:
- curve25519
- nacl/box
@ -149,7 +149,7 @@ imports:
- ripemd160
- salsa20/salsa
- name: golang.org/x/net
version: c73622c77280266305273cb545f54516ced95b93
version: 9dfe39835686865bff950a07b394c12a98ddc811
subpackages:
- context
- http2
@ -159,18 +159,18 @@ imports:
- lex/httplex
- trace
- name: golang.org/x/sys
version: b98136db334ff9cb24f28a68e3be3cb6608f7630
version: 82aafbf43bf885069dc71b7e7c2f9d7a614d47da
subpackages:
- unix
- name: golang.org/x/text
version: 6eab0e8f74e86c598ec3b6fad4888e0c11482d48
version: 88f656faf3f37f690df1a32515b479415e1a6769
subpackages:
- secure/bidirule
- transform
- unicode/bidi
- unicode/norm
- name: google.golang.org/genproto
version: f676e0f3ac6395ff1a529ae59a6670878a8371a6
version: 891aceb7c239e72692819142dfca057bdcbfcb96
subpackages:
- googleapis/rpc/status
- name: google.golang.org/grpc
@ -193,9 +193,9 @@ imports:
- tap
- transport
- name: gopkg.in/go-playground/validator.v9
version: 1304298bf10d085adec514b076772a79c9cadb6b
version: 61caf9d3038e1af346dbf5c2e16f6678e1548364
- name: gopkg.in/yaml.v2
version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
version: 287cf08546ab5e7e37d55a84f7ed3fd1db036de5
testImports:
- name: github.com/davecgh/go-spew
version: 04cdfd42973bb9c8589fd6a731800cf222fde1a9


+ 1
- 1
glide.yaml View File

@ -26,7 +26,7 @@ import:
- package: github.com/tendermint/go-crypto
version: ~0.4.1
- package: github.com/tendermint/go-wire
version: ~0.7.1
version: develop
subpackages:
- data
- package: github.com/tendermint/iavl


+ 88
- 68
p2p/addrbook.go View File

@ -7,6 +7,7 @@ package p2p
import (
"encoding/binary"
"encoding/json"
"fmt"
"math"
"math/rand"
"net"
@ -40,7 +41,7 @@ const (
// old buckets over which an address group will be spread.
oldBucketsPerGroup = 4
// new buckets over which an source address group will be spread.
// new buckets over which a source address group will be spread.
newBucketsPerGroup = 32
// buckets a frequently seen new address may end up in.
@ -79,18 +80,22 @@ const (
type AddrBook struct {
cmn.BaseService
mtx sync.Mutex
// immutable after creation
filePath string
routabilityStrict bool
rand *rand.Rand
key string
ourAddrs map[string]*NetAddress
addrLookup map[string]*knownAddress // new & old
addrNew []map[string]*knownAddress
addrOld []map[string]*knownAddress
wg sync.WaitGroup
nOld int
nNew int
// accessed concurrently
mtx sync.Mutex
rand *rand.Rand
ourAddrs map[string]*NetAddress
addrLookup map[string]*knownAddress // new & old
bucketsOld []map[string]*knownAddress
bucketsNew []map[string]*knownAddress
nOld int
nNew int
wg sync.WaitGroup
}
// NewAddrBook creates a new address book.
@ -112,14 +117,14 @@ func NewAddrBook(filePath string, routabilityStrict bool) *AddrBook {
func (a *AddrBook) init() {
a.key = crypto.CRandHex(24) // 24/2 * 8 = 96 bits
// New addr buckets
a.addrNew = make([]map[string]*knownAddress, newBucketCount)
for i := range a.addrNew {
a.addrNew[i] = make(map[string]*knownAddress)
a.bucketsNew = make([]map[string]*knownAddress, newBucketCount)
for i := range a.bucketsNew {
a.bucketsNew[i] = make(map[string]*knownAddress)
}
// Old addr buckets
a.addrOld = make([]map[string]*knownAddress, oldBucketCount)
for i := range a.addrOld {
a.addrOld[i] = make(map[string]*knownAddress)
a.bucketsOld = make([]map[string]*knownAddress, oldBucketCount)
for i := range a.bucketsOld {
a.bucketsOld[i] = make(map[string]*knownAddress)
}
}
@ -145,6 +150,7 @@ func (a *AddrBook) Wait() {
a.wg.Wait()
}
// AddOurAddress adds another one of our addresses.
func (a *AddrBook) AddOurAddress(addr *NetAddress) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -152,6 +158,7 @@ func (a *AddrBook) AddOurAddress(addr *NetAddress) {
a.ourAddrs[addr.String()] = addr
}
// OurAddresses returns a list of our addresses.
func (a *AddrBook) OurAddresses() []*NetAddress {
addrs := []*NetAddress{}
for _, addr := range a.ourAddrs {
@ -160,18 +167,20 @@ func (a *AddrBook) OurAddresses() []*NetAddress {
return addrs
}
// AddAddress adds the given address as received from the given source.
// NOTE: addr must not be nil
func (a *AddrBook) AddAddress(addr *NetAddress, src *NetAddress) {
func (a *AddrBook) AddAddress(addr *NetAddress, src *NetAddress) error {
a.mtx.Lock()
defer a.mtx.Unlock()
a.Logger.Info("Add address to book", "addr", addr, "src", src)
a.addAddress(addr, src)
return a.addAddress(addr, src)
}
// NeedMoreAddrs returns true if there are not have enough addresses in the book.
func (a *AddrBook) NeedMoreAddrs() bool {
return a.Size() < needAddressThreshold
}
// Size returns the number of addresses in the book.
func (a *AddrBook) Size() int {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -182,7 +191,12 @@ func (a *AddrBook) size() int {
return a.nNew + a.nOld
}
// Pick an address to connect to with new/old bias.
// PickAddress picks an address to connect to.
// The address is picked randomly from an old or new bucket according
// to the newBias argument, which must be between [0, 100] (or else is truncated to that range)
// and determines how biased we are to pick an address from a new bucket.
// PickAddress returns nil if the AddrBook is empty or if we try to pick
// from an empty bucket.
func (a *AddrBook) PickAddress(newBias int) *NetAddress {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -201,40 +215,34 @@ func (a *AddrBook) PickAddress(newBias int) *NetAddress {
oldCorrelation := math.Sqrt(float64(a.nOld)) * (100.0 - float64(newBias))
newCorrelation := math.Sqrt(float64(a.nNew)) * float64(newBias)
if (newCorrelation+oldCorrelation)*a.rand.Float64() < oldCorrelation {
// pick random Old bucket.
var bucket map[string]*knownAddress = nil
for len(bucket) == 0 {
bucket = a.addrOld[a.rand.Intn(len(a.addrOld))]
}
// pick a random ka from bucket.
randIndex := a.rand.Intn(len(bucket))
for _, ka := range bucket {
if randIndex == 0 {
return ka.Addr
}
randIndex--
}
cmn.PanicSanity("Should not happen")
} else {
// pick random New bucket.
var bucket map[string]*knownAddress = nil
for len(bucket) == 0 {
bucket = a.addrNew[a.rand.Intn(len(a.addrNew))]
// pick a random peer from a random bucket
var bucket map[string]*knownAddress
pickFromOldBucket := (newCorrelation+oldCorrelation)*a.rand.Float64() < oldCorrelation
if (pickFromOldBucket && a.nOld == 0) ||
(!pickFromOldBucket && a.nNew == 0) {
return nil
}
// loop until we pick a random non-empty bucket
for len(bucket) == 0 {
if pickFromOldBucket {
bucket = a.bucketsOld[a.rand.Intn(len(a.bucketsOld))]
} else {
bucket = a.bucketsNew[a.rand.Intn(len(a.bucketsNew))]
}
// pick a random ka from bucket.
randIndex := a.rand.Intn(len(bucket))
for _, ka := range bucket {
if randIndex == 0 {
return ka.Addr
}
randIndex--
}
// pick a random index and loop over the map to return that index
randIndex := a.rand.Intn(len(bucket))
for _, ka := range bucket {
if randIndex == 0 {
return ka.Addr
}
cmn.PanicSanity("Should not happen")
randIndex--
}
return nil
}
// MarkGood marks the peer as good and moves it into an "old" bucket.
// XXX: we never call this!
func (a *AddrBook) MarkGood(addr *NetAddress) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -248,6 +256,7 @@ func (a *AddrBook) MarkGood(addr *NetAddress) {
}
}
// MarkAttempt marks that an attempt was made to connect to the address.
func (a *AddrBook) MarkAttempt(addr *NetAddress) {
a.mtx.Lock()
defer a.mtx.Unlock()
@ -301,6 +310,7 @@ func (a *AddrBook) GetSelection() []*NetAddress {
// Fisher-Yates shuffle the array. We only need to do the first
// `numAddresses' since we are throwing the rest.
// XXX: What's the point of this if we already loop randomly through addrLookup ?
for i := 0; i < numAddresses; i++ {
// pick a number between current index and the end
j := rand.Intn(len(allAddr)-i) + i
@ -370,7 +380,7 @@ func (a *AddrBook) loadFromFile(filePath string) bool {
// Restore all the fields...
// Restore the key
a.key = aJSON.Key
// Restore .addrNew & .addrOld
// Restore .bucketsNew & .bucketsOld
for _, ka := range aJSON.Addrs {
for _, bucketIndex := range ka.Buckets {
bucket := a.getBucket(ka.BucketType, bucketIndex)
@ -397,17 +407,17 @@ func (a *AddrBook) Save() {
func (a *AddrBook) saveRoutine() {
defer a.wg.Done()
dumpAddressTicker := time.NewTicker(dumpAddressInterval)
saveFileTicker := time.NewTicker(dumpAddressInterval)
out:
for {
select {
case <-dumpAddressTicker.C:
case <-saveFileTicker.C:
a.saveToFile(a.filePath)
case <-a.Quit:
break out
}
}
dumpAddressTicker.Stop()
saveFileTicker.Stop()
a.saveToFile(a.filePath)
a.Logger.Info("Address handler done")
}
@ -415,9 +425,9 @@ out:
func (a *AddrBook) getBucket(bucketType byte, bucketIdx int) map[string]*knownAddress {
switch bucketType {
case bucketTypeNew:
return a.addrNew[bucketIdx]
return a.bucketsNew[bucketIdx]
case bucketTypeOld:
return a.addrOld[bucketIdx]
return a.bucketsOld[bucketIdx]
default:
cmn.PanicSanity("Should not happen")
return nil
@ -472,7 +482,7 @@ func (a *AddrBook) addToOldBucket(ka *knownAddress, bucketIdx int) bool {
}
addrStr := ka.Addr.String()
bucket := a.getBucket(bucketTypeNew, bucketIdx)
bucket := a.getBucket(bucketTypeOld, bucketIdx)
// Already exists?
if _, ok := bucket[addrStr]; ok {
@ -538,14 +548,13 @@ func (a *AddrBook) pickOldest(bucketType byte, bucketIdx int) *knownAddress {
return oldest
}
func (a *AddrBook) addAddress(addr, src *NetAddress) {
func (a *AddrBook) addAddress(addr, src *NetAddress) error {
if a.routabilityStrict && !addr.Routable() {
a.Logger.Error(cmn.Fmt("Cannot add non-routable address %v", addr))
return
return fmt.Errorf("Cannot add non-routable address %v", addr)
}
if _, ok := a.ourAddrs[addr.String()]; ok {
// Ignore our own listener address.
return
return fmt.Errorf("Cannot add ourselves with address %v", addr)
}
ka := a.addrLookup[addr.String()]
@ -553,16 +562,16 @@ func (a *AddrBook) addAddress(addr, src *NetAddress) {
if ka != nil {
// Already old.
if ka.isOld() {
return
return nil
}
// Already in max new buckets.
if len(ka.Buckets) == maxNewBucketsPerAddress {
return
return nil
}
// The more entries we have, the less likely we are to add more.
factor := int32(2 * len(ka.Buckets))
if a.rand.Int31n(factor) != 0 {
return
return nil
}
} else {
ka = newKnownAddress(addr, src)
@ -572,12 +581,13 @@ func (a *AddrBook) addAddress(addr, src *NetAddress) {
a.addToNewBucket(ka, bucket)
a.Logger.Info("Added new address", "address", addr, "total", a.size())
return nil
}
// Make space in the new buckets by expiring the really bad entries.
// If no bad entries are available we remove the oldest.
func (a *AddrBook) expireNew(bucketIdx int) {
for addrStr, ka := range a.addrNew[bucketIdx] {
for addrStr, ka := range a.bucketsNew[bucketIdx] {
// If an entry is bad, throw it away
if ka.isBad() {
a.Logger.Info(cmn.Fmt("expiring bad address %v", addrStr))
@ -679,8 +689,8 @@ func (a *AddrBook) calcOldBucket(addr *NetAddress) int {
}
// Return a string representing the network group of this address.
// This is the /16 for IPv6, the /32 (/36 for he.net) for IPv6, the string
// "local" for a local address and the string "unroutable for an unroutable
// This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string
// "local" for a local address and the string "unroutable" for an unroutable
// address.
func (a *AddrBook) groupKey(na *NetAddress) string {
if a.routabilityStrict && na.Local() {
@ -806,8 +816,8 @@ func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
}
/*
An address is bad if the address in question has not been tried in the last
minute and meets one of the following criteria:
An address is bad if the address in question is a New address, has not been tried in the last
minute, and meets one of the following criteria:
1) It claims to be from the future
2) It hasn't been seen in over a month
@ -816,14 +826,23 @@ func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
All addresses that meet these criteria are assumed to be worthless and not
worth keeping hold of.
XXX: so a good peer needs us to call MarkGood before the conditions above are reached!
*/
func (ka *knownAddress) isBad() bool {
// Is Old --> good
if ka.BucketType == bucketTypeOld {
return false
}
// Has been attempted in the last minute --> good
if ka.LastAttempt.Before(time.Now().Add(-1 * time.Minute)) {
return false
}
// Over a month old?
// Too old?
// XXX: does this mean if we've kept a connection up for this long we'll disconnect?!
// and shouldn't it be .Before ?
if ka.LastAttempt.After(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
return true
}
@ -834,6 +853,7 @@ func (ka *knownAddress) isBad() bool {
}
// Hasn't succeeded in too long?
// XXX: does this mean if we've kept a connection up for this long we'll disconnect?!
if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
ka.Attempts >= maxFailures {
return true


+ 39
- 0
p2p/addrbook_test.go View File

@ -23,6 +23,42 @@ func createTempFileName(prefix string) string {
return fname
}
func TestAddrBookPickAddress(t *testing.T) {
assert := assert.New(t)
fname := createTempFileName("addrbook_test")
// 0 addresses
book := NewAddrBook(fname, true)
book.SetLogger(log.TestingLogger())
assert.Zero(book.Size())
addr := book.PickAddress(50)
assert.Nil(addr, "expected no address")
randAddrs := randNetAddressPairs(t, 1)
addrSrc := randAddrs[0]
book.AddAddress(addrSrc.addr, addrSrc.src)
// pick an address when we only have new address
addr = book.PickAddress(0)
assert.NotNil(addr, "expected an address")
addr = book.PickAddress(50)
assert.NotNil(addr, "expected an address")
addr = book.PickAddress(100)
assert.NotNil(addr, "expected an address")
// pick an address when we only have old address
book.MarkGood(addrSrc.addr)
addr = book.PickAddress(0)
assert.NotNil(addr, "expected an address")
addr = book.PickAddress(50)
assert.NotNil(addr, "expected an address")
// in this case, nNew==0 but we biased 100% to new, so we return nil
addr = book.PickAddress(100)
assert.Nil(addr, "did not expected an address")
}
func TestAddrBookSaveLoad(t *testing.T) {
fname := createTempFileName("addrbook_test")
@ -76,6 +112,7 @@ func TestAddrBookLookup(t *testing.T) {
}
func TestAddrBookPromoteToOld(t *testing.T) {
assert := assert.New(t)
fname := createTempFileName("addrbook_test")
randAddrs := randNetAddressPairs(t, 100)
@ -106,6 +143,8 @@ func TestAddrBookPromoteToOld(t *testing.T) {
if len(selection) > book.Size() {
t.Errorf("selection could not be bigger than the book")
}
assert.Equal(book.Size(), 100, "expecting book size to be 100")
}
func TestAddrBookHandlesDuplicates(t *testing.T) {


+ 6
- 3
p2p/connection.go View File

@ -11,10 +11,13 @@ import (
"time"
wire "github.com/tendermint/go-wire"
tmencoding "github.com/tendermint/go-wire/nowriter/tmencoding"
cmn "github.com/tendermint/tmlibs/common"
flow "github.com/tendermint/tmlibs/flowrate"
)
var legacy = tmencoding.Legacy
const (
numBatchMsgPackets = 10
minReadBufferSize = 1024
@ -308,12 +311,12 @@ FOR_LOOP:
}
case <-c.pingTimer.Ch:
c.Logger.Debug("Send Ping")
wire.WriteByte(packetTypePing, c.bufWriter, &n, &err)
legacy.WriteOctet(packetTypePing, c.bufWriter, &n, &err)
c.sendMonitor.Update(int(n))
c.flush()
case <-c.pong:
c.Logger.Debug("Send Pong")
wire.WriteByte(packetTypePong, c.bufWriter, &n, &err)
legacy.WriteOctet(packetTypePong, c.bufWriter, &n, &err)
c.sendMonitor.Update(int(n))
c.flush()
case <-c.quit:
@ -661,7 +664,7 @@ func (ch *Channel) writeMsgPacketTo(w io.Writer) (n int, err error) {
}
func writeMsgPacketTo(packet msgPacket, w io.Writer, n *int, err *error) {
wire.WriteByte(packetTypeMsg, w, n, err)
legacy.WriteOctet(packetTypeMsg, w, n, err)
wire.WriteBinary(packet, w, n, err)
}


+ 19
- 33
p2p/pex_reactor.go View File

@ -240,43 +240,29 @@ func (r *PEXReactor) ensurePeers() {
return
}
toDial := make(map[string]*NetAddress)
// bias to prefer more vetted peers when we have fewer connections.
// not perfect, but somewhate ensures that we prioritize connecting to more-vetted
newBias := cmn.MinInt(numOutPeers, 8)*10 + 10
// Try to pick numToDial addresses to dial.
for i := 0; i < numToDial; i++ {
// The purpose of newBias is to first prioritize old (more vetted) peers
// when we have few connections, but to allow for new (less vetted) peers
// if we already have many connections. This algorithm isn't perfect, but
// it somewhat ensures that we prioritize connecting to more-vetted
// peers.
newBias := cmn.MinInt(numOutPeers, 8)*10 + 10
var picked *NetAddress
// Try to fetch a new peer 3 times.
// This caps the maximum number of tries to 3 * numToDial.
for j := 0; j < 3; j++ {
try := r.book.PickAddress(newBias)
if try == nil {
break
}
_, alreadySelected := toDial[try.IP.String()]
alreadyDialing := r.Switch.IsDialing(try)
alreadyConnected := r.Switch.Peers().Has(try.IP.String())
if alreadySelected || alreadyDialing || alreadyConnected {
// r.Logger.Info("Cannot dial address", "addr", try,
// "alreadySelected", alreadySelected,
// "alreadyDialing", alreadyDialing,
// "alreadyConnected", alreadyConnected)
continue
} else {
r.Logger.Info("Will dial address", "addr", try)
picked = try
break
}
toDial := make(map[string]*NetAddress)
// Try maxAttempts times to pick numToDial addresses to dial
maxAttempts := numToDial * 3
for i := 0; i < maxAttempts && len(toDial) < numToDial; i++ {
try := r.book.PickAddress(newBias)
if try == nil {
continue
}
if _, selected := toDial[try.IP.String()]; selected {
continue
}
if dialling := r.Switch.IsDialing(try); dialling {
continue
}
if picked == nil {
if connected := r.Switch.Peers().Has(try.IP.String()); connected {
continue
}
toDial[picked.IP.String()] = picked
r.Logger.Info("Will dial address", "addr", try)
toDial[try.IP.String()] = try
}
// Dial picked addresses


+ 6
- 3
p2p/switch.go View File

@ -295,7 +295,6 @@ func (sw *Switch) startInitPeer(peer *peer) {
// DialSeeds dials a list of seeds asynchronously in random order.
func (sw *Switch) DialSeeds(addrBook *AddrBook, seeds []string) error {
netAddrs, err := NewNetAddressStrings(seeds)
if err != nil {
return err
@ -315,11 +314,15 @@ func (sw *Switch) DialSeeds(addrBook *AddrBook, seeds []string) error {
addrBook.Save()
}
// Ensure we have a completely undeterministic PRNG. cmd.RandInt64() draws
// from a seed that's initialized with OS entropy on process start.
rng := rand.New(rand.NewSource(cmn.RandInt64()))
// permute the list, dial them in random order.
perm := rand.Perm(len(netAddrs))
perm := rng.Perm(len(netAddrs))
for i := 0; i < len(perm); i++ {
go func(i int) {
time.Sleep(time.Duration(rand.Int63n(3000)) * time.Millisecond)
time.Sleep(time.Duration(rng.Int63n(3000)) * time.Millisecond)
j := perm[i]
sw.dialSeed(netAddrs[j])
}(i)


p2p/trust/trustmetric_test.go → p2p/trust/trustmetric_test.go_ View File


Loading…
Cancel
Save