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  }