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 }