mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
ListOfKnownAddresses is removed panic if addrbook size is less than zero CrawlPeers does not attempt to connect to existing or peers we're currently dialing various perf. fixes improved tests (though not complete) move IsDialingOrExistingAddress check into DialPeerWithAddress (Fixes #2716) * addrbook: preallocate memory when saving addrbook to file * addrbook: remove oldestFirst struct and check for ID * oldestFirst replaced with sort.Slice * ID is now mandatory, so no need to check * addrbook: remove ListOfKnownAddresses GetSelection is used instead in seed mode. * addrbook: panic if size is less than 0 * rewrite addrbook#saveToFile to not use a counter * test AttemptDisconnects func * move IsDialingOrExistingAddress check into DialPeerWithAddress * save and cleanup crawl peer data * get rid of DefaultSeedDisconnectWaitPeriod * make linter happy * fix TestPEXReactorSeedMode * fix comment * add a changelog entry * Apply suggestions from code review Co-Authored-By: melekes <anton.kalyaev@gmail.com> * rename ErrDialingOrExistingAddress to ErrCurrentlyDialingOrExistingAddress * lowercase errors * do not persist seed data pros: - no extra files - less IO cons: - if the node crashes, seed might crawl a peer too soon * fixes after Ethan's review * add a changelog entry * we should only consult Switch about peers checking addrbook size does not make sense since only PEX reactor uses it for dialing peers! https://github.com/tendermint/tendermint/pull/3011#discussion_r270948875
130 lines
3.1 KiB
Go
130 lines
3.1 KiB
Go
package pex
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/tendermint/tendermint/p2p"
|
|
)
|
|
|
|
// knownAddress tracks information about a known network address
|
|
// that is used to determine how viable an address is.
|
|
type knownAddress struct {
|
|
Addr *p2p.NetAddress `json:"addr"`
|
|
Src *p2p.NetAddress `json:"src"`
|
|
Attempts int32 `json:"attempts"`
|
|
LastAttempt time.Time `json:"last_attempt"`
|
|
LastSuccess time.Time `json:"last_success"`
|
|
BucketType byte `json:"bucket_type"`
|
|
Buckets []int `json:"buckets"`
|
|
}
|
|
|
|
func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
|
|
return &knownAddress{
|
|
Addr: addr,
|
|
Src: src,
|
|
Attempts: 0,
|
|
LastAttempt: time.Now(),
|
|
BucketType: bucketTypeNew,
|
|
Buckets: nil,
|
|
}
|
|
}
|
|
|
|
func (ka *knownAddress) ID() p2p.ID {
|
|
return ka.Addr.ID
|
|
}
|
|
|
|
func (ka *knownAddress) isOld() bool {
|
|
return ka.BucketType == bucketTypeOld
|
|
}
|
|
|
|
func (ka *knownAddress) isNew() bool {
|
|
return ka.BucketType == bucketTypeNew
|
|
}
|
|
|
|
func (ka *knownAddress) markAttempt() {
|
|
now := time.Now()
|
|
ka.LastAttempt = now
|
|
ka.Attempts++
|
|
}
|
|
|
|
func (ka *knownAddress) markGood() {
|
|
now := time.Now()
|
|
ka.LastAttempt = now
|
|
ka.Attempts = 0
|
|
ka.LastSuccess = now
|
|
}
|
|
|
|
func (ka *knownAddress) addBucketRef(bucketIdx int) int {
|
|
for _, bucket := range ka.Buckets {
|
|
if bucket == bucketIdx {
|
|
// TODO refactor to return error?
|
|
// log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
|
|
return -1
|
|
}
|
|
}
|
|
ka.Buckets = append(ka.Buckets, bucketIdx)
|
|
return len(ka.Buckets)
|
|
}
|
|
|
|
func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
|
|
buckets := []int{}
|
|
for _, bucket := range ka.Buckets {
|
|
if bucket != bucketIdx {
|
|
buckets = append(buckets, bucket)
|
|
}
|
|
}
|
|
if len(buckets) != len(ka.Buckets)-1 {
|
|
// TODO refactor to return error?
|
|
// log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
|
|
return -1
|
|
}
|
|
ka.Buckets = buckets
|
|
return len(ka.Buckets)
|
|
}
|
|
|
|
/*
|
|
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 week
|
|
3) It has failed at least three times and never succeeded
|
|
4) It has failed ten times in the last week
|
|
|
|
All addresses that meet these criteria are assumed to be worthless and not
|
|
worth keeping hold of.
|
|
|
|
*/
|
|
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.After(time.Now().Add(-1 * time.Minute)) {
|
|
return false
|
|
}
|
|
|
|
// TODO: From the future?
|
|
|
|
// Too old?
|
|
// TODO: should be a timestamp of last seen, not just last attempt
|
|
if ka.LastAttempt.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
|
|
return true
|
|
}
|
|
|
|
// Never succeeded?
|
|
if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
|
|
return true
|
|
}
|
|
|
|
// Hasn't succeeded in too long?
|
|
if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
|
|
ka.Attempts >= maxFailures {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|