Example #1
0
// 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
}
Example #2
0
// 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()
}