github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/node/api/hostdb_test.go (about)

     1  package api
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/url"
     9  	"path/filepath"
    10  	"testing"
    11  	"time"
    12  
    13  	"SiaPrime/build"
    14  	"SiaPrime/crypto"
    15  	"SiaPrime/modules"
    16  	"SiaPrime/modules/consensus"
    17  	"SiaPrime/modules/gateway"
    18  	"SiaPrime/modules/host"
    19  	"SiaPrime/modules/miner"
    20  	"SiaPrime/modules/renter"
    21  	"SiaPrime/modules/transactionpool"
    22  	"SiaPrime/modules/wallet"
    23  )
    24  
    25  // TestHostDBHostsActiveHandler checks the behavior of the call to
    26  // /hostdb/active.
    27  func TestHostDBHostsActiveHandler(t *testing.T) {
    28  	if testing.Short() {
    29  		t.SkipNow()
    30  	}
    31  	st, err := createServerTester(t.Name())
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  	defer st.server.panicClose()
    36  
    37  	// Try the call with numhosts unset, and set to -1, 0, and 1.
    38  	var ah HostdbActiveGET
    39  	err = st.getAPI("/hostdb/active", &ah)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	if len(ah.Hosts) != 0 {
    44  		t.Fatal(len(ah.Hosts))
    45  	}
    46  	err = st.getAPI("/hostdb/active?numhosts=-1", &ah)
    47  	if err == nil {
    48  		t.Fatal("expecting an error, got:", err)
    49  	}
    50  	err = st.getAPI("/hostdb/active?numhosts=0", &ah)
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	if len(ah.Hosts) != 0 {
    55  		t.Fatal(len(ah.Hosts))
    56  	}
    57  	err = st.getAPI("/hostdb/active?numhosts=1", &ah)
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  	if len(ah.Hosts) != 0 {
    62  		t.Fatal(len(ah.Hosts))
    63  	}
    64  
    65  	// announce the host and start accepting contracts
    66  	err = st.announceHost()
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	err = st.acceptContracts()
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	err = st.setHostStorage()
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	// Try the call with with numhosts unset, and set to -1, 0, 1, and 2.
    80  	err = st.getAPI("/hostdb/active", &ah)
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  	if len(ah.Hosts) != 1 {
    85  		t.Fatal(len(ah.Hosts))
    86  	}
    87  	err = st.getAPI("/hostdb/active?numhosts=-1", &ah)
    88  	if err == nil {
    89  		t.Fatal("expecting an error, got:", err)
    90  	}
    91  	err = st.getAPI("/hostdb/active?numhosts=0", &ah)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  	if len(ah.Hosts) != 0 {
    96  		t.Fatal(len(ah.Hosts))
    97  	}
    98  	err = st.getAPI("/hostdb/active?numhosts=1", &ah)
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  	if len(ah.Hosts) != 1 {
   103  		t.Fatal(len(ah.Hosts))
   104  	}
   105  	err = st.getAPI("/hostdb/active?numhosts=2", &ah)
   106  	if err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	if len(ah.Hosts) != 1 {
   110  		t.Fatal(len(ah.Hosts))
   111  	}
   112  }
   113  
   114  // TestHostDBHostsAllHandler checks that announcing a host adds it to the list
   115  // of all hosts.
   116  func TestHostDBHostsAllHandler(t *testing.T) {
   117  	if testing.Short() {
   118  		t.SkipNow()
   119  	}
   120  	st, err := createServerTester(t.Name())
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  	defer st.server.panicClose()
   125  
   126  	// Try the call before any hosts have been declared.
   127  	var ah HostdbAllGET
   128  	if err = st.getAPI("/hostdb/all", &ah); err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	if len(ah.Hosts) != 0 {
   132  		t.Fatalf("expected 0 hosts, got %v", len(ah.Hosts))
   133  	}
   134  	// Announce the host and try the call again.
   135  	if err = st.announceHost(); err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	if err = st.getAPI("/hostdb/all", &ah); err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	if len(ah.Hosts) != 1 {
   142  		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
   143  	}
   144  }
   145  
   146  // TestHostDBHostsHandler checks that the hosts handler is easily able to return
   147  func TestHostDBHostsHandler(t *testing.T) {
   148  	if testing.Short() {
   149  		t.SkipNow()
   150  	}
   151  	st, err := createServerTester(t.Name())
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	defer st.server.panicClose()
   156  
   157  	// Announce the host and then get the list of hosts.
   158  	var ah HostdbActiveGET
   159  	if err = st.announceHost(); err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	if err = st.getAPI("/hostdb/active", &ah); err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	if len(ah.Hosts) != 1 {
   166  		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
   167  	}
   168  
   169  	// Parse the pubkey from the returned list of hosts and use it to form a
   170  	// request regarding the specific host.
   171  	keyString := ah.Hosts[0].PublicKey.String()
   172  	if keyString != ah.Hosts[0].PublicKeyString {
   173  		t.Error("actual key string and provided string do not match")
   174  	}
   175  	query := fmt.Sprintf("/hostdb/hosts/%s", ah.Hosts[0].PublicKeyString)
   176  
   177  	// Get the detailed info for the host.
   178  	var hh HostdbHostsGET
   179  	if err = st.getAPI(query, &hh); err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	// Check that none of the values equal zero. A value of zero indicates that
   184  	// the field is no longer being tracked/reported, which could break
   185  	// compatibility for some apps. The default needs to be '1', not zero.
   186  	if hh.ScoreBreakdown.Score.IsZero() {
   187  		t.Error("Zero vaue score in score breakdown")
   188  	}
   189  	if hh.ScoreBreakdown.AgeAdjustment == 0 {
   190  		t.Error("Zero value in host score breakdown")
   191  	}
   192  	if hh.ScoreBreakdown.BurnAdjustment == 0 {
   193  		t.Error("Zero value in host score breakdown")
   194  	}
   195  	if hh.ScoreBreakdown.CollateralAdjustment == 0 {
   196  		t.Error("Zero value in host score breakdown")
   197  	}
   198  	if hh.ScoreBreakdown.PriceAdjustment == 0 {
   199  		t.Error("Zero value in host score breakdown")
   200  	}
   201  	if hh.ScoreBreakdown.StorageRemainingAdjustment == 0 {
   202  		t.Error("Zero value in host score breakdown")
   203  	}
   204  	if hh.ScoreBreakdown.UptimeAdjustment == 0 {
   205  		t.Error("Zero value in host score breakdown")
   206  	}
   207  	if hh.ScoreBreakdown.VersionAdjustment == 0 {
   208  		t.Error("Zero value in host score breakdown")
   209  	}
   210  
   211  	// Check that none of the supported values equals 1. A value of 1 indicates
   212  	// that the hostdb is not performing any penalties or rewards for that
   213  	// field, meaning that the calibration for that field is probably incorrect.
   214  	if hh.ScoreBreakdown.AgeAdjustment == 1 {
   215  		t.Error("One value in host score breakdown")
   216  	}
   217  	// Burn adjustment is not yet supported.
   218  	//
   219  	// if hh.ScoreBreakdown.BurnAdjustment == 1 {
   220  	//	t.Error("One value in host score breakdown")
   221  	// }
   222  	if hh.ScoreBreakdown.CollateralAdjustment == 1 {
   223  		t.Error("One value in host score breakdown")
   224  	}
   225  	if hh.ScoreBreakdown.PriceAdjustment == 1 {
   226  		t.Error("One value in host score breakdown")
   227  	}
   228  	if hh.ScoreBreakdown.StorageRemainingAdjustment == 1 {
   229  		t.Error("One value in host score breakdown")
   230  	}
   231  	if hh.ScoreBreakdown.UptimeAdjustment == 1 {
   232  		t.Error("One value in host score breakdown")
   233  	}
   234  	if hh.ScoreBreakdown.VersionAdjustment == 1 {
   235  		t.Error("One value in host score breakdown")
   236  	}
   237  }
   238  
   239  // assembleHostHostname is assembleServerTester but you can specify which
   240  // hostname the host should use.
   241  func assembleHostPort(key crypto.TwofishKey, hostHostname string, testdir string) (*serverTester, error) {
   242  	// assembleServerTester should not get called during short tests, as it
   243  	// takes a long time to run.
   244  	if testing.Short() {
   245  		panic("assembleServerTester called during short tests")
   246  	}
   247  
   248  	// Create the modules.
   249  	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
   250  	if err != nil {
   251  		return nil, err
   252  	}
   253  	cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir))
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir))
   258  	if err != nil {
   259  		return nil, err
   260  	}
   261  	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  	encrypted, err := w.Encrypted()
   266  	if err != nil {
   267  		return nil, err
   268  	}
   269  	if !encrypted {
   270  		_, err = w.Encrypt(key)
   271  		if err != nil {
   272  			return nil, err
   273  		}
   274  	}
   275  	err = w.Unlock(key)
   276  	if err != nil {
   277  		return nil, err
   278  	}
   279  	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
   280  	if err != nil {
   281  		return nil, err
   282  	}
   283  	h, err := host.New(cs, g, tp, w, hostHostname, filepath.Join(testdir, modules.HostDir))
   284  	if err != nil {
   285  		return nil, err
   286  	}
   287  	r, err := renter.New(g, cs, w, tp, filepath.Join(testdir, modules.RenterDir))
   288  	if err != nil {
   289  		return nil, err
   290  	}
   291  	srv, err := NewServer("localhost:0", "Sia-PrimeAgent", "", cs, nil, g, h, m, r, tp, w, nil, nil, nil)
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  
   296  	// Assemble the serverTester.
   297  	st := &serverTester{
   298  		cs:        cs,
   299  		gateway:   g,
   300  		host:      h,
   301  		miner:     m,
   302  		renter:    r,
   303  		tpool:     tp,
   304  		wallet:    w,
   305  		walletKey: key,
   306  
   307  		server: srv,
   308  
   309  		dir: testdir,
   310  	}
   311  
   312  	// TODO: A more reasonable way of listening for server errors.
   313  	go func() {
   314  		listenErr := srv.Serve()
   315  		if listenErr != nil {
   316  			panic(listenErr)
   317  		}
   318  	}()
   319  	return st, nil
   320  }
   321  
   322  // TestHostDBScanOnlineOffline checks that both online and offline hosts get
   323  // scanned in the hostdb.
   324  func TestHostDBScanOnlineOffline(t *testing.T) {
   325  	if testing.Short() || !build.VLONG {
   326  		t.SkipNow()
   327  	}
   328  	t.Parallel()
   329  	st, err := createServerTester(t.Name())
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  	defer st.panicClose()
   334  	stHost, err := blankServerTester(t.Name() + "-Host")
   335  	if err != nil {
   336  		t.Fatal(err)
   337  	}
   338  	sts := []*serverTester{st, stHost}
   339  	err = fullyConnectNodes(sts)
   340  	if err != nil {
   341  		t.Fatal(err)
   342  	}
   343  	err = fundAllNodes(sts)
   344  	if err != nil {
   345  		t.Fatal(err)
   346  	}
   347  
   348  	// Announce the host.
   349  	err = stHost.acceptContracts()
   350  	if err != nil {
   351  		t.Fatal(err)
   352  	}
   353  	err = stHost.setHostStorage()
   354  	if err != nil {
   355  		t.Fatal(err)
   356  	}
   357  	err = stHost.announceHost()
   358  	if err != nil {
   359  		t.Fatal(err)
   360  	}
   361  
   362  	// Verify the host is visible.
   363  	var ah HostdbActiveGET
   364  	for i := 0; i < 50; i++ {
   365  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   366  			t.Fatal(err)
   367  		}
   368  		if len(ah.Hosts) == 1 {
   369  			break
   370  		}
   371  		time.Sleep(time.Millisecond * 100)
   372  	}
   373  	if len(ah.Hosts) != 1 {
   374  		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
   375  	}
   376  	hostAddr := ah.Hosts[0].NetAddress
   377  
   378  	// Close the host and wait for a scan to knock the host out of the hostdb.
   379  	err = stHost.server.Close()
   380  	if err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	err = build.Retry(60, time.Second, func() error {
   384  		if err := st.getAPI("/hostdb/active", &ah); err != nil {
   385  			return err
   386  		}
   387  		if len(ah.Hosts) == 0 {
   388  			return nil
   389  		}
   390  		return errors.New("host still in hostdb")
   391  	})
   392  	if err != nil {
   393  		t.Fatal(err)
   394  	}
   395  
   396  	// Reopen the host and wait for a scan to bring the host back into the
   397  	// hostdb.
   398  	stHost, err = assembleHostPort(stHost.walletKey, string(hostAddr), stHost.dir)
   399  	if err != nil {
   400  		t.Fatal(err)
   401  	}
   402  	defer stHost.panicClose()
   403  	sts[1] = stHost
   404  	err = fullyConnectNodes(sts)
   405  	if err != nil {
   406  		t.Fatal(err)
   407  	}
   408  	err = build.Retry(60, time.Second, func() error {
   409  		// Get the hostdb internals.
   410  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   411  			return err
   412  		}
   413  		if len(ah.Hosts) != 1 {
   414  			return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts))
   415  		}
   416  		return nil
   417  	})
   418  	if err != nil {
   419  		t.Fatal(err)
   420  	}
   421  }
   422  
   423  // TestHostDBAndRenterDownloadDynamicIPs checks that the hostdb and the renter are
   424  // successfully able to follow a host that has changed IP addresses and then
   425  // re-announced.
   426  func TestHostDBAndRenterDownloadDynamicIPs(t *testing.T) {
   427  	if testing.Short() || !build.VLONG {
   428  		t.SkipNow()
   429  	}
   430  	t.Parallel()
   431  	st, err := createServerTester(t.Name())
   432  	if err != nil {
   433  		t.Fatal(err)
   434  	}
   435  	defer st.panicClose()
   436  	stHost, err := blankServerTester(t.Name() + "-Host")
   437  	if err != nil {
   438  		t.Fatal(err)
   439  	}
   440  	sts := []*serverTester{st, stHost}
   441  	err = fullyConnectNodes(sts)
   442  	if err != nil {
   443  		t.Fatal(err)
   444  	}
   445  	err = fundAllNodes(sts)
   446  	if err != nil {
   447  		t.Fatal(err)
   448  	}
   449  
   450  	// Announce the host.
   451  	err = stHost.acceptContracts()
   452  	if err != nil {
   453  		t.Fatal(err)
   454  	}
   455  	err = stHost.setHostStorage()
   456  	if err != nil {
   457  		t.Fatal(err)
   458  	}
   459  	err = stHost.announceHost()
   460  	if err != nil {
   461  		t.Fatal(err)
   462  	}
   463  
   464  	// Pull the host's net address and pubkey from the hostdb.
   465  	var ah HostdbActiveGET
   466  	for i := 0; i < 50; i++ {
   467  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   468  			t.Fatal(err)
   469  		}
   470  		if len(ah.Hosts) == 1 {
   471  			break
   472  		}
   473  		time.Sleep(time.Millisecond * 100)
   474  	}
   475  	if len(ah.Hosts) != 1 {
   476  		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
   477  	}
   478  	addr := ah.Hosts[0].NetAddress
   479  	pks := ah.Hosts[0].PublicKeyString
   480  
   481  	// Upload a file to the host.
   482  	allowanceValues := url.Values{}
   483  	testFunds := "10000000000000000000000000000" // 10k SC
   484  	testPeriod := "10"
   485  	testPeriodInt := 10
   486  	allowanceValues.Set("funds", testFunds)
   487  	allowanceValues.Set("period", testPeriod)
   488  	err = st.stdPostAPI("/renter", allowanceValues)
   489  	if err != nil {
   490  		t.Fatal(err)
   491  	}
   492  	// Create a file.
   493  	path := filepath.Join(st.dir, "test.dat")
   494  	err = createRandFile(path, 1024)
   495  	if err != nil {
   496  		t.Fatal(err)
   497  	}
   498  	// Upload the file to the renter.
   499  	uploadValues := url.Values{}
   500  	uploadValues.Set("source", path)
   501  	err = st.stdPostAPI("/renter/upload/test", uploadValues)
   502  	if err != nil {
   503  		t.Fatal(err)
   504  	}
   505  	// Only one piece will be uploaded (10% at current redundancy).
   506  	var rf RenterFiles
   507  	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
   508  		st.getAPI("/renter/files", &rf)
   509  		time.Sleep(100 * time.Millisecond)
   510  	}
   511  	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
   512  		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
   513  	}
   514  
   515  	// Try downloading the file.
   516  	downpath := filepath.Join(st.dir, "testdown.dat")
   517  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
   518  	if err != nil {
   519  		t.Fatal(err)
   520  	}
   521  	// Check that the download has the right contents.
   522  	orig, err := ioutil.ReadFile(path)
   523  	if err != nil {
   524  		t.Fatal(err)
   525  	}
   526  	download, err := ioutil.ReadFile(downpath)
   527  	if err != nil {
   528  		t.Fatal(err)
   529  	}
   530  	if !bytes.Equal(orig, download) {
   531  		t.Fatal("data mismatch when downloading a file")
   532  	}
   533  
   534  	// Mine a block before resetting the host, so that the host doesn't lose
   535  	// it's contracts when the transaction pool resets.
   536  	_, err = st.miner.AddBlock()
   537  	if err != nil {
   538  		t.Fatal(err)
   539  	}
   540  	_, err = synchronizationCheck(sts)
   541  	if err != nil {
   542  		t.Fatal(err)
   543  	}
   544  	// Give time for the upgrade to happen.
   545  	time.Sleep(time.Second * 3)
   546  
   547  	// Close and re-open the host. This should reset the host's address, as the
   548  	// host should now be on a new port.
   549  	err = stHost.server.Close()
   550  	if err != nil {
   551  		t.Fatal(err)
   552  	}
   553  	stHost, err = assembleServerTester(stHost.walletKey, stHost.dir)
   554  	if err != nil {
   555  		t.Fatal(err)
   556  	}
   557  	defer stHost.panicClose()
   558  	sts[1] = stHost
   559  	err = fullyConnectNodes(sts)
   560  	if err != nil {
   561  		t.Fatal(err)
   562  	}
   563  	err = stHost.announceHost()
   564  	if err != nil {
   565  		t.Fatal(err)
   566  	}
   567  	// Pull the host's net address and pubkey from the hostdb.
   568  	err = build.Retry(100, time.Millisecond*200, func() error {
   569  		// Get the hostdb internals.
   570  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   571  			return err
   572  		}
   573  
   574  		// Get the host's internals.
   575  		var hg HostGET
   576  		if err = stHost.getAPI("/host", &hg); err != nil {
   577  			return err
   578  		}
   579  
   580  		if len(ah.Hosts) != 1 {
   581  			return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts))
   582  		}
   583  		if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress {
   584  			return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress)
   585  		}
   586  		return nil
   587  	})
   588  	if err != nil {
   589  		t.Fatal(err)
   590  	}
   591  	if ah.Hosts[0].PublicKeyString != pks {
   592  		t.Error("public key appears to have changed for host")
   593  	}
   594  	if ah.Hosts[0].NetAddress == addr {
   595  		t.Log("NetAddress did not change for the new host")
   596  	}
   597  
   598  	// Try downloading the file.
   599  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
   600  	if err != nil {
   601  		t.Fatal(err)
   602  	}
   603  	// Check that the download has the right contents.
   604  	download, err = ioutil.ReadFile(downpath)
   605  	if err != nil {
   606  		t.Fatal(err)
   607  	}
   608  	if !bytes.Equal(orig, download) {
   609  		t.Fatal("data mismatch when downloading a file")
   610  	}
   611  
   612  	// Mine enough blocks that multiple renew cylces happen. After the renewing
   613  	// happens, the file should still be downloadable. This is to check that the
   614  	// renewal doesn't throw things off.
   615  	for i := 0; i < testPeriodInt; i++ {
   616  		_, err = st.miner.AddBlock()
   617  		if err != nil {
   618  			t.Fatal(err)
   619  		}
   620  		_, err = synchronizationCheck(sts)
   621  		if err != nil {
   622  			t.Fatal(err)
   623  		}
   624  	}
   625  	err = build.Retry(100, time.Millisecond*100, func() error {
   626  		err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
   627  		if err != nil {
   628  			return err
   629  		}
   630  		// Try downloading the file.
   631  		// Check that the download has the right contents.
   632  		download, err = ioutil.ReadFile(downpath)
   633  		if err != nil {
   634  			return err
   635  		}
   636  		if !bytes.Equal(orig, download) {
   637  			return errors.New("downloaded file does not equal the original")
   638  		}
   639  		return nil
   640  	})
   641  	if err != nil {
   642  		t.Fatal(err)
   643  	}
   644  }
   645  
   646  // TestHostDBAndRenterUploadDynamicIPs checks that the hostdb and the renter are
   647  // successfully able to follow a host that has changed IP addresses and then
   648  // re-announced.
   649  func TestHostDBAndRenterUploadDynamicIPs(t *testing.T) {
   650  	if testing.Short() || !build.VLONG {
   651  		t.SkipNow()
   652  	}
   653  	t.Parallel()
   654  	st, err := createServerTester(t.Name())
   655  	if err != nil {
   656  		t.Fatal(err)
   657  	}
   658  	defer st.panicClose()
   659  	stHost, err := blankServerTester(t.Name() + "-Host")
   660  	if err != nil {
   661  		t.Fatal(err)
   662  	}
   663  	sts := []*serverTester{st, stHost}
   664  	err = fullyConnectNodes(sts)
   665  	if err != nil {
   666  		t.Fatal(err)
   667  	}
   668  	err = fundAllNodes(sts)
   669  	if err != nil {
   670  		t.Fatal(err)
   671  	}
   672  
   673  	// Announce the host.
   674  	err = stHost.acceptContracts()
   675  	if err != nil {
   676  		t.Fatal(err)
   677  	}
   678  	err = stHost.setHostStorage()
   679  	if err != nil {
   680  		t.Fatal(err)
   681  	}
   682  	err = stHost.announceHost()
   683  	if err != nil {
   684  		t.Fatal(err)
   685  	}
   686  
   687  	// Pull the host's net address and pubkey from the hostdb.
   688  	var ah HostdbActiveGET
   689  	for i := 0; i < 50; i++ {
   690  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   691  			t.Fatal(err)
   692  		}
   693  		if len(ah.Hosts) == 1 {
   694  			break
   695  		}
   696  		time.Sleep(time.Millisecond * 100)
   697  	}
   698  	if len(ah.Hosts) != 1 {
   699  		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
   700  	}
   701  	addr := ah.Hosts[0].NetAddress
   702  	pks := ah.Hosts[0].PublicKeyString
   703  
   704  	// Upload a file to the host.
   705  	allowanceValues := url.Values{}
   706  	testFunds := "10000000000000000000000000000" // 10k SC
   707  	testPeriod := "10"
   708  	testPeriodInt := 10
   709  	allowanceValues.Set("funds", testFunds)
   710  	allowanceValues.Set("period", testPeriod)
   711  	err = st.stdPostAPI("/renter", allowanceValues)
   712  	if err != nil {
   713  		t.Fatal(err)
   714  	}
   715  	// Create a file.
   716  	path := filepath.Join(st.dir, "test.dat")
   717  	err = createRandFile(path, 1024)
   718  	if err != nil {
   719  		t.Fatal(err)
   720  	}
   721  	// Upload the file to the renter.
   722  	uploadValues := url.Values{}
   723  	uploadValues.Set("source", path)
   724  	err = st.stdPostAPI("/renter/upload/test", uploadValues)
   725  	if err != nil {
   726  		t.Fatal(err)
   727  	}
   728  	// Only one piece will be uploaded (10% at current redundancy).
   729  	var rf RenterFiles
   730  	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
   731  		st.getAPI("/renter/files", &rf)
   732  		time.Sleep(100 * time.Millisecond)
   733  	}
   734  	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
   735  		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
   736  	}
   737  
   738  	// Mine a block before resetting the host, so that the host doesn't lose
   739  	// it's contracts when the transaction pool resets.
   740  	_, err = st.miner.AddBlock()
   741  	if err != nil {
   742  		t.Fatal(err)
   743  	}
   744  	_, err = synchronizationCheck(sts)
   745  	if err != nil {
   746  		t.Fatal(err)
   747  	}
   748  	// Give time for the upgrade to happen.
   749  	time.Sleep(time.Second * 3)
   750  
   751  	// Close and re-open the host. This should reset the host's address, as the
   752  	// host should now be on a new port.
   753  	err = stHost.server.Close()
   754  	if err != nil {
   755  		t.Fatal(err)
   756  	}
   757  	stHost, err = assembleServerTester(stHost.walletKey, stHost.dir)
   758  	if err != nil {
   759  		t.Fatal(err)
   760  	}
   761  	defer stHost.panicClose()
   762  	sts[1] = stHost
   763  	err = fullyConnectNodes(sts)
   764  	if err != nil {
   765  		t.Fatal(err)
   766  	}
   767  	err = stHost.announceHost()
   768  	if err != nil {
   769  		t.Fatal(err)
   770  	}
   771  	// Pull the host's net address and pubkey from the hostdb.
   772  	err = build.Retry(50, time.Millisecond*100, func() error {
   773  		// Get the hostdb internals.
   774  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   775  			return err
   776  		}
   777  
   778  		// Get the host's internals.
   779  		var hg HostGET
   780  		if err = stHost.getAPI("/host", &hg); err != nil {
   781  			return err
   782  		}
   783  
   784  		if len(ah.Hosts) != 1 {
   785  			return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts))
   786  		}
   787  		if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress {
   788  			return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress)
   789  		}
   790  		return nil
   791  	})
   792  	if err != nil {
   793  		t.Fatal(err)
   794  	}
   795  	if ah.Hosts[0].PublicKeyString != pks {
   796  		t.Error("public key appears to have changed for host")
   797  	}
   798  	if ah.Hosts[0].NetAddress == addr {
   799  		t.Log("NetAddress did not change for the new host")
   800  	}
   801  
   802  	// Try uploading a second file.
   803  	path2 := filepath.Join(st.dir, "test2.dat")
   804  	test2Size := modules.SectorSize*2 + 1
   805  	err = createRandFile(path2, int(test2Size))
   806  	if err != nil {
   807  		t.Fatal(err)
   808  	}
   809  	uploadValues = url.Values{}
   810  	uploadValues.Set("source", path2)
   811  	err = st.stdPostAPI("/renter/upload/test2", uploadValues)
   812  	if err != nil {
   813  		t.Fatal(err)
   814  	}
   815  	// Only one piece will be uploaded (10% at current redundancy).
   816  	for i := 0; i < 200 && (len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10); i++ {
   817  		st.getAPI("/renter/files", &rf)
   818  		time.Sleep(100 * time.Millisecond)
   819  	}
   820  	if len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10 {
   821  		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0], rf.Files[1])
   822  	}
   823  
   824  	// Try downloading the second file.
   825  	downpath2 := filepath.Join(st.dir, "testdown2.dat")
   826  	err = st.stdGetAPI("/renter/download/test2?destination=" + downpath2)
   827  	if err != nil {
   828  		t.Fatal(err)
   829  	}
   830  	// Check that the download has the right contents.
   831  	orig2, err := ioutil.ReadFile(path2)
   832  	if err != nil {
   833  		t.Fatal(err)
   834  	}
   835  	download2, err := ioutil.ReadFile(downpath2)
   836  	if err != nil {
   837  		t.Fatal(err)
   838  	}
   839  	if !bytes.Equal(orig2, download2) {
   840  		t.Fatal("data mismatch when downloading a file")
   841  	}
   842  
   843  	// Mine enough blocks that multiple renew cylces happen. After the renewing
   844  	// happens, the file should still be downloadable. This is to check that the
   845  	// renewal doesn't throw things off.
   846  	for i := 0; i < testPeriodInt; i++ {
   847  		_, err = st.miner.AddBlock()
   848  		if err != nil {
   849  			t.Fatal(err)
   850  		}
   851  		_, err = synchronizationCheck(sts)
   852  		if err != nil {
   853  			t.Fatal(err)
   854  		}
   855  		// Give time for the upgrade to happen.
   856  		time.Sleep(time.Second * 3)
   857  	}
   858  
   859  	// Try downloading the file.
   860  	downpath := filepath.Join(st.dir, "testdown.dat")
   861  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
   862  	if err != nil {
   863  		t.Fatal(err)
   864  	}
   865  	// Check that the download has the right contents.
   866  	download, err := ioutil.ReadFile(downpath)
   867  	if err != nil {
   868  		t.Fatal(err)
   869  	}
   870  	orig, err := ioutil.ReadFile(path)
   871  	if err != nil {
   872  		t.Fatal(err)
   873  	}
   874  	if !bytes.Equal(orig, download) {
   875  		t.Fatal("data mismatch when downloading a file")
   876  	}
   877  
   878  	// Try downloading the second file.
   879  	err = st.stdGetAPI("/renter/download/test2?destination=" + downpath2)
   880  	if err != nil {
   881  		t.Fatal(err)
   882  	}
   883  	// Check that the download has the right contents.
   884  	orig2, err = ioutil.ReadFile(path2)
   885  	if err != nil {
   886  		t.Fatal(err)
   887  	}
   888  	download2, err = ioutil.ReadFile(downpath2)
   889  	if err != nil {
   890  		t.Fatal(err)
   891  	}
   892  	if !bytes.Equal(orig2, download2) {
   893  		t.Fatal("data mismatch when downloading a file")
   894  	}
   895  }
   896  
   897  // TestHostDBAndRenterFormDynamicIPs checks that the hostdb and the renter are
   898  // successfully able to follow a host that has changed IP addresses and then
   899  // re-announced.
   900  func TestHostDBAndRenterFormDynamicIPs(t *testing.T) {
   901  	if testing.Short() || !build.VLONG {
   902  		t.SkipNow()
   903  	}
   904  	t.Parallel()
   905  	st, err := createServerTester(t.Name())
   906  	if err != nil {
   907  		t.Fatal(err)
   908  	}
   909  	defer st.panicClose()
   910  	stHost, err := blankServerTester(t.Name() + "-Host")
   911  	if err != nil {
   912  		t.Fatal(err)
   913  	}
   914  	sts := []*serverTester{st, stHost}
   915  	err = fullyConnectNodes(sts)
   916  	if err != nil {
   917  		t.Fatal(err)
   918  	}
   919  	err = fundAllNodes(sts)
   920  	if err != nil {
   921  		t.Fatal(err)
   922  	}
   923  
   924  	// Announce the host.
   925  	err = stHost.acceptContracts()
   926  	if err != nil {
   927  		t.Fatal(err)
   928  	}
   929  	err = stHost.setHostStorage()
   930  	if err != nil {
   931  		t.Fatal(err)
   932  	}
   933  	err = stHost.announceHost()
   934  	if err != nil {
   935  		t.Fatal(err)
   936  	}
   937  
   938  	// Pull the host's net address and pubkey from the hostdb.
   939  	var ah HostdbActiveGET
   940  	for i := 0; i < 50; i++ {
   941  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   942  			t.Fatal(err)
   943  		}
   944  		if len(ah.Hosts) == 1 {
   945  			break
   946  		}
   947  		time.Sleep(time.Millisecond * 100)
   948  	}
   949  	if len(ah.Hosts) != 1 {
   950  		t.Fatalf("expected 1 host, got %v", len(ah.Hosts))
   951  	}
   952  	addr := ah.Hosts[0].NetAddress
   953  	pks := ah.Hosts[0].PublicKeyString
   954  
   955  	// Mine a block before resetting the host, so that the host doesn't lose
   956  	// it's contracts when the transaction pool resets.
   957  	_, err = st.miner.AddBlock()
   958  	if err != nil {
   959  		t.Fatal(err)
   960  	}
   961  	_, err = synchronizationCheck(sts)
   962  	if err != nil {
   963  		t.Fatal(err)
   964  	}
   965  	// Give time for the upgrade to happen.
   966  	time.Sleep(time.Second * 3)
   967  
   968  	// Close and re-open the host. This should reset the host's address, as the
   969  	// host should now be on a new port.
   970  	err = stHost.server.Close()
   971  	if err != nil {
   972  		t.Fatal(err)
   973  	}
   974  	stHost, err = assembleServerTester(stHost.walletKey, stHost.dir)
   975  	if err != nil {
   976  		t.Fatal(err)
   977  	}
   978  	defer stHost.panicClose()
   979  	sts[1] = stHost
   980  	err = fullyConnectNodes(sts)
   981  	if err != nil {
   982  		t.Fatal(err)
   983  	}
   984  	err = stHost.announceHost()
   985  	if err != nil {
   986  		t.Fatal(err)
   987  	}
   988  	// Pull the host's net address and pubkey from the hostdb.
   989  	err = build.Retry(50, time.Millisecond*100, func() error {
   990  		// Get the hostdb internals.
   991  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
   992  			return err
   993  		}
   994  
   995  		// Get the host's internals.
   996  		var hg HostGET
   997  		if err = stHost.getAPI("/host", &hg); err != nil {
   998  			return err
   999  		}
  1000  
  1001  		if len(ah.Hosts) != 1 {
  1002  			return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts))
  1003  		}
  1004  		if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress {
  1005  			return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress)
  1006  		}
  1007  		return nil
  1008  	})
  1009  	if err != nil {
  1010  		t.Fatal(err)
  1011  	}
  1012  	if ah.Hosts[0].PublicKeyString != pks {
  1013  		t.Error("public key appears to have changed for host")
  1014  	}
  1015  	if ah.Hosts[0].NetAddress == addr {
  1016  		t.Log("NetAddress did not change for the new host")
  1017  	}
  1018  
  1019  	// Upload a file to the host.
  1020  	allowanceValues := url.Values{}
  1021  	testFunds := "10000000000000000000000000000" // 10k SC
  1022  	testPeriod := "10"
  1023  	testPeriodInt := 10
  1024  	allowanceValues.Set("funds", testFunds)
  1025  	allowanceValues.Set("period", testPeriod)
  1026  	err = st.stdPostAPI("/renter", allowanceValues)
  1027  	if err != nil {
  1028  		t.Fatal(err)
  1029  	}
  1030  	// Create a file.
  1031  	path := filepath.Join(st.dir, "test.dat")
  1032  	err = createRandFile(path, 1024)
  1033  	if err != nil {
  1034  		t.Fatal(err)
  1035  	}
  1036  	// Upload the file to the renter.
  1037  	uploadValues := url.Values{}
  1038  	uploadValues.Set("source", path)
  1039  	err = st.stdPostAPI("/renter/upload/test", uploadValues)
  1040  	if err != nil {
  1041  		t.Fatal(err)
  1042  	}
  1043  	// Only one piece will be uploaded (10% at current redundancy).
  1044  	var rf RenterFiles
  1045  	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
  1046  		st.getAPI("/renter/files", &rf)
  1047  		time.Sleep(100 * time.Millisecond)
  1048  	}
  1049  	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
  1050  		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
  1051  	}
  1052  
  1053  	// Try downloading the file.
  1054  	downpath := filepath.Join(st.dir, "testdown.dat")
  1055  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
  1056  	if err != nil {
  1057  		t.Fatal(err)
  1058  	}
  1059  	// Check that the download has the right contents.
  1060  	orig, err := ioutil.ReadFile(path)
  1061  	if err != nil {
  1062  		t.Fatal(err)
  1063  	}
  1064  	download, err := ioutil.ReadFile(downpath)
  1065  	if err != nil {
  1066  		t.Fatal(err)
  1067  	}
  1068  	if !bytes.Equal(orig, download) {
  1069  		t.Fatal("data mismatch when downloading a file")
  1070  	}
  1071  
  1072  	// Mine enough blocks that multiple renew cylces happen. After the renewing
  1073  	// happens, the file should still be downloadable. This is to check that the
  1074  	// renewal doesn't throw things off.
  1075  	for i := 0; i < testPeriodInt; i++ {
  1076  		_, err = st.miner.AddBlock()
  1077  		if err != nil {
  1078  			t.Fatal(err)
  1079  		}
  1080  		_, err = synchronizationCheck(sts)
  1081  		if err != nil {
  1082  			t.Fatal(err)
  1083  		}
  1084  		// Give time for the upgrade to happen.
  1085  		time.Sleep(time.Second * 3)
  1086  	}
  1087  
  1088  	// Try downloading the file.
  1089  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
  1090  	if err != nil {
  1091  		t.Fatal(err)
  1092  	}
  1093  	// Check that the download has the right contents.
  1094  	download, err = ioutil.ReadFile(downpath)
  1095  	if err != nil {
  1096  		t.Fatal(err)
  1097  	}
  1098  	if !bytes.Equal(orig, download) {
  1099  		t.Fatal("data mismatch when downloading a file")
  1100  	}
  1101  }
  1102  
  1103  // TestHostDBAndRenterRenewDynamicIPs checks that the hostdb and the renter are
  1104  // successfully able to follow a host that has changed IP addresses and then
  1105  // re-announced.
  1106  func TestHostDBAndRenterRenewDynamicIPs(t *testing.T) {
  1107  	if testing.Short() || !build.VLONG {
  1108  		t.SkipNow()
  1109  	}
  1110  	t.Parallel()
  1111  	st, err := createServerTester(t.Name())
  1112  	if err != nil {
  1113  		t.Fatal(err)
  1114  	}
  1115  	defer st.panicClose()
  1116  	stHost, err := blankServerTester(t.Name() + "-Host")
  1117  	if err != nil {
  1118  		t.Fatal(err)
  1119  	}
  1120  	sts := []*serverTester{st, stHost}
  1121  	err = fullyConnectNodes(sts)
  1122  	if err != nil {
  1123  		t.Fatal(err)
  1124  	}
  1125  	err = fundAllNodes(sts)
  1126  	if err != nil {
  1127  		t.Fatal(err)
  1128  	}
  1129  
  1130  	// Announce the host.
  1131  	err = stHost.acceptContracts()
  1132  	if err != nil {
  1133  		t.Fatal(err)
  1134  	}
  1135  	err = stHost.setHostStorage()
  1136  	if err != nil {
  1137  		t.Fatal(err)
  1138  	}
  1139  	err = stHost.announceHost()
  1140  	if err != nil {
  1141  		t.Fatal(err)
  1142  	}
  1143  	var ah HostdbActiveGET
  1144  	err = build.Retry(50, 100*time.Millisecond, func() error {
  1145  		if err := st.getAPI("/hostdb/active", &ah); err != nil {
  1146  			return err
  1147  		}
  1148  		if len(ah.Hosts) != 1 {
  1149  			return errors.New("host not found in hostdb")
  1150  		}
  1151  		return nil
  1152  	})
  1153  
  1154  	// Upload a file to the host.
  1155  	allowanceValues := url.Values{}
  1156  	testFunds := "10000000000000000000000000000" // 10k SC
  1157  	testPeriod := "10"
  1158  	testPeriodInt := 10
  1159  	allowanceValues.Set("funds", testFunds)
  1160  	allowanceValues.Set("period", testPeriod)
  1161  	err = st.stdPostAPI("/renter", allowanceValues)
  1162  	if err != nil {
  1163  		t.Fatal(err)
  1164  	}
  1165  	// Create a file.
  1166  	path := filepath.Join(st.dir, "test.dat")
  1167  	err = createRandFile(path, 1024)
  1168  	if err != nil {
  1169  		t.Fatal(err)
  1170  	}
  1171  	// Upload the file to the renter.
  1172  	uploadValues := url.Values{}
  1173  	uploadValues.Set("source", path)
  1174  	err = st.stdPostAPI("/renter/upload/test", uploadValues)
  1175  	if err != nil {
  1176  		t.Fatal(err)
  1177  	}
  1178  	// Only one piece will be uploaded (10% at current redundancy).
  1179  	var rf RenterFiles
  1180  	for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ {
  1181  		st.getAPI("/renter/files", &rf)
  1182  		time.Sleep(100 * time.Millisecond)
  1183  	}
  1184  	if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 {
  1185  		t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0])
  1186  	}
  1187  
  1188  	// Try downloading the file.
  1189  	downpath := filepath.Join(st.dir, "testdown.dat")
  1190  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
  1191  	if err != nil {
  1192  		t.Fatal(err)
  1193  	}
  1194  	// Check that the download has the right contents.
  1195  	orig, err := ioutil.ReadFile(path)
  1196  	if err != nil {
  1197  		t.Fatal(err)
  1198  	}
  1199  	download, err := ioutil.ReadFile(downpath)
  1200  	if err != nil {
  1201  		t.Fatal(err)
  1202  	}
  1203  	if !bytes.Equal(orig, download) {
  1204  		t.Fatal("data mismatch when downloading a file")
  1205  	}
  1206  
  1207  	// Mine a block before resetting the host, so that the host doesn't lose
  1208  	// it's contracts when the transaction pool resets.
  1209  	_, err = st.miner.AddBlock()
  1210  	if err != nil {
  1211  		t.Fatal(err)
  1212  	}
  1213  	_, err = synchronizationCheck(sts)
  1214  	if err != nil {
  1215  		t.Fatal(err)
  1216  	}
  1217  	// Give time for the upgrade to happen.
  1218  	time.Sleep(time.Second * 3)
  1219  
  1220  	// Close and re-open the host. This should reset the host's address, as the
  1221  	// host should now be on a new port.
  1222  	err = stHost.server.Close()
  1223  	if err != nil {
  1224  		t.Fatal(err)
  1225  	}
  1226  	stHost, err = assembleServerTester(stHost.walletKey, stHost.dir)
  1227  	if err != nil {
  1228  		t.Fatal(err)
  1229  	}
  1230  	defer stHost.panicClose()
  1231  	sts[1] = stHost
  1232  	err = fullyConnectNodes(sts)
  1233  	if err != nil {
  1234  		t.Fatal(err)
  1235  	}
  1236  	err = stHost.announceHost()
  1237  	if err != nil {
  1238  		t.Fatal(err)
  1239  	}
  1240  	err = waitForBlock(stHost.cs.CurrentBlock().ID(), st)
  1241  	if err != nil {
  1242  		t.Fatal()
  1243  	}
  1244  	// Pull the host's net address and pubkey from the hostdb.
  1245  	err = build.Retry(50, time.Millisecond*100, func() error {
  1246  		// Get the hostdb internals.
  1247  		if err = st.getAPI("/hostdb/active", &ah); err != nil {
  1248  			return err
  1249  		}
  1250  
  1251  		// Get the host's internals.
  1252  		var hg HostGET
  1253  		if err = stHost.getAPI("/host", &hg); err != nil {
  1254  			return err
  1255  		}
  1256  
  1257  		if len(ah.Hosts) != 1 {
  1258  			return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts))
  1259  		}
  1260  		if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress {
  1261  			return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress)
  1262  		}
  1263  		return nil
  1264  	})
  1265  	if err != nil {
  1266  		t.Fatal(err)
  1267  	}
  1268  
  1269  	// Mine enough blocks that multiple renew cylces happen. After the renewing
  1270  	// happens, the file should still be downloadable.
  1271  	for i := 0; i < testPeriodInt; i++ {
  1272  		_, err = st.miner.AddBlock()
  1273  		if err != nil {
  1274  			t.Fatal(err)
  1275  		}
  1276  		_, err = synchronizationCheck(sts)
  1277  		if err != nil {
  1278  			t.Fatal(err)
  1279  		}
  1280  		// Give time for the upgrade to happen.
  1281  		time.Sleep(time.Second * 3)
  1282  	}
  1283  
  1284  	// Try downloading the file.
  1285  	err = st.stdGetAPI("/renter/download/test?destination=" + downpath)
  1286  	if err != nil {
  1287  		t.Fatal(err)
  1288  	}
  1289  	// Check that the download has the right contents.
  1290  	download, err = ioutil.ReadFile(downpath)
  1291  	if err != nil {
  1292  		t.Fatal(err)
  1293  	}
  1294  	if !bytes.Equal(orig, download) {
  1295  		t.Fatal("data mismatch when downloading a file")
  1296  	}
  1297  }