github.com/DFWallet/tendermint-cosmos@v0.0.2/p2p/pex/known_address.go (about)

     1  package pex
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/DFWallet/tendermint-cosmos/p2p"
     7  )
     8  
     9  // knownAddress tracks information about a known network address
    10  // that is used to determine how viable an address is.
    11  type knownAddress struct {
    12  	Addr        *p2p.NetAddress `json:"addr"`
    13  	Src         *p2p.NetAddress `json:"src"`
    14  	Buckets     []int           `json:"buckets"`
    15  	Attempts    int32           `json:"attempts"`
    16  	BucketType  byte            `json:"bucket_type"`
    17  	LastAttempt time.Time       `json:"last_attempt"`
    18  	LastSuccess time.Time       `json:"last_success"`
    19  	LastBanTime time.Time       `json:"last_ban_time"`
    20  }
    21  
    22  func newKnownAddress(addr *p2p.NetAddress, src *p2p.NetAddress) *knownAddress {
    23  	return &knownAddress{
    24  		Addr:        addr,
    25  		Src:         src,
    26  		Attempts:    0,
    27  		LastAttempt: time.Now(),
    28  		BucketType:  bucketTypeNew,
    29  		Buckets:     nil,
    30  	}
    31  }
    32  
    33  func (ka *knownAddress) ID() p2p.ID {
    34  	return ka.Addr.ID
    35  }
    36  
    37  func (ka *knownAddress) isOld() bool {
    38  	return ka.BucketType == bucketTypeOld
    39  }
    40  
    41  func (ka *knownAddress) isNew() bool {
    42  	return ka.BucketType == bucketTypeNew
    43  }
    44  
    45  func (ka *knownAddress) markAttempt() {
    46  	now := time.Now()
    47  	ka.LastAttempt = now
    48  	ka.Attempts++
    49  }
    50  
    51  func (ka *knownAddress) markGood() {
    52  	now := time.Now()
    53  	ka.LastAttempt = now
    54  	ka.Attempts = 0
    55  	ka.LastSuccess = now
    56  }
    57  
    58  func (ka *knownAddress) ban(banTime time.Duration) {
    59  	if ka.LastBanTime.Before(time.Now().Add(banTime)) {
    60  		ka.LastBanTime = time.Now().Add(banTime)
    61  	}
    62  }
    63  
    64  func (ka *knownAddress) isBanned() bool {
    65  	return ka.LastBanTime.After(time.Now())
    66  }
    67  
    68  func (ka *knownAddress) addBucketRef(bucketIdx int) int {
    69  	for _, bucket := range ka.Buckets {
    70  		if bucket == bucketIdx {
    71  			// TODO refactor to return error?
    72  			// log.Warn(Fmt("Bucket already exists in ka.Buckets: %v", ka))
    73  			return -1
    74  		}
    75  	}
    76  	ka.Buckets = append(ka.Buckets, bucketIdx)
    77  	return len(ka.Buckets)
    78  }
    79  
    80  func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
    81  	buckets := []int{}
    82  	for _, bucket := range ka.Buckets {
    83  		if bucket != bucketIdx {
    84  			buckets = append(buckets, bucket)
    85  		}
    86  	}
    87  	if len(buckets) != len(ka.Buckets)-1 {
    88  		// TODO refactor to return error?
    89  		// log.Warn(Fmt("bucketIdx not found in ka.Buckets: %v", ka))
    90  		return -1
    91  	}
    92  	ka.Buckets = buckets
    93  	return len(ka.Buckets)
    94  }
    95  
    96  /*
    97     An address is bad if the address in question is a New address, has not been tried in the last
    98     minute, and meets one of the following criteria:
    99  
   100     1) It claims to be from the future
   101     2) It hasn't been seen in over a week
   102     3) It has failed at least three times and never succeeded
   103     4) It has failed ten times in the last week
   104  
   105     All addresses that meet these criteria are assumed to be worthless and not
   106     worth keeping hold of.
   107  
   108  */
   109  func (ka *knownAddress) isBad() bool {
   110  	// Is Old --> good
   111  	if ka.BucketType == bucketTypeOld {
   112  		return false
   113  	}
   114  
   115  	// Has been attempted in the last minute --> good
   116  	if ka.LastAttempt.After(time.Now().Add(-1 * time.Minute)) {
   117  		return false
   118  	}
   119  
   120  	// TODO: From the future?
   121  
   122  	// Too old?
   123  	// TODO: should be a timestamp of last seen, not just last attempt
   124  	if ka.LastAttempt.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
   125  		return true
   126  	}
   127  
   128  	// Never succeeded?
   129  	if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
   130  		return true
   131  	}
   132  
   133  	// Hasn't succeeded in too long?
   134  	if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
   135  		ka.Attempts >= maxFailures {
   136  		return true
   137  	}
   138  
   139  	return false
   140  }