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 }