github.com/decred/dcrlnd@v0.7.6/lntest/itest/lnd_routing_test.go (about) 1 package itest 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/hex" 7 "fmt" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/decred/dcrd/dcrutil/v4" 13 "github.com/decred/dcrd/wire" 14 "github.com/decred/dcrlnd/chainreg" 15 "github.com/decred/dcrlnd/lnrpc" 16 "github.com/decred/dcrlnd/lnrpc/routerrpc" 17 "github.com/decred/dcrlnd/lntest" 18 "github.com/decred/dcrlnd/lntest/wait" 19 "github.com/decred/dcrlnd/lnwire" 20 "github.com/stretchr/testify/require" 21 "google.golang.org/protobuf/proto" 22 "matheusd.com/testctx" 23 ) 24 25 type singleHopSendToRouteCase struct { 26 name string 27 28 // streaming tests streaming SendToRoute if true, otherwise tests 29 // synchronous SenToRoute. 30 streaming bool 31 32 // routerrpc submits the request to the routerrpc subserver if true, 33 // otherwise submits to the main rpc server. 34 routerrpc bool 35 } 36 37 var singleHopSendToRouteCases = []singleHopSendToRouteCase{ 38 { 39 name: "regular main sync", 40 }, 41 { 42 name: "regular main stream", 43 streaming: true, 44 }, 45 { 46 name: "regular routerrpc sync", 47 routerrpc: true, 48 }, 49 { 50 name: "mpp main sync", 51 }, 52 { 53 name: "mpp main stream", 54 streaming: true, 55 }, 56 { 57 name: "mpp routerrpc sync", 58 routerrpc: true, 59 }, 60 } 61 62 // testSingleHopSendToRoute tests that payments are properly processed through a 63 // provided route with a single hop. We'll create the following network 64 // topology: 65 // 66 // Carol --100k--> Dave 67 // 68 // We'll query the daemon for routes from Carol to Dave and then send payments 69 // by feeding the route back into the various SendToRoute RPC methods. Here we 70 // test all three SendToRoute endpoints, forcing each to perform both a regular 71 // payment and an MPP payment. 72 func testSingleHopSendToRoute(net *lntest.NetworkHarness, t *harnessTest) { 73 for _, test := range singleHopSendToRouteCases { 74 test := test 75 76 t.t.Run(test.name, func(t1 *testing.T) { 77 ht := newHarnessTest(t1, t.lndHarness) 78 ht.RunTestCase(&testCase{ 79 name: test.name, 80 test: func(_ *lntest.NetworkHarness, tt *harnessTest) { 81 testSingleHopSendToRouteCase(net, tt, test) 82 }, 83 }) 84 }) 85 } 86 } 87 88 func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest, 89 test singleHopSendToRouteCase) { 90 91 const chanAmt = dcrutil.Amount(100000) 92 const paymentAmtSat = 1000 93 const numPayments = 5 94 const amountPaid = int64(numPayments * paymentAmtSat) 95 96 ctxb := context.Background() 97 var networkChans []*lnrpc.ChannelPoint 98 99 // Create Carol and Dave, then establish a channel between them. Carol 100 // is the sole funder of the channel with 100k satoshis. The network 101 // topology should look like: 102 // Carol -> 100k -> Dave 103 carol := net.NewNode(t.t, "Carol", nil) 104 defer shutdownAndAssert(net, t, carol) 105 106 dave := net.NewNode(t.t, "Dave", nil) 107 defer shutdownAndAssert(net, t, dave) 108 109 net.ConnectNodes(t.t, carol, dave) 110 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 111 112 // Open a channel with 100k satoshis between Carol and Dave with Carol 113 // being the sole funder of the channel. 114 chanPointCarol := openChannelAndAssert( 115 t, net, carol, dave, 116 lntest.OpenChannelParams{ 117 Amt: chanAmt, 118 }, 119 ) 120 networkChans = append(networkChans, chanPointCarol) 121 122 carolChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointCarol) 123 if err != nil { 124 t.Fatalf("unable to get txid: %v", err) 125 } 126 carolFundPoint := wire.OutPoint{ 127 Hash: *carolChanTXID, 128 Index: chanPointCarol.OutputIndex, 129 } 130 131 // Wait for all nodes to have seen all channels. 132 nodes := []*lntest.HarnessNode{carol, dave} 133 for _, chanPoint := range networkChans { 134 for _, node := range nodes { 135 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 136 if err != nil { 137 t.Fatalf("unable to get txid: %v", err) 138 } 139 point := wire.OutPoint{ 140 Hash: *txid, 141 Index: chanPoint.OutputIndex, 142 } 143 144 err = node.WaitForNetworkChannelOpen(chanPoint) 145 if err != nil { 146 t.Fatalf("%s(%d): timeout waiting for "+ 147 "channel(%s) open: %v", node.Name(), 148 node.NodeID, point, err) 149 } 150 } 151 } 152 153 // Create invoices for Dave, which expect a payment from Carol. 154 payReqs, rHashes, _, err := createPayReqs( 155 dave, paymentAmtSat, numPayments, 156 ) 157 if err != nil { 158 t.Fatalf("unable to create pay reqs: %v", err) 159 } 160 161 // Reconstruct payment addresses. 162 var payAddrs [][]byte 163 for _, payReq := range payReqs { 164 ctx, _ := context.WithTimeout( 165 context.Background(), defaultTimeout, 166 ) 167 resp, err := dave.DecodePayReq( 168 ctx, 169 &lnrpc.PayReqString{PayReq: payReq}, 170 ) 171 if err != nil { 172 t.Fatalf("decode pay req: %v", err) 173 } 174 payAddrs = append(payAddrs, resp.PaymentAddr) 175 } 176 177 // Assert Carol and Dave are synced to the chain before proceeding, to 178 // ensure the queried route will have a valid final CLTV once the HTLC 179 // reaches Dave. 180 _, minerHeight, err := net.Miner.Node.GetBestBlock(testctx.New(t.t)) 181 if err != nil { 182 t.Fatalf("unable to get best height: %v", err) 183 } 184 require.NoError(t.t, waitForNodeBlockHeight(carol, minerHeight)) 185 require.NoError(t.t, waitForNodeBlockHeight(dave, minerHeight)) 186 187 // Query for routes to pay from Carol to Dave using the default CLTV 188 // config. 189 routesReq := &lnrpc.QueryRoutesRequest{ 190 PubKey: dave.PubKeyStr, 191 Amt: paymentAmtSat, 192 } 193 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 194 routes, err := carol.QueryRoutes(ctxt, routesReq) 195 if err != nil { 196 t.Fatalf("unable to get route from %s: %v", 197 carol.Name(), err) 198 } 199 200 // There should only be one route to try, so take the first item. 201 r := routes.Routes[0] 202 203 // Construct a closure that will set MPP fields on the route, which 204 // allows us to test MPP payments. 205 setMPPFields := func(i int) { 206 hop := r.Hops[len(r.Hops)-1] 207 hop.TlvPayload = true 208 hop.MppRecord = &lnrpc.MPPRecord{ 209 PaymentAddr: payAddrs[i], 210 TotalAmtMAtoms: paymentAmtSat * 1000, 211 } 212 } 213 214 // Construct closures for each of the payment types covered: 215 // - main rpc server sync 216 // - main rpc server streaming 217 // - routerrpc server sync 218 sendToRouteSync := func() { 219 for i, rHash := range rHashes { 220 setMPPFields(i) 221 222 sendReq := &lnrpc.SendToRouteRequest{ 223 PaymentHash: rHash, 224 Route: r, 225 } 226 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 227 resp, err := carol.SendToRouteSync( 228 ctxt, sendReq, 229 ) 230 if err != nil { 231 t.Fatalf("unable to send to route for "+ 232 "%s: %v", carol.Name(), err) 233 } 234 if resp.PaymentError != "" { 235 t.Fatalf("received payment error from %s: %v", 236 carol.Name(), resp.PaymentError) 237 } 238 } 239 } 240 sendToRouteStream := func() { 241 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 242 alicePayStream, err := carol.SendToRoute(ctxt) // nolint:staticcheck 243 if err != nil { 244 t.Fatalf("unable to create payment stream for "+ 245 "carol: %v", err) 246 } 247 248 for i, rHash := range rHashes { 249 setMPPFields(i) 250 251 sendReq := &lnrpc.SendToRouteRequest{ 252 PaymentHash: rHash, 253 Route: routes.Routes[0], 254 } 255 err := alicePayStream.Send(sendReq) 256 257 if err != nil { 258 t.Fatalf("unable to send payment: %v", err) 259 } 260 261 resp, err := alicePayStream.Recv() 262 if err != nil { 263 t.Fatalf("unable to send payment: %v", err) 264 } 265 if resp.PaymentError != "" { 266 t.Fatalf("received payment error: %v", 267 resp.PaymentError) 268 } 269 } 270 } 271 sendToRouteRouterRPC := func() { 272 for i, rHash := range rHashes { 273 setMPPFields(i) 274 275 sendReq := &routerrpc.SendToRouteRequest{ 276 PaymentHash: rHash, 277 Route: r, 278 } 279 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 280 resp, err := carol.RouterClient.SendToRouteV2( 281 ctxt, sendReq, 282 ) 283 if err != nil { 284 t.Fatalf("unable to send to route for "+ 285 "%s: %v", carol.Name(), err) 286 } 287 if resp.Failure != nil { 288 t.Fatalf("received payment error from %s: %v", 289 carol.Name(), resp.Failure) 290 } 291 } 292 } 293 294 // Using Carol as the node as the source, send the payments 295 // synchronously via the the routerrpc's SendToRoute, or via the main RPC 296 // server's SendToRoute streaming or sync calls. 297 switch { 298 case !test.routerrpc && test.streaming: 299 sendToRouteStream() 300 case !test.routerrpc && !test.streaming: 301 sendToRouteSync() 302 case test.routerrpc && !test.streaming: 303 sendToRouteRouterRPC() 304 default: 305 t.Fatalf("routerrpc does not support streaming send_to_route") 306 } 307 308 // Verify that the payment's from Carol's PoV have the correct payment 309 // hash and amount. 310 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 311 paymentsResp, err := carol.ListPayments( 312 ctxt, &lnrpc.ListPaymentsRequest{}, 313 ) 314 if err != nil { 315 t.Fatalf("error when obtaining %s payments: %v", 316 carol.Name(), err) 317 } 318 if len(paymentsResp.Payments) != numPayments { 319 t.Fatalf("incorrect number of payments, got %v, want %v", 320 len(paymentsResp.Payments), numPayments) 321 } 322 323 for i, p := range paymentsResp.Payments { 324 // Assert that the payment hashes for each payment match up. 325 rHashHex := hex.EncodeToString(rHashes[i]) 326 if p.PaymentHash != rHashHex { 327 t.Fatalf("incorrect payment hash for payment %d, "+ 328 "want: %s got: %s", 329 i, rHashHex, p.PaymentHash) 330 } 331 332 // Assert that each payment has no invoice since the payment was 333 // completed using SendToRoute. 334 if p.PaymentRequest != "" { 335 t.Fatalf("incorrect payment request for payment: %d, "+ 336 "want: \"\", got: %s", 337 i, p.PaymentRequest) 338 } 339 340 // Assert the payment amount is correct. 341 if p.ValueAtoms != paymentAmtSat { 342 t.Fatalf("incorrect payment amt for payment %d, "+ 343 "want: %d, got: %d", 344 i, paymentAmtSat, p.ValueAtoms) 345 } 346 347 // Assert exactly one htlc was made. 348 if len(p.Htlcs) != 1 { 349 t.Fatalf("expected 1 htlc for payment %d, got: %d", 350 i, len(p.Htlcs)) 351 } 352 353 // Assert the htlc's route is populated. 354 htlc := p.Htlcs[0] 355 if htlc.Route == nil { 356 t.Fatalf("expected route for payment %d", i) 357 } 358 359 // Assert the hop has exactly one hop. 360 if len(htlc.Route.Hops) != 1 { 361 t.Fatalf("expected 1 hop for payment %d, got: %d", 362 i, len(htlc.Route.Hops)) 363 } 364 365 // If this is an MPP test, assert the MPP record's fields are 366 // properly populated. Otherwise the hop should not have an MPP 367 // record. 368 hop := htlc.Route.Hops[0] 369 if hop.MppRecord == nil { 370 t.Fatalf("expected mpp record for mpp payment") 371 } 372 373 if hop.MppRecord.TotalAmtMAtoms != paymentAmtSat*1000 { 374 t.Fatalf("incorrect mpp total msat for payment %d "+ 375 "want: %d, got: %d", 376 i, paymentAmtSat*1000, 377 hop.MppRecord.TotalAmtMAtoms) 378 } 379 380 expAddr := payAddrs[i] 381 if !bytes.Equal(hop.MppRecord.PaymentAddr, expAddr) { 382 t.Fatalf("incorrect mpp payment addr for payment %d "+ 383 "want: %x, got: %x", 384 i, expAddr, hop.MppRecord.PaymentAddr) 385 } 386 } 387 388 // Verify that the invoices's from Dave's PoV have the correct payment 389 // hash and amount. 390 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 391 invoicesResp, err := dave.ListInvoices( 392 ctxt, &lnrpc.ListInvoiceRequest{}, 393 ) 394 if err != nil { 395 t.Fatalf("error when obtaining %s payments: %v", 396 dave.Name(), err) 397 } 398 if len(invoicesResp.Invoices) != numPayments { 399 t.Fatalf("incorrect number of invoices, got %v, want %v", 400 len(invoicesResp.Invoices), numPayments) 401 } 402 403 for i, inv := range invoicesResp.Invoices { 404 // Assert that the payment hashes match up. 405 if !bytes.Equal(inv.RHash, rHashes[i]) { 406 t.Fatalf("incorrect payment hash for invoice %d, "+ 407 "want: %x got: %x", 408 i, rHashes[i], inv.RHash) 409 } 410 411 // Assert that the amount paid to the invoice is correct. 412 if inv.AmtPaidAtoms != paymentAmtSat { 413 t.Fatalf("incorrect payment amt for invoice %d, "+ 414 "want: %d, got %d", 415 i, paymentAmtSat, inv.AmtPaidAtoms) 416 } 417 } 418 419 // At this point all the channels within our proto network should be 420 // shifted by 5k satoshis in the direction of Dave, the sink within the 421 // payment flow generated above. The order of asserts corresponds to 422 // increasing of time is needed to embed the HTLC in commitment 423 // transaction, in channel Carol->Dave, order is Dave and then Carol. 424 assertAmountPaid(t, "Carol(local) => Dave(remote)", dave, 425 carolFundPoint, int64(0), amountPaid) 426 assertAmountPaid(t, "Carol(local) => Dave(remote)", carol, 427 carolFundPoint, amountPaid, int64(0)) 428 429 closeChannelAndAssert(t, net, carol, chanPointCarol, false) 430 } 431 432 // testMultiHopSendToRoute tests that payments are properly processed 433 // through a provided route. We'll create the following network topology: 434 // 435 // Alice --100k--> Bob --100k--> Carol 436 // 437 // We'll query the daemon for routes from Alice to Carol and then 438 // send payments through the routes. 439 func testMultiHopSendToRoute(net *lntest.NetworkHarness, t *harnessTest) { 440 t.t.Run("with cache", func(tt *testing.T) { 441 ht := newHarnessTest(tt, t.lndHarness) 442 runMultiHopSendToRoute(net, ht, true) 443 }) 444 if *dbBackendFlag == "bbolt" { 445 t.t.Run("without cache", func(tt *testing.T) { 446 ht := newHarnessTest(tt, t.lndHarness) 447 runMultiHopSendToRoute(net, ht, false) 448 }) 449 } 450 } 451 452 // runMultiHopSendToRoute tests that payments are properly processed 453 // through a provided route. We'll create the following network topology: 454 // 455 // Alice --100k--> Bob --100k--> Carol 456 // 457 // We'll query the daemon for routes from Alice to Carol and then 458 // send payments through the routes. 459 func runMultiHopSendToRoute(net *lntest.NetworkHarness, t *harnessTest, 460 useGraphCache bool) { 461 462 ctxb := context.Background() 463 464 var opts []string 465 if !useGraphCache { 466 opts = append(opts, "--db.no-graph-cache") 467 } 468 469 alice := net.NewNode(t.t, "Alice", opts) 470 defer shutdownAndAssert(net, t, alice) 471 472 net.ConnectNodes(t.t, alice, net.Bob) 473 net.SendCoins(t.t, dcrutil.AtomsPerCoin, alice) 474 475 const chanAmt = dcrutil.Amount(100000) 476 var networkChans []*lnrpc.ChannelPoint 477 478 // Open a channel with 100k satoshis between Alice and Bob with Alice 479 // being the sole funder of the channel. 480 chanPointAlice := openChannelAndAssert( 481 t, net, alice, net.Bob, 482 lntest.OpenChannelParams{ 483 Amt: chanAmt, 484 }, 485 ) 486 networkChans = append(networkChans, chanPointAlice) 487 488 aliceChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointAlice) 489 if err != nil { 490 t.Fatalf("unable to get txid: %v", err) 491 } 492 aliceFundPoint := wire.OutPoint{ 493 Hash: *aliceChanTXID, 494 Index: chanPointAlice.OutputIndex, 495 } 496 497 // Create Carol and establish a channel from Bob. Bob is the sole funder 498 // of the channel with 100k satoshis. The network topology should look like: 499 // Alice -> Bob -> Carol 500 carol := net.NewNode(t.t, "Carol", nil) 501 defer shutdownAndAssert(net, t, carol) 502 503 net.ConnectNodes(t.t, carol, net.Bob) 504 net.SendCoins(t.t, dcrutil.AtomsPerCoin, net.Bob) 505 506 chanPointBob := openChannelAndAssert( 507 t, net, net.Bob, carol, 508 lntest.OpenChannelParams{ 509 Amt: chanAmt, 510 }, 511 ) 512 networkChans = append(networkChans, chanPointBob) 513 bobChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointBob) 514 if err != nil { 515 t.Fatalf("unable to get txid: %v", err) 516 } 517 bobFundPoint := wire.OutPoint{ 518 Hash: *bobChanTXID, 519 Index: chanPointBob.OutputIndex, 520 } 521 522 // Wait for all nodes to have seen all channels. 523 nodes := []*lntest.HarnessNode{alice, net.Bob, carol} 524 nodeNames := []string{"Alice", "Bob", "Carol"} 525 for _, chanPoint := range networkChans { 526 for i, node := range nodes { 527 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 528 if err != nil { 529 t.Fatalf("unable to get txid: %v", err) 530 } 531 point := wire.OutPoint{ 532 Hash: *txid, 533 Index: chanPoint.OutputIndex, 534 } 535 536 err = node.WaitForNetworkChannelOpen(chanPoint) 537 if err != nil { 538 t.Fatalf("%s(%d): timeout waiting for "+ 539 "channel(%s) open: %v", nodeNames[i], 540 node.NodeID, point, err) 541 } 542 } 543 } 544 545 // Create 5 invoices for Carol, which expect a payment from Alice for 1k 546 // satoshis with a different preimage each time. 547 const ( 548 numPayments = 5 549 paymentAmt = 1000 550 ) 551 _, rHashes, invoices, err := createPayReqs( 552 carol, paymentAmt, numPayments, 553 ) 554 if err != nil { 555 t.Fatalf("unable to create pay reqs: %v", err) 556 } 557 558 // Construct a route from Alice to Carol for each of the invoices 559 // created above. We set FinalCltvDelta to 40 since by default 560 // QueryRoutes returns the last hop with a final cltv delta of 9 where 561 // as the default in htlcswitch is 40. 562 routesReq := &lnrpc.QueryRoutesRequest{ 563 PubKey: carol.PubKeyStr, 564 Amt: paymentAmt, 565 FinalCltvDelta: chainreg.DefaultDecredTimeLockDelta, 566 } 567 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 568 routes, err := alice.QueryRoutes(ctxt, routesReq) 569 if err != nil { 570 t.Fatalf("unable to get route: %v", err) 571 } 572 573 // We'll wait for all parties to recognize the new channels within the 574 // network. 575 err = carol.WaitForNetworkChannelOpen(chanPointBob) 576 if err != nil { 577 t.Fatalf("bob didn't advertise his channel in time: %v", err) 578 } 579 580 time.Sleep(time.Millisecond * 50) 581 582 // Using Alice as the source, pay to the 5 invoices from Carol created 583 // above. 584 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 585 586 for i, rHash := range rHashes { 587 // Manually set the MPP payload a new for each payment since 588 // the payment addr will change with each invoice, although we 589 // can re-use the route itself. 590 route := *routes.Routes[0] 591 route.Hops[len(route.Hops)-1].TlvPayload = true 592 route.Hops[len(route.Hops)-1].MppRecord = &lnrpc.MPPRecord{ 593 PaymentAddr: invoices[i].PaymentAddr, 594 TotalAmtMAtoms: int64( 595 lnwire.NewMAtomsFromAtoms(paymentAmt), 596 ), 597 } 598 599 sendReq := &routerrpc.SendToRouteRequest{ 600 PaymentHash: rHash, 601 Route: &route, 602 } 603 resp, err := alice.RouterClient.SendToRouteV2(ctxt, sendReq) 604 if err != nil { 605 t.Fatalf("unable to send payment: %v", err) 606 } 607 608 if resp.Failure != nil { 609 t.Fatalf("received payment error: %v", resp.Failure) 610 } 611 } 612 613 // When asserting the amount of satoshis moved, we'll factor in the 614 // default base fee, as we didn't modify the fee structure when 615 // creating the seed nodes in the network. 616 const baseFee = 1 617 618 // At this point all the channels within our proto network should be 619 // shifted by 5k satoshis in the direction of Carol, the sink within the 620 // payment flow generated above. The order of asserts corresponds to 621 // increasing of time is needed to embed the HTLC in commitment 622 // transaction, in channel Alice->Bob->Carol, order is Carol, Bob, 623 // Alice. 624 const amountPaid = int64(5000) 625 assertAmountPaid(t, "Bob(local) => Carol(remote)", carol, 626 bobFundPoint, int64(0), amountPaid) 627 assertAmountPaid(t, "Bob(local) => Carol(remote)", net.Bob, 628 bobFundPoint, amountPaid, int64(0)) 629 assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Bob, 630 aliceFundPoint, int64(0), amountPaid+(baseFee*numPayments)) 631 assertAmountPaid(t, "Alice(local) => Bob(remote)", alice, 632 aliceFundPoint, amountPaid+(baseFee*numPayments), int64(0)) 633 634 closeChannelAndAssert(t, net, alice, chanPointAlice, false) 635 closeChannelAndAssert(t, net, carol, chanPointBob, false) 636 } 637 638 // testSendToRouteErrorPropagation tests propagation of errors that occur 639 // while processing a multi-hop payment through an unknown route. 640 func testSendToRouteErrorPropagation(net *lntest.NetworkHarness, t *harnessTest) { 641 ctxb := context.Background() 642 643 const chanAmt = dcrutil.Amount(100000) 644 645 // Open a channel with 100k satoshis between Alice and Bob with Alice 646 // being the sole funder of the channel. 647 chanPointAlice := openChannelAndAssert( 648 t, net, net.Alice, net.Bob, 649 lntest.OpenChannelParams{ 650 Amt: chanAmt, 651 }, 652 ) 653 654 err := net.Alice.WaitForNetworkChannelOpen(chanPointAlice) 655 if err != nil { 656 t.Fatalf("alice didn't advertise her channel: %v", err) 657 } 658 659 // Create a new nodes (Carol and Charlie), load her with some funds, 660 // then establish a connection between Carol and Charlie with a channel 661 // that has identical capacity to the one created above.Then we will 662 // get route via queryroutes call which will be fake route for Alice -> 663 // Bob graph. 664 // 665 // The network topology should now look like: Alice -> Bob; Carol -> Charlie. 666 carol := net.NewNode(t.t, "Carol", nil) 667 defer shutdownAndAssert(net, t, carol) 668 669 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 670 671 charlie := net.NewNode(t.t, "Charlie", nil) 672 defer shutdownAndAssert(net, t, charlie) 673 674 net.SendCoins(t.t, dcrutil.AtomsPerCoin, charlie) 675 676 net.ConnectNodes(t.t, carol, charlie) 677 678 chanPointCarol := openChannelAndAssert( 679 t, net, carol, charlie, 680 lntest.OpenChannelParams{ 681 Amt: chanAmt, 682 }, 683 ) 684 err = carol.WaitForNetworkChannelOpen(chanPointCarol) 685 if err != nil { 686 t.Fatalf("carol didn't advertise her channel: %v", err) 687 } 688 689 // Query routes from Carol to Charlie which will be an invalid route 690 // for Alice -> Bob. 691 fakeReq := &lnrpc.QueryRoutesRequest{ 692 PubKey: charlie.PubKeyStr, 693 Amt: int64(1), 694 } 695 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 696 fakeRoute, err := carol.QueryRoutes(ctxt, fakeReq) 697 if err != nil { 698 t.Fatalf("unable get fake route: %v", err) 699 } 700 701 // Create 1 invoices for Bob, which expect a payment from Alice for 1k 702 // satoshis 703 const paymentAmt = 1000 704 705 invoice := &lnrpc.Invoice{ 706 Memo: "testing", 707 Value: paymentAmt, 708 } 709 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 710 resp, err := net.Bob.AddInvoice(ctxt, invoice) 711 if err != nil { 712 t.Fatalf("unable to add invoice: %v", err) 713 } 714 715 rHash := resp.RHash 716 717 // Using Alice as the source, pay to the 5 invoices from Bob created above. 718 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 719 alicePayStream, err := net.Alice.SendToRoute(ctxt) 720 if err != nil { 721 t.Fatalf("unable to create payment stream for alice: %v", err) 722 } 723 724 sendReq := &lnrpc.SendToRouteRequest{ 725 PaymentHash: rHash, 726 Route: fakeRoute.Routes[0], 727 } 728 729 if err := alicePayStream.Send(sendReq); err != nil { 730 t.Fatalf("unable to send payment: %v", err) 731 } 732 733 // At this place we should get an rpc error with notification 734 // that edge is not found on hop(0) 735 if _, err := alicePayStream.Recv(); err != nil && strings.Contains(err.Error(), 736 "edge not found") { 737 738 } else if err != nil { 739 t.Fatalf("payment stream has been closed but fake route has consumed: %v", err) 740 } 741 742 closeChannelAndAssert(t, net, net.Alice, chanPointAlice, false) 743 closeChannelAndAssert(t, net, carol, chanPointCarol, false) 744 } 745 746 // testPrivateChannels tests that a private channel can be used for 747 // routing by the two endpoints of the channel, but is not known by 748 // the rest of the nodes in the graph. 749 func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) { 750 ctxb := context.Background() 751 752 const chanAmt = dcrutil.Amount(100000) 753 var networkChans []*lnrpc.ChannelPoint 754 755 // We create the following topology: 756 // 757 // Dave --100k--> Alice --200k--> Bob 758 // ^ ^ 759 // | | 760 // 100k 100k 761 // | | 762 // +---- Carol ----+ 763 // 764 // where the 100k channel between Carol and Alice is private. 765 766 // Open a channel with 200k satoshis between Alice and Bob. 767 chanPointAlice := openChannelAndAssert( 768 t, net, net.Alice, net.Bob, 769 lntest.OpenChannelParams{ 770 Amt: chanAmt * 2, 771 }, 772 ) 773 networkChans = append(networkChans, chanPointAlice) 774 775 aliceChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointAlice) 776 if err != nil { 777 t.Fatalf("unable to get txid: %v", err) 778 } 779 aliceFundPoint := wire.OutPoint{ 780 Hash: *aliceChanTXID, 781 Index: chanPointAlice.OutputIndex, 782 } 783 784 // Create Dave, and a channel to Alice of 100k. 785 dave := net.NewNode(t.t, "Dave", nil) 786 defer shutdownAndAssert(net, t, dave) 787 788 net.ConnectNodes(t.t, dave, net.Alice) 789 net.SendCoins(t.t, dcrutil.AtomsPerCoin, dave) 790 791 chanPointDave := openChannelAndAssert( 792 t, net, dave, net.Alice, 793 lntest.OpenChannelParams{ 794 Amt: chanAmt, 795 }, 796 ) 797 networkChans = append(networkChans, chanPointDave) 798 daveChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointDave) 799 if err != nil { 800 t.Fatalf("unable to get txid: %v", err) 801 } 802 daveFundPoint := wire.OutPoint{ 803 Hash: *daveChanTXID, 804 Index: chanPointDave.OutputIndex, 805 } 806 807 // Next, we'll create Carol and establish a channel from her to 808 // Dave of 100k. 809 carol := net.NewNode(t.t, "Carol", nil) 810 defer shutdownAndAssert(net, t, carol) 811 812 net.ConnectNodes(t.t, carol, dave) 813 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 814 815 chanPointCarol := openChannelAndAssert( 816 t, net, carol, dave, 817 lntest.OpenChannelParams{ 818 Amt: chanAmt, 819 }, 820 ) 821 networkChans = append(networkChans, chanPointCarol) 822 823 carolChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointCarol) 824 if err != nil { 825 t.Fatalf("unable to get txid: %v", err) 826 } 827 carolFundPoint := wire.OutPoint{ 828 Hash: *carolChanTXID, 829 Index: chanPointCarol.OutputIndex, 830 } 831 832 // Wait for all nodes to have seen all these channels, as they 833 // are all public. 834 nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} 835 nodeNames := []string{"Alice", "Bob", "Carol", "Dave"} 836 for _, chanPoint := range networkChans { 837 for i, node := range nodes { 838 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 839 if err != nil { 840 t.Fatalf("unable to get txid: %v", err) 841 } 842 point := wire.OutPoint{ 843 Hash: *txid, 844 Index: chanPoint.OutputIndex, 845 } 846 847 err = node.WaitForNetworkChannelOpen(chanPoint) 848 if err != nil { 849 t.Fatalf("%s(%d): timeout waiting for "+ 850 "channel(%s) open: %v", nodeNames[i], 851 node.NodeID, point, err) 852 } 853 } 854 } 855 // Now create a _private_ channel directly between Carol and 856 // Alice of 100k. 857 net.ConnectNodes(t.t, carol, net.Alice) 858 chanOpenUpdate := openChannelStream( 859 t, net, carol, net.Alice, 860 lntest.OpenChannelParams{ 861 Amt: chanAmt, 862 Private: true, 863 }, 864 ) 865 if err != nil { 866 t.Fatalf("unable to open channel: %v", err) 867 } 868 869 // One block is enough to make the channel ready for use, since the 870 // nodes have defaultNumConfs=1 set. 871 block := mineBlocks(t, net, 1, 1)[0] 872 873 chanPointPrivate, err := net.WaitForChannelOpen(chanOpenUpdate) 874 if err != nil { 875 t.Fatalf("error while waiting for channel open: %v", err) 876 } 877 fundingTxID, err := lnrpc.GetChanPointFundingTxid(chanPointPrivate) 878 if err != nil { 879 t.Fatalf("unable to get txid: %v", err) 880 } 881 assertTxInBlock(t, block, fundingTxID) 882 883 // The channel should be listed in the peer information returned by 884 // both peers. 885 privateFundPoint := wire.OutPoint{ 886 Hash: *fundingTxID, 887 Index: chanPointPrivate.OutputIndex, 888 } 889 err = net.AssertChannelExists(carol, &privateFundPoint) 890 if err != nil { 891 t.Fatalf("unable to assert channel existence: %v", err) 892 } 893 err = net.AssertChannelExists(net.Alice, &privateFundPoint) 894 if err != nil { 895 t.Fatalf("unable to assert channel existence: %v", err) 896 } 897 898 // The channel should be available for payments between Carol and Alice. 899 // We check this by sending payments from Carol to Bob, that 900 // collectively would deplete at least one of Carol's channels. 901 902 // Create 2 invoices for Bob, each of 70k satoshis. Since each of 903 // Carol's channels is of size 100k, these payments cannot succeed 904 // by only using one of the channels. 905 const numPayments = 2 906 const paymentAmt = 70000 907 payReqs, _, _, err := createPayReqs( 908 net.Bob, paymentAmt, numPayments, 909 ) 910 if err != nil { 911 t.Fatalf("unable to create pay reqs: %v", err) 912 } 913 914 time.Sleep(time.Millisecond * 50) 915 916 // Let Carol pay the invoices. 917 err = completePaymentRequests(carol, carol.RouterClient, payReqs, true) 918 if err != nil { 919 t.Fatalf("unable to send payments: %v", err) 920 } 921 922 // When asserting the amount of satoshis moved, we'll factor in the 923 // default base fee, as we didn't modify the fee structure when 924 // creating the seed nodes in the network. 925 const baseFee = 1 926 927 // Bob should have received 140k satoshis from Alice. 928 assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Bob, 929 aliceFundPoint, int64(0), 2*paymentAmt) 930 931 // Alice sent 140k to Bob. 932 assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Alice, 933 aliceFundPoint, 2*paymentAmt, int64(0)) 934 935 // Alice received 70k + fee from Dave. 936 assertAmountPaid(t, "Dave(local) => Alice(remote)", net.Alice, 937 daveFundPoint, int64(0), paymentAmt+baseFee) 938 939 // Dave sent 70k+fee to Alice. 940 assertAmountPaid(t, "Dave(local) => Alice(remote)", dave, 941 daveFundPoint, paymentAmt+baseFee, int64(0)) 942 943 // Dave received 70k+fee of two hops from Carol. 944 assertAmountPaid(t, "Carol(local) => Dave(remote)", dave, 945 carolFundPoint, int64(0), paymentAmt+baseFee*2) 946 947 // Carol sent 70k+fee of two hops to Dave. 948 assertAmountPaid(t, "Carol(local) => Dave(remote)", carol, 949 carolFundPoint, paymentAmt+baseFee*2, int64(0)) 950 951 // Alice received 70k+fee from Carol. 952 assertAmountPaid(t, "Carol(local) [private=>] Alice(remote)", 953 net.Alice, privateFundPoint, int64(0), paymentAmt+baseFee) 954 955 // Carol sent 70k+fee to Alice. 956 assertAmountPaid(t, "Carol(local) [private=>] Alice(remote)", 957 carol, privateFundPoint, paymentAmt+baseFee, int64(0)) 958 959 // Alice should also be able to route payments using this channel, 960 // so send two payments of 60k back to Carol. 961 const paymentAmt60k = 60000 962 payReqs, _, _, err = createPayReqs( 963 carol, paymentAmt60k, numPayments, 964 ) 965 if err != nil { 966 t.Fatalf("unable to create pay reqs: %v", err) 967 } 968 969 time.Sleep(time.Millisecond * 50) 970 971 // Let Bob pay the invoices. 972 err = completePaymentRequests( 973 net.Alice, net.Alice.RouterClient, payReqs, true, 974 ) 975 if err != nil { 976 t.Fatalf("unable to send payments: %v", err) 977 } 978 979 // Finally, we make sure Dave and Bob does not know about the 980 // private channel between Carol and Alice. We first mine 981 // plenty of blocks, such that the channel would have been 982 // announced in case it was public. 983 mineBlocks(t, net, 10, 0) 984 985 // We create a helper method to check how many edges each of the 986 // nodes know about. Carol and Alice should know about 4, while 987 // Bob and Dave should only know about 3, since one channel is 988 // private. 989 numChannels := func(node *lntest.HarnessNode, includeUnannounced bool) int { 990 req := &lnrpc.ChannelGraphRequest{ 991 IncludeUnannounced: includeUnannounced, 992 } 993 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 994 chanGraph, err := node.DescribeGraph(ctxt, req) 995 if err != nil { 996 t.Fatalf("unable go describegraph: %v", err) 997 } 998 return len(chanGraph.Edges) 999 } 1000 1001 var predErr error 1002 err = wait.Predicate(func() bool { 1003 aliceChans := numChannels(net.Alice, true) 1004 if aliceChans != 4 { 1005 predErr = fmt.Errorf("expected Alice to know 4 edges, "+ 1006 "had %v", aliceChans) 1007 return false 1008 } 1009 alicePubChans := numChannels(net.Alice, false) 1010 if alicePubChans != 3 { 1011 predErr = fmt.Errorf("expected Alice to know 3 public edges, "+ 1012 "had %v", alicePubChans) 1013 return false 1014 } 1015 bobChans := numChannels(net.Bob, true) 1016 if bobChans != 3 { 1017 predErr = fmt.Errorf("expected Bob to know 3 edges, "+ 1018 "had %v", bobChans) 1019 return false 1020 } 1021 carolChans := numChannels(carol, true) 1022 if carolChans != 4 { 1023 predErr = fmt.Errorf("expected Carol to know 4 edges, "+ 1024 "had %v", carolChans) 1025 return false 1026 } 1027 carolPubChans := numChannels(carol, false) 1028 if carolPubChans != 3 { 1029 predErr = fmt.Errorf("expected Carol to know 3 public edges, "+ 1030 "had %v", carolPubChans) 1031 return false 1032 } 1033 daveChans := numChannels(dave, true) 1034 if daveChans != 3 { 1035 predErr = fmt.Errorf("expected Dave to know 3 edges, "+ 1036 "had %v", daveChans) 1037 return false 1038 } 1039 return true 1040 }, defaultTimeout) 1041 if err != nil { 1042 t.Fatalf("%v", predErr) 1043 } 1044 1045 // Close all channels. 1046 closeChannelAndAssert(t, net, net.Alice, chanPointAlice, false) 1047 closeChannelAndAssert(t, net, dave, chanPointDave, false) 1048 closeChannelAndAssert(t, net, carol, chanPointCarol, false) 1049 closeChannelAndAssert(t, net, carol, chanPointPrivate, false) 1050 } 1051 1052 // testInvoiceRoutingHints tests that the routing hints for an invoice are 1053 // created properly. 1054 func testInvoiceRoutingHints(net *lntest.NetworkHarness, t *harnessTest) { 1055 ctxb := context.Background() 1056 1057 const chanAmt = dcrutil.Amount(100000) 1058 1059 // Throughout this test, we'll be opening a channel between Alice and 1060 // several other parties. 1061 // 1062 // First, we'll create a private channel between Alice and Bob. This 1063 // will be the only channel that will be considered as a routing hint 1064 // throughout this test. We'll include a push amount since we currently 1065 // require channels to have enough remote balance to cover the invoice's 1066 // payment. 1067 chanPointBob := openChannelAndAssert( 1068 t, net, net.Alice, net.Bob, 1069 lntest.OpenChannelParams{ 1070 Amt: chanAmt, 1071 PushAmt: chanAmt / 2, 1072 Private: true, 1073 }, 1074 ) 1075 1076 // Then, we'll create Carol's node and open a public channel between her 1077 // and Alice. This channel will not be considered as a routing hint due 1078 // to it being public. 1079 carol := net.NewNode(t.t, "Carol", nil) 1080 defer shutdownAndAssert(net, t, carol) 1081 1082 net.ConnectNodes(t.t, net.Alice, carol) 1083 chanPointCarol := openChannelAndAssert( 1084 t, net, net.Alice, carol, 1085 lntest.OpenChannelParams{ 1086 Amt: chanAmt, 1087 PushAmt: chanAmt / 2, 1088 }, 1089 ) 1090 1091 // We'll also create a public channel between Bob and Carol to ensure 1092 // that Bob gets selected as the only routing hint. We do this as 1093 // we should only include routing hints for nodes that are publicly 1094 // advertised, otherwise we'd end up leaking information about nodes 1095 // that wish to stay unadvertised. 1096 net.ConnectNodes(t.t, net.Bob, carol) 1097 chanPointBobCarol := openChannelAndAssert( 1098 t, net, net.Bob, carol, 1099 lntest.OpenChannelParams{ 1100 Amt: chanAmt, 1101 PushAmt: chanAmt / 2, 1102 }, 1103 ) 1104 1105 // Then, we'll create Dave's node and open a private channel between him 1106 // and Alice. We will not include a push amount in order to not consider 1107 // this channel as a routing hint as it will not have enough remote 1108 // balance for the invoice's amount. 1109 dave := net.NewNode(t.t, "Dave", nil) 1110 defer shutdownAndAssert(net, t, dave) 1111 1112 net.ConnectNodes(t.t, net.Alice, dave) 1113 chanPointDave := openChannelAndAssert( 1114 t, net, net.Alice, dave, 1115 lntest.OpenChannelParams{ 1116 Amt: chanAmt, 1117 Private: true, 1118 }, 1119 ) 1120 1121 // Finally, we'll create Eve's node and open a private channel between 1122 // her and Alice. This time though, we'll take Eve's node down after the 1123 // channel has been created to avoid populating routing hints for 1124 // inactive channels. 1125 eve := net.NewNode(t.t, "Eve", nil) 1126 net.ConnectNodes(t.t, net.Alice, eve) 1127 chanPointEve := openChannelAndAssert( 1128 t, net, net.Alice, eve, 1129 lntest.OpenChannelParams{ 1130 Amt: chanAmt, 1131 PushAmt: chanAmt / 2, 1132 Private: true, 1133 }, 1134 ) 1135 1136 // Make sure all the channels have been opened. 1137 chanNames := []string{ 1138 "alice-bob", "alice-carol", "bob-carol", "alice-dave", 1139 "alice-eve", 1140 } 1141 aliceChans := []*lnrpc.ChannelPoint{ 1142 chanPointBob, chanPointCarol, chanPointBobCarol, chanPointDave, 1143 chanPointEve, 1144 } 1145 for i, chanPoint := range aliceChans { 1146 err := net.Alice.WaitForNetworkChannelOpen(chanPoint) 1147 if err != nil { 1148 t.Fatalf("timed out waiting for channel open %s: %v", 1149 chanNames[i], err) 1150 } 1151 } 1152 1153 // Now that the channels are open, we'll take down Eve's node. 1154 shutdownAndAssert(net, t, eve) 1155 1156 // Create an invoice for Alice that will populate the routing hints. 1157 invoice := &lnrpc.Invoice{ 1158 Memo: "routing hints", 1159 Value: int64(chanAmt / 4), 1160 Private: true, 1161 } 1162 1163 // Due to the way the channels were set up above, the channel between 1164 // Alice and Bob should be the only channel used as a routing hint. 1165 var predErr error 1166 var decoded *lnrpc.PayReq 1167 err := wait.Predicate(func() bool { 1168 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 1169 resp, err := net.Alice.AddInvoice(ctxt, invoice) 1170 if err != nil { 1171 predErr = fmt.Errorf("unable to add invoice: %v", err) 1172 return false 1173 } 1174 1175 // We'll decode the invoice's payment request to determine which 1176 // channels were used as routing hints. 1177 payReq := &lnrpc.PayReqString{ 1178 PayReq: resp.PaymentRequest, 1179 } 1180 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 1181 decoded, err = net.Alice.DecodePayReq(ctxt, payReq) 1182 if err != nil { 1183 predErr = fmt.Errorf("unable to decode payment "+ 1184 "request: %v", err) 1185 return false 1186 } 1187 1188 if len(decoded.RouteHints) != 1 { 1189 predErr = fmt.Errorf("expected one route hint, got %d", 1190 len(decoded.RouteHints)) 1191 return false 1192 } 1193 return true 1194 }, defaultTimeout) 1195 if err != nil { 1196 t.Fatalf(predErr.Error()) 1197 } 1198 1199 hops := decoded.RouteHints[0].HopHints 1200 if len(hops) != 1 { 1201 t.Fatalf("expected one hop in route hint, got %d", len(hops)) 1202 } 1203 chanID := hops[0].ChanId 1204 1205 // We'll need the short channel ID of the channel between Alice and Bob 1206 // to make sure the routing hint is for this channel. 1207 listReq := &lnrpc.ListChannelsRequest{} 1208 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 1209 listResp, err := net.Alice.ListChannels(ctxt, listReq) 1210 if err != nil { 1211 t.Fatalf("unable to retrieve alice's channels: %v", err) 1212 } 1213 1214 var aliceBobChanID uint64 1215 for _, channel := range listResp.Channels { 1216 if channel.RemotePubkey == net.Bob.PubKeyStr { 1217 aliceBobChanID = channel.ChanId 1218 } 1219 } 1220 1221 if aliceBobChanID == 0 { 1222 t.Fatalf("channel between alice and bob not found") 1223 } 1224 1225 if chanID != aliceBobChanID { 1226 t.Fatalf("expected channel ID %d, got %d", aliceBobChanID, 1227 chanID) 1228 } 1229 1230 // Now that we've confirmed the routing hints were added correctly, we 1231 // can close all the channels and shut down all the nodes created. 1232 closeChannelAndAssert(t, net, net.Alice, chanPointBob, false) 1233 closeChannelAndAssert(t, net, net.Alice, chanPointCarol, false) 1234 closeChannelAndAssert(t, net, net.Bob, chanPointBobCarol, false) 1235 closeChannelAndAssert(t, net, net.Alice, chanPointDave, false) 1236 1237 // The channel between Alice and Eve should be force closed since Eve 1238 // is offline. 1239 closeChannelAndAssert(t, net, net.Alice, chanPointEve, true) 1240 1241 // Cleanup by mining the force close and sweep transaction. 1242 cleanupForceClose(t, net, net.Alice, chanPointEve) 1243 } 1244 1245 // testMultiHopOverPrivateChannels tests that private channels can be used as 1246 // intermediate hops in a route for payments. 1247 func testMultiHopOverPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) { 1248 ctxb := context.Background() 1249 1250 // We'll test that multi-hop payments over private channels work as 1251 // intended. To do so, we'll create the following topology: 1252 // private public private 1253 // Alice <--100k--> Bob <--100k--> Carol <--100k--> Dave 1254 const chanAmt = dcrutil.Amount(100000) 1255 1256 // First, we'll open a private channel between Alice and Bob with Alice 1257 // being the funder. 1258 chanPointAlice := openChannelAndAssert( 1259 t, net, net.Alice, net.Bob, 1260 lntest.OpenChannelParams{ 1261 Amt: chanAmt, 1262 Private: true, 1263 }, 1264 ) 1265 1266 err := net.Alice.WaitForNetworkChannelOpen(chanPointAlice) 1267 if err != nil { 1268 t.Fatalf("alice didn't see the channel alice <-> bob before "+ 1269 "timeout: %v", err) 1270 } 1271 err = net.Bob.WaitForNetworkChannelOpen(chanPointAlice) 1272 if err != nil { 1273 t.Fatalf("bob didn't see the channel alice <-> bob before "+ 1274 "timeout: %v", err) 1275 } 1276 1277 // Retrieve Alice's funding outpoint. 1278 aliceChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointAlice) 1279 if err != nil { 1280 t.Fatalf("unable to get txid: %v", err) 1281 } 1282 aliceFundPoint := wire.OutPoint{ 1283 Hash: *aliceChanTXID, 1284 Index: chanPointAlice.OutputIndex, 1285 } 1286 1287 // Next, we'll create Carol's node and open a public channel between 1288 // her and Bob with Bob being the funder. 1289 carol := net.NewNode(t.t, "Carol", nil) 1290 defer shutdownAndAssert(net, t, carol) 1291 1292 net.ConnectNodes(t.t, net.Bob, carol) 1293 chanPointBob := openChannelAndAssert( 1294 t, net, net.Bob, carol, 1295 lntest.OpenChannelParams{ 1296 Amt: chanAmt, 1297 }, 1298 ) 1299 1300 err = net.Bob.WaitForNetworkChannelOpen(chanPointBob) 1301 if err != nil { 1302 t.Fatalf("bob didn't see the channel bob <-> carol before "+ 1303 "timeout: %v", err) 1304 } 1305 err = carol.WaitForNetworkChannelOpen(chanPointBob) 1306 if err != nil { 1307 t.Fatalf("carol didn't see the channel bob <-> carol before "+ 1308 "timeout: %v", err) 1309 } 1310 err = net.Alice.WaitForNetworkChannelOpen(chanPointBob) 1311 if err != nil { 1312 t.Fatalf("alice didn't see the channel bob <-> carol before "+ 1313 "timeout: %v", err) 1314 } 1315 1316 // Retrieve Bob's funding outpoint. 1317 bobChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointBob) 1318 if err != nil { 1319 t.Fatalf("unable to get txid: %v", err) 1320 } 1321 bobFundPoint := wire.OutPoint{ 1322 Hash: *bobChanTXID, 1323 Index: chanPointBob.OutputIndex, 1324 } 1325 1326 // Next, we'll create Dave's node and open a private channel between him 1327 // and Carol with Carol being the funder. 1328 dave := net.NewNode(t.t, "Dave", nil) 1329 defer shutdownAndAssert(net, t, dave) 1330 1331 net.ConnectNodes(t.t, carol, dave) 1332 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 1333 1334 chanPointCarol := openChannelAndAssert( 1335 t, net, carol, dave, 1336 lntest.OpenChannelParams{ 1337 Amt: chanAmt, 1338 Private: true, 1339 }, 1340 ) 1341 1342 err = carol.WaitForNetworkChannelOpen(chanPointCarol) 1343 if err != nil { 1344 t.Fatalf("carol didn't see the channel carol <-> dave before "+ 1345 "timeout: %v", err) 1346 } 1347 err = dave.WaitForNetworkChannelOpen(chanPointCarol) 1348 if err != nil { 1349 t.Fatalf("dave didn't see the channel carol <-> dave before "+ 1350 "timeout: %v", err) 1351 } 1352 err = dave.WaitForNetworkChannelOpen(chanPointBob) 1353 if err != nil { 1354 t.Fatalf("dave didn't see the channel bob <-> carol before "+ 1355 "timeout: %v", err) 1356 } 1357 1358 // Retrieve Carol's funding point. 1359 carolChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointCarol) 1360 if err != nil { 1361 t.Fatalf("unable to get txid: %v", err) 1362 } 1363 carolFundPoint := wire.OutPoint{ 1364 Hash: *carolChanTXID, 1365 Index: chanPointCarol.OutputIndex, 1366 } 1367 1368 // Now that all the channels are set up according to the topology from 1369 // above, we can proceed to test payments. We'll create an invoice for 1370 // Dave of 20k satoshis and pay it with Alice. Since there is no public 1371 // route from Alice to Dave, we'll need to use the private channel 1372 // between Carol and Dave as a routing hint encoded in the invoice. 1373 const paymentAmt = 20000 1374 1375 // Create the invoice for Dave. 1376 invoice := &lnrpc.Invoice{ 1377 Memo: "two hopz!", 1378 Value: paymentAmt, 1379 Private: true, 1380 } 1381 1382 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 1383 resp, err := dave.AddInvoice(ctxt, invoice) 1384 if err != nil { 1385 t.Fatalf("unable to add invoice for dave: %v", err) 1386 } 1387 1388 // Let Alice pay the invoice. 1389 payReqs := []string{resp.PaymentRequest} 1390 err = completePaymentRequests( 1391 net.Alice, net.Alice.RouterClient, payReqs, true, 1392 ) 1393 if err != nil { 1394 t.Fatalf("unable to send payments from alice to dave: %v", err) 1395 } 1396 1397 // When asserting the amount of satoshis moved, we'll factor in the 1398 // default base fee, as we didn't modify the fee structure when opening 1399 // the channels. 1400 const baseFee = 1 1401 1402 // Dave should have received 20k satoshis from Carol. 1403 assertAmountPaid(t, "Carol(local) [private=>] Dave(remote)", 1404 dave, carolFundPoint, 0, paymentAmt) 1405 1406 // Carol should have sent 20k satoshis to Dave. 1407 assertAmountPaid(t, "Carol(local) [private=>] Dave(remote)", 1408 carol, carolFundPoint, paymentAmt, 0) 1409 1410 // Carol should have received 20k satoshis + fee for one hop from Bob. 1411 assertAmountPaid(t, "Bob(local) => Carol(remote)", 1412 carol, bobFundPoint, 0, paymentAmt+baseFee) 1413 1414 // Bob should have sent 20k satoshis + fee for one hop to Carol. 1415 assertAmountPaid(t, "Bob(local) => Carol(remote)", 1416 net.Bob, bobFundPoint, paymentAmt+baseFee, 0) 1417 1418 // Bob should have received 20k satoshis + fee for two hops from Alice. 1419 assertAmountPaid(t, "Alice(local) [private=>] Bob(remote)", net.Bob, 1420 aliceFundPoint, 0, paymentAmt+baseFee*2) 1421 1422 // Alice should have sent 20k satoshis + fee for two hops to Bob. 1423 assertAmountPaid(t, "Alice(local) [private=>] Bob(remote)", net.Alice, 1424 aliceFundPoint, paymentAmt+baseFee*2, 0) 1425 1426 // At this point, the payment was successful. We can now close all the 1427 // channels and shutdown the nodes created throughout this test. 1428 closeChannelAndAssert(t, net, net.Alice, chanPointAlice, false) 1429 closeChannelAndAssert(t, net, net.Bob, chanPointBob, false) 1430 closeChannelAndAssert(t, net, carol, chanPointCarol, false) 1431 } 1432 1433 // computeFee calculates the payment fee as specified in BOLT07 1434 func computeFee(baseFee, feeRate, amt lnwire.MilliAtom) lnwire.MilliAtom { 1435 return baseFee + amt*feeRate/1000000 1436 } 1437 1438 // testQueryRoutes checks the response of queryroutes. 1439 // We'll create the following network topology: 1440 // 1441 // Alice --> Bob --> Carol --> Dave 1442 // 1443 // and query the daemon for routes from Alice to Dave. 1444 func testQueryRoutes(net *lntest.NetworkHarness, t *harnessTest) { 1445 ctxb := context.Background() 1446 1447 const chanAmt = dcrutil.Amount(100000) 1448 var networkChans []*lnrpc.ChannelPoint 1449 1450 // Open a channel between Alice and Bob. 1451 chanPointAlice := openChannelAndAssert( 1452 t, net, net.Alice, net.Bob, 1453 lntest.OpenChannelParams{ 1454 Amt: chanAmt, 1455 }, 1456 ) 1457 networkChans = append(networkChans, chanPointAlice) 1458 1459 // Create Carol and establish a channel from Bob. 1460 carol := net.NewNode(t.t, "Carol", nil) 1461 defer shutdownAndAssert(net, t, carol) 1462 1463 net.ConnectNodes(t.t, carol, net.Bob) 1464 net.SendCoins(t.t, dcrutil.AtomsPerCoin, net.Bob) 1465 1466 chanPointBob := openChannelAndAssert( 1467 t, net, net.Bob, carol, 1468 lntest.OpenChannelParams{ 1469 Amt: chanAmt, 1470 }, 1471 ) 1472 networkChans = append(networkChans, chanPointBob) 1473 1474 // Create Dave and establish a channel from Carol. 1475 dave := net.NewNode(t.t, "Dave", nil) 1476 defer shutdownAndAssert(net, t, dave) 1477 1478 net.ConnectNodes(t.t, dave, carol) 1479 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 1480 1481 chanPointCarol := openChannelAndAssert( 1482 t, net, carol, dave, 1483 lntest.OpenChannelParams{ 1484 Amt: chanAmt, 1485 }, 1486 ) 1487 networkChans = append(networkChans, chanPointCarol) 1488 1489 // Wait for all nodes to have seen all channels. 1490 nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} 1491 nodeNames := []string{"Alice", "Bob", "Carol", "Dave"} 1492 for _, chanPoint := range networkChans { 1493 for i, node := range nodes { 1494 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 1495 if err != nil { 1496 t.Fatalf("unable to get txid: %v", err) 1497 } 1498 point := wire.OutPoint{ 1499 Hash: *txid, 1500 Index: chanPoint.OutputIndex, 1501 } 1502 1503 err = node.WaitForNetworkChannelOpen(chanPoint) 1504 if err != nil { 1505 t.Fatalf("%s(%d): timeout waiting for "+ 1506 "channel(%s) open: %v", nodeNames[i], 1507 node.NodeID, point, err) 1508 } 1509 } 1510 } 1511 1512 // Query for routes to pay from Alice to Dave. 1513 const paymentAmt = 1000 1514 routesReq := &lnrpc.QueryRoutesRequest{ 1515 PubKey: dave.PubKeyStr, 1516 Amt: paymentAmt, 1517 } 1518 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 1519 routesRes, err := net.Alice.QueryRoutes(ctxt, routesReq) 1520 if err != nil { 1521 t.Fatalf("unable to get route: %v", err) 1522 } 1523 1524 const mSat = 1000 1525 feePerHopMSat := computeFee(1000, 1, paymentAmt*mSat) 1526 1527 for i, route := range routesRes.Routes { 1528 expectedTotalFeesMSat := 1529 lnwire.MilliAtom(len(route.Hops)-1) * feePerHopMSat 1530 expectedTotalAmtMSat := (paymentAmt * mSat) + expectedTotalFeesMSat 1531 1532 if route.TotalFees != route.TotalFeesMAtoms/mSat { // nolint:staticcheck 1533 t.Fatalf("route %v: total fees %v (msat) does not "+ 1534 "round down to %v (sat)", 1535 i, route.TotalFeesMAtoms, route.TotalFees) // nolint:staticcheck 1536 } 1537 if route.TotalFeesMAtoms != int64(expectedTotalFeesMSat) { 1538 t.Fatalf("route %v: total fees in msat expected %v got %v", 1539 i, expectedTotalFeesMSat, route.TotalFeesMAtoms) 1540 } 1541 1542 if route.TotalAmt != route.TotalAmtMAtoms/mSat { // nolint:staticcheck 1543 t.Fatalf("route %v: total amt %v (msat) does not "+ 1544 "round down to %v (sat)", 1545 i, route.TotalAmtMAtoms, route.TotalAmt) // nolint:staticcheck 1546 } 1547 if route.TotalAmtMAtoms != int64(expectedTotalAmtMSat) { 1548 t.Fatalf("route %v: total amt in msat expected %v got %v", 1549 i, expectedTotalAmtMSat, route.TotalAmtMAtoms) 1550 } 1551 1552 // For all hops except the last, we check that fee equals feePerHop 1553 // and amount to forward deducts feePerHop on each hop. 1554 expectedAmtToForwardMSat := expectedTotalAmtMSat 1555 for j, hop := range route.Hops[:len(route.Hops)-1] { 1556 expectedAmtToForwardMSat -= feePerHopMSat 1557 1558 if hop.Fee != hop.FeeMAtoms/mSat { // nolint:staticcheck 1559 t.Fatalf("route %v hop %v: fee %v (msat) does not "+ 1560 "round down to %v (sat)", 1561 i, j, hop.FeeMAtoms, hop.Fee) // nolint:staticcheck 1562 } 1563 if hop.FeeMAtoms != int64(feePerHopMSat) { 1564 t.Fatalf("route %v hop %v: fee in msat expected %v got %v", 1565 i, j, feePerHopMSat, hop.FeeMAtoms) 1566 } 1567 1568 if hop.AmtToForward != hop.AmtToForwardMAtoms/mSat { // nolint:staticcheck 1569 t.Fatalf("route %v hop %v: amt to forward %v (msat) does not "+ 1570 "round down to %v (sat)", 1571 i, j, hop.AmtToForwardMAtoms, hop.AmtToForward) // nolint:staticcheck 1572 } 1573 if hop.AmtToForwardMAtoms != int64(expectedAmtToForwardMSat) { 1574 t.Fatalf("route %v hop %v: amt to forward in msat "+ 1575 "expected %v got %v", 1576 i, j, expectedAmtToForwardMSat, hop.AmtToForwardMAtoms) 1577 } 1578 } 1579 // Last hop should have zero fee and amount to forward should equal 1580 // payment amount. 1581 hop := route.Hops[len(route.Hops)-1] 1582 1583 if hop.Fee != 0 || hop.FeeMAtoms != 0 { // nolint:staticcheck 1584 t.Fatalf("route %v hop %v: fee expected 0 got %v (sat) %v (msat)", 1585 i, len(route.Hops)-1, hop.Fee, hop.FeeMAtoms) // nolint:staticcheck 1586 } 1587 1588 if hop.AmtToForward != hop.AmtToForwardMAtoms/mSat { // nolint:staticcheck 1589 t.Fatalf("route %v hop %v: amt to forward %v (msat) does not "+ 1590 "round down to %v (sat)", 1591 i, len(route.Hops)-1, hop.AmtToForwardMAtoms, hop.AmtToForward) // nolint:staticcheck 1592 } 1593 if hop.AmtToForwardMAtoms != paymentAmt*mSat { 1594 t.Fatalf("route %v hop %v: amt to forward in msat "+ 1595 "expected %v got %v", 1596 i, len(route.Hops)-1, paymentAmt*mSat, hop.AmtToForwardMAtoms) 1597 } 1598 } 1599 1600 // While we're here, we test updating mission control's config values 1601 // and assert that they are correctly updated and check that our mission 1602 // control import function updates appropriately. 1603 testMissionControlCfg(t.t, net.Alice) 1604 testMissionControlImport( 1605 t.t, net.Alice, net.Bob.PubKey[:], carol.PubKey[:], 1606 ) 1607 1608 // We clean up the test case by closing channels that were created for 1609 // the duration of the tests. 1610 closeChannelAndAssert(t, net, net.Alice, chanPointAlice, false) 1611 closeChannelAndAssert(t, net, net.Bob, chanPointBob, false) 1612 closeChannelAndAssert(t, net, carol, chanPointCarol, false) 1613 } 1614 1615 // testMissionControlCfg tests getting and setting of a node's mission control 1616 // config, resetting to the original values after testing so that no other 1617 // tests are affected. 1618 func testMissionControlCfg(t *testing.T, node *lntest.HarnessNode) { 1619 ctxb := context.Background() 1620 startCfg, err := node.RouterClient.GetMissionControlConfig( 1621 ctxb, &routerrpc.GetMissionControlConfigRequest{}, 1622 ) 1623 require.NoError(t, err) 1624 1625 cfg := &routerrpc.MissionControlConfig{ 1626 HalfLifeSeconds: 8000, 1627 HopProbability: 0.8, 1628 Weight: 0.3, 1629 MaximumPaymentResults: 30, 1630 MinimumFailureRelaxInterval: 60, 1631 } 1632 1633 _, err = node.RouterClient.SetMissionControlConfig( 1634 ctxb, &routerrpc.SetMissionControlConfigRequest{ 1635 Config: cfg, 1636 }, 1637 ) 1638 require.NoError(t, err) 1639 1640 resp, err := node.RouterClient.GetMissionControlConfig( 1641 ctxb, &routerrpc.GetMissionControlConfigRequest{}, 1642 ) 1643 require.NoError(t, err) 1644 require.True(t, proto.Equal(cfg, resp.Config)) 1645 1646 _, err = node.RouterClient.SetMissionControlConfig( 1647 ctxb, &routerrpc.SetMissionControlConfigRequest{ 1648 Config: startCfg.Config, 1649 }, 1650 ) 1651 require.NoError(t, err) 1652 } 1653 1654 // testMissionControlImport tests import of mission control results from an 1655 // external source. 1656 func testMissionControlImport(t *testing.T, node *lntest.HarnessNode, 1657 fromNode, toNode []byte) { 1658 1659 ctxb := context.Background() 1660 1661 // Reset mission control so that our query will return the default 1662 // probability for our first request. 1663 _, err := node.RouterClient.ResetMissionControl( 1664 ctxb, &routerrpc.ResetMissionControlRequest{}, 1665 ) 1666 require.NoError(t, err, "could not reset mission control") 1667 1668 // Get our baseline probability for a 10 msat hop between our target 1669 // nodes. 1670 var amount int64 = 10 1671 probReq := &routerrpc.QueryProbabilityRequest{ 1672 FromNode: fromNode, 1673 ToNode: toNode, 1674 AmtMAtoms: amount, 1675 } 1676 1677 importHistory := &routerrpc.PairData{ 1678 FailTime: time.Now().Unix(), 1679 FailAmtMAtoms: amount, 1680 } 1681 1682 // Assert that our history is not already equal to the value we want to 1683 // set. This should not happen because we have just cleared our state. 1684 resp1, err := node.RouterClient.QueryProbability(ctxb, probReq) 1685 require.NoError(t, err, "query probability failed") 1686 require.Zero(t, resp1.History.FailTime) 1687 require.Zero(t, resp1.History.FailAmtMAtoms) 1688 1689 // Now, we import a single entry which tracks a failure of the amount 1690 // we want to query between our nodes. 1691 req := &routerrpc.XImportMissionControlRequest{ 1692 Pairs: []*routerrpc.PairHistory{ 1693 { 1694 NodeFrom: fromNode, 1695 NodeTo: toNode, 1696 History: importHistory, 1697 }, 1698 }, 1699 } 1700 1701 _, err = node.RouterClient.XImportMissionControl(ctxb, req) 1702 require.NoError(t, err, "could not import config") 1703 1704 resp2, err := node.RouterClient.QueryProbability(ctxb, probReq) 1705 require.NoError(t, err, "query probability failed") 1706 require.Equal(t, importHistory.FailTime, resp2.History.FailTime) 1707 require.Equal(t, importHistory.FailAmtMAtoms, resp2.History.FailAmtMAtoms) 1708 1709 // Finally, check that we will fail if inconsistent sat/msat values are 1710 // set. 1711 importHistory.FailAmtAtoms = amount * 2 1712 _, err = node.RouterClient.XImportMissionControl(ctxb, req) 1713 require.Error(t, err, "mismatched import amounts succeeded") 1714 } 1715 1716 // testRouteFeeCutoff tests that we are able to prevent querying routes and 1717 // sending payments that incur a fee higher than the fee limit. 1718 func testRouteFeeCutoff(net *lntest.NetworkHarness, t *harnessTest) { 1719 ctxb := context.Background() 1720 1721 // For this test, we'll create the following topology: 1722 // 1723 // --- Bob --- 1724 // / \ 1725 // Alice ---- ---- Dave 1726 // \ / 1727 // -- Carol -- 1728 // 1729 // Alice will attempt to send payments to Dave that should not incur a 1730 // fee greater than the fee limit expressed as a percentage of the 1731 // amount and as a fixed amount of satoshis. 1732 const chanAmt = dcrutil.Amount(100000) 1733 1734 // Open a channel between Alice and Bob. 1735 chanPointAliceBob := openChannelAndAssert( 1736 t, net, net.Alice, net.Bob, 1737 lntest.OpenChannelParams{ 1738 Amt: chanAmt, 1739 }, 1740 ) 1741 1742 // Create Carol's node and open a channel between her and Alice with 1743 // Alice being the funder. 1744 carol := net.NewNode(t.t, "Carol", nil) 1745 defer shutdownAndAssert(net, t, carol) 1746 1747 net.ConnectNodes(t.t, carol, net.Alice) 1748 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 1749 1750 chanPointAliceCarol := openChannelAndAssert( 1751 t, net, net.Alice, carol, 1752 lntest.OpenChannelParams{ 1753 Amt: chanAmt, 1754 }, 1755 ) 1756 1757 // Create Dave's node and open a channel between him and Bob with Bob 1758 // being the funder. 1759 dave := net.NewNode(t.t, "Dave", nil) 1760 defer shutdownAndAssert(net, t, dave) 1761 1762 net.ConnectNodes(t.t, dave, net.Bob) 1763 chanPointBobDave := openChannelAndAssert( 1764 t, net, net.Bob, dave, 1765 lntest.OpenChannelParams{ 1766 Amt: chanAmt, 1767 }, 1768 ) 1769 1770 // Open a channel between Carol and Dave. 1771 net.ConnectNodes(t.t, carol, dave) 1772 chanPointCarolDave := openChannelAndAssert( 1773 t, net, carol, dave, 1774 lntest.OpenChannelParams{ 1775 Amt: chanAmt, 1776 }, 1777 ) 1778 1779 // Now that all the channels were set up, we'll wait for all the nodes 1780 // to have seen all the channels. 1781 nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} 1782 nodeNames := []string{"alice", "bob", "carol", "dave"} 1783 networkChans := []*lnrpc.ChannelPoint{ 1784 chanPointAliceBob, chanPointAliceCarol, chanPointBobDave, 1785 chanPointCarolDave, 1786 } 1787 for _, chanPoint := range networkChans { 1788 for i, node := range nodes { 1789 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 1790 if err != nil { 1791 t.Fatalf("unable to get txid: %v", err) 1792 } 1793 outpoint := wire.OutPoint{ 1794 Hash: *txid, 1795 Index: chanPoint.OutputIndex, 1796 } 1797 1798 err = node.WaitForNetworkChannelOpen(chanPoint) 1799 if err != nil { 1800 t.Fatalf("%s(%d) timed out waiting for "+ 1801 "channel(%s) open: %v", nodeNames[i], 1802 node.NodeID, outpoint, err) 1803 } 1804 } 1805 } 1806 1807 // The payments should only be successful across the route: 1808 // Alice -> Bob -> Dave 1809 // Therefore, we'll update the fee policy on Carol's side for the 1810 // channel between her and Dave to invalidate the route: 1811 // Alice -> Carol -> Dave 1812 baseFee := int64(10000) 1813 feeRate := int64(5) 1814 timeLockDelta := uint32(chainreg.DefaultDecredTimeLockDelta) 1815 maxHtlc := calculateMaxHtlc(chanAmt) 1816 1817 expectedPolicy := &lnrpc.RoutingPolicy{ 1818 FeeBaseMAtoms: baseFee, 1819 FeeRateMilliMAtoms: testFeeBase * feeRate, 1820 TimeLockDelta: timeLockDelta, 1821 MinHtlc: 1000, // default value 1822 MaxHtlcMAtoms: maxHtlc, 1823 } 1824 1825 updateFeeReq := &lnrpc.PolicyUpdateRequest{ 1826 BaseFeeMAtoms: baseFee, 1827 FeeRate: float64(feeRate), 1828 TimeLockDelta: timeLockDelta, 1829 MaxHtlcMAtoms: maxHtlc, 1830 Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{ 1831 ChanPoint: chanPointCarolDave, 1832 }, 1833 } 1834 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 1835 if _, err := carol.UpdateChannelPolicy(ctxt, updateFeeReq); err != nil { 1836 t.Fatalf("unable to update chan policy: %v", err) 1837 } 1838 1839 // Wait for Alice to receive the channel update from Carol. 1840 assertChannelPolicyUpdate( 1841 t.t, net.Alice, carol.PubKeyStr, 1842 expectedPolicy, chanPointCarolDave, false, 1843 ) 1844 1845 // We'll also need the channel IDs for Bob's channels in order to 1846 // confirm the route of the payments. 1847 listReq := &lnrpc.ListChannelsRequest{} 1848 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 1849 listResp, err := net.Bob.ListChannels(ctxt, listReq) 1850 if err != nil { 1851 t.Fatalf("unable to retrieve bob's channels: %v", err) 1852 } 1853 1854 var aliceBobChanID, bobDaveChanID uint64 1855 for _, channel := range listResp.Channels { 1856 switch channel.RemotePubkey { 1857 case net.Alice.PubKeyStr: 1858 aliceBobChanID = channel.ChanId 1859 case dave.PubKeyStr: 1860 bobDaveChanID = channel.ChanId 1861 } 1862 } 1863 1864 if aliceBobChanID == 0 { 1865 t.Fatalf("channel between alice and bob not found") 1866 } 1867 if bobDaveChanID == 0 { 1868 t.Fatalf("channel between bob and dave not found") 1869 } 1870 hopChanIDs := []uint64{aliceBobChanID, bobDaveChanID} 1871 1872 // checkRoute is a helper closure to ensure the route contains the 1873 // correct intermediate hops. 1874 checkRoute := func(route *lnrpc.Route) { 1875 if len(route.Hops) != 2 { 1876 t.Fatalf("expected two hops, got %d", len(route.Hops)) 1877 } 1878 1879 for i, hop := range route.Hops { 1880 if hop.ChanId != hopChanIDs[i] { 1881 t.Fatalf("expected chan id %d, got %d", 1882 hopChanIDs[i], hop.ChanId) 1883 } 1884 } 1885 } 1886 1887 // We'll be attempting to send two payments from Alice to Dave. One will 1888 // have a fee cutoff expressed as a percentage of the amount and the 1889 // other will have it expressed as a fixed amount of satoshis. 1890 const paymentAmt = 100 1891 carolFee := computeFee(lnwire.MilliAtom(baseFee), 1, paymentAmt) 1892 1893 // testFeeCutoff is a helper closure that will ensure the different 1894 // types of fee limits work as intended when querying routes and sending 1895 // payments. 1896 testFeeCutoff := func(feeLimit *lnrpc.FeeLimit) { 1897 queryRoutesReq := &lnrpc.QueryRoutesRequest{ 1898 PubKey: dave.PubKeyStr, 1899 Amt: paymentAmt, 1900 FeeLimit: feeLimit, 1901 } 1902 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 1903 routesResp, err := net.Alice.QueryRoutes(ctxt, queryRoutesReq) 1904 if err != nil { 1905 t.Fatalf("unable to get routes: %v", err) 1906 } 1907 1908 checkRoute(routesResp.Routes[0]) 1909 1910 invoice := &lnrpc.Invoice{Value: paymentAmt} 1911 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 1912 invoiceResp, err := dave.AddInvoice(ctxt, invoice) 1913 if err != nil { 1914 t.Fatalf("unable to create invoice: %v", err) 1915 } 1916 1917 sendReq := &routerrpc.SendPaymentRequest{ 1918 PaymentRequest: invoiceResp.PaymentRequest, 1919 TimeoutSeconds: 60, 1920 FeeLimitMAtoms: noFeeLimitMAtoms, 1921 } 1922 switch limit := feeLimit.Limit.(type) { 1923 case *lnrpc.FeeLimit_Fixed: 1924 sendReq.FeeLimitMAtoms = 1000 * limit.Fixed 1925 case *lnrpc.FeeLimit_Percent: 1926 sendReq.FeeLimitMAtoms = 1000 * paymentAmt * limit.Percent / 100 1927 } 1928 1929 result := sendAndAssertSuccess(t, net.Alice, sendReq) 1930 1931 checkRoute(result.Htlcs[0].Route) 1932 } 1933 1934 // We'll start off using percentages first. Since the fee along the 1935 // route using Carol as an intermediate hop is 10% of the payment's 1936 // amount, we'll use a lower percentage in order to invalid that route. 1937 feeLimitPercent := &lnrpc.FeeLimit{ 1938 Limit: &lnrpc.FeeLimit_Percent{ 1939 Percent: baseFee/1000 - 1, 1940 }, 1941 } 1942 testFeeCutoff(feeLimitPercent) 1943 1944 // Now we'll test using fixed fee limit amounts. Since we computed the 1945 // fee for the route using Carol as an intermediate hop earlier, we can 1946 // use a smaller value in order to invalidate that route. 1947 feeLimitFixed := &lnrpc.FeeLimit{ 1948 Limit: &lnrpc.FeeLimit_Fixed{ 1949 Fixed: int64(carolFee.ToAtoms()) - 1, 1950 }, 1951 } 1952 testFeeCutoff(feeLimitFixed) 1953 1954 // Once we're done, close the channels and shut down the nodes created 1955 // throughout this test. 1956 closeChannelAndAssert(t, net, net.Alice, chanPointAliceBob, false) 1957 closeChannelAndAssert(t, net, net.Alice, chanPointAliceCarol, false) 1958 closeChannelAndAssert(t, net, net.Bob, chanPointBobDave, false) 1959 closeChannelAndAssert(t, net, carol, chanPointCarolDave, false) 1960 }