github.com/decred/dcrlnd@v0.7.6/lntest/itest/lnd_funding_test.go (about) 1 package itest 2 3 import ( 4 "context" 5 "crypto/rand" 6 "fmt" 7 "testing" 8 "time" 9 10 "github.com/decred/dcrd/chaincfg/chainhash" 11 "github.com/decred/dcrd/dcrutil/v4" 12 "github.com/decred/dcrd/wire" 13 "github.com/decred/dcrlnd/input" 14 "github.com/decred/dcrlnd/labels" 15 "github.com/decred/dcrlnd/lnrpc" 16 "github.com/decred/dcrlnd/lnrpc/walletrpc" 17 "github.com/decred/dcrlnd/lntest" 18 "github.com/decred/dcrlnd/lnwire" 19 "github.com/stretchr/testify/require" 20 ) 21 22 // testBasicChannelFunding performs a test exercising expected behavior from a 23 // basic funding workflow. The test creates a new channel between Alice and 24 // Bob, then immediately closes the channel after asserting some expected post 25 // conditions. Finally, the chain itself is checked to ensure the closing 26 // transaction was mined. 27 func testBasicChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { 28 // Run through the test with combinations of all the different 29 // commitment types. 30 allTypes := []lnrpc.CommitmentType{ 31 lnrpc.CommitmentType_LEGACY, 32 lnrpc.CommitmentType_STATIC_REMOTE_KEY, 33 lnrpc.CommitmentType_ANCHORS, 34 } 35 36 // testFunding is a function closure that takes Carol and Dave's 37 // commitment types and test the funding flow. 38 testFunding := func(carolCommitType, daveCommitType lnrpc.CommitmentType) { 39 // Based on the current tweak variable for Carol, we'll 40 // preferentially signal the legacy commitment format. We do 41 // the same for Dave shortly below. 42 carolArgs := nodeArgsForCommitType(carolCommitType) 43 carol := net.NewNode(t.t, "Carol", carolArgs) 44 defer shutdownAndAssert(net, t, carol) 45 46 // Each time, we'll send Carol a new set of coins in order to 47 // fund the channel. 48 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 49 50 daveArgs := nodeArgsForCommitType(daveCommitType) 51 dave := net.NewNode(t.t, "Dave", daveArgs) 52 defer shutdownAndAssert(net, t, dave) 53 54 // Before we start the test, we'll ensure both sides are 55 // connected to the funding flow can properly be executed. 56 net.EnsureConnected(t.t, carol, dave) 57 58 carolChannel, daveChannel, closeChan, err := basicChannelFundingTest( 59 t, net, carol, dave, nil, 60 ) 61 if err != nil { 62 t.Fatalf("failed funding flow: %v", err) 63 } 64 65 // Both nodes should report the same commitment 66 // type. 67 chansCommitType := carolChannel.CommitmentType 68 if daveChannel.CommitmentType != chansCommitType { 69 t.Fatalf("commit types don't match, "+ 70 "carol got %v, dave got %v", 71 carolChannel.CommitmentType, 72 daveChannel.CommitmentType, 73 ) 74 } 75 76 // Now check that the commitment type reported 77 // by both nodes is what we expect. It will be 78 // the minimum of the two nodes' preference, in 79 // the order Legacy, Tweakless, Anchors. 80 expType := carolCommitType 81 82 switch daveCommitType { 83 84 // Dave supports anchors, type will be what 85 // Carol supports. 86 case lnrpc.CommitmentType_ANCHORS: 87 88 // Dave only supports tweakless, channel will 89 // be downgraded to this type if Carol supports 90 // anchors. 91 case lnrpc.CommitmentType_STATIC_REMOTE_KEY: 92 if expType == lnrpc.CommitmentType_ANCHORS { 93 expType = lnrpc.CommitmentType_STATIC_REMOTE_KEY 94 } 95 96 // Dave only supoprts legacy type, channel will 97 // be downgraded to this type. 98 case lnrpc.CommitmentType_LEGACY: 99 expType = lnrpc.CommitmentType_LEGACY 100 101 default: 102 t.Fatalf("invalid commit type %v", 103 daveCommitType) 104 } 105 106 // Check that the signalled type matches what we 107 // expect. 108 switch { 109 case expType == lnrpc.CommitmentType_ANCHORS && 110 chansCommitType == lnrpc.CommitmentType_ANCHORS: 111 112 case expType == lnrpc.CommitmentType_STATIC_REMOTE_KEY && 113 chansCommitType == lnrpc.CommitmentType_STATIC_REMOTE_KEY: 114 115 case expType == lnrpc.CommitmentType_LEGACY && 116 chansCommitType == lnrpc.CommitmentType_LEGACY: 117 118 default: 119 t.Fatalf("expected nodes to signal "+ 120 "commit type %v, instead got "+ 121 "%v", expType, chansCommitType) 122 } 123 124 // As we've concluded this sub-test case we'll 125 // now close out the channel for both sides. 126 closeChan() 127 128 shutdownAndAssert(net, t, carol) 129 shutdownAndAssert(net, t, dave) 130 } 131 132 test: 133 // We'll test all possible combinations of the feature bit presence 134 // that both nodes can signal for this new channel type. We'll make a 135 // new Carol+Dave for each test instance as well. 136 for _, carolCommitType := range allTypes { 137 for _, daveCommitType := range allTypes { 138 cc := carolCommitType 139 dc := daveCommitType 140 141 testName := fmt.Sprintf( 142 "carol_commit=%v,dave_commit=%v", cc, dc, 143 ) 144 145 logLine := fmt.Sprintf( 146 "---- basic channel funding subtest %s ----\n", 147 testName, 148 ) 149 net.Alice.AddToLog(logLine) 150 151 success := t.t.Run(testName, func(t *testing.T) { 152 testFunding(cc, dc) 153 }) 154 155 if !success { 156 break test 157 } 158 } 159 } 160 } 161 162 // basicChannelFundingTest is a sub-test of the main testBasicChannelFunding 163 // test. Given two nodes: Alice and Bob, it'll assert proper channel creation, 164 // then return a function closure that should be called to assert proper 165 // channel closure. 166 func basicChannelFundingTest(t *harnessTest, net *lntest.NetworkHarness, 167 alice *lntest.HarnessNode, bob *lntest.HarnessNode, 168 fundingShim *lnrpc.FundingShim) (*lnrpc.Channel, *lnrpc.Channel, func(), error) { 169 170 chanAmt := defaultChanAmt 171 pushAmt := dcrutil.Amount(100000) 172 atomsPerByte := dcrutil.Amount(1) 173 174 // Record nodes' channel balance before testing. 175 aliceChannelBalance := getChannelBalance(t, alice) 176 bobChannelBalance := getChannelBalance(t, bob) 177 178 // Creates a helper closure to be used below which asserts the proper 179 // response to a channel balance RPC. 180 checkChannelBalance := func(node *lntest.HarnessNode, 181 oldChannelBalance *lnrpc.ChannelBalanceResponse, 182 local, remote dcrutil.Amount) { 183 184 newResp := oldChannelBalance 185 186 newResp.LocalBalance.Atoms += uint64(local) 187 newResp.LocalBalance.Matoms += uint64( 188 lnwire.NewMAtomsFromAtoms(local), 189 ) 190 newResp.RemoteBalance.Atoms += uint64(remote) 191 newResp.RemoteBalance.Matoms += uint64( 192 lnwire.NewMAtomsFromAtoms(remote), 193 ) 194 // Deprecated fields. 195 newResp.Balance += int64(local) 196 assertChannelBalanceResp(t, node, newResp) 197 } 198 199 // First establish a channel with a capacity of 0.16 DCR between Alice 200 // and Bob with Alice pushing 100k atoms to Bob's side during 201 // funding. This function will block until the channel itself is fully 202 // open or an error occurs in the funding process. A series of 203 // assertions will be executed to ensure the funding process completed 204 // successfully. 205 chanPoint := openChannelAndAssert( 206 t, net, alice, bob, 207 lntest.OpenChannelParams{ 208 Amt: chanAmt, 209 PushAmt: pushAmt, 210 FundingShim: fundingShim, 211 AtomsPerByte: atomsPerByte, 212 }, 213 ) 214 215 err := alice.WaitForNetworkChannelOpen(chanPoint) 216 require.NoError(t.t, err, "alice didn't report channel") 217 218 err = bob.WaitForNetworkChannelOpen(chanPoint) 219 require.NoError(t.t, err, "bob didn't report channel") 220 221 cType, err := channelCommitType(alice, chanPoint) 222 if err != nil { 223 return nil, nil, nil, fmt.Errorf("unable to get channel "+ 224 "type: %v", err) 225 } 226 227 // With the channel open, ensure that the amount specified above has 228 // properly been pushed to Bob. 229 aliceLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0) 230 checkChannelBalance( 231 alice, aliceChannelBalance, aliceLocalBalance, pushAmt, 232 ) 233 checkChannelBalance( 234 bob, bobChannelBalance, pushAmt, aliceLocalBalance, 235 ) 236 237 req := &lnrpc.ListChannelsRequest{} 238 aliceChannel, err := alice.ListChannels(context.Background(), req) 239 if err != nil { 240 return nil, nil, nil, fmt.Errorf("unable to obtain chan: %v", err) 241 } 242 243 bobChannel, err := bob.ListChannels(context.Background(), req) 244 if err != nil { 245 return nil, nil, nil, fmt.Errorf("unable to obtain chan: %v", err) 246 } 247 248 closeChan := func() { 249 // Finally, immediately close the channel. This function will 250 // also block until the channel is closed and will additionally 251 // assert the relevant channel closing post conditions. 252 closeChannelAndAssert(t, net, alice, chanPoint, false) 253 } 254 255 return aliceChannel.Channels[0], bobChannel.Channels[0], closeChan, nil 256 } 257 258 // testUnconfirmedChannelFunding tests that our unconfirmed change outputs can 259 // be used to fund channels. 260 func testUnconfirmedChannelFunding(net *lntest.NetworkHarness, t *harnessTest) { 261 ctxb := context.Background() 262 263 const ( 264 chanAmt = defaultChanAmt 265 pushAmt = dcrutil.Amount(100000) 266 ) 267 268 // We'll start off by creating a node for Carol. 269 carol := net.NewNode(t.t, "Carol", nil) 270 defer shutdownAndAssert(net, t, carol) 271 272 // We'll send her some confirmed funds. 273 net.SendCoins(t.t, 2*chanAmt, carol) 274 275 // Now let Carol send some funds to herself, making a unconfirmed 276 // change output. 277 addrReq := &lnrpc.NewAddressRequest{ 278 Type: lnrpc.AddressType_PUBKEY_HASH, 279 } 280 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 281 resp, err := carol.NewAddress(ctxt, addrReq) 282 if err != nil { 283 t.Fatalf("unable to get new address: %v", err) 284 } 285 286 sendReq := &lnrpc.SendCoinsRequest{ 287 Addr: resp.Address, 288 Amount: int64(chanAmt) / 5, 289 } 290 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 291 _, err = carol.SendCoins(ctxt, sendReq) 292 if err != nil { 293 t.Fatalf("unable to send coins: %v", err) 294 } 295 296 // Make sure the unconfirmed tx is seen in the mempool. 297 _, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout) 298 if err != nil { 299 t.Fatalf("failed to find tx in miner mempool: %v", err) 300 } 301 302 // Now, we'll connect her to Alice so that they can open a channel 303 // together. The funding flow should select Carol's unconfirmed output 304 // as she doesn't have any other funds since it's a new node. 305 net.ConnectNodes(t.t, carol, net.Alice) 306 307 chanOpenUpdate := openChannelStream( 308 t, net, carol, net.Alice, 309 lntest.OpenChannelParams{ 310 Amt: chanAmt, 311 PushAmt: pushAmt, 312 SpendUnconfirmed: true, 313 }, 314 ) 315 316 // Creates a helper closure to be used below which asserts the proper 317 // response to a channel balance RPC. 318 checkChannelBalance := func(node *lntest.HarnessNode, 319 local, remote, pendingLocal, pendingRemote dcrutil.Amount) { 320 expectedResponse := &lnrpc.ChannelBalanceResponse{ 321 LocalBalance: &lnrpc.Amount{ 322 Atoms: uint64(local), 323 Matoms: uint64(lnwire.NewMAtomsFromAtoms( 324 local, 325 )), 326 }, 327 RemoteBalance: &lnrpc.Amount{ 328 Atoms: uint64(remote), 329 Matoms: uint64(lnwire.NewMAtomsFromAtoms( 330 remote, 331 )), 332 }, 333 PendingOpenLocalBalance: &lnrpc.Amount{ 334 Atoms: uint64(pendingLocal), 335 Matoms: uint64(lnwire.NewMAtomsFromAtoms( 336 pendingLocal, 337 )), 338 }, 339 PendingOpenRemoteBalance: &lnrpc.Amount{ 340 Atoms: uint64(pendingRemote), 341 Matoms: uint64(lnwire.NewMAtomsFromAtoms( 342 pendingRemote, 343 )), 344 }, 345 UnsettledLocalBalance: &lnrpc.Amount{}, 346 UnsettledRemoteBalance: &lnrpc.Amount{}, 347 // Deprecated fields. 348 Balance: int64(local), 349 PendingOpenBalance: int64(pendingLocal), 350 } 351 assertChannelBalanceResp(t, node, expectedResponse) 352 } 353 354 // As the channel is pending open, it's expected Carol has both zero 355 // local and remote balances, and pending local/remote should not be 356 // zero. 357 // 358 // Note that atm we haven't obtained the chanPoint yet, so we use the 359 // type directly. 360 cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY 361 carolLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0) 362 checkChannelBalance(carol, 0, 0, carolLocalBalance, pushAmt) 363 364 // For Alice, her local/remote balances should be zero, and the 365 // local/remote balances are the mirror of Carol's. 366 checkChannelBalance(net.Alice, 0, 0, pushAmt, carolLocalBalance) 367 368 // Confirm the channel and wait for it to be recognized by both 369 // parties. Two transactions should be mined, the unconfirmed spend and 370 // the funding tx. 371 mineBlocks(t, net, 6, 2) 372 chanPoint, err := net.WaitForChannelOpen(chanOpenUpdate) 373 require.NoError(t.t, err, "error while waitinng for channel open") 374 375 // With the channel open, we'll check the balances on each side of the 376 // channel as a sanity check to ensure things worked out as intended. 377 378 checkChannelBalance(carol, carolLocalBalance, pushAmt, 0, 0) 379 checkChannelBalance(net.Alice, pushAmt, carolLocalBalance, 0, 0) 380 381 // Now that we're done with the test, the channel can be closed. 382 closeChannelAndAssert(t, net, carol, chanPoint, false) 383 } 384 385 // testExternalFundingChanPoint tests that we're able to carry out a normal 386 // channel funding workflow given a channel point that was constructed outside 387 // the main daemon. 388 func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { 389 ctxb := context.Background() 390 391 // First, we'll create two new nodes that we'll use to open channel 392 // between for this test. 393 carol := net.NewNode(t.t, "carol", nil) 394 defer shutdownAndAssert(net, t, carol) 395 396 dave := net.NewNode(t.t, "dave", nil) 397 defer shutdownAndAssert(net, t, dave) 398 399 // Carol will be funding the channel, so we'll send some coins over to 400 // her and ensure they have enough confirmations before we proceed. 401 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 402 403 // Before we start the test, we'll ensure both sides are connected to 404 // the funding flow can properly be executed. 405 net.EnsureConnected(t.t, carol, dave) 406 407 // At this point, we're ready to simulate our external channel funding 408 // flow. To start with, we'll create a pending channel with a shim for 409 // a transaction that will never be published. 410 const thawHeight uint32 = 10 411 const chanSize = defaultChanAmt 412 fundingShim1, chanPoint1, _ := deriveFundingShim( 413 net, t, carol, dave, chanSize, thawHeight, false, 414 ) 415 _ = openChannelStream( 416 t, net, carol, dave, lntest.OpenChannelParams{ 417 Amt: chanSize, 418 FundingShim: fundingShim1, 419 }, 420 ) 421 assertNumOpenChannelsPending(t, carol, dave, 1) 422 423 // That channel is now pending forever and normally would saturate the 424 // max pending channel limit for both nodes. But because the channel is 425 // externally funded, we should still be able to open another one. Let's 426 // do exactly that now. For this one we publish the transaction so we 427 // can mine it later. 428 fundingShim2, chanPoint2, _ := deriveFundingShim( 429 net, t, carol, dave, chanSize, thawHeight, true, 430 ) 431 432 // At this point, we'll now carry out the normal basic channel funding 433 // test as everything should now proceed as normal (a regular channel 434 // funding flow). 435 carolChan, daveChan, _, err := basicChannelFundingTest( 436 t, net, carol, dave, fundingShim2, 437 ) 438 require.NoError(t.t, err) 439 440 // Both channels should be marked as frozen with the proper thaw 441 // height. 442 if carolChan.ThawHeight != thawHeight { 443 t.Fatalf("expected thaw height of %v, got %v", 444 carolChan.ThawHeight, thawHeight) 445 } 446 if daveChan.ThawHeight != thawHeight { 447 t.Fatalf("expected thaw height of %v, got %v", 448 daveChan.ThawHeight, thawHeight) 449 } 450 451 // Next, to make sure the channel functions as normal, we'll make some 452 // payments within the channel. 453 payAmt := dcrutil.Amount(100000) 454 invoice := &lnrpc.Invoice{ 455 Memo: "new chans", 456 Value: int64(payAmt), 457 } 458 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 459 resp, err := dave.AddInvoice(ctxt, invoice) 460 require.NoError(t.t, err) 461 err = completePaymentRequests( 462 carol, carol.RouterClient, []string{resp.PaymentRequest}, true, 463 ) 464 require.NoError(t.t, err) 465 466 // Now that the channels are open, and we've confirmed that they're 467 // operational, we'll now ensure that the channels are frozen as 468 // intended (if requested). 469 // 470 // First, we'll try to close the channel as Carol, the initiator. This 471 // should fail as a frozen channel only allows the responder to 472 // initiate a channel close. 473 _, _, err = net.CloseChannel(carol, chanPoint2, false) 474 require.Error(t.t, err, 475 "carol wasn't denied a co-op close attempt "+ 476 "for a frozen channel", 477 ) 478 479 // Next we'll try but this time with Dave (the responder) as the 480 // initiator. This time the channel should be closed as normal. 481 closeChannelAndAssert(t, net, dave, chanPoint2, false) 482 483 // As a last step, we check if we still have the pending channel hanging 484 // around because we never published the funding TX. 485 assertNumOpenChannelsPending(t, carol, dave, 1) 486 487 // Let's make sure we can abandon it. 488 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 489 _, err = carol.AbandonChannel(ctxt, &lnrpc.AbandonChannelRequest{ 490 ChannelPoint: chanPoint1, 491 PendingFundingShimOnly: true, 492 }) 493 require.NoError(t.t, err) 494 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 495 _, err = dave.AbandonChannel(ctxt, &lnrpc.AbandonChannelRequest{ 496 ChannelPoint: chanPoint1, 497 PendingFundingShimOnly: true, 498 }) 499 require.NoError(t.t, err) 500 501 // It should now not appear in the pending channels anymore. 502 assertNumOpenChannelsPending(t, carol, dave, 0) 503 } 504 505 // testFundingPersistence is intended to ensure that the Funding Manager 506 // persists the state of new channels prior to broadcasting the channel's 507 // funding transaction. This ensures that the daemon maintains an up-to-date 508 // representation of channels if the system is restarted or disconnected. 509 // testFundingPersistence mirrors testBasicChannelFunding, but adds restarts 510 // and checks for the state of channels with unconfirmed funding transactions. 511 func testChannelFundingPersistence(net *lntest.NetworkHarness, t *harnessTest) { 512 chanAmt := defaultChanAmt 513 pushAmt := dcrutil.Amount(0) 514 515 // As we need to create a channel that requires more than 1 516 // confirmation before it's open, with the current set of defaults, 517 // we'll need to create a new node instance. 518 const numConfs = 5 519 carolArgs := []string{fmt.Sprintf("--defaultchanconfs=%v", numConfs)} 520 carol := net.NewNode(t.t, "Carol", carolArgs) 521 522 // Clean up carol's node when the test finishes. 523 defer shutdownAndAssert(net, t, carol) 524 525 net.ConnectNodes(t.t, net.Alice, carol) 526 527 // Create a new channel that requires 5 confs before it's considered 528 // open, then broadcast the funding transaction 529 pendingUpdate, err := net.OpenPendingChannel( 530 net.Alice, carol, chanAmt, pushAmt, 531 ) 532 if err != nil { 533 t.Fatalf("unable to open channel: %v", err) 534 } 535 536 // At this point, the channel's funding transaction will have been 537 // broadcast, but not confirmed. Alice and Bob's nodes should reflect 538 // this when queried via RPC. 539 assertNumOpenChannelsPending(t, net.Alice, carol, 1) 540 541 // Restart both nodes to test that the appropriate state has been 542 // persisted and that both nodes recover gracefully. 543 if err := net.RestartNode(net.Alice, nil); err != nil { 544 t.Fatalf("Node restart failed: %v", err) 545 } 546 if err := net.RestartNode(carol, nil); err != nil { 547 t.Fatalf("Node restart failed: %v", err) 548 } 549 550 fundingTxID, err := chainhash.NewHash(pendingUpdate.Txid) 551 if err != nil { 552 t.Fatalf("unable to convert funding txid into chainhash.Hash:"+ 553 " %v", err) 554 } 555 fundingTxStr := fundingTxID.String() 556 557 // Mine a block, then wait for Alice's node to notify us that the 558 // channel has been opened. The funding transaction should be found 559 // within the newly mined block. 560 block := mineBlocks(t, net, 1, 1)[0] 561 assertTxInBlock(t, block, fundingTxID) 562 563 // Get the height that our transaction confirmed at. 564 _, height, err := net.Miner.Node.GetBestBlock(context.Background()) 565 require.NoError(t.t, err, "could not get best block") 566 567 // Restart both nodes to test that the appropriate state has been 568 // persisted and that both nodes recover gracefully. 569 if err := net.RestartNode(net.Alice, nil); err != nil { 570 t.Fatalf("Node restart failed: %v", err) 571 } 572 if err := net.RestartNode(carol, nil); err != nil { 573 t.Fatalf("Node restart failed: %v", err) 574 } 575 576 // The following block ensures that after both nodes have restarted, 577 // they have reconnected before the execution of the next test. 578 net.EnsureConnected(t.t, net.Alice, carol) 579 580 // Next, mine enough blocks s.t the channel will open with a single 581 // additional block mined. 582 if _, err := net.Generate(3); err != nil { 583 t.Fatalf("unable to mine blocks: %v", err) 584 } 585 586 // Assert that our wallet has our opening transaction with a label 587 // that does not have a channel ID set yet, because we have not 588 // reached our required confirmations. 589 tx := findTxAtHeight(t, height, fundingTxStr, net.Alice) 590 591 // At this stage, we expect the transaction to be labelled, but not with 592 // our channel ID because our transaction has not yet confirmed. 593 _ = labels.MakeLabel(labels.LabelTypeChannelOpen, nil) 594 // require.Equal(t.t, label, tx.Label, "open channel label wrong") 595 _ = tx // This is not supported in dcrw 596 597 // Both nodes should still show a single channel as pending. 598 time.Sleep(time.Second * 1) 599 assertNumOpenChannelsPending(t, net.Alice, carol, 1) 600 601 // Finally, mine the last block which should mark the channel as open. 602 if _, err := net.Generate(1); err != nil { 603 t.Fatalf("unable to mine blocks: %v", err) 604 } 605 606 // At this point, the channel should be fully opened and there should 607 // be no pending channels remaining for either node. 608 time.Sleep(time.Second * 1) 609 assertNumOpenChannelsPending(t, net.Alice, carol, 0) 610 611 // The channel should be listed in the peer information returned by 612 // both peers. 613 outPoint := wire.OutPoint{ 614 Hash: *fundingTxID, 615 Index: pendingUpdate.OutputIndex, 616 } 617 618 // Re-lookup our transaction in the block that it confirmed in. 619 _ = findTxAtHeight(t, height, fundingTxStr, net.Alice) 620 621 // Create an additional check for our channel assertion that will 622 // check that our label is as expected. 623 check := func(channel *lnrpc.Channel) { 624 shortChanID := lnwire.NewShortChanIDFromInt( 625 channel.ChanId, 626 ) 627 628 _ = labels.MakeLabel( 629 labels.LabelTypeChannelOpen, &shortChanID, 630 ) 631 // require.Equal(t.t, label, tx.Label, 632 // "open channel label not updated") 633 } 634 635 // Check both nodes to ensure that the channel is ready for operation. 636 err = net.AssertChannelExists(net.Alice, &outPoint, check) 637 if err != nil { 638 t.Fatalf("unable to assert channel existence: %v", err) 639 } 640 if err := net.AssertChannelExists(carol, &outPoint); err != nil { 641 t.Fatalf("unable to assert channel existence: %v", err) 642 } 643 644 // Finally, immediately close the channel. This function will also 645 // block until the channel is closed and will additionally assert the 646 // relevant channel closing post conditions. 647 chanPoint := &lnrpc.ChannelPoint{ 648 FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ 649 FundingTxidBytes: pendingUpdate.Txid, 650 }, 651 OutputIndex: pendingUpdate.OutputIndex, 652 } 653 closeChannelAndAssert(t, net, net.Alice, chanPoint, false) 654 } 655 656 // deriveFundingShim creates a channel funding shim by deriving the necessary 657 // keys on both sides. 658 func deriveFundingShim(net *lntest.NetworkHarness, t *harnessTest, 659 carol, dave *lntest.HarnessNode, chanSize dcrutil.Amount, 660 thawHeight uint32, publish bool) (*lnrpc.FundingShim, 661 *lnrpc.ChannelPoint, *chainhash.Hash) { 662 663 ctxb := context.Background() 664 keyLoc := &walletrpc.KeyReq{KeyFamily: 0} 665 carolFundingKey, err := carol.WalletKitClient.DeriveNextKey(ctxb, keyLoc) 666 require.NoError(t.t, err) 667 daveFundingKey, err := dave.WalletKitClient.DeriveNextKey(ctxb, keyLoc) 668 require.NoError(t.t, err) 669 670 // Now that we have the multi-sig keys for each party, we can manually 671 // construct the funding transaction. We'll instruct the backend to 672 // immediately create and broadcast a transaction paying out an exact 673 // amount. Normally this would reside in the mempool, but we just 674 // confirm it now for simplicity. 675 _, fundingOutput, err := input.GenFundingPkScript( 676 carolFundingKey.RawKeyBytes, daveFundingKey.RawKeyBytes, 677 int64(chanSize), 678 ) 679 require.NoError(t.t, err) 680 681 var txid *chainhash.Hash 682 targetOutputs := []*wire.TxOut{fundingOutput} 683 if publish { 684 txid, err = net.Miner.SendOutputs( 685 ctxb, targetOutputs, 1e4, 686 ) 687 require.NoError(t.t, err) 688 } else { 689 tx, err := net.Miner.CreateTransaction(ctxb, targetOutputs, 1e4) 690 require.NoError(t.t, err) 691 692 txHash := tx.TxHash() 693 txid = &txHash 694 } 695 696 // At this point, we can being our external channel funding workflow. 697 // We'll start by generating a pending channel ID externally that will 698 // be used to track this new funding type. 699 var pendingChanID [32]byte 700 _, err = rand.Read(pendingChanID[:]) 701 require.NoError(t.t, err) 702 703 // Now that we have the pending channel ID, Dave (our responder) will 704 // register the intent to receive a new channel funding workflow using 705 // the pending channel ID. 706 chanPoint := &lnrpc.ChannelPoint{ 707 FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ 708 FundingTxidBytes: txid[:], 709 }, 710 } 711 chanPointShim := &lnrpc.ChanPointShim{ 712 Amt: int64(chanSize), 713 ChanPoint: chanPoint, 714 LocalKey: &lnrpc.KeyDescriptor{ 715 RawKeyBytes: daveFundingKey.RawKeyBytes, 716 KeyLoc: &lnrpc.KeyLocator{ 717 KeyFamily: daveFundingKey.KeyLoc.KeyFamily, 718 KeyIndex: daveFundingKey.KeyLoc.KeyIndex, 719 }, 720 }, 721 RemoteKey: carolFundingKey.RawKeyBytes, 722 PendingChanId: pendingChanID[:], 723 ThawHeight: thawHeight, 724 } 725 fundingShim := &lnrpc.FundingShim{ 726 Shim: &lnrpc.FundingShim_ChanPointShim{ 727 ChanPointShim: chanPointShim, 728 }, 729 } 730 _, err = dave.FundingStateStep(ctxb, &lnrpc.FundingTransitionMsg{ 731 Trigger: &lnrpc.FundingTransitionMsg_ShimRegister{ 732 ShimRegister: fundingShim, 733 }, 734 }) 735 require.NoError(t.t, err) 736 737 // If we attempt to register the same shim (has the same pending chan 738 // ID), then we should get an error. 739 _, err = dave.FundingStateStep(ctxb, &lnrpc.FundingTransitionMsg{ 740 Trigger: &lnrpc.FundingTransitionMsg_ShimRegister{ 741 ShimRegister: fundingShim, 742 }, 743 }) 744 if err == nil { 745 t.Fatalf("duplicate pending channel ID funding shim " + 746 "registration should trigger an error") 747 } 748 749 // We'll take the chan point shim we just registered for Dave (the 750 // responder), and swap the local/remote keys before we feed it in as 751 // Carol's funding shim as the initiator. 752 fundingShim.GetChanPointShim().LocalKey = &lnrpc.KeyDescriptor{ 753 RawKeyBytes: carolFundingKey.RawKeyBytes, 754 KeyLoc: &lnrpc.KeyLocator{ 755 KeyFamily: carolFundingKey.KeyLoc.KeyFamily, 756 KeyIndex: carolFundingKey.KeyLoc.KeyIndex, 757 }, 758 } 759 fundingShim.GetChanPointShim().RemoteKey = daveFundingKey.RawKeyBytes 760 761 return fundingShim, chanPoint, txid 762 } 763 764 // testBatchChanFunding makes sure multiple channels can be opened in one batch 765 // transaction in an atomic way. 766 func testBatchChanFunding(net *lntest.NetworkHarness, t *harnessTest) { 767 t.t.Skip("PSBT funding is not supported") 768 769 ctxb := context.Background() 770 771 // First, we'll create two new nodes that we'll use to open channels 772 // to during this test. Carol has a high minimum funding amount that 773 // we'll use to trigger an error during the batch channel open. 774 carol := net.NewNode(t.t, "carol", []string{"--minchansize=200000"}) 775 defer shutdownAndAssert(net, t, carol) 776 777 dave := net.NewNode(t.t, "dave", nil) 778 defer shutdownAndAssert(net, t, dave) 779 780 // Before we start the test, we'll ensure Alice is connected to Carol 781 // and Dave so she can open channels to both of them (and Bob). 782 net.EnsureConnected(t.t, net.Alice, net.Bob) 783 net.EnsureConnected(t.t, net.Alice, carol) 784 net.EnsureConnected(t.t, net.Alice, dave) 785 786 // Let's create our batch TX request. This first one should fail as we 787 // open a channel to Carol that is too small for her min chan size. 788 batchReq := &lnrpc.BatchOpenChannelRequest{ 789 AtomsPerByte: 12, 790 MinConfs: 1, 791 Channels: []*lnrpc.BatchOpenChannel{{ 792 NodePubkey: net.Bob.PubKey[:], 793 LocalFundingAmount: 100_000, 794 }, { 795 NodePubkey: carol.PubKey[:], 796 LocalFundingAmount: 100_000, 797 }, { 798 NodePubkey: dave.PubKey[:], 799 LocalFundingAmount: 100_000, 800 }}, 801 } 802 803 ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) 804 defer cancel() 805 _, err := net.Alice.BatchOpenChannel(ctxt, batchReq) 806 require.Error(t.t, err) 807 require.Contains(t.t, err.Error(), "initial negotiation failed") 808 809 // Let's fix the minimum amount for Carol now and try again. 810 batchReq.Channels[1].LocalFundingAmount = 200_000 811 ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) 812 defer cancel() 813 batchResp, err := net.Alice.BatchOpenChannel(ctxt, batchReq) 814 require.NoError(t.t, err) 815 require.Len(t.t, batchResp.PendingChannels, 3) 816 817 txHash, err := chainhash.NewHash(batchResp.PendingChannels[0].Txid) 818 require.NoError(t.t, err) 819 820 chanPoint1 := &lnrpc.ChannelPoint{ 821 FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ 822 FundingTxidBytes: batchResp.PendingChannels[0].Txid, 823 }, 824 OutputIndex: batchResp.PendingChannels[0].OutputIndex, 825 } 826 chanPoint2 := &lnrpc.ChannelPoint{ 827 FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ 828 FundingTxidBytes: batchResp.PendingChannels[1].Txid, 829 }, 830 OutputIndex: batchResp.PendingChannels[1].OutputIndex, 831 } 832 chanPoint3 := &lnrpc.ChannelPoint{ 833 FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ 834 FundingTxidBytes: batchResp.PendingChannels[2].Txid, 835 }, 836 OutputIndex: batchResp.PendingChannels[2].OutputIndex, 837 } 838 839 block := mineBlocks(t, net, 6, 1)[0] 840 assertTxInBlock(t, block, txHash) 841 err = net.Alice.WaitForNetworkChannelOpen(chanPoint1) 842 require.NoError(t.t, err) 843 err = net.Alice.WaitForNetworkChannelOpen(chanPoint2) 844 require.NoError(t.t, err) 845 err = net.Alice.WaitForNetworkChannelOpen(chanPoint3) 846 require.NoError(t.t, err) 847 848 // With the channel open, ensure that it is counted towards Carol's 849 // total channel balance. 850 balReq := &lnrpc.ChannelBalanceRequest{} 851 ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) 852 defer cancel() 853 balRes, err := net.Alice.ChannelBalance(ctxt, balReq) 854 require.NoError(t.t, err) 855 require.NotEqual(t.t, int64(0), balRes.LocalBalance.Atoms) 856 857 // Next, to make sure the channel functions as normal, we'll make some 858 // payments within the channel. 859 payAmt := dcrutil.Amount(100000) 860 invoice := &lnrpc.Invoice{ 861 Memo: "new chans", 862 Value: int64(payAmt), 863 } 864 ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) 865 defer cancel() 866 resp, err := carol.AddInvoice(ctxt, invoice) 867 require.NoError(t.t, err) 868 err = completePaymentRequests( 869 net.Alice, net.Alice.RouterClient, 870 []string{resp.PaymentRequest}, true, 871 ) 872 require.NoError(t.t, err) 873 874 // To conclude, we'll close the newly created channel between Carol and 875 // Dave. This function will also block until the channel is closed and 876 // will additionally assert the relevant channel closing post 877 // conditions. 878 closeChannelAndAssert(t, net, net.Alice, chanPoint1, false) 879 closeChannelAndAssert(t, net, net.Alice, chanPoint2, false) 880 closeChannelAndAssert(t, net, net.Alice, chanPoint3, false) 881 }