github.com/pure-x-eth/consensus_tm@v0.0.0-20230502163723-e3c2ff987250/p2p/pex/known_address.go (about)

     1  package pex
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/pure-x-eth/consensus_tm/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  func (ka *knownAddress) isBad() bool {
   109  	// Is Old --> good
   110  	if ka.BucketType == bucketTypeOld {
   111  		return false
   112  	}
   113  
   114  	// Has been attempted in the last minute --> good
   115  	if ka.LastAttempt.After(time.Now().Add(-1 * time.Minute)) {
   116  		return false
   117  	}
   118  
   119  	// TODO: From the future?
   120  
   121  	// Too old?
   122  	// TODO: should be a timestamp of last seen, not just last attempt
   123  	if ka.LastAttempt.Before(time.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
   124  		return true
   125  	}
   126  
   127  	// Never succeeded?
   128  	if ka.LastSuccess.IsZero() && ka.Attempts >= numRetries {
   129  		return true
   130  	}
   131  
   132  	// Hasn't succeeded in too long?
   133  	if ka.LastSuccess.Before(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
   134  		ka.Attempts >= maxFailures {
   135  		return true
   136  	}
   137  
   138  	return false
   139  }