github.com/number571/tendermint@v0.34.11-gost/internal/p2p/pex/known_address.go (about)

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