Beispiel #1
0
// managedRPCSettings is an rpc that returns the host's settings.
func (h *Host) managedRPCSettings(conn net.Conn) error {
	// Set the negotiation deadline.
	conn.SetDeadline(time.Now().Add(modules.NegotiateSettingsTime))

	// The revision number is updated so that the renter can be certain that
	// they have the most recent copy of the settings. The revision number and
	// signature can be compared against other settings objects that the renter
	// may have, and if the new revision number is not higher the renter can
	// suspect foul play. Largely, the revision number is in place to enable
	// renters to share host settings with each other, a feature that has not
	// yet been implemented.
	//
	// While updating the revision number, also grab the secret key and
	// external settings.
	var hes modules.HostExternalSettings
	var secretKey crypto.SecretKey
	h.mu.Lock()
	h.revisionNumber++
	secretKey = h.secretKey
	hes = h.externalSettings()
	h.mu.Unlock()

	// Write the settings to the renter. If the write fails, return a
	// connection error.
	err := crypto.WriteSignedObject(conn, hes, secretKey)
	if err != nil {
		return ErrorConnection("failed WriteSignedObject during RPCSettings: " + err.Error())
	}
	return nil
}
Beispiel #2
0
// TestThreadedProbeHosts tests the threadedProbeHosts method.
func TestThreadedProbeHosts(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	hdb := bareHostDB()
	hdb.persist = &memPersist{}

	// create a host to send to threadedProbeHosts
	sk, pk, err := crypto.GenerateKeyPair()
	if err != nil {
		t.Fatal(err)
	}
	h := new(hostEntry)
	h.NetAddress = "foo"
	h.AcceptingContracts = true
	h.PublicKey = types.SiaPublicKey{
		Algorithm: types.SignatureEd25519,
		Key:       pk[:],
	}
	h.Reliability = baseWeight // enough to withstand a few failures

	// define a helper function for running threadedProbeHosts. We send the
	// hostEntry, close the channel, and then call threadedProbeHosts.
	// threadedProbeHosts will receive the host, loop once, and return after
	// seeing the channel has closed.
	//
	// NOTE: since threadedProbeHosts decrements hdb.threadGroup, we Add(100)
	// to prevent it from going negative. This is acceptable because we don't
	// call hdb.Close in this test.
	hdb.threadGroup.Add(100)
	runProbe := func(h *hostEntry) {
		hdb.scanPool <- h
		close(hdb.scanPool)
		hdb.threadedProbeHosts()
		// reset hdb.scanPool
		hdb.scanPool = make(chan *hostEntry, 1)
	}

	// make the dial fail
	hdb.dialer = probeDialer(func(modules.NetAddress, time.Duration) (net.Conn, error) {
		return nil, net.UnknownNetworkError("fail")
	})
	runProbe(h)
	if len(hdb.ActiveHosts()) != 0 {
		t.Error("unresponsive host was added")
	}

	// make the RPC fail
	hdb.dialer = probeDialer(func(modules.NetAddress, time.Duration) (net.Conn, error) {
		ourPipe, theirPipe := net.Pipe()
		ourPipe.Close()
		return theirPipe, nil
	})
	runProbe(h)
	if len(hdb.ActiveHosts()) != 0 {
		t.Error("unresponsive host was added")
	}

	// normal host
	hdb.dialer = probeDialer(func(modules.NetAddress, time.Duration) (net.Conn, error) {
		// create an in-memory conn and spawn a goroutine to handle our half
		ourConn, theirConn := net.Pipe()
		go func() {
			// read the RPC
			encoding.ReadObject(ourConn, new(types.Specifier), types.SpecifierLen)
			// write host settings
			crypto.WriteSignedObject(ourConn, modules.HostExternalSettings{
				AcceptingContracts: true,
				NetAddress:         "probed",
			}, sk)
			ourConn.Close()
		}()
		return theirConn, nil
	})
	runProbe(h)
	if len(hdb.ActiveHosts()) != 1 {
		t.Error("host was not added")
	}
}
Beispiel #3
0
// TestThreadedProbeHostsCorruption tests the threadedProbeHosts method,
// specifically checking for corruption of the hostdb if the weight of a host
// changes after a scan.
func TestThreadedProbeHostsCorruption(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}

	hdb := bareHostDB()
	hdb.persist = &memPersist{}

	// create a host to send to threadedProbeHosts
	sk, pk, err := crypto.GenerateKeyPair()
	if err != nil {
		t.Fatal(err)
	}
	h := new(hostEntry)
	h.NetAddress = "foo"
	h.AcceptingContracts = true
	h.PublicKey = types.SiaPublicKey{
		Algorithm: types.SignatureEd25519,
		Key:       pk[:],
	}
	h.Reliability = baseWeight // enough to withstand a few failures

	// define a helper function for running threadedProbeHosts. We send the
	// hostEntry, close the channel, and then call threadedProbeHosts.
	// threadedProbeHosts will receive the host, loop once, and return after
	// seeing the channel has closed.
	//
	// NOTE: since threadedProbeHosts decrements hdb.threadGroup, we Add(100)
	// to prevent it from going negative. This is acceptable because we don't
	// call hdb.Close in this test.
	hdb.threadGroup.Add(100)
	runProbe := func(h *hostEntry) {
		hdb.scanPool <- h
		close(hdb.scanPool)
		hdb.threadedProbeHosts()
		// reset hdb.scanPool
		hdb.scanPool = make(chan *hostEntry, 1)
	}

	// Add a normal host.
	hdb.dialer = probeDialer(func(modules.NetAddress, time.Duration) (net.Conn, error) {
		// create an in-memory conn and spawn a goroutine to handle our half
		ourConn, theirConn := net.Pipe()
		go func() {
			// read the RPC
			encoding.ReadObject(ourConn, new(types.Specifier), types.SpecifierLen)
			// write host settings
			crypto.WriteSignedObject(ourConn, modules.HostExternalSettings{
				AcceptingContracts: true,
				StoragePrice:       types.NewCurrency64(15e6),
				NetAddress:         "probed",
			}, sk)
			ourConn.Close()
		}()
		return theirConn, nil
	})
	runProbe(h)
	if len(hdb.ActiveHosts()) != 1 {
		t.Error("host was not added")
	}

	// Add the host again, this time changing the storage price, which will
	// change the weight of the host, which at one point would cause a
	// corruption of the host tree.
	hdb.dialer = probeDialer(func(modules.NetAddress, time.Duration) (net.Conn, error) {
		// create an in-memory conn and spawn a goroutine to handle our half
		ourConn, theirConn := net.Pipe()
		go func() {
			// read the RPC
			encoding.ReadObject(ourConn, new(types.Specifier), types.SpecifierLen)
			// write host settings
			crypto.WriteSignedObject(ourConn, modules.HostExternalSettings{
				AcceptingContracts: true,
				StoragePrice:       types.NewCurrency64(15e3), // Lower than the previous, to cause a higher weight.
				NetAddress:         "probed",
			}, sk)
			ourConn.Close()
		}()
		return theirConn, nil
	})
	runProbe(h)
	if len(hdb.ActiveHosts()) != 1 {
		t.Error("host was not added")
	}

	// Check that the host tree has not been corrupted.
	err = repeatCheck(hdb.hostTree)
	if err != nil {
		t.Error(err)
	}
	err = uniformTreeVerification(hdb, 1)
	if err != nil {
		t.Error(err)
	}
}