From e7d0754615377dae6c81e79e7020ffdf021ec683 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 24 Oct 2024 16:44:36 +0800 Subject: [PATCH 1/6] lntest: make sure minRelayFeerate is reset So every test starts with the default minRelayFeerate. --- lntest/fee_service.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lntest/fee_service.go b/lntest/fee_service.go index 0514a387ea..5138e05d64 100644 --- a/lntest/fee_service.go +++ b/lntest/fee_service.go @@ -159,6 +159,7 @@ func (f *FeeService) SetMinRelayFeerate(fee chainfee.SatPerKVByte) { func (f *FeeService) Reset() { f.lock.Lock() f.feeRateMap = make(map[uint32]uint32) + f.minRelayFeerate = chainfee.FeePerKwFloor.FeePerKVByte() f.lock.Unlock() // Initialize default fee estimate. From a745d74e7ccd523cfcb66160c78625e829378519 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 24 Oct 2024 18:24:38 +0800 Subject: [PATCH 2/6] lntest: make sure standby nodes' edges are cleaned --- lntest/harness.go | 12 ++++++++++++ lntest/harness_assertion.go | 21 ++++++++++++++++++--- lntest/node/state.go | 18 ++++++++++++++++-- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/lntest/harness.go b/lntest/harness.go index c68c3ad089..fd35b84d46 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -909,6 +909,18 @@ func (h *HarnessTest) validateNodeState(hn *node.HarnessNode) error { "delete all of them properly", hn.Name()) } + // The number of public edges should be zero. + if hn.State.Edge.Public != 0 { + return fmt.Errorf("%s: found active public egdes, please "+ + "clean them properly", hn.Name()) + } + + // The number of edges should be zero. + if hn.State.Edge.Total != 0 { + return fmt.Errorf("%s: found active edges, please "+ + "clean them properly", hn.Name()) + } + return nil } diff --git a/lntest/harness_assertion.go b/lntest/harness_assertion.go index d56e70703f..d6c7391773 100644 --- a/lntest/harness_assertion.go +++ b/lntest/harness_assertion.go @@ -19,6 +19,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" @@ -251,19 +252,33 @@ func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode, old = hn.State.Edge.Total } + // filterDisabled is a helper closure that filters out disabled + // channels. + filterDisabled := func(edge *lnrpc.ChannelEdge) bool { + if edge.Node1Policy.Disabled { + return false + } + if edge.Node2Policy.Disabled { + return false + } + + return true + } + err := wait.NoError(func() error { req := &lnrpc.ChannelGraphRequest{ IncludeUnannounced: includeUnannounced, } - chanGraph := hn.RPC.DescribeGraph(req) - total := len(chanGraph.Edges) + resp := hn.RPC.DescribeGraph(req) + activeEdges := fn.Filter(filterDisabled, resp.Edges) + total := len(activeEdges) if total-old == expected { if expected != 0 { // NOTE: assume edges come in ascending order // that the old edges are at the front of the // slice. - edges = chanGraph.Edges[old:] + edges = activeEdges[old:] } return nil diff --git a/lntest/node/state.go b/lntest/node/state.go index bab178bd04..6b94462402 100644 --- a/lntest/node/state.go +++ b/lntest/node/state.go @@ -7,6 +7,7 @@ import ( "time" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lntest/rpc" @@ -308,13 +309,26 @@ func (s *State) updateUTXOStats() { // updateEdgeStats counts the total edges. func (s *State) updateEdgeStats() { + // filterDisabled is a helper closure that filters out disabled + // channels. + filterDisabled := func(edge *lnrpc.ChannelEdge) bool { + if edge.Node1Policy.Disabled { + return false + } + if edge.Node2Policy.Disabled { + return false + } + + return true + } + req := &lnrpc.ChannelGraphRequest{IncludeUnannounced: true} resp := s.rpc.DescribeGraph(req) - s.Edge.Total = len(resp.Edges) + s.Edge.Total = len(fn.Filter(filterDisabled, resp.Edges)) req = &lnrpc.ChannelGraphRequest{IncludeUnannounced: false} resp = s.rpc.DescribeGraph(req) - s.Edge.Public = len(resp.Edges) + s.Edge.Public = len(fn.Filter(filterDisabled, resp.Edges)) } // updateWalletBalance creates stats for the node's wallet balance. From 9682aa7a786a110944cccbafdb94e92ab5280e3b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 24 Oct 2024 20:14:15 +0800 Subject: [PATCH 3/6] itest: fix `testZeroConfChannelOpen` and `testOptionScidAlias` Use a new node instead of standby node to avoid closing the channels in the end. --- itest/lnd_zero_conf_test.go | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/itest/lnd_zero_conf_test.go b/itest/lnd_zero_conf_test.go index d638703769..e0dd74b1b6 100644 --- a/itest/lnd_zero_conf_test.go +++ b/itest/lnd_zero_conf_test.go @@ -31,7 +31,11 @@ func testZeroConfChannelOpen(ht *lntest.HarnessTest) { "--protocol.anchors", } - bob := ht.Bob + bob := ht.NewNode("Bob", nil) + + // We'll give Bob some coins in order to fund the channel. + ht.FundCoins(btcutil.SatoshiPerBitcoin, bob) + carol := ht.NewNode("Carol", scidAliasArgs) ht.EnsureConnected(bob, carol) @@ -40,7 +44,7 @@ func testZeroConfChannelOpen(ht *lntest.HarnessTest) { p := lntest.OpenChannelParams{ Amt: chanAmt, } - chanPoint := ht.OpenChannel(bob, carol, p) + ht.OpenChannel(bob, carol, p) // Spin-up Dave so Carol can open a zero-conf channel to him. dave := ht.NewNode("Dave", scidAliasArgs) @@ -182,9 +186,6 @@ func testZeroConfChannelOpen(ht *lntest.HarnessTest) { ht.CompletePaymentRequests( dave, []string{eveInvoiceResp.PaymentRequest}, ) - - // Close standby node's channels. - ht.CloseChannel(bob, chanPoint) } // testOptionScidAlias checks that opening an option_scid_alias channel-type @@ -239,7 +240,11 @@ func optionScidAliasScenario(ht *lntest.HarnessTest, chantype, private bool) { "--protocol.anchors", } - bob := ht.Bob + bob := ht.NewNode("Bob", nil) + + // We'll give Bob some coins in order to fund the channel. + ht.FundCoins(btcutil.SatoshiPerBitcoin, bob) + carol := ht.NewNode("Carol", scidAliasArgs) dave := ht.NewNode("Dave", scidAliasArgs) @@ -285,21 +290,6 @@ func optionScidAliasScenario(ht *lntest.HarnessTest, chantype, private bool) { } fundingPoint2 := ht.OpenChannel(bob, carol, p) - defer func() { - // TODO(yy): remove the sleep once the following bug is fixed. - // When the payment is reported as settled by Bob, it's - // expected the commitment dance is finished and all subsequent - // states have been updated. Yet we'd receive the error `cannot - // co-op close channel with active htlcs` or `link failed to - // shutdown` if we close the channel. We need to investigate - // the order of settling the payments and updating commitments - // to understand and fix. - time.Sleep(2 * time.Second) - - // Close standby node's channels. - ht.CloseChannel(bob, fundingPoint2) - }() - // Wait until Dave receives the Bob<->Carol channel. ht.AssertTopologyChannelOpen(dave, fundingPoint2) From 35992e1503ead5f214ece751cc473dfd5a50ac58 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 18 Oct 2024 02:59:46 +0800 Subject: [PATCH 4/6] lntest+itest: expore method `createSimpleNetwork` So it can be used via `ht.CreateSimpleNetwork`. --- itest/lnd_misc_test.go | 7 +- itest/lnd_payment_test.go | 9 ++- itest/lnd_routing_test.go | 5 +- itest/lnd_sweep_test.go | 80 ++++---------------- lntest/harness.go | 152 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 74 deletions(-) diff --git a/itest/lnd_misc_test.go b/itest/lnd_misc_test.go index ae0cbcd54a..ccd879ab6e 100644 --- a/itest/lnd_misc_test.go +++ b/itest/lnd_misc_test.go @@ -1421,9 +1421,10 @@ func testSendSelectedCoinsChannelReserve(ht *lntest.HarnessTest) { // Create a two-hop network: Alice -> Bob. // // NOTE: Alice will have one UTXO after the funding. - _, nodes := createSimpleNetwork( - ht, []string{"--protocol.anchors"}, 2, - lntest.OpenChannelParams{ + cfg := []string{"--protocol.anchors"} + cfgs := [][]string{cfg, cfg} + _, nodes := ht.CreateSimpleNetwork( + cfgs, lntest.OpenChannelParams{ Amt: chanAmt, }, ) diff --git a/itest/lnd_payment_test.go b/itest/lnd_payment_test.go index 5012212063..cb64093737 100644 --- a/itest/lnd_payment_test.go +++ b/itest/lnd_payment_test.go @@ -41,9 +41,10 @@ func testPaymentSucceededHTLCRemoteSwept(ht *lntest.HarnessTest) { openChannelParams := lntest.OpenChannelParams{ Amt: chanAmt, } + cfgs := [][]string{nil, nil} // Create a two hop network: Alice -> Bob. - chanPoints, nodes := createSimpleNetwork(ht, nil, 2, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) chanPoint := chanPoints[0] alice, bob := nodes[0], nodes[1] @@ -197,9 +198,10 @@ func runTestPaymentHTLCTimeout(ht *lntest.HarnessTest, restartAlice bool) { openChannelParams := lntest.OpenChannelParams{ Amt: chanAmt, } + cfgs := [][]string{nil, nil} // Create a two hop network: Alice -> Bob. - chanPoints, nodes := createSimpleNetwork(ht, nil, 2, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) chanPoint := chanPoints[0] alice, bob := nodes[0], nodes[1] @@ -1247,9 +1249,10 @@ func runSendToRouteFailHTLCTimeout(ht *lntest.HarnessTest, restartAlice bool) { openChannelParams := lntest.OpenChannelParams{ Amt: chanAmt, } + cfgs := [][]string{nil, nil} // Create a two hop network: Alice -> Bob. - chanPoints, nodes := createSimpleNetwork(ht, nil, 2, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) chanPoint := chanPoints[0] alice, bob := nodes[0], nodes[1] diff --git a/itest/lnd_routing_test.go b/itest/lnd_routing_test.go index d92de5aba5..c2fc6886bd 100644 --- a/itest/lnd_routing_test.go +++ b/itest/lnd_routing_test.go @@ -1525,8 +1525,9 @@ func testRouteFeeCutoff(ht *lntest.HarnessTest) { func testFeeLimitAfterQueryRoutes(ht *lntest.HarnessTest) { // Create a three hop network: Alice -> Bob -> Carol. chanAmt := btcutil.Amount(100000) - chanPoints, nodes := createSimpleNetwork( - ht, []string{}, 3, lntest.OpenChannelParams{Amt: chanAmt}, + cfgs := [][]string{nil, nil, nil} + chanPoints, nodes := ht.CreateSimpleNetwork( + cfgs, lntest.OpenChannelParams{Amt: chanAmt}, ) alice, bob, carol := nodes[0], nodes[1], nodes[2] chanPointAliceBob, chanPointBobCarol := chanPoints[0], chanPoints[1] diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index fbe3e6e4c6..17e0910b63 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -98,12 +98,14 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // swept so we can focus on testing HTLCs. fmt.Sprintf("--bitcoin.defaultremotedelay=%v", cltvDelta*10), } + cfgs := [][]string{cfg, cfg, cfg} + openChannelParams := lntest.OpenChannelParams{ Amt: invoiceAmt * 10, } // Create a three hop network: Alice -> Bob -> Carol. - chanPoints, nodes := createSimpleNetwork(ht, cfg, 3, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) // Unwrap the results. abChanPoint, bcChanPoint := chanPoints[0], chanPoints[1] @@ -426,12 +428,14 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // swept so we can focus on testing HTLCs. fmt.Sprintf("--bitcoin.defaultremotedelay=%v", cltvDelta*10), } + cfgs := [][]string{cfg, cfg, cfg} + openChannelParams := lntest.OpenChannelParams{ Amt: invoiceAmt * 10, } // Create a three hop network: Alice -> Bob -> Carol. - chanPoints, nodes := createSimpleNetwork(ht, cfg, 3, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) // Unwrap the results. abChanPoint, bcChanPoint := chanPoints[0], chanPoints[1] @@ -771,12 +775,14 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // swept so we can focus on testing HTLCs. fmt.Sprintf("--bitcoin.defaultremotedelay=%v", cltvDelta*10), } + cfgs := [][]string{cfg, cfg, cfg} + openChannelParams := lntest.OpenChannelParams{ Amt: invoiceAmt * 10, } // Create a three hop network: Alice -> Bob -> Carol. - chanPoints, nodes := createSimpleNetwork(ht, cfg, 3, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) // Unwrap the results. abChanPoint, bcChanPoint := chanPoints[0], chanPoints[1] @@ -1298,13 +1304,15 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { fmt.Sprintf("--sweeper.nodeadlineconftarget=%v", deadline), fmt.Sprintf("--bitcoin.defaultremotedelay=%v", toLocalCSV), } + cfgs := [][]string{cfg, cfg} + openChannelParams := lntest.OpenChannelParams{ Amt: fundAmt, PushAmt: bobBalance, } // Create a two hop network: Alice -> Bob. - chanPoints, nodes := createSimpleNetwork(ht, cfg, 2, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) // Unwrap the results. chanPoint := chanPoints[0] @@ -1780,67 +1788,6 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { ht.MineBlocksAndAssertNumTxes(1, 2) } -// createSimpleNetwork creates the specified number of nodes and makes a -// topology of `node1 -> node2 -> node3...`. Each node is created using the -// specified config, the neighbors are connected, and the channels are opened. -// Each node will be funded with a single UTXO of 1 BTC except the last one. -func createSimpleNetwork(ht *lntest.HarnessTest, nodeCfg []string, - numNodes int, p lntest.OpenChannelParams) ([]*lnrpc.ChannelPoint, - []*node.HarnessNode) { - - // Make a slice of nodes. - nodes := make([]*node.HarnessNode, numNodes) - - // Create new nodes. - for i := range nodes { - nodeName := fmt.Sprintf("Node%q", string(rune('A'+i))) - n := ht.NewNode(nodeName, nodeCfg) - nodes[i] = n - } - - // Connect the nodes in a chain. - for i := 1; i < len(nodes); i++ { - nodeA := nodes[i-1] - nodeB := nodes[i] - ht.EnsureConnected(nodeA, nodeB) - } - - // Fund all the nodes expect the last one. - for i := 0; i < len(nodes)-1; i++ { - node := nodes[i] - ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, node) - } - - // Mine 1 block to get the above coins confirmed. - ht.MineBlocksAndAssertNumTxes(1, numNodes-1) - - // Open channels in batch to save blocks mined. - reqs := make([]*lntest.OpenChannelRequest, 0, len(nodes)-1) - for i := 0; i < len(nodes)-1; i++ { - nodeA := nodes[i] - nodeB := nodes[i+1] - - req := &lntest.OpenChannelRequest{ - Local: nodeA, - Remote: nodeB, - Param: p, - } - reqs = append(reqs, req) - } - resp := ht.OpenMultiChannelsAsync(reqs) - - // Make sure the nodes know each other's channels if they are public. - if !p.Private { - for _, node := range nodes { - for _, chanPoint := range resp { - ht.AssertTopologyChannelOpen(node, chanPoint) - } - } - } - - return resp, nodes -} - // testBumpFee checks that when a new input is requested, it's first bumped via // CPFP, then RBF. Along the way, we check the `BumpFee` can properly update // the fee function used by supplying new params. @@ -2185,9 +2132,10 @@ func testBumpForceCloseFee(ht *lntest.HarnessTest) { cfg := []string{ "--protocol.anchors", } + cfgs := [][]string{cfg, cfg} // Create a two hop network: Alice -> Bob. - chanPoints, nodes := createSimpleNetwork(ht, cfg, 2, openChannelParams) + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) // Unwrap the results. chanPoint := chanPoints[0] diff --git a/lntest/harness.go b/lntest/harness.go index fd35b84d46..274f224139 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -2209,3 +2209,155 @@ func (h *HarnessTest) SendCoins(a, b *node.HarnessNode, return tx } + +// CreateSimpleNetwork creates the number of nodes specified by the number of +// configs and makes a topology of `node1 -> node2 -> node3...`. Each node is +// created using the specified config, the neighbors are connected, and the +// channels are opened. Each node will be funded with a single UTXO of 1 BTC +// except the last one. +// +// For instance, to create a network with 2 nodes that share the same node +// config, +// +// cfg := []string{"--protocol.anchors"} +// cfgs := [][]string{cfg, cfg} +// params := OpenChannelParams{...} +// chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, params) +// +// This will create two nodes and open an anchor channel between them. +func (h *HarnessTest) CreateSimpleNetwork(nodeCfgs [][]string, + p OpenChannelParams) ([]*lnrpc.ChannelPoint, []*node.HarnessNode) { + + // Create new nodes. + nodes := h.createNodes(nodeCfgs) + + var resp []*lnrpc.ChannelPoint + + // Open zero-conf channels if specified. + if p.ZeroConf { + resp = h.openZeroConfChannelsForNodes(nodes, p) + } else { + // Open channels between the nodes. + resp = h.openChannelsForNodes(nodes, p) + } + + return resp, nodes +} + +// acceptChannel is used to accept a single channel that comes across. This +// should be run in a goroutine and is used to test nodes with the zero-conf +// feature bit. +func acceptChannel(t *testing.T, zeroConf bool, stream rpc.AcceptorClient) { + req, err := stream.Recv() + require.NoError(t, err) + + resp := &lnrpc.ChannelAcceptResponse{ + Accept: true, + PendingChanId: req.PendingChanId, + ZeroConf: zeroConf, + } + err = stream.Send(resp) + require.NoError(t, err) +} + +// createNodes creates the number of nodes specified by the number of configs. +// Each node is created using the specified config, the neighbors are +// connected. +func (h *HarnessTest) createNodes(nodeCfgs [][]string) []*node.HarnessNode { + // Get the number of nodes. + numNodes := len(nodeCfgs) + + // Make a slice of nodes. + nodes := make([]*node.HarnessNode, numNodes) + + // Create new nodes. + for i, nodeCfg := range nodeCfgs { + nodeName := fmt.Sprintf("Node%q", string(rune('A'+i))) + n := h.NewNode(nodeName, nodeCfg) + nodes[i] = n + } + + // Connect the nodes in a chain. + for i := 1; i < len(nodes); i++ { + nodeA := nodes[i-1] + nodeB := nodes[i] + h.EnsureConnected(nodeA, nodeB) + } + + // Fund all the nodes expect the last one. + for i := 0; i < len(nodes)-1; i++ { + node := nodes[i] + h.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, node) + } + + // Mine 1 block to get the above coins confirmed. + h.MineBlocksAndAssertNumTxes(1, numNodes-1) + + return nodes +} + +// openChannelsForNodes takes a list of nodes and makes a topology of `node1 -> +// node2 -> node3...`. +func (h *HarnessTest) openChannelsForNodes(nodes []*node.HarnessNode, + p OpenChannelParams) []*lnrpc.ChannelPoint { + + // Sanity check the params. + require.False(h, p.ZeroConf, "zero-conf channels must be disabled") + require.Greater(h, len(nodes), 1, "need at least 2 nodes") + + // Open channels in batch to save blocks mined. + reqs := make([]*OpenChannelRequest, 0, len(nodes)-1) + for i := 0; i < len(nodes)-1; i++ { + nodeA := nodes[i] + nodeB := nodes[i+1] + + req := &OpenChannelRequest{ + Local: nodeA, + Remote: nodeB, + Param: p, + } + reqs = append(reqs, req) + } + resp := h.OpenMultiChannelsAsync(reqs) + + // Make sure the nodes know each other's channels if they are public. + if !p.Private { + for _, node := range nodes { + for _, chanPoint := range resp { + h.AssertTopologyChannelOpen(node, chanPoint) + } + } + } + + return resp +} + +// openZeroConfChannelsForNodes takes a list of nodes and makes a topology of +// `node1 -> node2 -> node3...` with zero-conf channels. +func (h *HarnessTest) openZeroConfChannelsForNodes(nodes []*node.HarnessNode, + p OpenChannelParams) []*lnrpc.ChannelPoint { + + // Sanity check the params. + require.True(h, p.ZeroConf, "zero-conf channels must be enabled") + require.Greater(h, len(nodes), 1, "need at least 2 nodes") + + // We are opening numNodes-1 channels. + cancels := make([]context.CancelFunc, 0, len(nodes)-1) + + // Create the channel acceptors. + for _, node := range nodes[1:] { + acceptor, cancel := node.RPC.ChannelAcceptor() + go acceptChannel(h.T, true, acceptor) + + cancels = append(cancels, cancel) + } + + // Open channels between the nodes. + resp := h.openChannelsForNodes(nodes, p) + + for _, cancel := range cancels { + cancel() + } + + return resp +} From d27ff34b045b598c4a42fbac1e11e5daa22052c8 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 24 Oct 2024 23:10:41 +0800 Subject: [PATCH 5/6] lntest+itest: rename `AssertNumEdges` to `AssertNumActiveEdges` To properly reflect what the assertion is. --- itest/lnd_channel_graph_test.go | 6 ++--- itest/lnd_mpp_test.go | 2 +- itest/lnd_open_channel_test.go | 4 +-- itest/lnd_route_blinding_test.go | 6 ++--- itest/lnd_routing_test.go | 12 ++++----- lntest/harness_assertion.go | 45 +++++++++++++++++++++++++++++--- 6 files changed, 57 insertions(+), 18 deletions(-) diff --git a/itest/lnd_channel_graph_test.go b/itest/lnd_channel_graph_test.go index cf97bcf390..566d02c9ca 100644 --- a/itest/lnd_channel_graph_test.go +++ b/itest/lnd_channel_graph_test.go @@ -237,17 +237,17 @@ func testUnannouncedChannels(ht *lntest.HarnessTest) { fundingChanPoint := ht.WaitForChannelOpenEvent(chanOpenUpdate) // Alice should have 1 edge in her graph. - ht.AssertNumEdges(alice, 1, true) + ht.AssertNumActiveEdges(alice, 1, true) // Channels should not be announced yet, hence Alice should have no // announced edges in her graph. - ht.AssertNumEdges(alice, 0, false) + ht.AssertNumActiveEdges(alice, 0, false) // Mine 4 more blocks, and check that the channel is now announced. ht.MineBlocks(4) // Give the network a chance to learn that auth proof is confirmed. - ht.AssertNumEdges(alice, 1, false) + ht.AssertNumActiveEdges(alice, 1, false) // Close the channel used during the test. ht.CloseChannel(alice, fundingChanPoint) diff --git a/itest/lnd_mpp_test.go b/itest/lnd_mpp_test.go index b5cd147dd7..37da783c18 100644 --- a/itest/lnd_mpp_test.go +++ b/itest/lnd_mpp_test.go @@ -299,7 +299,7 @@ func (m *mppTestScenario) openChannels(r *mppOpenChannelRequest) { } // Each node should have exactly 6 edges. - m.ht.AssertNumEdges(hn, len(m.channelPoints), false) + m.ht.AssertNumActiveEdges(hn, len(m.channelPoints), false) } } diff --git a/itest/lnd_open_channel_test.go b/itest/lnd_open_channel_test.go index a196d71c5f..48e68fba0b 100644 --- a/itest/lnd_open_channel_test.go +++ b/itest/lnd_open_channel_test.go @@ -84,7 +84,7 @@ func testOpenChannelAfterReorg(ht *lntest.HarnessTest) { ht.AssertTopologyChannelOpen(bob, chanPoint) // Alice should now have 1 edge in her graph. - ht.AssertNumEdges(alice, 1, true) + ht.AssertNumActiveEdges(alice, 1, true) // Now we disconnect Alice's chain backend from the original miner, and // connect the two miners together. Since the temporary miner knows @@ -112,7 +112,7 @@ func testOpenChannelAfterReorg(ht *lntest.HarnessTest) { // Since the fundingtx was reorged out, Alice should now have no edges // in her graph. - ht.AssertNumEdges(alice, 0, true) + ht.AssertNumActiveEdges(alice, 0, true) // Cleanup by mining the funding tx again, then closing the channel. block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index ba5d40ec8f..b921103ac2 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -985,7 +985,7 @@ func testMPPToSingleBlindedPath(ht *lntest.HarnessTest) { } // Each node should have exactly numPublic edges. - ht.AssertNumEdges(hn, numPublic, false) + ht.AssertNumActiveEdges(hn, numPublic, false) } // Make Dave create an invoice with a blinded path for Alice to pay. @@ -1156,7 +1156,7 @@ func testBlindedRouteDummyHops(ht *lntest.HarnessTest) { } // Each node should have exactly 5 edges. - ht.AssertNumEdges(hn, len(channelPoints), false) + ht.AssertNumActiveEdges(hn, len(channelPoints), false) } // Make Dave create an invoice with a blinded path for Alice to pay. @@ -1325,7 +1325,7 @@ func testMPPToMultipleBlindedPaths(ht *lntest.HarnessTest) { } // Each node should have exactly 5 edges. - ht.AssertNumEdges(hn, len(channelPoints), false) + ht.AssertNumActiveEdges(hn, len(channelPoints), false) } // Ok now make a payment that must be split to succeed. diff --git a/itest/lnd_routing_test.go b/itest/lnd_routing_test.go index c2fc6886bd..343cb2b993 100644 --- a/itest/lnd_routing_test.go +++ b/itest/lnd_routing_test.go @@ -591,12 +591,12 @@ func testPrivateChannels(ht *lntest.HarnessTest) { // Carol and Alice should know about 4, while Bob and Dave should only // know about 3, since one channel is private. - ht.AssertNumEdges(alice, 4, true) - ht.AssertNumEdges(alice, 3, false) - ht.AssertNumEdges(bob, 3, true) - ht.AssertNumEdges(carol, 4, true) - ht.AssertNumEdges(carol, 3, false) - ht.AssertNumEdges(dave, 3, true) + ht.AssertNumActiveEdges(alice, 4, true) + ht.AssertNumActiveEdges(alice, 3, false) + ht.AssertNumActiveEdges(bob, 3, true) + ht.AssertNumActiveEdges(carol, 4, true) + ht.AssertNumActiveEdges(carol, 3, false) + ht.AssertNumActiveEdges(dave, 3, true) // Close all channels. ht.CloseChannel(alice, chanPointAlice) diff --git a/lntest/harness_assertion.go b/lntest/harness_assertion.go index d6c7391773..3d1039846e 100644 --- a/lntest/harness_assertion.go +++ b/lntest/harness_assertion.go @@ -240,9 +240,9 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) { h.AssertPeerConnected(b, a) } -// AssertNumEdges checks that an expected number of edges can be found in the -// node specified. -func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode, +// AssertNumActiveEdges checks that an expected number of active edges can be +// found in the node specified. +func (h *HarnessTest) AssertNumActiveEdges(hn *node.HarnessNode, expected int, includeUnannounced bool) []*lnrpc.ChannelEdge { var edges []*lnrpc.ChannelEdge @@ -293,6 +293,45 @@ func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode, return edges } +// AssertNumEdges checks that an expected number of edges can be found in the +// node specified. +func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode, + expected int, includeUnannounced bool) []*lnrpc.ChannelEdge { + + var edges []*lnrpc.ChannelEdge + + old := hn.State.Edge.Public + if includeUnannounced { + old = hn.State.Edge.Total + } + + err := wait.NoError(func() error { + req := &lnrpc.ChannelGraphRequest{ + IncludeUnannounced: includeUnannounced, + } + resp := hn.RPC.DescribeGraph(req) + total := len(resp.Edges) + + if total-old == expected { + if expected != 0 { + // NOTE: assume edges come in ascending order + // that the old edges are at the front of the + // slice. + edges = resp.Edges[old:] + } + + return nil + } + + return errNumNotMatched(hn.Name(), "num of channel edges", + expected, total-old, total, old) + }, DefaultTimeout) + + require.NoError(h, err, "timeout while checking for edges") + + return edges +} + // ReceiveOpenChannelUpdate waits until a message is received on the stream or // the timeout is reached. func (h *HarnessTest) ReceiveOpenChannelUpdate( From 7dd9a176252155d5b6aa73fe75908570cc801fe3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 24 Oct 2024 23:23:59 +0800 Subject: [PATCH 6/6] lntest+itest: fix `testUpdateChanStatus` --- itest/lnd_channel_graph_test.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/itest/lnd_channel_graph_test.go b/itest/lnd_channel_graph_test.go index 566d02c9ca..54ddd2ca21 100644 --- a/itest/lnd_channel_graph_test.go +++ b/itest/lnd_channel_graph_test.go @@ -42,25 +42,23 @@ import ( // thus a following operation will fail if it relies on the channel being // enabled. func testUpdateChanStatus(ht *lntest.HarnessTest) { - // Create two fresh nodes and open a channel between them. - alice, bob := ht.Alice, ht.Bob - args := []string{ + // Prepare params. + chanAmt := btcutil.Amount(100_000) + openChannelParams := lntest.OpenChannelParams{ + Amt: chanAmt, + } + cfg := []string{ "--minbackoff=60s", "--chan-enable-timeout=3s", "--chan-disable-timeout=6s", "--chan-status-sample-interval=0.5s", } - ht.RestartNodeWithExtraArgs(alice, args) - ht.RestartNodeWithExtraArgs(bob, args) - ht.EnsureConnected(alice, bob) + cfgs := [][]string{cfg, cfg} - // Open a channel with 100k satoshis between Alice and Bob with Alice - // being the sole funder of the channel. - chanAmt := btcutil.Amount(100000) - chanPoint := ht.OpenChannel( - alice, bob, lntest.OpenChannelParams{Amt: chanAmt}, - ) - defer ht.CloseChannel(alice, chanPoint) + // Create two fresh nodes and open a channel between them. + chanPoints, nodes := ht.CreateSimpleNetwork(cfgs, openChannelParams) + chanPoint := chanPoints[0] + alice, bob := nodes[0], nodes[1] // assertEdgeDisabled ensures that Alice has the correct Disabled state // for given channel from her DescribeGraph.