gitlab.com/jokerrs1/Sia@v1.3.2/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 "github.com/NebulousLabs/Sia/build" 14 "github.com/NebulousLabs/Sia/crypto" 15 "github.com/NebulousLabs/Sia/modules" 16 "github.com/NebulousLabs/Sia/modules/consensus" 17 "github.com/NebulousLabs/Sia/modules/gateway" 18 "github.com/NebulousLabs/Sia/modules/host" 19 "github.com/NebulousLabs/Sia/modules/miner" 20 "github.com/NebulousLabs/Sia/modules/renter" 21 "github.com/NebulousLabs/Sia/modules/transactionpool" 22 "github.com/NebulousLabs/Sia/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 if !w.Encrypted() { 266 _, err = w.Encrypt(key) 267 if err != nil { 268 return nil, err 269 } 270 } 271 err = w.Unlock(key) 272 if err != nil { 273 return nil, err 274 } 275 m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir)) 276 if err != nil { 277 return nil, err 278 } 279 h, err := host.New(cs, tp, w, hostHostname, filepath.Join(testdir, modules.HostDir)) 280 if err != nil { 281 return nil, err 282 } 283 r, err := renter.New(g, cs, w, tp, filepath.Join(testdir, modules.RenterDir)) 284 if err != nil { 285 return nil, err 286 } 287 srv, err := NewServer("localhost:0", "Sia-Agent", "", cs, nil, g, h, m, r, tp, w) 288 if err != nil { 289 return nil, err 290 } 291 292 // Assemble the serverTester. 293 st := &serverTester{ 294 cs: cs, 295 gateway: g, 296 host: h, 297 miner: m, 298 renter: r, 299 tpool: tp, 300 wallet: w, 301 walletKey: key, 302 303 server: srv, 304 305 dir: testdir, 306 } 307 308 // TODO: A more reasonable way of listening for server errors. 309 go func() { 310 listenErr := srv.Serve() 311 if listenErr != nil { 312 panic(listenErr) 313 } 314 }() 315 return st, nil 316 } 317 318 // TestHostDBScanOnlineOffline checks that both online and offline hosts get 319 // scanned in the hostdb. 320 func TestHostDBScanOnlineOffline(t *testing.T) { 321 if testing.Short() || !build.VLONG { 322 t.SkipNow() 323 } 324 t.Parallel() 325 st, err := createServerTester(t.Name()) 326 if err != nil { 327 t.Fatal(err) 328 } 329 defer st.panicClose() 330 stHost, err := blankServerTester(t.Name() + "-Host") 331 if err != nil { 332 t.Fatal(err) 333 } 334 sts := []*serverTester{st, stHost} 335 err = fullyConnectNodes(sts) 336 if err != nil { 337 t.Fatal(err) 338 } 339 err = fundAllNodes(sts) 340 if err != nil { 341 t.Fatal(err) 342 } 343 344 // Announce the host. 345 err = stHost.acceptContracts() 346 if err != nil { 347 t.Fatal(err) 348 } 349 err = stHost.setHostStorage() 350 if err != nil { 351 t.Fatal(err) 352 } 353 err = stHost.announceHost() 354 if err != nil { 355 t.Fatal(err) 356 } 357 358 // Verify the host is visible. 359 var ah HostdbActiveGET 360 for i := 0; i < 50; i++ { 361 if err = st.getAPI("/hostdb/active", &ah); err != nil { 362 t.Fatal(err) 363 } 364 if len(ah.Hosts) == 1 { 365 break 366 } 367 time.Sleep(time.Millisecond * 100) 368 } 369 if len(ah.Hosts) != 1 { 370 t.Fatalf("expected 1 host, got %v", len(ah.Hosts)) 371 } 372 hostAddr := ah.Hosts[0].NetAddress 373 374 // Close the host and wait for a scan to knock the host out of the hostdb. 375 err = stHost.server.Close() 376 if err != nil { 377 t.Fatal(err) 378 } 379 err = retry(60, time.Second, func() error { 380 if err := st.getAPI("/hostdb/active", &ah); err != nil { 381 return err 382 } 383 if len(ah.Hosts) == 0 { 384 return nil 385 } 386 return errors.New("host still in hostdb") 387 }) 388 if err != nil { 389 t.Fatal(err) 390 } 391 392 // Reopen the host and wait for a scan to bring the host back into the 393 // hostdb. 394 stHost, err = assembleHostPort(stHost.walletKey, string(hostAddr), stHost.dir) 395 if err != nil { 396 t.Fatal(err) 397 } 398 defer stHost.panicClose() 399 sts[1] = stHost 400 err = fullyConnectNodes(sts) 401 if err != nil { 402 t.Fatal(err) 403 } 404 err = retry(60, time.Second, func() error { 405 // Get the hostdb internals. 406 if err = st.getAPI("/hostdb/active", &ah); err != nil { 407 return err 408 } 409 if len(ah.Hosts) != 1 { 410 return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts)) 411 } 412 return nil 413 }) 414 if err != nil { 415 t.Fatal(err) 416 } 417 } 418 419 // TestHostDBAndRenterDownloadDynamicIPs checks that the hostdb and the renter are 420 // successfully able to follow a host that has changed IP addresses and then 421 // re-announced. 422 func TestHostDBAndRenterDownloadDynamicIPs(t *testing.T) { 423 if testing.Short() || !build.VLONG { 424 t.SkipNow() 425 } 426 t.Parallel() 427 st, err := createServerTester(t.Name()) 428 if err != nil { 429 t.Fatal(err) 430 } 431 defer st.panicClose() 432 stHost, err := blankServerTester(t.Name() + "-Host") 433 if err != nil { 434 t.Fatal(err) 435 } 436 sts := []*serverTester{st, stHost} 437 err = fullyConnectNodes(sts) 438 if err != nil { 439 t.Fatal(err) 440 } 441 err = fundAllNodes(sts) 442 if err != nil { 443 t.Fatal(err) 444 } 445 446 // Announce the host. 447 err = stHost.acceptContracts() 448 if err != nil { 449 t.Fatal(err) 450 } 451 err = stHost.setHostStorage() 452 if err != nil { 453 t.Fatal(err) 454 } 455 err = stHost.announceHost() 456 if err != nil { 457 t.Fatal(err) 458 } 459 460 // Pull the host's net address and pubkey from the hostdb. 461 var ah HostdbActiveGET 462 for i := 0; i < 50; i++ { 463 if err = st.getAPI("/hostdb/active", &ah); err != nil { 464 t.Fatal(err) 465 } 466 if len(ah.Hosts) == 1 { 467 break 468 } 469 time.Sleep(time.Millisecond * 100) 470 } 471 if len(ah.Hosts) != 1 { 472 t.Fatalf("expected 1 host, got %v", len(ah.Hosts)) 473 } 474 addr := ah.Hosts[0].NetAddress 475 pks := ah.Hosts[0].PublicKeyString 476 477 // Upload a file to the host. 478 allowanceValues := url.Values{} 479 testFunds := "10000000000000000000000000000" // 10k SC 480 testPeriod := "10" 481 testPeriodInt := 10 482 allowanceValues.Set("funds", testFunds) 483 allowanceValues.Set("period", testPeriod) 484 err = st.stdPostAPI("/renter", allowanceValues) 485 if err != nil { 486 t.Fatal(err) 487 } 488 // Create a file. 489 path := filepath.Join(st.dir, "test.dat") 490 err = createRandFile(path, 1024) 491 if err != nil { 492 t.Fatal(err) 493 } 494 // Upload the file to the renter. 495 uploadValues := url.Values{} 496 uploadValues.Set("source", path) 497 err = st.stdPostAPI("/renter/upload/test", uploadValues) 498 if err != nil { 499 t.Fatal(err) 500 } 501 // Only one piece will be uploaded (10% at current redundancy). 502 var rf RenterFiles 503 for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ { 504 st.getAPI("/renter/files", &rf) 505 time.Sleep(100 * time.Millisecond) 506 } 507 if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 { 508 t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0]) 509 } 510 511 // Try downloading the file. 512 downpath := filepath.Join(st.dir, "testdown.dat") 513 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 514 if err != nil { 515 t.Fatal(err) 516 } 517 // Check that the download has the right contents. 518 orig, err := ioutil.ReadFile(path) 519 if err != nil { 520 t.Fatal(err) 521 } 522 download, err := ioutil.ReadFile(downpath) 523 if err != nil { 524 t.Fatal(err) 525 } 526 if !bytes.Equal(orig, download) { 527 t.Fatal("data mismatch when downloading a file") 528 } 529 530 // Mine a block before resetting the host, so that the host doesn't lose 531 // it's contracts when the transaction pool resets. 532 _, err = st.miner.AddBlock() 533 if err != nil { 534 t.Fatal(err) 535 } 536 _, err = synchronizationCheck(sts) 537 if err != nil { 538 t.Fatal(err) 539 } 540 // Give time for the upgrade to happen. 541 time.Sleep(time.Second * 3) 542 543 // Close and re-open the host. This should reset the host's address, as the 544 // host should now be on a new port. 545 err = stHost.server.Close() 546 if err != nil { 547 t.Fatal(err) 548 } 549 stHost, err = assembleServerTester(stHost.walletKey, stHost.dir) 550 if err != nil { 551 t.Fatal(err) 552 } 553 defer stHost.panicClose() 554 sts[1] = stHost 555 err = fullyConnectNodes(sts) 556 if err != nil { 557 t.Fatal(err) 558 } 559 err = stHost.announceHost() 560 if err != nil { 561 t.Fatal(err) 562 } 563 // Pull the host's net address and pubkey from the hostdb. 564 err = retry(100, time.Millisecond*200, func() error { 565 // Get the hostdb internals. 566 if err = st.getAPI("/hostdb/active", &ah); err != nil { 567 return err 568 } 569 570 // Get the host's internals. 571 var hg HostGET 572 if err = stHost.getAPI("/host", &hg); err != nil { 573 return err 574 } 575 576 if len(ah.Hosts) != 1 { 577 return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts)) 578 } 579 if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress { 580 return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress) 581 } 582 return nil 583 }) 584 if err != nil { 585 t.Fatal(err) 586 } 587 if ah.Hosts[0].PublicKeyString != pks { 588 t.Error("public key appears to have changed for host") 589 } 590 if ah.Hosts[0].NetAddress == addr { 591 t.Log("NetAddress did not change for the new host") 592 } 593 594 // Try downloading the file. 595 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 596 if err != nil { 597 t.Fatal(err) 598 } 599 // Check that the download has the right contents. 600 download, err = ioutil.ReadFile(downpath) 601 if err != nil { 602 t.Fatal(err) 603 } 604 if !bytes.Equal(orig, download) { 605 t.Fatal("data mismatch when downloading a file") 606 } 607 608 // Mine enough blocks that multiple renew cylces happen. After the renewing 609 // happens, the file should still be downloadable. This is to check that the 610 // renewal doesn't throw things off. 611 for i := 0; i < testPeriodInt; i++ { 612 _, err = st.miner.AddBlock() 613 if err != nil { 614 t.Fatal(err) 615 } 616 _, err = synchronizationCheck(sts) 617 if err != nil { 618 t.Fatal(err) 619 } 620 } 621 err = retry(100, time.Millisecond*100, func() error { 622 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 623 if err != nil { 624 return err 625 } 626 // Try downloading the file. 627 // Check that the download has the right contents. 628 download, err = ioutil.ReadFile(downpath) 629 if err != nil { 630 return err 631 } 632 if !bytes.Equal(orig, download) { 633 return errors.New("downloaded file does not equal the original") 634 } 635 return nil 636 }) 637 if err != nil { 638 t.Fatal(err) 639 } 640 } 641 642 // TestHostDBAndRenterUploadDynamicIPs checks that the hostdb and the renter are 643 // successfully able to follow a host that has changed IP addresses and then 644 // re-announced. 645 func TestHostDBAndRenterUploadDynamicIPs(t *testing.T) { 646 if testing.Short() || !build.VLONG { 647 t.SkipNow() 648 } 649 t.Parallel() 650 st, err := createServerTester(t.Name()) 651 if err != nil { 652 t.Fatal(err) 653 } 654 defer st.panicClose() 655 stHost, err := blankServerTester(t.Name() + "-Host") 656 if err != nil { 657 t.Fatal(err) 658 } 659 sts := []*serverTester{st, stHost} 660 err = fullyConnectNodes(sts) 661 if err != nil { 662 t.Fatal(err) 663 } 664 err = fundAllNodes(sts) 665 if err != nil { 666 t.Fatal(err) 667 } 668 669 // Announce the host. 670 err = stHost.acceptContracts() 671 if err != nil { 672 t.Fatal(err) 673 } 674 err = stHost.setHostStorage() 675 if err != nil { 676 t.Fatal(err) 677 } 678 err = stHost.announceHost() 679 if err != nil { 680 t.Fatal(err) 681 } 682 683 // Pull the host's net address and pubkey from the hostdb. 684 var ah HostdbActiveGET 685 for i := 0; i < 50; i++ { 686 if err = st.getAPI("/hostdb/active", &ah); err != nil { 687 t.Fatal(err) 688 } 689 if len(ah.Hosts) == 1 { 690 break 691 } 692 time.Sleep(time.Millisecond * 100) 693 } 694 if len(ah.Hosts) != 1 { 695 t.Fatalf("expected 1 host, got %v", len(ah.Hosts)) 696 } 697 addr := ah.Hosts[0].NetAddress 698 pks := ah.Hosts[0].PublicKeyString 699 700 // Upload a file to the host. 701 allowanceValues := url.Values{} 702 testFunds := "10000000000000000000000000000" // 10k SC 703 testPeriod := "10" 704 testPeriodInt := 10 705 allowanceValues.Set("funds", testFunds) 706 allowanceValues.Set("period", testPeriod) 707 err = st.stdPostAPI("/renter", allowanceValues) 708 if err != nil { 709 t.Fatal(err) 710 } 711 // Create a file. 712 path := filepath.Join(st.dir, "test.dat") 713 err = createRandFile(path, 1024) 714 if err != nil { 715 t.Fatal(err) 716 } 717 // Upload the file to the renter. 718 uploadValues := url.Values{} 719 uploadValues.Set("source", path) 720 err = st.stdPostAPI("/renter/upload/test", uploadValues) 721 if err != nil { 722 t.Fatal(err) 723 } 724 // Only one piece will be uploaded (10% at current redundancy). 725 var rf RenterFiles 726 for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ { 727 st.getAPI("/renter/files", &rf) 728 time.Sleep(100 * time.Millisecond) 729 } 730 if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 { 731 t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0]) 732 } 733 734 // Mine a block before resetting the host, so that the host doesn't lose 735 // it's contracts when the transaction pool resets. 736 _, err = st.miner.AddBlock() 737 if err != nil { 738 t.Fatal(err) 739 } 740 _, err = synchronizationCheck(sts) 741 if err != nil { 742 t.Fatal(err) 743 } 744 // Give time for the upgrade to happen. 745 time.Sleep(time.Second * 3) 746 747 // Close and re-open the host. This should reset the host's address, as the 748 // host should now be on a new port. 749 err = stHost.server.Close() 750 if err != nil { 751 t.Fatal(err) 752 } 753 stHost, err = assembleServerTester(stHost.walletKey, stHost.dir) 754 if err != nil { 755 t.Fatal(err) 756 } 757 defer stHost.panicClose() 758 sts[1] = stHost 759 err = fullyConnectNodes(sts) 760 if err != nil { 761 t.Fatal(err) 762 } 763 err = stHost.announceHost() 764 if err != nil { 765 t.Fatal(err) 766 } 767 // Pull the host's net address and pubkey from the hostdb. 768 err = retry(50, time.Millisecond*100, func() error { 769 // Get the hostdb internals. 770 if err = st.getAPI("/hostdb/active", &ah); err != nil { 771 return err 772 } 773 774 // Get the host's internals. 775 var hg HostGET 776 if err = stHost.getAPI("/host", &hg); err != nil { 777 return err 778 } 779 780 if len(ah.Hosts) != 1 { 781 return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts)) 782 } 783 if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress { 784 return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress) 785 } 786 return nil 787 }) 788 if err != nil { 789 t.Fatal(err) 790 } 791 if ah.Hosts[0].PublicKeyString != pks { 792 t.Error("public key appears to have changed for host") 793 } 794 if ah.Hosts[0].NetAddress == addr { 795 t.Log("NetAddress did not change for the new host") 796 } 797 798 // Try uploading a second file. 799 path2 := filepath.Join(st.dir, "test2.dat") 800 test2Size := modules.SectorSize*2 + 1 801 err = createRandFile(path2, int(test2Size)) 802 if err != nil { 803 t.Fatal(err) 804 } 805 uploadValues = url.Values{} 806 uploadValues.Set("source", path2) 807 err = st.stdPostAPI("/renter/upload/test2", uploadValues) 808 if err != nil { 809 t.Fatal(err) 810 } 811 // Only one piece will be uploaded (10% at current redundancy). 812 for i := 0; i < 200 && (len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10); i++ { 813 st.getAPI("/renter/files", &rf) 814 time.Sleep(100 * time.Millisecond) 815 } 816 if len(rf.Files) != 2 || rf.Files[0].UploadProgress < 10 || rf.Files[1].UploadProgress < 10 { 817 t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0], rf.Files[1]) 818 } 819 820 // Try downloading the second file. 821 downpath2 := filepath.Join(st.dir, "testdown2.dat") 822 err = st.stdGetAPI("/renter/download/test2?destination=" + downpath2) 823 if err != nil { 824 t.Fatal(err) 825 } 826 // Check that the download has the right contents. 827 orig2, err := ioutil.ReadFile(path2) 828 if err != nil { 829 t.Fatal(err) 830 } 831 download2, err := ioutil.ReadFile(downpath2) 832 if err != nil { 833 t.Fatal(err) 834 } 835 if !bytes.Equal(orig2, download2) { 836 t.Fatal("data mismatch when downloading a file") 837 } 838 839 // Mine enough blocks that multiple renew cylces happen. After the renewing 840 // happens, the file should still be downloadable. This is to check that the 841 // renewal doesn't throw things off. 842 for i := 0; i < testPeriodInt; i++ { 843 _, err = st.miner.AddBlock() 844 if err != nil { 845 t.Fatal(err) 846 } 847 _, err = synchronizationCheck(sts) 848 if err != nil { 849 t.Fatal(err) 850 } 851 // Give time for the upgrade to happen. 852 time.Sleep(time.Second * 3) 853 } 854 855 // Try downloading the file. 856 downpath := filepath.Join(st.dir, "testdown.dat") 857 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 858 if err != nil { 859 t.Fatal(err) 860 } 861 // Check that the download has the right contents. 862 download, err := ioutil.ReadFile(downpath) 863 if err != nil { 864 t.Fatal(err) 865 } 866 orig, err := ioutil.ReadFile(path) 867 if err != nil { 868 t.Fatal(err) 869 } 870 if !bytes.Equal(orig, download) { 871 t.Fatal("data mismatch when downloading a file") 872 } 873 874 // Try downloading the second file. 875 err = st.stdGetAPI("/renter/download/test2?destination=" + downpath2) 876 if err != nil { 877 t.Fatal(err) 878 } 879 // Check that the download has the right contents. 880 orig2, err = ioutil.ReadFile(path2) 881 if err != nil { 882 t.Fatal(err) 883 } 884 download2, err = ioutil.ReadFile(downpath2) 885 if err != nil { 886 t.Fatal(err) 887 } 888 if !bytes.Equal(orig2, download2) { 889 t.Fatal("data mismatch when downloading a file") 890 } 891 } 892 893 // TestHostDBAndRenterFormDynamicIPs checks that the hostdb and the renter are 894 // successfully able to follow a host that has changed IP addresses and then 895 // re-announced. 896 func TestHostDBAndRenterFormDynamicIPs(t *testing.T) { 897 if testing.Short() || !build.VLONG { 898 t.SkipNow() 899 } 900 t.Parallel() 901 st, err := createServerTester(t.Name()) 902 if err != nil { 903 t.Fatal(err) 904 } 905 defer st.panicClose() 906 stHost, err := blankServerTester(t.Name() + "-Host") 907 if err != nil { 908 t.Fatal(err) 909 } 910 sts := []*serverTester{st, stHost} 911 err = fullyConnectNodes(sts) 912 if err != nil { 913 t.Fatal(err) 914 } 915 err = fundAllNodes(sts) 916 if err != nil { 917 t.Fatal(err) 918 } 919 920 // Announce the host. 921 err = stHost.acceptContracts() 922 if err != nil { 923 t.Fatal(err) 924 } 925 err = stHost.setHostStorage() 926 if err != nil { 927 t.Fatal(err) 928 } 929 err = stHost.announceHost() 930 if err != nil { 931 t.Fatal(err) 932 } 933 934 // Pull the host's net address and pubkey from the hostdb. 935 var ah HostdbActiveGET 936 for i := 0; i < 50; i++ { 937 if err = st.getAPI("/hostdb/active", &ah); err != nil { 938 t.Fatal(err) 939 } 940 if len(ah.Hosts) == 1 { 941 break 942 } 943 time.Sleep(time.Millisecond * 100) 944 } 945 if len(ah.Hosts) != 1 { 946 t.Fatalf("expected 1 host, got %v", len(ah.Hosts)) 947 } 948 addr := ah.Hosts[0].NetAddress 949 pks := ah.Hosts[0].PublicKeyString 950 951 // Mine a block before resetting the host, so that the host doesn't lose 952 // it's contracts when the transaction pool resets. 953 _, err = st.miner.AddBlock() 954 if err != nil { 955 t.Fatal(err) 956 } 957 _, err = synchronizationCheck(sts) 958 if err != nil { 959 t.Fatal(err) 960 } 961 // Give time for the upgrade to happen. 962 time.Sleep(time.Second * 3) 963 964 // Close and re-open the host. This should reset the host's address, as the 965 // host should now be on a new port. 966 err = stHost.server.Close() 967 if err != nil { 968 t.Fatal(err) 969 } 970 stHost, err = assembleServerTester(stHost.walletKey, stHost.dir) 971 if err != nil { 972 t.Fatal(err) 973 } 974 defer stHost.panicClose() 975 sts[1] = stHost 976 err = fullyConnectNodes(sts) 977 if err != nil { 978 t.Fatal(err) 979 } 980 err = stHost.announceHost() 981 if err != nil { 982 t.Fatal(err) 983 } 984 // Pull the host's net address and pubkey from the hostdb. 985 err = retry(50, time.Millisecond*100, func() error { 986 // Get the hostdb internals. 987 if err = st.getAPI("/hostdb/active", &ah); err != nil { 988 return err 989 } 990 991 // Get the host's internals. 992 var hg HostGET 993 if err = stHost.getAPI("/host", &hg); err != nil { 994 return err 995 } 996 997 if len(ah.Hosts) != 1 { 998 return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts)) 999 } 1000 if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress { 1001 return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress) 1002 } 1003 return nil 1004 }) 1005 if err != nil { 1006 t.Fatal(err) 1007 } 1008 if ah.Hosts[0].PublicKeyString != pks { 1009 t.Error("public key appears to have changed for host") 1010 } 1011 if ah.Hosts[0].NetAddress == addr { 1012 t.Log("NetAddress did not change for the new host") 1013 } 1014 1015 // Upload a file to the host. 1016 allowanceValues := url.Values{} 1017 testFunds := "10000000000000000000000000000" // 10k SC 1018 testPeriod := "10" 1019 testPeriodInt := 10 1020 allowanceValues.Set("funds", testFunds) 1021 allowanceValues.Set("period", testPeriod) 1022 err = st.stdPostAPI("/renter", allowanceValues) 1023 if err != nil { 1024 t.Fatal(err) 1025 } 1026 // Create a file. 1027 path := filepath.Join(st.dir, "test.dat") 1028 err = createRandFile(path, 1024) 1029 if err != nil { 1030 t.Fatal(err) 1031 } 1032 // Upload the file to the renter. 1033 uploadValues := url.Values{} 1034 uploadValues.Set("source", path) 1035 err = st.stdPostAPI("/renter/upload/test", uploadValues) 1036 if err != nil { 1037 t.Fatal(err) 1038 } 1039 // Only one piece will be uploaded (10% at current redundancy). 1040 var rf RenterFiles 1041 for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ { 1042 st.getAPI("/renter/files", &rf) 1043 time.Sleep(100 * time.Millisecond) 1044 } 1045 if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 { 1046 t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0]) 1047 } 1048 1049 // Try downloading the file. 1050 downpath := filepath.Join(st.dir, "testdown.dat") 1051 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 1052 if err != nil { 1053 t.Fatal(err) 1054 } 1055 // Check that the download has the right contents. 1056 orig, err := ioutil.ReadFile(path) 1057 if err != nil { 1058 t.Fatal(err) 1059 } 1060 download, err := ioutil.ReadFile(downpath) 1061 if err != nil { 1062 t.Fatal(err) 1063 } 1064 if !bytes.Equal(orig, download) { 1065 t.Fatal("data mismatch when downloading a file") 1066 } 1067 1068 // Mine enough blocks that multiple renew cylces happen. After the renewing 1069 // happens, the file should still be downloadable. This is to check that the 1070 // renewal doesn't throw things off. 1071 for i := 0; i < testPeriodInt; i++ { 1072 _, err = st.miner.AddBlock() 1073 if err != nil { 1074 t.Fatal(err) 1075 } 1076 _, err = synchronizationCheck(sts) 1077 if err != nil { 1078 t.Fatal(err) 1079 } 1080 // Give time for the upgrade to happen. 1081 time.Sleep(time.Second * 3) 1082 } 1083 1084 // Try downloading the file. 1085 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 1086 if err != nil { 1087 t.Fatal(err) 1088 } 1089 // Check that the download has the right contents. 1090 download, err = ioutil.ReadFile(downpath) 1091 if err != nil { 1092 t.Fatal(err) 1093 } 1094 if !bytes.Equal(orig, download) { 1095 t.Fatal("data mismatch when downloading a file") 1096 } 1097 } 1098 1099 // TestHostDBAndRenterRenewDynamicIPs checks that the hostdb and the renter are 1100 // successfully able to follow a host that has changed IP addresses and then 1101 // re-announced. 1102 func TestHostDBAndRenterRenewDynamicIPs(t *testing.T) { 1103 if testing.Short() || !build.VLONG { 1104 t.SkipNow() 1105 } 1106 t.Parallel() 1107 st, err := createServerTester(t.Name()) 1108 if err != nil { 1109 t.Fatal(err) 1110 } 1111 defer st.panicClose() 1112 stHost, err := blankServerTester(t.Name() + "-Host") 1113 if err != nil { 1114 t.Fatal(err) 1115 } 1116 sts := []*serverTester{st, stHost} 1117 err = fullyConnectNodes(sts) 1118 if err != nil { 1119 t.Fatal(err) 1120 } 1121 err = fundAllNodes(sts) 1122 if err != nil { 1123 t.Fatal(err) 1124 } 1125 1126 // Announce the host. 1127 err = stHost.acceptContracts() 1128 if err != nil { 1129 t.Fatal(err) 1130 } 1131 err = stHost.setHostStorage() 1132 if err != nil { 1133 t.Fatal(err) 1134 } 1135 err = stHost.announceHost() 1136 if err != nil { 1137 t.Fatal(err) 1138 } 1139 var ah HostdbActiveGET 1140 err = retry(50, 100*time.Millisecond, func() error { 1141 if err := st.getAPI("/hostdb/active", &ah); err != nil { 1142 return err 1143 } 1144 if len(ah.Hosts) != 1 { 1145 return errors.New("host not found in hostdb") 1146 } 1147 return nil 1148 }) 1149 1150 // Upload a file to the host. 1151 allowanceValues := url.Values{} 1152 testFunds := "10000000000000000000000000000" // 10k SC 1153 testPeriod := "10" 1154 testPeriodInt := 10 1155 allowanceValues.Set("funds", testFunds) 1156 allowanceValues.Set("period", testPeriod) 1157 err = st.stdPostAPI("/renter", allowanceValues) 1158 if err != nil { 1159 t.Fatal(err) 1160 } 1161 // Create a file. 1162 path := filepath.Join(st.dir, "test.dat") 1163 err = createRandFile(path, 1024) 1164 if err != nil { 1165 t.Fatal(err) 1166 } 1167 // Upload the file to the renter. 1168 uploadValues := url.Values{} 1169 uploadValues.Set("source", path) 1170 err = st.stdPostAPI("/renter/upload/test", uploadValues) 1171 if err != nil { 1172 t.Fatal(err) 1173 } 1174 // Only one piece will be uploaded (10% at current redundancy). 1175 var rf RenterFiles 1176 for i := 0; i < 200 && (len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10); i++ { 1177 st.getAPI("/renter/files", &rf) 1178 time.Sleep(100 * time.Millisecond) 1179 } 1180 if len(rf.Files) != 1 || rf.Files[0].UploadProgress < 10 { 1181 t.Fatal("the uploading is not succeeding for some reason:", rf.Files[0]) 1182 } 1183 1184 // Try downloading the file. 1185 downpath := filepath.Join(st.dir, "testdown.dat") 1186 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 1187 if err != nil { 1188 t.Fatal(err) 1189 } 1190 // Check that the download has the right contents. 1191 orig, err := ioutil.ReadFile(path) 1192 if err != nil { 1193 t.Fatal(err) 1194 } 1195 download, err := ioutil.ReadFile(downpath) 1196 if err != nil { 1197 t.Fatal(err) 1198 } 1199 if !bytes.Equal(orig, download) { 1200 t.Fatal("data mismatch when downloading a file") 1201 } 1202 1203 // Mine a block before resetting the host, so that the host doesn't lose 1204 // it's contracts when the transaction pool resets. 1205 _, err = st.miner.AddBlock() 1206 if err != nil { 1207 t.Fatal(err) 1208 } 1209 _, err = synchronizationCheck(sts) 1210 if err != nil { 1211 t.Fatal(err) 1212 } 1213 // Give time for the upgrade to happen. 1214 time.Sleep(time.Second * 3) 1215 1216 // Close and re-open the host. This should reset the host's address, as the 1217 // host should now be on a new port. 1218 err = stHost.server.Close() 1219 if err != nil { 1220 t.Fatal(err) 1221 } 1222 stHost, err = assembleServerTester(stHost.walletKey, stHost.dir) 1223 if err != nil { 1224 t.Fatal(err) 1225 } 1226 defer stHost.panicClose() 1227 sts[1] = stHost 1228 err = fullyConnectNodes(sts) 1229 if err != nil { 1230 t.Fatal(err) 1231 } 1232 err = stHost.announceHost() 1233 if err != nil { 1234 t.Fatal(err) 1235 } 1236 err = waitForBlock(stHost.cs.CurrentBlock().ID(), st) 1237 if err != nil { 1238 t.Fatal() 1239 } 1240 // Pull the host's net address and pubkey from the hostdb. 1241 err = retry(50, time.Millisecond*100, func() error { 1242 // Get the hostdb internals. 1243 if err = st.getAPI("/hostdb/active", &ah); err != nil { 1244 return err 1245 } 1246 1247 // Get the host's internals. 1248 var hg HostGET 1249 if err = stHost.getAPI("/host", &hg); err != nil { 1250 return err 1251 } 1252 1253 if len(ah.Hosts) != 1 { 1254 return fmt.Errorf("expected 1 host, got %v", len(ah.Hosts)) 1255 } 1256 if ah.Hosts[0].NetAddress != hg.ExternalSettings.NetAddress { 1257 return fmt.Errorf("hostdb net address doesn't match host net address: %v : %v", ah.Hosts[0].NetAddress, hg.ExternalSettings.NetAddress) 1258 } 1259 return nil 1260 }) 1261 if err != nil { 1262 t.Fatal(err) 1263 } 1264 1265 // Mine enough blocks that multiple renew cylces happen. After the renewing 1266 // happens, the file should still be downloadable. 1267 for i := 0; i < testPeriodInt; i++ { 1268 _, err = st.miner.AddBlock() 1269 if err != nil { 1270 t.Fatal(err) 1271 } 1272 _, err = synchronizationCheck(sts) 1273 if err != nil { 1274 t.Fatal(err) 1275 } 1276 // Give time for the upgrade to happen. 1277 time.Sleep(time.Second * 3) 1278 } 1279 1280 // Try downloading the file. 1281 err = st.stdGetAPI("/renter/download/test?destination=" + downpath) 1282 if err != nil { 1283 t.Fatal(err) 1284 } 1285 // Check that the download has the right contents. 1286 download, err = ioutil.ReadFile(downpath) 1287 if err != nil { 1288 t.Fatal(err) 1289 } 1290 if !bytes.Equal(orig, download) { 1291 t.Fatal("data mismatch when downloading a file") 1292 } 1293 }