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