gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/hostdb/update.go (about)

     1  package hostdb
     2  
     3  import (
     4  	"time"
     5  
     6  	"gitlab.com/NebulousLabs/errors"
     7  	"gitlab.com/SkynetLabs/skyd/build"
     8  	"gitlab.com/SkynetLabs/skyd/skymodules"
     9  	"go.sia.tech/siad/modules"
    10  	"go.sia.tech/siad/types"
    11  )
    12  
    13  // findHostAnnouncements returns a list of the host announcements found within
    14  // a given block. No check is made to see that the ip address found in the
    15  // announcement is actually a valid ip address.
    16  func findHostAnnouncements(b types.Block) (announcements []skymodules.HostDBEntry) {
    17  	for _, t := range b.Transactions {
    18  		// the HostAnnouncement must be prefaced by the standard host
    19  		// announcement string
    20  		for _, arb := range t.ArbitraryData {
    21  			addr, pubKey, err := modules.DecodeAnnouncement(arb)
    22  			if err != nil {
    23  				continue
    24  			}
    25  
    26  			// Add the announcement to the slice being returned.
    27  			var host skymodules.HostDBEntry
    28  			host.NetAddress = addr
    29  			host.PublicKey = pubKey
    30  			announcements = append(announcements, host)
    31  		}
    32  	}
    33  	return
    34  }
    35  
    36  // insertBlockchainHost adds a host entry to the state. The host will be inserted
    37  // into the set of all hosts, and if it is online and responding to requests it
    38  // will be put into the list of active hosts.
    39  func (hdb *HostDB) insertBlockchainHost(host skymodules.HostDBEntry) {
    40  	// Remove garbage hosts and local hosts (but allow local hosts in testing).
    41  	if err := host.NetAddress.IsValid(); err != nil {
    42  		hdb.staticLog.Debugf("WARN: host '%v' has an invalid NetAddress: %v", host.NetAddress, err)
    43  		return
    44  	}
    45  	// Ignore all local hosts announced through the blockchain.
    46  	if build.Release == "standard" && host.NetAddress.IsLocal() {
    47  		return
    48  	}
    49  
    50  	// Make sure the host gets into the host tree so it does not get dropped if
    51  	// shutdown occurs before a scan can be performed.
    52  	oldEntry, exists := hdb.staticHostTree.Select(host.PublicKey)
    53  	if exists {
    54  		// Replace the netaddress with the most recently announced netaddress.
    55  		// Also replace the FirstSeen value with the current block height if
    56  		// the first seen value has been set to zero (no hosts actually have a
    57  		// first seen height of zero, but due to rescans hosts can end up with
    58  		// a zero-value FirstSeen field.
    59  		oldEntry.NetAddress = host.NetAddress
    60  		if oldEntry.FirstSeen == 0 {
    61  			oldEntry.FirstSeen = hdb.blockHeight
    62  		}
    63  		// Resolve the host's used subnets and update the timestamp if they
    64  		// changed. We only update the timestamp if resolving the ipNets was
    65  		// successful.
    66  		ipNets, err := hdb.staticLookupIPNets(oldEntry.NetAddress)
    67  		if err == nil && !equalIPNets(ipNets, oldEntry.IPNets) {
    68  			oldEntry.IPNets = ipNets
    69  			oldEntry.LastIPNetChange = time.Now()
    70  		}
    71  		// Modify hosttree
    72  		err = hdb.modify(oldEntry)
    73  		if errors.Contains(err, errHostDomainBlocked) {
    74  			// Host is blocked, remove from the hosttree
    75  			err = errors.AddContext(hdb.remove(oldEntry.PublicKey), "unable to remove blocked host from host tree")
    76  		}
    77  		if err != nil {
    78  			hdb.staticLog.Println("ERROR: unable to modify host entry of host tree after a blockchain scan:", err)
    79  		}
    80  	} else {
    81  		host.FirstSeen = hdb.blockHeight
    82  		// Insert into hosttree
    83  		err := hdb.insert(host)
    84  		if errors.Contains(err, errHostDomainBlocked) {
    85  			hdb.staticLog.Debugf("Could not insert host %v to the hostdb. Host domain blocked %v\n", host.PublicKey.String(), host.NetAddress)
    86  		} else if err != nil {
    87  			hdb.staticLog.Println("ERROR: unable to insert host entry into host tree after a blockchain scan:", err)
    88  		}
    89  	}
    90  
    91  	// Add the host to the scan queue.
    92  	hdb.queueScan(host)
    93  }
    94  
    95  // ProcessConsensusChange will be called by the consensus set every time there
    96  // is a change in the blockchain. Updates will always be called in order.
    97  func (hdb *HostDB) ProcessConsensusChange(cc modules.ConsensusChange) {
    98  	hdb.mu.Lock()
    99  	defer hdb.mu.Unlock()
   100  
   101  	// Update the hostdb's understanding of the block height.
   102  	for _, block := range cc.RevertedBlocks {
   103  		// Only doing the block check if the height is above zero saves hashing
   104  		// and saves a nontrivial amount of time during IBD.
   105  		if hdb.blockHeight > 0 || block.ID() != types.GenesisID {
   106  			hdb.blockHeight--
   107  		} else if hdb.blockHeight != 0 {
   108  			// Sanity check - if the current block is the genesis block, the
   109  			// hostdb height should be set to zero.
   110  			hdb.staticLog.Critical("Hostdb has detected a genesis block, but the height of the hostdb is set to ", hdb.blockHeight)
   111  			hdb.blockHeight = 0
   112  		}
   113  	}
   114  	for _, block := range cc.AppliedBlocks {
   115  		// Only doing the block check if the height is above zero saves hashing
   116  		// and saves a nontrivial amount of time during IBD.
   117  		if hdb.blockHeight > 0 || block.ID() != types.GenesisID {
   118  			hdb.blockHeight++
   119  		} else if hdb.blockHeight != 0 {
   120  			// Sanity check - if the current block is the genesis block, the
   121  			// hostdb height should be set to zero.
   122  			hdb.staticLog.Critical("Hostdb has detected a genesis block, but the height of the hostdb is set to ", hdb.blockHeight)
   123  			hdb.blockHeight = 0
   124  		}
   125  	}
   126  
   127  	// Add hosts announced in blocks that were applied.
   128  	for _, block := range cc.AppliedBlocks {
   129  		for _, host := range findHostAnnouncements(block) {
   130  			hdb.staticLog.Debugln("Found a host in a host announcement:", host.NetAddress, host.PublicKey)
   131  			hdb.insertBlockchainHost(host)
   132  		}
   133  	}
   134  
   135  	hdb.synced = cc.Synced
   136  	hdb.lastChange = cc.ID
   137  }