// managedUpdateEntry updates an entry in the hostdb after a scan has taken // place. func (hdb *HostDB) managedUpdateEntry(entry *hostEntry, newSettings modules.HostExternalSettings, netErr error) { hdb.mu.Lock() defer hdb.mu.Unlock() // Regardless of whether the host responded, add it to allHosts. priorHost, exists := hdb.allHosts[entry.NetAddress] if !exists { hdb.allHosts[entry.NetAddress] = entry } // If the scan was unsuccessful, decrement the host's reliability. if netErr != nil { if exists && bytes.Equal(priorHost.PublicKey.Key, entry.PublicKey.Key) { // Only decrement the reliability if the public key in the // hostdb matches the public key in the host announcement - // the failure may just be a failed signature, indicating // the wrong public key. hdb.decrementReliability(entry.NetAddress, UnreachablePenalty) } return } // The host entry should be updated to reflect the new weight. The safety // properties of the tree require that the weight does not change while the // node is in the tree, so the node must be removed before the settings and // weight are changed. existingNode, exists := hdb.activeHosts[entry.NetAddress] if exists { existingNode.removeNode() delete(hdb.activeHosts, entry.NetAddress) } // Update the host settings, reliability, and weight. The old NetAddress // must be preserved. newSettings.NetAddress = entry.HostExternalSettings.NetAddress entry.HostExternalSettings = newSettings entry.Reliability = MaxReliability entry.Weight = calculateHostWeight(*entry) entry.Online = true // If 'maxActiveHosts' has not been reached, add the host to the // activeHosts tree. if _, exists := hdb.activeHosts[entry.NetAddress]; exists || len(hdb.activeHosts) < maxActiveHosts { hdb.insertNode(entry) } hdb.save() }
// verifySettings reads a signed HostSettings object from conn, validates the // signature, and checks for discrepancies between the known settings and the // received settings. If there is a discrepancy, the hostDB is notified. The // received settings are returned. func verifySettings(conn net.Conn, host modules.HostDBEntry) (modules.HostDBEntry, error) { // convert host key (types.SiaPublicKey) to a crypto.PublicKey if host.PublicKey.Algorithm != types.SignatureEd25519 || len(host.PublicKey.Key) != crypto.PublicKeySize { build.Critical("hostdb did not filter out host with wrong signature algorithm:", host.PublicKey.Algorithm) return modules.HostDBEntry{}, errors.New("host used unsupported signature algorithm") } var pk crypto.PublicKey copy(pk[:], host.PublicKey.Key) // read signed host settings var recvSettings modules.HostExternalSettings if err := crypto.ReadSignedObject(conn, &recvSettings, modules.NegotiateMaxHostExternalSettingsLen, pk); err != nil { return modules.HostDBEntry{}, errors.New("couldn't read host's settings: " + err.Error()) } // TODO: check recvSettings against host.HostExternalSettings. If there is // a discrepancy, write the error to conn. if recvSettings.NetAddress != host.NetAddress { // for now, just overwrite the NetAddress, since we know that // host.NetAddress works (it was the one we dialed to get conn) recvSettings.NetAddress = host.NetAddress } host.HostExternalSettings = recvSettings return host, nil }