github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/renter/hostdb/update.go (about) 1 package hostdb 2 3 import ( 4 "time" 5 6 "SiaPrime/build" 7 "SiaPrime/modules" 8 "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 err = hdb.hostTree.Modify(oldEntry) 70 if err != nil { 71 hdb.log.Println("ERROR: unable to modify host entry of host tree after a blockchain scan:", err) 72 } 73 } else { 74 host.FirstSeen = hdb.blockHeight 75 err := hdb.hostTree.Insert(host) 76 if err != nil { 77 hdb.log.Println("ERROR: unable to insert host entry into host tree after a blockchain scan:", err) 78 } 79 } 80 81 // Add the host to the scan queue. 82 hdb.queueScan(host) 83 } 84 85 // ProcessConsensusChange will be called by the consensus set every time there 86 // is a change in the blockchain. Updates will always be called in order. 87 func (hdb *HostDB) ProcessConsensusChange(cc modules.ConsensusChange) { 88 hdb.mu.Lock() 89 defer hdb.mu.Unlock() 90 91 // Update the hostdb's understanding of the block height. 92 for _, block := range cc.RevertedBlocks { 93 // Only doing the block check if the height is above zero saves hashing 94 // and saves a nontrivial amount of time during IBD. 95 if hdb.blockHeight > 0 || block.ID() != types.GenesisID { 96 hdb.blockHeight-- 97 } else if hdb.blockHeight != 0 { 98 // Sanity check - if the current block is the genesis block, the 99 // hostdb height should be set to zero. 100 hdb.log.Critical("Hostdb has detected a genesis block, but the height of the hostdb is set to ", hdb.blockHeight) 101 hdb.blockHeight = 0 102 } 103 } 104 for _, block := range cc.AppliedBlocks { 105 // Only doing the block check if the height is above zero saves hashing 106 // and saves a nontrivial amount of time during IBD. 107 if hdb.blockHeight > 0 || block.ID() != types.GenesisID { 108 hdb.blockHeight++ 109 } else if hdb.blockHeight != 0 { 110 // Sanity check - if the current block is the genesis block, the 111 // hostdb height should be set to zero. 112 hdb.log.Critical("Hostdb has detected a genesis block, but the height of the hostdb is set to ", hdb.blockHeight) 113 hdb.blockHeight = 0 114 } 115 } 116 117 // Add hosts announced in blocks that were applied. 118 for _, block := range cc.AppliedBlocks { 119 for _, host := range findHostAnnouncements(block) { 120 hdb.log.Debugln("Found a host in a host announcement:", host.NetAddress, host.PublicKey) 121 hdb.insertBlockchainHost(host) 122 } 123 } 124 125 hdb.lastChange = cc.ID 126 }