github.com/decred/dcrlnd@v0.7.6/netann/chan_status_manager_test.go (about)

     1  package netann_test
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"encoding/binary"
     7  	"fmt"
     8  	"io"
     9  	"sync"
    10  	"sync/atomic"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    15  	"github.com/decred/dcrd/wire"
    16  	"github.com/decred/dcrlnd/channeldb"
    17  	"github.com/decred/dcrlnd/keychain"
    18  	"github.com/decred/dcrlnd/lnwire"
    19  	"github.com/decred/dcrlnd/netann"
    20  )
    21  
    22  var (
    23  	testKeyLoc = keychain.KeyLocator{Family: keychain.KeyFamilyNodeKey}
    24  
    25  	// testSigBytes specifies a testing signature with the minimal length.
    26  	testSigBytes = []byte{
    27  		0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00,
    28  	}
    29  )
    30  
    31  // randOutpoint creates a random wire.Outpoint.
    32  func randOutpoint(t *testing.T) wire.OutPoint {
    33  	t.Helper()
    34  
    35  	var buf [36]byte
    36  	_, err := io.ReadFull(rand.Reader, buf[:])
    37  	if err != nil {
    38  		t.Fatalf("unable to generate random outpoint: %v", err)
    39  	}
    40  
    41  	op := wire.OutPoint{}
    42  	copy(op.Hash[:], buf[:32])
    43  	op.Index = binary.BigEndian.Uint32(buf[32:])
    44  
    45  	return op
    46  }
    47  
    48  var shortChanIDs uint64
    49  
    50  // createChannel generates a channeldb.OpenChannel with a random chanpoint and
    51  // short channel id.
    52  func createChannel(t *testing.T) *channeldb.OpenChannel {
    53  	t.Helper()
    54  
    55  	sid := atomic.AddUint64(&shortChanIDs, 1)
    56  
    57  	return &channeldb.OpenChannel{
    58  		ShortChannelID:  lnwire.NewShortChanIDFromInt(sid),
    59  		ChannelFlags:    lnwire.FFAnnounceChannel,
    60  		FundingOutpoint: randOutpoint(t),
    61  	}
    62  }
    63  
    64  // createEdgePolicies generates an edge info and two directional edge policies.
    65  // The remote party's public key is generated randomly, and then sorted against
    66  // our `pubkey` with the direction bit set appropriately in the policies. Our
    67  // update will be created with the disabled bit set if startEnabled is false.
    68  func createEdgePolicies(t *testing.T, channel *channeldb.OpenChannel,
    69  	pubkey *secp256k1.PublicKey, startEnabled bool) (*channeldb.ChannelEdgeInfo,
    70  	*channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy) {
    71  
    72  	var (
    73  		pubkey1 [33]byte
    74  		pubkey2 [33]byte
    75  		dir1    lnwire.ChanUpdateChanFlags
    76  		dir2    lnwire.ChanUpdateChanFlags
    77  	)
    78  
    79  	// Set pubkey1 to OUR pubkey.
    80  	copy(pubkey1[:], pubkey.SerializeCompressed())
    81  
    82  	// Set the disabled bit appropriately on our update.
    83  	if !startEnabled {
    84  		dir1 |= lnwire.ChanUpdateDisabled
    85  	}
    86  
    87  	// Generate and set pubkey2 for THEIR pubkey.
    88  	privKey2, err := secp256k1.GeneratePrivateKey()
    89  	if err != nil {
    90  		t.Fatalf("unable to generate key pair: %v", err)
    91  	}
    92  	copy(pubkey2[:], privKey2.PubKey().SerializeCompressed())
    93  
    94  	// Set pubkey1 to the lower of the two pubkeys.
    95  	if bytes.Compare(pubkey2[:], pubkey1[:]) < 0 {
    96  		pubkey1, pubkey2 = pubkey2, pubkey1
    97  		dir1, dir2 = dir2, dir1
    98  	}
    99  
   100  	// Now that the ordering has been established, set pubkey2's direction
   101  	// bit.
   102  	dir2 |= lnwire.ChanUpdateDirection
   103  
   104  	return &channeldb.ChannelEdgeInfo{
   105  			ChannelPoint:  channel.FundingOutpoint,
   106  			NodeKey1Bytes: pubkey1,
   107  			NodeKey2Bytes: pubkey2,
   108  		},
   109  		&channeldb.ChannelEdgePolicy{
   110  			ChannelID:    channel.ShortChanID().ToUint64(),
   111  			ChannelFlags: dir1,
   112  			LastUpdate:   time.Now(),
   113  			SigBytes:     testSigBytes,
   114  		},
   115  		&channeldb.ChannelEdgePolicy{
   116  			ChannelID:    channel.ShortChanID().ToUint64(),
   117  			ChannelFlags: dir2,
   118  			LastUpdate:   time.Now(),
   119  			SigBytes:     testSigBytes,
   120  		}
   121  }
   122  
   123  type mockGraph struct {
   124  	mu        sync.Mutex
   125  	channels  []*channeldb.OpenChannel
   126  	chanInfos map[wire.OutPoint]*channeldb.ChannelEdgeInfo
   127  	chanPols1 map[wire.OutPoint]*channeldb.ChannelEdgePolicy
   128  	chanPols2 map[wire.OutPoint]*channeldb.ChannelEdgePolicy
   129  	sidToCid  map[lnwire.ShortChannelID]wire.OutPoint
   130  
   131  	updates chan *lnwire.ChannelUpdate
   132  }
   133  
   134  func newMockGraph(t *testing.T, numChannels int,
   135  	startActive, startEnabled bool, pubKey *secp256k1.PublicKey) *mockGraph {
   136  
   137  	g := &mockGraph{
   138  		channels:  make([]*channeldb.OpenChannel, 0, numChannels),
   139  		chanInfos: make(map[wire.OutPoint]*channeldb.ChannelEdgeInfo),
   140  		chanPols1: make(map[wire.OutPoint]*channeldb.ChannelEdgePolicy),
   141  		chanPols2: make(map[wire.OutPoint]*channeldb.ChannelEdgePolicy),
   142  		sidToCid:  make(map[lnwire.ShortChannelID]wire.OutPoint),
   143  		updates:   make(chan *lnwire.ChannelUpdate, 2*numChannels),
   144  	}
   145  
   146  	for i := 0; i < numChannels; i++ {
   147  		c := createChannel(t)
   148  
   149  		info, pol1, pol2 := createEdgePolicies(
   150  			t, c, pubKey, startEnabled,
   151  		)
   152  
   153  		g.addChannel(c)
   154  		g.addEdgePolicy(c, info, pol1, pol2)
   155  	}
   156  
   157  	return g
   158  }
   159  
   160  func (g *mockGraph) FetchAllOpenChannels() ([]*channeldb.OpenChannel, error) {
   161  	return g.chans(), nil
   162  }
   163  
   164  func (g *mockGraph) FetchChannelEdgesByOutpoint(
   165  	op *wire.OutPoint) (*channeldb.ChannelEdgeInfo,
   166  	*channeldb.ChannelEdgePolicy, *channeldb.ChannelEdgePolicy, error) {
   167  
   168  	g.mu.Lock()
   169  	defer g.mu.Unlock()
   170  
   171  	info, ok := g.chanInfos[*op]
   172  	if !ok {
   173  		return nil, nil, nil, channeldb.ErrEdgeNotFound
   174  	}
   175  
   176  	pol1 := g.chanPols1[*op]
   177  	pol2 := g.chanPols2[*op]
   178  
   179  	return info, pol1, pol2, nil
   180  }
   181  
   182  func (g *mockGraph) ApplyChannelUpdate(update *lnwire.ChannelUpdate) error {
   183  	g.mu.Lock()
   184  	defer g.mu.Unlock()
   185  
   186  	outpoint, ok := g.sidToCid[update.ShortChannelID]
   187  	if !ok {
   188  		return fmt.Errorf("unknown short channel id: %v",
   189  			update.ShortChannelID)
   190  	}
   191  
   192  	pol1 := g.chanPols1[outpoint]
   193  	pol2 := g.chanPols2[outpoint]
   194  
   195  	// Determine which policy we should update by making the flags on the
   196  	// policies and updates, and seeing which match up.
   197  	var update1 bool
   198  	switch {
   199  	case update.ChannelFlags&lnwire.ChanUpdateDirection ==
   200  		pol1.ChannelFlags&lnwire.ChanUpdateDirection:
   201  		update1 = true
   202  
   203  	case update.ChannelFlags&lnwire.ChanUpdateDirection ==
   204  		pol2.ChannelFlags&lnwire.ChanUpdateDirection:
   205  		update1 = false
   206  
   207  	default:
   208  		return fmt.Errorf("unable to find policy to update")
   209  	}
   210  
   211  	timestamp := time.Unix(int64(update.Timestamp), 0)
   212  
   213  	policy := &channeldb.ChannelEdgePolicy{
   214  		ChannelID:    update.ShortChannelID.ToUint64(),
   215  		ChannelFlags: update.ChannelFlags,
   216  		LastUpdate:   timestamp,
   217  		SigBytes:     testSigBytes,
   218  	}
   219  
   220  	if update1 {
   221  		g.chanPols1[outpoint] = policy
   222  	} else {
   223  		g.chanPols2[outpoint] = policy
   224  	}
   225  
   226  	// Send the update to network. This channel should be sufficiently
   227  	// buffered to avoid deadlocking.
   228  	g.updates <- update
   229  
   230  	return nil
   231  }
   232  
   233  func (g *mockGraph) chans() []*channeldb.OpenChannel {
   234  	g.mu.Lock()
   235  	defer g.mu.Unlock()
   236  
   237  	channels := make([]*channeldb.OpenChannel, 0, len(g.channels))
   238  	channels = append(channels, g.channels...)
   239  
   240  	return channels
   241  }
   242  
   243  func (g *mockGraph) addChannel(channel *channeldb.OpenChannel) {
   244  	g.mu.Lock()
   245  	defer g.mu.Unlock()
   246  
   247  	g.channels = append(g.channels, channel)
   248  }
   249  
   250  func (g *mockGraph) addEdgePolicy(c *channeldb.OpenChannel,
   251  	info *channeldb.ChannelEdgeInfo,
   252  	pol1, pol2 *channeldb.ChannelEdgePolicy) {
   253  
   254  	g.mu.Lock()
   255  	defer g.mu.Unlock()
   256  
   257  	g.chanInfos[c.FundingOutpoint] = info
   258  	g.chanPols1[c.FundingOutpoint] = pol1
   259  	g.chanPols2[c.FundingOutpoint] = pol2
   260  	g.sidToCid[c.ShortChanID()] = c.FundingOutpoint
   261  }
   262  
   263  func (g *mockGraph) removeChannel(channel *channeldb.OpenChannel) {
   264  	g.mu.Lock()
   265  	defer g.mu.Unlock()
   266  
   267  	for i, c := range g.channels {
   268  		if c.FundingOutpoint != channel.FundingOutpoint {
   269  			continue
   270  		}
   271  
   272  		g.channels = append(g.channels[:i], g.channels[i+1:]...)
   273  		delete(g.chanInfos, c.FundingOutpoint)
   274  		delete(g.chanPols1, c.FundingOutpoint)
   275  		delete(g.chanPols2, c.FundingOutpoint)
   276  		delete(g.sidToCid, c.ShortChanID())
   277  		return
   278  	}
   279  }
   280  
   281  type mockSwitch struct {
   282  	mu       sync.Mutex
   283  	isActive map[lnwire.ChannelID]bool
   284  }
   285  
   286  func newMockSwitch() *mockSwitch {
   287  	return &mockSwitch{
   288  		isActive: make(map[lnwire.ChannelID]bool),
   289  	}
   290  }
   291  
   292  func (s *mockSwitch) HasActiveLink(chanID lnwire.ChannelID) bool {
   293  	s.mu.Lock()
   294  	defer s.mu.Unlock()
   295  
   296  	// If the link is found, we will returns it's active status. In the
   297  	// real switch, it returns EligibleToForward().
   298  	active, ok := s.isActive[chanID]
   299  	if ok {
   300  		return active
   301  	}
   302  
   303  	return false
   304  }
   305  
   306  func (s *mockSwitch) SetStatus(chanID lnwire.ChannelID, active bool) {
   307  	s.mu.Lock()
   308  	defer s.mu.Unlock()
   309  
   310  	s.isActive[chanID] = active
   311  }
   312  
   313  func newManagerCfg(t *testing.T, numChannels int,
   314  	startEnabled bool) (*netann.ChanStatusConfig, *mockGraph, *mockSwitch) {
   315  
   316  	t.Helper()
   317  
   318  	privKey, err := secp256k1.GeneratePrivateKey()
   319  	if err != nil {
   320  		t.Fatalf("unable to generate key pair: %v", err)
   321  	}
   322  	privKeySigner := keychain.NewPrivKeyMessageSigner(privKey, testKeyLoc)
   323  
   324  	graph := newMockGraph(
   325  		t, numChannels, startEnabled, startEnabled, privKey.PubKey(),
   326  	)
   327  	htlcSwitch := newMockSwitch()
   328  
   329  	cfg := &netann.ChanStatusConfig{
   330  		ChanStatusSampleInterval: 50 * time.Millisecond,
   331  		ChanEnableTimeout:        500 * time.Millisecond,
   332  		ChanDisableTimeout:       time.Second,
   333  		OurPubKey:                privKey.PubKey(),
   334  		OurKeyLoc:                testKeyLoc,
   335  		MessageSigner:            netann.NewNodeSigner(privKeySigner),
   336  		IsChannelActive:          htlcSwitch.HasActiveLink,
   337  		ApplyChannelUpdate:       graph.ApplyChannelUpdate,
   338  		DB:                       graph,
   339  		Graph:                    graph,
   340  	}
   341  
   342  	return cfg, graph, htlcSwitch
   343  }
   344  
   345  type testHarness struct {
   346  	t                  *testing.T
   347  	numChannels        int
   348  	graph              *mockGraph
   349  	htlcSwitch         *mockSwitch
   350  	mgr                *netann.ChanStatusManager
   351  	ourPubKey          *secp256k1.PublicKey
   352  	safeDisableTimeout time.Duration
   353  }
   354  
   355  // newHarness returns a new testHarness for testing a ChanStatusManager. The
   356  // mockGraph will be populated with numChannels channels. The startActive and
   357  // startEnabled govern the initial state of the channels wrt the htlcswitch and
   358  // the network, respectively.
   359  func newHarness(t *testing.T, numChannels int,
   360  	startActive, startEnabled bool) testHarness {
   361  
   362  	cfg, graph, htlcSwitch := newManagerCfg(t, numChannels, startEnabled)
   363  
   364  	mgr, err := netann.NewChanStatusManager(cfg)
   365  	if err != nil {
   366  		t.Fatalf("unable to create chan status manager: %v", err)
   367  	}
   368  
   369  	err = mgr.Start()
   370  	if err != nil {
   371  		t.Fatalf("unable to start chan status manager: %v", err)
   372  	}
   373  
   374  	h := testHarness{
   375  		t:                  t,
   376  		numChannels:        numChannels,
   377  		graph:              graph,
   378  		htlcSwitch:         htlcSwitch,
   379  		mgr:                mgr,
   380  		ourPubKey:          cfg.OurPubKey,
   381  		safeDisableTimeout: (3 * cfg.ChanDisableTimeout) / 2, // 1.5x
   382  	}
   383  
   384  	// Initialize link status as requested.
   385  	if startActive {
   386  		h.markActive(h.graph.channels)
   387  	} else {
   388  		h.markInactive(h.graph.channels)
   389  	}
   390  
   391  	return h
   392  }
   393  
   394  // markActive updates the active status of the passed channels within the mock
   395  // switch to active.
   396  func (h *testHarness) markActive(channels []*channeldb.OpenChannel) {
   397  	h.t.Helper()
   398  
   399  	for _, channel := range channels {
   400  		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
   401  		h.htlcSwitch.SetStatus(chanID, true)
   402  	}
   403  }
   404  
   405  // markInactive updates the active status of the passed channels within the mock
   406  // switch to inactive.
   407  func (h *testHarness) markInactive(channels []*channeldb.OpenChannel) {
   408  	h.t.Helper()
   409  
   410  	for _, channel := range channels {
   411  		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
   412  		h.htlcSwitch.SetStatus(chanID, false)
   413  	}
   414  }
   415  
   416  // assertEnables requests enables for all of the passed channels, and asserts
   417  // that the errors returned from RequestEnable matches expErr.
   418  func (h *testHarness) assertEnables(channels []*channeldb.OpenChannel, expErr error,
   419  	manual bool) {
   420  
   421  	h.t.Helper()
   422  
   423  	for _, channel := range channels {
   424  		h.assertEnable(channel.FundingOutpoint, expErr, manual)
   425  	}
   426  }
   427  
   428  // assertDisables requests disables for all of the passed channels, and asserts
   429  // that the errors returned from RequestDisable matches expErr.
   430  func (h *testHarness) assertDisables(channels []*channeldb.OpenChannel, expErr error,
   431  	manual bool) {
   432  
   433  	h.t.Helper()
   434  
   435  	for _, channel := range channels {
   436  		h.assertDisable(channel.FundingOutpoint, expErr, manual)
   437  	}
   438  }
   439  
   440  // assertAutos requests auto state management for all of the passed channels, and
   441  // asserts that the errors returned from RequestAuto matches expErr.
   442  func (h *testHarness) assertAutos(channels []*channeldb.OpenChannel,
   443  	expErr error) {
   444  
   445  	h.t.Helper()
   446  
   447  	for _, channel := range channels {
   448  		h.assertAuto(channel.FundingOutpoint, expErr)
   449  	}
   450  }
   451  
   452  // assertEnable requests an enable for the given outpoint, and asserts that the
   453  // returned error matches expErr.
   454  func (h *testHarness) assertEnable(outpoint wire.OutPoint, expErr error,
   455  	manual bool) {
   456  
   457  	h.t.Helper()
   458  
   459  	err := h.mgr.RequestEnable(outpoint, manual)
   460  	if err != expErr {
   461  		h.t.Fatalf("expected enable error: %v, got %v", expErr, err)
   462  	}
   463  }
   464  
   465  // assertDisable requests a disable for the given outpoint, and asserts that the
   466  // returned error matches expErr.
   467  func (h *testHarness) assertDisable(outpoint wire.OutPoint, expErr error,
   468  	manual bool) {
   469  
   470  	h.t.Helper()
   471  
   472  	err := h.mgr.RequestDisable(outpoint, manual)
   473  	if err != expErr {
   474  		h.t.Fatalf("expected disable error: %v, got %v", expErr, err)
   475  	}
   476  }
   477  
   478  // assertAuto requests auto state management for the given outpoint, and asserts
   479  // that the returned error matches expErr.
   480  func (h *testHarness) assertAuto(outpoint wire.OutPoint, expErr error) {
   481  	h.t.Helper()
   482  
   483  	err := h.mgr.RequestAuto(outpoint)
   484  	if err != expErr {
   485  		h.t.Fatalf("expected error: %v, got %v", expErr, err)
   486  	}
   487  }
   488  
   489  // assertNoUpdates waits for the specified duration, and asserts that no updates
   490  // are announced on the network.
   491  func (h *testHarness) assertNoUpdates(duration time.Duration) {
   492  	h.t.Helper()
   493  
   494  	h.assertUpdates(nil, false, duration)
   495  }
   496  
   497  // assertUpdates waits for the specified duration, asserting that an update
   498  // are receive on the network for each of the passed OpenChannels, and that all
   499  // of their disable bits are set to match expEnabled. The expEnabled parameter
   500  // is ignored if channels is nil.
   501  func (h *testHarness) assertUpdates(channels []*channeldb.OpenChannel,
   502  	expEnabled bool, duration time.Duration) {
   503  
   504  	h.t.Helper()
   505  
   506  	// Compute an index of the expected short channel ids for which we want
   507  	// to received updates.
   508  	expSids := sidsFromChans(channels)
   509  
   510  	timeout := time.After(duration)
   511  	recvdSids := make(map[lnwire.ShortChannelID]struct{})
   512  	for {
   513  		select {
   514  		case upd := <-h.graph.updates:
   515  			// Assert that the received short channel id is one that
   516  			// we expect. If no updates were expected, this will
   517  			// always fail on the first update received.
   518  			if _, ok := expSids[upd.ShortChannelID]; !ok {
   519  				h.t.Fatalf("received update for unexpected "+
   520  					"short chan id: %v", upd.ShortChannelID)
   521  			}
   522  
   523  			// Assert that the disabled bit is set properly.
   524  			enabled := upd.ChannelFlags&lnwire.ChanUpdateDisabled !=
   525  				lnwire.ChanUpdateDisabled
   526  			if expEnabled != enabled {
   527  				h.t.Fatalf("expected enabled: %v, actual: %v",
   528  					expEnabled, enabled)
   529  			}
   530  
   531  			recvdSids[upd.ShortChannelID] = struct{}{}
   532  
   533  		case <-timeout:
   534  			// Time is up, assert that the correct number of unique
   535  			// updates was received.
   536  			if len(recvdSids) == len(channels) {
   537  				return
   538  			}
   539  
   540  			h.t.Fatalf("expected %d updates, got %d",
   541  				len(channels), len(recvdSids))
   542  		}
   543  	}
   544  }
   545  
   546  // sidsFromChans returns an index contain the short channel ids of each channel
   547  // provided in the list of OpenChannels.
   548  func sidsFromChans(
   549  	channels []*channeldb.OpenChannel) map[lnwire.ShortChannelID]struct{} {
   550  
   551  	sids := make(map[lnwire.ShortChannelID]struct{})
   552  	for _, channel := range channels {
   553  		sids[channel.ShortChanID()] = struct{}{}
   554  	}
   555  	return sids
   556  }
   557  
   558  type stateMachineTest struct {
   559  	name         string
   560  	startEnabled bool
   561  	startActive  bool
   562  	fn           func(testHarness)
   563  }
   564  
   565  var stateMachineTests = []stateMachineTest{
   566  	{
   567  		name:         "active and enabled is stable",
   568  		startActive:  true,
   569  		startEnabled: true,
   570  		fn: func(h testHarness) {
   571  			// No updates should be sent because being active and
   572  			// enabled should be a stable state.
   573  			h.assertNoUpdates(h.safeDisableTimeout)
   574  		},
   575  	},
   576  	{
   577  		name:         "inactive and disabled is stable",
   578  		startActive:  false,
   579  		startEnabled: false,
   580  		fn: func(h testHarness) {
   581  			// No updates should be sent because being inactive and
   582  			// disabled should be a stable state.
   583  			h.assertNoUpdates(h.safeDisableTimeout)
   584  		},
   585  	},
   586  	{
   587  		name:         "start disabled request enable",
   588  		startActive:  true, // can't request enable unless active
   589  		startEnabled: false,
   590  		fn: func(h testHarness) {
   591  			// Request enables for all channels.
   592  			h.assertEnables(h.graph.chans(), nil, false)
   593  			// Expect to see them all enabled on the network.
   594  			h.assertUpdates(
   595  				h.graph.chans(), true, h.safeDisableTimeout,
   596  			)
   597  		},
   598  	},
   599  	{
   600  		name:         "start enabled request disable",
   601  		startActive:  true,
   602  		startEnabled: true,
   603  		fn: func(h testHarness) {
   604  			// Request disables for all channels.
   605  			h.assertDisables(h.graph.chans(), nil, false)
   606  			// Expect to see them all disabled on the network.
   607  			h.assertUpdates(
   608  				h.graph.chans(), false, h.safeDisableTimeout,
   609  			)
   610  		},
   611  	},
   612  	{
   613  		name:         "request enable already enabled",
   614  		startActive:  true,
   615  		startEnabled: true,
   616  		fn: func(h testHarness) {
   617  			// Request enables for already enabled channels.
   618  			h.assertEnables(h.graph.chans(), nil, false)
   619  			// Manager shouldn't send out any updates.
   620  			h.assertNoUpdates(h.safeDisableTimeout)
   621  		},
   622  	},
   623  	{
   624  		name:         "request disabled already disabled",
   625  		startActive:  false,
   626  		startEnabled: false,
   627  		fn: func(h testHarness) {
   628  			// Request disables for already enabled channels.
   629  			h.assertDisables(h.graph.chans(), nil, false)
   630  			// Manager shouldn't sent out any updates.
   631  			h.assertNoUpdates(h.safeDisableTimeout)
   632  		},
   633  	},
   634  	{
   635  		name:         "detect and disable inactive",
   636  		startActive:  true,
   637  		startEnabled: true,
   638  		fn: func(h testHarness) {
   639  			// Simulate disconnection and have links go inactive.
   640  			h.markInactive(h.graph.chans())
   641  			// Should see all channels passively disabled.
   642  			h.assertUpdates(
   643  				h.graph.chans(), false, h.safeDisableTimeout,
   644  			)
   645  		},
   646  	},
   647  	{
   648  		name:         "quick flap stays active",
   649  		startActive:  true,
   650  		startEnabled: true,
   651  		fn: func(h testHarness) {
   652  			// Simulate disconnection and have links go inactive.
   653  			h.markInactive(h.graph.chans())
   654  			// Allow 2 sample intervals to pass, but not long
   655  			// enough for a disable to occur.
   656  			time.Sleep(100 * time.Millisecond)
   657  			// Simulate reconnect by making channels active.
   658  			h.markActive(h.graph.chans())
   659  			// Request that all channels be reenabled.
   660  			h.assertEnables(h.graph.chans(), nil, false)
   661  			// Pending disable should have been canceled, and
   662  			// no updates sent. Channels remain enabled on the
   663  			// network.
   664  			h.assertNoUpdates(h.safeDisableTimeout)
   665  		},
   666  	},
   667  	{
   668  		name:         "no passive enable from becoming active",
   669  		startActive:  false,
   670  		startEnabled: false,
   671  		fn: func(h testHarness) {
   672  			// Simulate reconnect by making channels active.
   673  			h.markActive(h.graph.chans())
   674  			// No updates should be sent without explicit enable.
   675  			h.assertNoUpdates(h.safeDisableTimeout)
   676  		},
   677  	},
   678  	{
   679  		name:         "enable inactive channel fails",
   680  		startActive:  false,
   681  		startEnabled: false,
   682  		fn: func(h testHarness) {
   683  			// Request enable of inactive channels, expect error
   684  			// indicating that channel was not active.
   685  			h.assertEnables(
   686  				h.graph.chans(), netann.ErrEnableInactiveChan, false,
   687  			)
   688  			// No updates should be sent as a result of the failure.
   689  			h.assertNoUpdates(h.safeDisableTimeout)
   690  		},
   691  	},
   692  	{
   693  		name:         "enable unknown channel fails",
   694  		startActive:  false,
   695  		startEnabled: false,
   696  		fn: func(h testHarness) {
   697  			// Create channels unknown to the graph.
   698  			unknownChans := []*channeldb.OpenChannel{
   699  				createChannel(h.t),
   700  				createChannel(h.t),
   701  				createChannel(h.t),
   702  			}
   703  			// Request that they be enabled, which should return an
   704  			// error as the graph doesn't have an edge for them.
   705  			h.assertEnables(
   706  				unknownChans, channeldb.ErrEdgeNotFound, false,
   707  			)
   708  			// No updates should be sent as a result of the failure.
   709  			h.assertNoUpdates(h.safeDisableTimeout)
   710  		},
   711  	},
   712  	{
   713  		name:         "disable unknown channel fails",
   714  		startActive:  false,
   715  		startEnabled: false,
   716  		fn: func(h testHarness) {
   717  			// Create channels unknown to the graph.
   718  			unknownChans := []*channeldb.OpenChannel{
   719  				createChannel(h.t),
   720  				createChannel(h.t),
   721  				createChannel(h.t),
   722  			}
   723  			// Request that they be disabled, which should return an
   724  			// error as the graph doesn't have an edge for them.
   725  			h.assertDisables(
   726  				unknownChans, channeldb.ErrEdgeNotFound, false,
   727  			)
   728  			// No updates should be sent as a result of the failure.
   729  			h.assertNoUpdates(h.safeDisableTimeout)
   730  		},
   731  	},
   732  	{
   733  		name:         "add new channels",
   734  		startActive:  false,
   735  		startEnabled: false,
   736  		fn: func(h testHarness) {
   737  			// Allow the manager to enter a steady state for the
   738  			// initial channel set.
   739  			h.assertNoUpdates(h.safeDisableTimeout)
   740  
   741  			// Add a new channels to the graph, but don't yet add
   742  			// the edge policies. We should see no updates sent
   743  			// since the manager can't access the policies.
   744  			newChans := []*channeldb.OpenChannel{
   745  				createChannel(h.t),
   746  				createChannel(h.t),
   747  				createChannel(h.t),
   748  			}
   749  			for _, c := range newChans {
   750  				h.graph.addChannel(c)
   751  			}
   752  			h.assertNoUpdates(h.safeDisableTimeout)
   753  
   754  			// Check that trying to enable the channel with unknown
   755  			// edges results in a failure.
   756  			h.assertEnables(newChans, channeldb.ErrEdgeNotFound, false)
   757  
   758  			// Now, insert edge policies for the channel into the
   759  			// graph, starting with the channel enabled, and mark
   760  			// the link active.
   761  			for _, c := range newChans {
   762  				info, pol1, pol2 := createEdgePolicies(
   763  					h.t, c, h.ourPubKey, true,
   764  				)
   765  				h.graph.addEdgePolicy(c, info, pol1, pol2)
   766  			}
   767  			h.markActive(newChans)
   768  
   769  			// We expect no updates to be sent since the channel is
   770  			// enabled and active.
   771  			h.assertNoUpdates(h.safeDisableTimeout)
   772  
   773  			// Finally, assert that enabling the channel doesn't
   774  			// return an error now that everything is in place.
   775  			h.assertEnables(newChans, nil, false)
   776  		},
   777  	},
   778  	{
   779  		name:         "remove channels then disable",
   780  		startActive:  true,
   781  		startEnabled: true,
   782  		fn: func(h testHarness) {
   783  			// Allow the manager to enter a steady state for the
   784  			// initial channel set.
   785  			h.assertNoUpdates(h.safeDisableTimeout)
   786  
   787  			// Select half of the current channels to remove.
   788  			channels := h.graph.chans()
   789  			rmChans := channels[:len(channels)/2]
   790  
   791  			// Mark the channel inactive and remove them from the
   792  			// graph. This should trigger the manager to attempt a
   793  			// mark the channel disabled, but will unable to do so
   794  			// because it can't find the edge policies.
   795  			h.markInactive(rmChans)
   796  			for _, c := range rmChans {
   797  				h.graph.removeChannel(c)
   798  			}
   799  			h.assertNoUpdates(h.safeDisableTimeout)
   800  
   801  			// Check that trying to enable the channel with unknown
   802  			// edges results in a failure.
   803  			h.assertDisables(rmChans, channeldb.ErrEdgeNotFound, false)
   804  		},
   805  	},
   806  	{
   807  		name:         "disable channels then remove",
   808  		startActive:  true,
   809  		startEnabled: true,
   810  		fn: func(h testHarness) {
   811  			// Allow the manager to enter a steady state for the
   812  			// initial channel set.
   813  			h.assertNoUpdates(h.safeDisableTimeout)
   814  
   815  			// Select half of the current channels to remove.
   816  			channels := h.graph.chans()
   817  			rmChans := channels[:len(channels)/2]
   818  
   819  			// Check that trying to enable the channel with unknown
   820  			// edges results in a failure.
   821  			h.assertDisables(rmChans, nil, false)
   822  
   823  			// Since the channels are still in the graph, we expect
   824  			// these channels to be disabled on the network.
   825  			h.assertUpdates(rmChans, false, h.safeDisableTimeout)
   826  
   827  			// Finally, remove  the channels from the graph and
   828  			// assert no more updates are sent.
   829  			for _, c := range rmChans {
   830  				h.graph.removeChannel(c)
   831  			}
   832  			h.assertNoUpdates(h.safeDisableTimeout)
   833  		},
   834  	},
   835  	{
   836  		name:         "request manual enable",
   837  		startActive:  true,
   838  		startEnabled: false,
   839  		fn: func(h testHarness) {
   840  			// Request manual enables for all channels.
   841  			h.assertEnables(h.graph.chans(), nil, true)
   842  
   843  			// Expect to see them all enabled on the network.
   844  			h.assertUpdates(
   845  				h.graph.chans(), true, h.safeDisableTimeout,
   846  			)
   847  
   848  			// Subsequent request disables with manual = false should succeed.
   849  			h.assertDisables(
   850  				h.graph.chans(), nil, false,
   851  			)
   852  
   853  			// Expect to see them all disabled on the network again.
   854  			h.assertUpdates(
   855  				h.graph.chans(), false, h.safeDisableTimeout,
   856  			)
   857  		},
   858  	},
   859  	{
   860  		name:         "request manual disable",
   861  		startActive:  true,
   862  		startEnabled: true,
   863  		fn: func(h testHarness) {
   864  			// Request manual disables for all channels.
   865  			h.assertDisables(h.graph.chans(), nil, true)
   866  
   867  			// Expect to see them all disabled on the network.
   868  			h.assertUpdates(
   869  				h.graph.chans(), false, h.safeDisableTimeout,
   870  			)
   871  
   872  			// Request enables with manual = false should fail.
   873  			h.assertEnables(
   874  				h.graph.chans(), netann.ErrEnableManuallyDisabledChan, false,
   875  			)
   876  
   877  			// Request enables with manual = true should succeed.
   878  			h.assertEnables(h.graph.chans(), nil, true)
   879  
   880  			// Expect to see them all enabled on the network again.
   881  			h.assertUpdates(
   882  				h.graph.chans(), true, h.safeDisableTimeout,
   883  			)
   884  		},
   885  	},
   886  	{
   887  		name:         "restore auto",
   888  		startActive:  true,
   889  		startEnabled: true,
   890  		fn: func(h testHarness) {
   891  			// Request manual disables for all channels.
   892  			h.assertDisables(h.graph.chans(), nil, true)
   893  
   894  			// Expect to see them all disabled on the network.
   895  			h.assertUpdates(
   896  				h.graph.chans(), false, h.safeDisableTimeout,
   897  			)
   898  
   899  			// Request enables with manual = false should fail.
   900  			h.assertEnables(
   901  				h.graph.chans(), netann.ErrEnableManuallyDisabledChan, false,
   902  			)
   903  
   904  			// Request enables with manual = false should succeed after
   905  			// restoring auto state management.
   906  			h.assertAutos(h.graph.chans(), nil)
   907  			h.assertEnables(h.graph.chans(), nil, false)
   908  
   909  			// Expect to see them all enabled on the network again.
   910  			h.assertUpdates(
   911  				h.graph.chans(), true, h.safeDisableTimeout,
   912  			)
   913  		},
   914  	},
   915  }
   916  
   917  // TestChanStatusManagerStateMachine tests the possible state transitions that
   918  // can be taken by the ChanStatusManager.
   919  func TestChanStatusManagerStateMachine(t *testing.T) {
   920  	t.Parallel()
   921  
   922  	for _, test := range stateMachineTests {
   923  		tc := test
   924  		t.Run(test.name, func(t *testing.T) {
   925  			t.Parallel()
   926  
   927  			const numChannels = 10
   928  			h := newHarness(
   929  				t, numChannels, tc.startActive, tc.startEnabled,
   930  			)
   931  			defer h.mgr.Stop()
   932  
   933  			tc.fn(h)
   934  		})
   935  	}
   936  }