github.com/decred/dcrlnd@v0.7.6/channeldb/db_test.go (about) 1 package channeldb 2 3 import ( 4 "io/ioutil" 5 "math" 6 "math/rand" 7 "net" 8 "os" 9 "path/filepath" 10 "reflect" 11 "testing" 12 13 "github.com/davecgh/go-spew/spew" 14 "github.com/decred/dcrd/chaincfg/chainhash" 15 "github.com/decred/dcrd/dcrutil/v4" 16 "github.com/decred/dcrd/wire" 17 "github.com/decred/dcrlnd/keychain" 18 "github.com/decred/dcrlnd/kvdb" 19 "github.com/decred/dcrlnd/lnwire" 20 "github.com/decred/dcrlnd/shachain" 21 "github.com/stretchr/testify/require" 22 ) 23 24 func TestOpenWithCreate(t *testing.T) { 25 t.Parallel() 26 27 // Checking for db file existence is not possible with postgres. 28 if kvdb.PostgresBackend { 29 t.Skip() 30 } 31 32 // First, create a temporary directory to be used for the duration of 33 // this test. 34 tempDirName, err := ioutil.TempDir("", "channeldb") 35 if err != nil { 36 t.Fatalf("unable to create temp dir: %v", err) 37 } 38 defer os.RemoveAll(tempDirName) 39 40 // Next, open thereby creating channeldb for the first time. 41 dbPath := filepath.Join(tempDirName, "cdb") 42 backend, cleanup, err := kvdb.GetTestBackend(dbPath, dbName) 43 if err != nil { 44 t.Fatalf("unable to get test db backend: %v", err) 45 } 46 defer cleanup() 47 48 cdb, err := CreateWithBackend(backend) 49 if err != nil { 50 t.Fatalf("unable to create channeldb: %v", err) 51 } 52 if err := cdb.Close(); err != nil { 53 t.Fatalf("unable to close channeldb: %v", err) 54 } 55 56 // The path should have been successfully created. 57 if !fileExists(dbPath) { 58 t.Fatalf("channeldb failed to create data directory") 59 } 60 61 // Now, reopen the same db in dry run migration mode. Since we have not 62 // applied any migrations, this should ignore the flag and not fail. 63 cdb, err = Open(dbPath, OptionDryRunMigration(true)) 64 if err != nil { 65 t.Fatalf("unable to create channeldb: %v", err) 66 } 67 if err := cdb.Close(); err != nil { 68 t.Fatalf("unable to close channeldb: %v", err) 69 } 70 } 71 72 // TestWipe tests that the database wipe operation completes successfully 73 // and that the buckets are deleted. It also checks that attempts to fetch 74 // information while the buckets are not set return the correct errors. 75 func TestWipe(t *testing.T) { 76 t.Parallel() 77 78 // First, create a temporary directory to be used for the duration of 79 // this test. 80 tempDirName, err := ioutil.TempDir("", "channeldb") 81 if err != nil { 82 t.Fatalf("unable to create temp dir: %v", err) 83 } 84 defer os.RemoveAll(tempDirName) 85 86 // Next, open thereby creating channeldb for the first time. 87 dbPath := filepath.Join(tempDirName, "cdb") 88 backend, cleanup, err := kvdb.GetTestBackend(dbPath, "cdb") 89 if err != nil { 90 t.Fatalf("unable to get test db backend: %v", err) 91 } 92 defer cleanup() 93 94 fullDB, err := CreateWithBackend(backend) 95 if err != nil { 96 t.Fatalf("unable to create channeldb: %v", err) 97 } 98 defer fullDB.Close() 99 100 if err := fullDB.Wipe(); err != nil { 101 t.Fatalf("unable to wipe channeldb: %v", err) 102 } 103 104 cdb := fullDB.ChannelStateDB() 105 106 // Check correct errors are returned 107 openChannels, err := cdb.FetchAllOpenChannels() 108 require.NoError(t, err, "fetching open channels") 109 require.Equal(t, 0, len(openChannels)) 110 111 closedChannels, err := cdb.FetchClosedChannels(false) 112 require.NoError(t, err, "fetching closed channels") 113 require.Equal(t, 0, len(closedChannels)) 114 } 115 116 // TestFetchClosedChannelForID tests that we are able to properly retrieve a 117 // ChannelCloseSummary from the DB given a ChannelID. 118 func TestFetchClosedChannelForID(t *testing.T) { 119 t.Parallel() 120 121 const numChans = 101 122 123 fullDB, cleanUp, err := MakeTestDB() 124 if err != nil { 125 t.Fatalf("unable to make test database: %v", err) 126 } 127 defer cleanUp() 128 129 cdb := fullDB.ChannelStateDB() 130 131 // Create the test channel state, that we will mutate the index of the 132 // funding point. 133 state := createTestChannelState(t, cdb) 134 135 // Now run through the number of channels, and modify the outpoint index 136 // to create new channel IDs. 137 for i := uint32(0); i < numChans; i++ { 138 // Save the open channel to disk. 139 state.FundingOutpoint.Index = i 140 141 // Write the channel to disk in a pending state. 142 createTestChannel( 143 t, cdb, 144 fundingPointOption(state.FundingOutpoint), 145 openChannelOption(), 146 ) 147 148 // Close the channel. To make sure we retrieve the correct 149 // summary later, we make them differ in the SettledBalance. 150 closeSummary := &ChannelCloseSummary{ 151 ChanPoint: state.FundingOutpoint, 152 RemotePub: state.IdentityPub, 153 SettledBalance: dcrutil.Amount(500 + i), 154 } 155 if err := state.CloseChannel(closeSummary); err != nil { 156 t.Fatalf("unable to close channel: %v", err) 157 } 158 } 159 160 // Now run though them all again and make sure we are able to retrieve 161 // summaries from the DB. 162 for i := uint32(0); i < numChans; i++ { 163 state.FundingOutpoint.Index = i 164 165 // We calculate the ChannelID and use it to fetch the summary. 166 cid := lnwire.NewChanIDFromOutPoint(&state.FundingOutpoint) 167 fetchedSummary, err := cdb.FetchClosedChannelForID(cid) 168 if err != nil { 169 t.Fatalf("unable to fetch close summary: %v", err) 170 } 171 172 // Make sure we retrieved the correct one by checking the 173 // SettledBalance. 174 if fetchedSummary.SettledBalance != dcrutil.Amount(500+i) { 175 t.Fatalf("summaries don't match: expected %v got %v", 176 dcrutil.Amount(500+i), 177 fetchedSummary.SettledBalance) 178 } 179 } 180 181 // As a final test we make sure that we get ErrClosedChannelNotFound 182 // for a ChannelID we didn't add to the DB. 183 state.FundingOutpoint.Index++ 184 cid := lnwire.NewChanIDFromOutPoint(&state.FundingOutpoint) 185 _, err = cdb.FetchClosedChannelForID(cid) 186 if err != ErrClosedChannelNotFound { 187 t.Fatalf("expected ErrClosedChannelNotFound, instead got: %v", err) 188 } 189 } 190 191 // TestAddrsForNode tests the we're able to properly obtain all the addresses 192 // for a target node. 193 func TestAddrsForNode(t *testing.T) { 194 t.Parallel() 195 196 fullDB, cleanUp, err := MakeTestDB() 197 if err != nil { 198 t.Fatalf("unable to make test database: %v", err) 199 } 200 defer cleanUp() 201 202 graph := fullDB.ChannelGraph() 203 204 // We'll make a test vertex to insert into the database, as the source 205 // node, but this node will only have half the number of addresses it 206 // usually does. 207 testNode, err := createTestVertex(fullDB) 208 if err != nil { 209 t.Fatalf("unable to create test node: %v", err) 210 } 211 testNode.Addresses = []net.Addr{testAddr} 212 if err := graph.SetSourceNode(testNode); err != nil { 213 t.Fatalf("unable to set source node: %v", err) 214 } 215 216 // Next, we'll make a link node with the same pubkey, but with an 217 // additional address. 218 nodePub, err := testNode.PubKey() 219 if err != nil { 220 t.Fatalf("unable to recv node pub: %v", err) 221 } 222 linkNode := NewLinkNode( 223 fullDB.channelStateDB.linkNodeDB, wire.MainNet, nodePub, 224 anotherAddr, 225 ) 226 if err := linkNode.Sync(); err != nil { 227 t.Fatalf("unable to sync link node: %v", err) 228 } 229 230 // Now that we've created a link node, as well as a vertex for the 231 // node, we'll query for all its addresses. 232 nodeAddrs, err := fullDB.AddrsForNode(nodePub) 233 if err != nil { 234 t.Fatalf("unable to obtain node addrs: %v", err) 235 } 236 237 expectedAddrs := make(map[string]struct{}) 238 expectedAddrs[testAddr.String()] = struct{}{} 239 expectedAddrs[anotherAddr.String()] = struct{}{} 240 241 // Finally, ensure that all the expected addresses are found. 242 if len(nodeAddrs) != len(expectedAddrs) { 243 t.Fatalf("expected %v addrs, got %v", 244 len(expectedAddrs), len(nodeAddrs)) 245 } 246 for _, addr := range nodeAddrs { 247 if _, ok := expectedAddrs[addr.String()]; !ok { 248 t.Fatalf("unexpected addr: %v", addr) 249 } 250 } 251 } 252 253 // TestFetchChannel tests that we're able to fetch an arbitrary channel from 254 // disk. 255 func TestFetchChannel(t *testing.T) { 256 t.Parallel() 257 258 fullDB, cleanUp, err := MakeTestDB() 259 if err != nil { 260 t.Fatalf("unable to make test database: %v", err) 261 } 262 defer cleanUp() 263 264 cdb := fullDB.ChannelStateDB() 265 266 // Create an open channel. 267 channelState := createTestChannel(t, cdb, openChannelOption()) 268 269 // Next, attempt to fetch the channel by its chan point. 270 dbChannel, err := cdb.FetchChannel(nil, channelState.FundingOutpoint) 271 if err != nil { 272 t.Fatalf("unable to fetch channel: %v", err) 273 } 274 275 // The decoded channel state should be identical to what we stored 276 // above. 277 if !reflect.DeepEqual(channelState, dbChannel) { 278 t.Fatalf("channel state doesn't match:: %v vs %v", 279 spew.Sdump(channelState), spew.Sdump(dbChannel)) 280 } 281 282 // If we attempt to query for a non-exist ante channel, then we should 283 // get an error. 284 channelState2 := createTestChannelState(t, cdb) 285 if err != nil { 286 t.Fatalf("unable to create channel state: %v", err) 287 } 288 channelState2.FundingOutpoint.Index ^= 1 289 290 _, err = cdb.FetchChannel(nil, channelState2.FundingOutpoint) 291 if err == nil { 292 t.Fatalf("expected query to fail") 293 } 294 } 295 296 func genRandomChannelShell() (*ChannelShell, error) { 297 var testPriv [32]byte 298 if _, err := rand.Read(testPriv[:]); err != nil { 299 return nil, err 300 } 301 302 _, pub := privKeyFromBytes(testPriv[:]) 303 304 var chanPoint wire.OutPoint 305 if _, err := rand.Read(chanPoint.Hash[:]); err != nil { 306 return nil, err 307 } 308 309 chanPoint.Index = uint32(rand.Intn(math.MaxUint16)) 310 311 chanStatus := ChanStatusDefault | ChanStatusRestored 312 313 var shaChainPriv [32]byte 314 if _, err := rand.Read(testPriv[:]); err != nil { 315 return nil, err 316 } 317 revRoot, err := chainhash.NewHash(shaChainPriv[:]) 318 if err != nil { 319 return nil, err 320 } 321 shaChainProducer := shachain.NewRevocationProducer(shachain.ShaHash(*revRoot)) 322 323 return &ChannelShell{ 324 NodeAddrs: []net.Addr{&net.TCPAddr{ 325 IP: net.ParseIP("127.0.0.1"), 326 Port: 18555, 327 }}, 328 Chan: &OpenChannel{ 329 chanStatus: chanStatus, 330 ChainHash: rev, 331 FundingOutpoint: chanPoint, 332 ShortChannelID: lnwire.NewShortChanIDFromInt( 333 uint64(rand.Int63()), 334 ), 335 IdentityPub: pub, 336 LocalChanCfg: ChannelConfig{ 337 ChannelConstraints: ChannelConstraints{ 338 CsvDelay: uint16(rand.Int63()), 339 }, 340 PaymentBasePoint: keychain.KeyDescriptor{ 341 KeyLocator: keychain.KeyLocator{ 342 Family: keychain.KeyFamily(rand.Int63()), 343 Index: uint32(rand.Int63()), 344 }, 345 }, 346 }, 347 RemoteCurrentRevocation: pub, 348 IsPending: false, 349 RevocationStore: shachain.NewRevocationStore(), 350 RevocationProducer: shaChainProducer, 351 }, 352 }, nil 353 } 354 355 // TestRestoreChannelShells tests that we're able to insert a partially channel 356 // populated to disk. This is useful for channel recovery purposes. We should 357 // find the new channel shell on disk, and also the db should be populated with 358 // an edge for that channel. 359 func TestRestoreChannelShells(t *testing.T) { 360 t.Parallel() 361 362 fullDB, cleanUp, err := MakeTestDB() 363 if err != nil { 364 t.Fatalf("unable to make test database: %v", err) 365 } 366 defer cleanUp() 367 368 cdb := fullDB.ChannelStateDB() 369 370 // First, we'll make our channel shell, it will only have the minimal 371 // amount of information required for us to initiate the data loss 372 // protection feature. 373 channelShell, err := genRandomChannelShell() 374 if err != nil { 375 t.Fatalf("unable to gen channel shell: %v", err) 376 } 377 378 // With the channel shell constructed, we'll now insert it into the 379 // database with the restoration method. 380 if err := cdb.RestoreChannelShells(channelShell); err != nil { 381 t.Fatalf("unable to restore channel shell: %v", err) 382 } 383 384 // Now that the channel has been inserted, we'll attempt to query for 385 // it to ensure we can properly locate it via various means. 386 // 387 // First, we'll attempt to query for all channels that we have with the 388 // node public key that was restored. 389 nodeChans, err := cdb.FetchOpenChannels(channelShell.Chan.IdentityPub) 390 if err != nil { 391 t.Fatalf("unable find channel: %v", err) 392 } 393 394 // We should now find a single channel from the database. 395 if len(nodeChans) != 1 { 396 t.Fatalf("unable to find restored channel by node "+ 397 "pubkey: %v", err) 398 } 399 400 // Ensure that it isn't possible to modify the commitment state machine 401 // of this restored channel. 402 channel := nodeChans[0] 403 err = channel.UpdateCommitment(nil, nil) 404 if err != ErrNoRestoredChannelMutation { 405 t.Fatalf("able to mutate restored channel") 406 } 407 err = channel.AppendRemoteCommitChain(nil) 408 if err != ErrNoRestoredChannelMutation { 409 t.Fatalf("able to mutate restored channel") 410 } 411 err = channel.AdvanceCommitChainTail(nil, nil) 412 if err != ErrNoRestoredChannelMutation { 413 t.Fatalf("able to mutate restored channel") 414 } 415 416 // That single channel should have the proper channel point, and also 417 // the expected set of flags to indicate that it was a restored 418 // channel. 419 if nodeChans[0].FundingOutpoint != channelShell.Chan.FundingOutpoint { 420 t.Fatalf("wrong funding outpoint: expected %v, got %v", 421 nodeChans[0].FundingOutpoint, 422 channelShell.Chan.FundingOutpoint) 423 } 424 if !nodeChans[0].HasChanStatus(ChanStatusRestored) { 425 t.Fatalf("node has wrong status flags: %v", 426 nodeChans[0].chanStatus) 427 } 428 429 // We should also be able to find the channel if we query for it 430 // directly. 431 _, err = cdb.FetchChannel(nil, channelShell.Chan.FundingOutpoint) 432 if err != nil { 433 t.Fatalf("unable to fetch channel: %v", err) 434 } 435 436 // We should also be able to find the link node that was inserted by 437 // its public key. 438 linkNode, err := fullDB.channelStateDB.linkNodeDB.FetchLinkNode( 439 channelShell.Chan.IdentityPub, 440 ) 441 if err != nil { 442 t.Fatalf("unable to fetch link node: %v", err) 443 } 444 445 // The node should have the same address, as specified in the channel 446 // shell. 447 if reflect.DeepEqual(linkNode.Addresses, channelShell.NodeAddrs) { 448 t.Fatalf("addr mismach: expected %v, got %v", 449 linkNode.Addresses, channelShell.NodeAddrs) 450 } 451 } 452 453 // TestAbandonChannel tests that the AbandonChannel method is able to properly 454 // remove a channel from the database and add a close channel summary. If 455 // called after a channel has already been removed, the method shouldn't return 456 // an error. 457 func TestAbandonChannel(t *testing.T) { 458 t.Parallel() 459 460 fullDB, cleanUp, err := MakeTestDB() 461 if err != nil { 462 t.Fatalf("unable to make test database: %v", err) 463 } 464 defer cleanUp() 465 466 cdb := fullDB.ChannelStateDB() 467 468 // If we attempt to abandon the state of a channel that doesn't exist 469 // in the open or closed channel bucket, then we should receive an 470 // error. 471 err = cdb.AbandonChannel(&wire.OutPoint{}, 0) 472 if err == nil { 473 t.Fatalf("removing non-existent channel should have failed") 474 } 475 476 // We'll now create a new channel in a pending state to abandon 477 // shortly. 478 chanState := createTestChannel(t, cdb) 479 480 // We should now be able to abandon the channel without any errors. 481 closeHeight := uint32(11) 482 err = cdb.AbandonChannel(&chanState.FundingOutpoint, closeHeight) 483 if err != nil { 484 t.Fatalf("unable to abandon channel: %v", err) 485 } 486 487 // At this point, the channel should no longer be found in the set of 488 // open channels. 489 _, err = cdb.FetchChannel(nil, chanState.FundingOutpoint) 490 if err != ErrChannelNotFound { 491 t.Fatalf("channel should not have been found: %v", err) 492 } 493 494 // However we should be able to retrieve a close channel summary for 495 // the channel. 496 _, err = cdb.FetchClosedChannel(&chanState.FundingOutpoint) 497 if err != nil { 498 t.Fatalf("unable to fetch closed channel: %v", err) 499 } 500 501 // Finally, if we attempt to abandon the channel again, we should get a 502 // nil error as the channel has already been abandoned. 503 err = cdb.AbandonChannel(&chanState.FundingOutpoint, closeHeight) 504 if err != nil { 505 t.Fatalf("unable to abandon channel: %v", err) 506 } 507 } 508 509 // TestFetchChannels tests the filtering of open channels in fetchChannels. 510 // It tests the case where no filters are provided (which is equivalent to 511 // FetchAllOpenChannels) and every combination of pending and waiting close. 512 func TestFetchChannels(t *testing.T) { 513 // Create static channel IDs for each kind of channel retrieved by 514 // fetchChannels so that the expected channel IDs can be set in tests. 515 var ( 516 // Pending is a channel that is pending open, and has not had 517 // a close initiated. 518 pendingChan = lnwire.NewShortChanIDFromInt(1) 519 520 // pendingWaitingClose is a channel that is pending open and 521 // has has its closing transaction broadcast. 522 pendingWaitingChan = lnwire.NewShortChanIDFromInt(2) 523 524 // openChan is a channel that has confirmed on chain. 525 openChan = lnwire.NewShortChanIDFromInt(3) 526 527 // openWaitingChan is a channel that has confirmed on chain, 528 // and it waiting for its close transaction to confirm. 529 openWaitingChan = lnwire.NewShortChanIDFromInt(4) 530 ) 531 532 tests := []struct { 533 name string 534 filters []fetchChannelsFilter 535 expectedChannels map[lnwire.ShortChannelID]bool 536 }{ 537 { 538 name: "get all channels", 539 filters: []fetchChannelsFilter{}, 540 expectedChannels: map[lnwire.ShortChannelID]bool{ 541 pendingChan: true, 542 pendingWaitingChan: true, 543 openChan: true, 544 openWaitingChan: true, 545 }, 546 }, 547 { 548 name: "pending channels", 549 filters: []fetchChannelsFilter{ 550 pendingChannelFilter(true), 551 }, 552 expectedChannels: map[lnwire.ShortChannelID]bool{ 553 pendingChan: true, 554 pendingWaitingChan: true, 555 }, 556 }, 557 { 558 name: "open channels", 559 filters: []fetchChannelsFilter{ 560 pendingChannelFilter(false), 561 }, 562 expectedChannels: map[lnwire.ShortChannelID]bool{ 563 openChan: true, 564 openWaitingChan: true, 565 }, 566 }, 567 { 568 name: "waiting close channels", 569 filters: []fetchChannelsFilter{ 570 waitingCloseFilter(true), 571 }, 572 expectedChannels: map[lnwire.ShortChannelID]bool{ 573 pendingWaitingChan: true, 574 openWaitingChan: true, 575 }, 576 }, 577 { 578 name: "not waiting close channels", 579 filters: []fetchChannelsFilter{ 580 waitingCloseFilter(false), 581 }, 582 expectedChannels: map[lnwire.ShortChannelID]bool{ 583 pendingChan: true, 584 openChan: true, 585 }, 586 }, 587 { 588 name: "pending waiting", 589 filters: []fetchChannelsFilter{ 590 pendingChannelFilter(true), 591 waitingCloseFilter(true), 592 }, 593 expectedChannels: map[lnwire.ShortChannelID]bool{ 594 pendingWaitingChan: true, 595 }, 596 }, 597 { 598 name: "pending, not waiting", 599 filters: []fetchChannelsFilter{ 600 pendingChannelFilter(true), 601 waitingCloseFilter(false), 602 }, 603 expectedChannels: map[lnwire.ShortChannelID]bool{ 604 pendingChan: true, 605 }, 606 }, 607 { 608 name: "open waiting", 609 filters: []fetchChannelsFilter{ 610 pendingChannelFilter(false), 611 waitingCloseFilter(true), 612 }, 613 expectedChannels: map[lnwire.ShortChannelID]bool{ 614 openWaitingChan: true, 615 }, 616 }, 617 { 618 name: "open, not waiting", 619 filters: []fetchChannelsFilter{ 620 pendingChannelFilter(false), 621 waitingCloseFilter(false), 622 }, 623 expectedChannels: map[lnwire.ShortChannelID]bool{ 624 openChan: true, 625 }, 626 }, 627 } 628 629 for _, test := range tests { 630 test := test 631 632 t.Run(test.name, func(t *testing.T) { 633 t.Parallel() 634 635 fullDB, cleanUp, err := MakeTestDB() 636 if err != nil { 637 t.Fatalf("unable to make test "+ 638 "database: %v", err) 639 } 640 defer cleanUp() 641 642 cdb := fullDB.ChannelStateDB() 643 644 // Create a pending channel that is not awaiting close. 645 createTestChannel( 646 t, cdb, channelIDOption(pendingChan), 647 ) 648 649 // Create a pending channel which has has been marked as 650 // broadcast, indicating that its closing transaction is 651 // waiting to confirm. 652 pendingClosing := createTestChannel( 653 t, cdb, 654 channelIDOption(pendingWaitingChan), 655 ) 656 657 err = pendingClosing.MarkCoopBroadcasted(nil, true) 658 if err != nil { 659 t.Fatalf("unexpected error: %v", err) 660 } 661 662 // Create a open channel that is not awaiting close. 663 createTestChannel( 664 t, cdb, 665 channelIDOption(openChan), 666 openChannelOption(), 667 ) 668 669 // Create a open channel which has has been marked as 670 // broadcast, indicating that its closing transaction is 671 // waiting to confirm. 672 openClosing := createTestChannel( 673 t, cdb, 674 channelIDOption(openWaitingChan), 675 openChannelOption(), 676 ) 677 err = openClosing.MarkCoopBroadcasted(nil, true) 678 if err != nil { 679 t.Fatalf("unexpected error: %v", err) 680 } 681 682 channels, err := fetchChannels(cdb, test.filters...) 683 if err != nil { 684 t.Fatalf("unexpected error: %v", err) 685 } 686 687 if len(channels) != len(test.expectedChannels) { 688 t.Fatalf("expected: %v channels, "+ 689 "got: %v", len(test.expectedChannels), 690 len(channels)) 691 } 692 693 for _, ch := range channels { 694 _, ok := test.expectedChannels[ch.ShortChannelID] 695 if !ok { 696 t.Fatalf("fetch channels unexpected "+ 697 "channel: %v", ch.ShortChannelID) 698 } 699 } 700 }) 701 } 702 } 703 704 // TestFetchHistoricalChannel tests lookup of historical channels. 705 func TestFetchHistoricalChannel(t *testing.T) { 706 fullDB, cleanUp, err := MakeTestDB() 707 if err != nil { 708 t.Fatalf("unable to make test database: %v", err) 709 } 710 defer cleanUp() 711 712 cdb := fullDB.ChannelStateDB() 713 714 // Create a an open channel in the database. 715 channel := createTestChannel(t, cdb, openChannelOption()) 716 717 // First, try to lookup a channel when nothing is in the bucket. As the 718 // bucket is auto-created (on start up), we'll get a channel not found 719 // error. 720 _, err = cdb.FetchHistoricalChannel(&channel.FundingOutpoint) 721 if err != ErrChannelNotFound { 722 t.Fatalf("expected no bucket, got: %v", err) 723 } 724 725 // Close the channel so that it will be written to the historical 726 // bucket. The values provided in the channel close summary are the 727 // minimum required for this call to run without panicking. 728 if err := channel.CloseChannel(&ChannelCloseSummary{ 729 ChanPoint: channel.FundingOutpoint, 730 RemotePub: channel.IdentityPub, 731 SettledBalance: dcrutil.Amount(500), 732 }); err != nil { 733 t.Fatalf("unexpected error closing channel: %v", err) 734 } 735 736 histChannel, err := cdb.FetchHistoricalChannel(&channel.FundingOutpoint) 737 if err != nil { 738 t.Fatalf("unexepected error getting channel: %v", err) 739 } 740 741 // FetchHistoricalChannel will attach the cdb to channel.Db, we set it 742 // here so that we can check that all other fields on the channel equal 743 // those on the historical channel. 744 channel.Db = cdb 745 746 if !reflect.DeepEqual(histChannel, channel) { 747 t.Fatalf("expected: %v, got: %v", channel, histChannel) 748 } 749 750 // Create an outpoint that will not be in the db and look it up. 751 badOutpoint := &wire.OutPoint{ 752 Hash: channel.FundingOutpoint.Hash, 753 Index: channel.FundingOutpoint.Index + 1, 754 } 755 _, err = cdb.FetchHistoricalChannel(badOutpoint) 756 if err != ErrChannelNotFound { 757 t.Fatalf("expected chan not found, got: %v", err) 758 } 759 760 }