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