lnd_mpp_test.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. package itest
  2. import (
  3. "time"
  4. "github.com/btcsuite/btcd/btcutil"
  5. "github.com/lightningnetwork/lnd/chainreg"
  6. "github.com/lightningnetwork/lnd/lnrpc"
  7. "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
  8. "github.com/lightningnetwork/lnd/lntest"
  9. "github.com/lightningnetwork/lnd/lntest/node"
  10. "github.com/lightningnetwork/lnd/lntypes"
  11. "github.com/lightningnetwork/lnd/routing/route"
  12. "github.com/stretchr/testify/require"
  13. )
  14. // testSendToRouteMultiPath tests that we are able to successfully route a
  15. // payment using multiple shards across different paths, by using SendToRoute.
  16. func testSendToRouteMultiPath(ht *lntest.HarnessTest) {
  17. mts := newMppTestScenario(ht)
  18. // To ensure the payment goes through separate paths, we'll set a
  19. // channel size that can only carry one shard at a time. We'll divide
  20. // the payment into 3 shards.
  21. const (
  22. paymentAmt = btcutil.Amount(300000)
  23. shardAmt = paymentAmt / 3
  24. chanAmt = shardAmt * 3 / 2
  25. )
  26. // Set up a network with three different paths Alice <-> Bob.
  27. // _ Eve _
  28. // / \
  29. // Alice -- Carol ---- Bob
  30. // \ /
  31. // \__ Dave ____/
  32. //
  33. req := &mppOpenChannelRequest{
  34. // Since the channel Alice-> Carol will have to carry two
  35. // shards, we make it larger.
  36. amtAliceCarol: chanAmt + shardAmt,
  37. amtAliceDave: chanAmt,
  38. amtCarolBob: chanAmt,
  39. amtCarolEve: chanAmt,
  40. amtDaveBob: chanAmt,
  41. amtEveBob: chanAmt,
  42. }
  43. mts.openChannels(req)
  44. // Make Bob create an invoice for Alice to pay.
  45. payReqs, rHashes, invoices := ht.CreatePayReqs(mts.bob, paymentAmt, 1)
  46. rHash := rHashes[0]
  47. payReq := payReqs[0]
  48. decodeResp := mts.bob.RPC.DecodePayReq(payReq)
  49. payAddr := decodeResp.PaymentAddr
  50. // Subscribe the invoice.
  51. stream := mts.bob.RPC.SubscribeSingleInvoice(rHash)
  52. // We'll send shards along three routes from Alice.
  53. sendRoutes := [][]*node.HarnessNode{
  54. {mts.carol, mts.bob},
  55. {mts.dave, mts.bob},
  56. {mts.carol, mts.eve, mts.bob},
  57. }
  58. responses := make(chan *lnrpc.HTLCAttempt, len(sendRoutes))
  59. for _, hops := range sendRoutes {
  60. // Build a route for the specified hops.
  61. r := mts.buildRoute(shardAmt, mts.alice, hops)
  62. // Set the MPP records to indicate this is a payment shard.
  63. hop := r.Hops[len(r.Hops)-1]
  64. hop.TlvPayload = true
  65. hop.MppRecord = &lnrpc.MPPRecord{
  66. PaymentAddr: payAddr,
  67. TotalAmtMsat: int64(paymentAmt * 1000),
  68. }
  69. // Send the shard.
  70. sendReq := &routerrpc.SendToRouteRequest{
  71. PaymentHash: rHash,
  72. Route: r,
  73. }
  74. // We'll send all shards in their own goroutine, since
  75. // SendToRoute will block as long as the payment is in flight.
  76. go func() {
  77. resp := mts.alice.RPC.SendToRouteV2(sendReq)
  78. responses <- resp
  79. }()
  80. }
  81. // Wait for all responses to be back, and check that they all
  82. // succeeded.
  83. timer := time.After(defaultTimeout)
  84. for range sendRoutes {
  85. var resp *lnrpc.HTLCAttempt
  86. select {
  87. case resp = <-responses:
  88. case <-timer:
  89. require.Fail(ht, "response not received")
  90. }
  91. require.Nil(ht, resp.Failure, "received payment failure")
  92. // All shards should come back with the preimage.
  93. require.Equal(ht, resp.Preimage, invoices[0].RPreimage,
  94. "preimage doesn't match")
  95. }
  96. // assertNumHtlcs is a helper that checks the node's latest payment,
  97. // and asserts it was split into num shards.
  98. assertNumHtlcs := func(hn *node.HarnessNode, num int) {
  99. var preimage lntypes.Preimage
  100. copy(preimage[:], invoices[0].RPreimage)
  101. payment := ht.AssertPaymentStatus(
  102. hn, preimage, lnrpc.Payment_SUCCEEDED,
  103. )
  104. htlcs := payment.Htlcs
  105. require.NotEmpty(ht, htlcs, "no htlcs")
  106. succeeded := 0
  107. for _, htlc := range htlcs {
  108. if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED {
  109. succeeded++
  110. }
  111. }
  112. require.Equal(ht, num, succeeded, "HTLCs not matched")
  113. }
  114. // assertSettledInvoice checks that the invoice for the given payment
  115. // hash is settled, and has been paid using num HTLCs.
  116. assertSettledInvoice := func(rhash []byte, num int) {
  117. var payHash lntypes.Hash
  118. copy(payHash[:], rhash)
  119. inv := ht.AssertInvoiceState(stream, lnrpc.Invoice_SETTLED)
  120. // Assert that the amount paid to the invoice is correct.
  121. require.EqualValues(ht, paymentAmt, inv.AmtPaidSat,
  122. "incorrect payment amt")
  123. require.Len(ht, inv.Htlcs, num, "wrong num of HTLCs")
  124. }
  125. // Finally check that the payment shows up with three settled HTLCs in
  126. // Alice's list of payments...
  127. assertNumHtlcs(mts.alice, 3)
  128. // ...and in Bob's list of paid invoices.
  129. assertSettledInvoice(rHash, 3)
  130. // Finally, close all channels.
  131. mts.closeChannels()
  132. }
  133. // mppTestScenario defines a test scenario used for testing MPP-related tests.
  134. // It has two standby nodes, alice and bob, and three new nodes, carol, dave,
  135. // and eve.
  136. type mppTestScenario struct {
  137. ht *lntest.HarnessTest
  138. alice, bob, carol, dave, eve *node.HarnessNode
  139. nodes []*node.HarnessNode
  140. // Keep a list of all our active channels.
  141. channelPoints []*lnrpc.ChannelPoint
  142. }
  143. // newMppTestScenario initializes a new mpp test scenario with five funded
  144. // nodes and connects them to have the following topology,
  145. //
  146. // _ Eve _
  147. // / \
  148. // Alice -- Carol ---- Bob
  149. // \ /
  150. // \__ Dave ____/
  151. func newMppTestScenario(ht *lntest.HarnessTest) *mppTestScenario {
  152. alice, bob := ht.Alice, ht.Bob
  153. ht.RestartNodeWithExtraArgs(bob, []string{
  154. "--maxpendingchannels=2",
  155. "--accept-amp",
  156. })
  157. // Create a five-node context consisting of Alice, Bob and three new
  158. // nodes.
  159. carol := ht.NewNode("carol", []string{
  160. "--maxpendingchannels=2",
  161. "--accept-amp",
  162. })
  163. dave := ht.NewNode("dave", nil)
  164. eve := ht.NewNode("eve", nil)
  165. // Connect nodes to ensure propagation of channels.
  166. ht.EnsureConnected(alice, carol)
  167. ht.EnsureConnected(alice, dave)
  168. ht.EnsureConnected(carol, bob)
  169. ht.EnsureConnected(carol, eve)
  170. ht.EnsureConnected(dave, bob)
  171. ht.EnsureConnected(eve, bob)
  172. // Send coins to the nodes and mine 1 blocks to confirm them.
  173. for i := 0; i < 2; i++ {
  174. ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, carol)
  175. ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, dave)
  176. ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, eve)
  177. ht.MineBlocks(1)
  178. }
  179. mts := &mppTestScenario{
  180. ht: ht,
  181. alice: alice,
  182. bob: bob,
  183. carol: carol,
  184. dave: dave,
  185. eve: eve,
  186. nodes: []*node.HarnessNode{alice, bob, carol, dave, eve},
  187. }
  188. return mts
  189. }
  190. // mppOpenChannelRequest defines the amounts used for each channel opening.
  191. type mppOpenChannelRequest struct {
  192. // Channel Alice=>Carol.
  193. amtAliceCarol btcutil.Amount
  194. // Channel Alice=>Dave.
  195. amtAliceDave btcutil.Amount
  196. // Channel Carol=>Bob.
  197. amtCarolBob btcutil.Amount
  198. // Channel Carol=>Eve.
  199. amtCarolEve btcutil.Amount
  200. // Channel Dave=>Bob.
  201. amtDaveBob btcutil.Amount
  202. // Channel Eve=>Bob.
  203. amtEveBob btcutil.Amount
  204. }
  205. // openChannels is a helper to open channels that sets up a network topology
  206. // with three different paths Alice <-> Bob as following,
  207. //
  208. // _ Eve _
  209. // / \
  210. // Alice -- Carol ---- Bob
  211. // \ /
  212. // \__ Dave ____/
  213. //
  214. // NOTE: all the channels are open together to save blocks mined.
  215. func (m *mppTestScenario) openChannels(r *mppOpenChannelRequest) {
  216. reqs := []*lntest.OpenChannelRequest{
  217. {
  218. Local: m.alice,
  219. Remote: m.carol,
  220. Param: lntest.OpenChannelParams{Amt: r.amtAliceCarol},
  221. },
  222. {
  223. Local: m.alice,
  224. Remote: m.dave,
  225. Param: lntest.OpenChannelParams{Amt: r.amtAliceDave},
  226. },
  227. {
  228. Local: m.carol,
  229. Remote: m.bob,
  230. Param: lntest.OpenChannelParams{Amt: r.amtCarolBob},
  231. },
  232. {
  233. Local: m.carol,
  234. Remote: m.eve,
  235. Param: lntest.OpenChannelParams{Amt: r.amtCarolEve},
  236. },
  237. {
  238. Local: m.dave,
  239. Remote: m.bob,
  240. Param: lntest.OpenChannelParams{Amt: r.amtDaveBob},
  241. },
  242. {
  243. Local: m.eve,
  244. Remote: m.bob,
  245. Param: lntest.OpenChannelParams{Amt: r.amtEveBob},
  246. },
  247. }
  248. m.channelPoints = m.ht.OpenMultiChannelsAsync(reqs)
  249. // Make sure every node has heard every channel.
  250. for _, hn := range m.nodes {
  251. for _, cp := range m.channelPoints {
  252. m.ht.AssertTopologyChannelOpen(hn, cp)
  253. }
  254. // Each node should have exactly 6 edges.
  255. m.ht.AssertNumEdges(hn, len(m.channelPoints), false)
  256. }
  257. }
  258. // closeChannels closes all the open channels from `openChannels`.
  259. func (m *mppTestScenario) closeChannels() {
  260. if m.ht.Failed() {
  261. m.ht.Log("Skipped closing channels for failed test")
  262. return
  263. }
  264. // Close all channels without mining the closing transactions.
  265. m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false)
  266. m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[1], false)
  267. m.ht.CloseChannelAssertPending(m.carol, m.channelPoints[2], false)
  268. m.ht.CloseChannelAssertPending(m.carol, m.channelPoints[3], false)
  269. m.ht.CloseChannelAssertPending(m.dave, m.channelPoints[4], false)
  270. m.ht.CloseChannelAssertPending(m.eve, m.channelPoints[5], false)
  271. // Now mine a block to include all the closing transactions.
  272. m.ht.MineBlocks(1)
  273. // Assert that the channels are closed.
  274. for _, hn := range m.nodes {
  275. m.ht.AssertNumWaitingClose(hn, 0)
  276. }
  277. }
  278. // Helper function for Alice to build a route from pubkeys.
  279. func (m *mppTestScenario) buildRoute(amt btcutil.Amount,
  280. sender *node.HarnessNode, hops []*node.HarnessNode) *lnrpc.Route {
  281. rpcHops := make([][]byte, 0, len(hops))
  282. for _, hop := range hops {
  283. k := hop.PubKeyStr
  284. pubkey, err := route.NewVertexFromStr(k)
  285. require.NoErrorf(m.ht, err, "error parsing %v: %v", k, err)
  286. rpcHops = append(rpcHops, pubkey[:])
  287. }
  288. req := &routerrpc.BuildRouteRequest{
  289. AmtMsat: int64(amt * 1000),
  290. FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta,
  291. HopPubkeys: rpcHops,
  292. }
  293. routeResp := sender.RPC.BuildRoute(req)
  294. return routeResp.Route
  295. }