github.com/nebulouslabs/sia@v1.3.7/modules/renter/hostdb/update.go (about)

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