github.com/decred/dcrlnd@v0.7.6/lntest/itest/lnd_multi-hop-payments_test.go (about) 1 package itest 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/decred/dcrd/dcrutil/v4" 8 "github.com/decred/dcrd/wire" 9 "github.com/decred/dcrlnd/chainreg" 10 "github.com/decred/dcrlnd/lnrpc" 11 "github.com/decred/dcrlnd/lnrpc/routerrpc" 12 "github.com/decred/dcrlnd/lntest" 13 ) 14 15 func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { 16 17 ctxb := context.Background() 18 19 const chanAmt = dcrutil.Amount(100000) 20 var networkChans []*lnrpc.ChannelPoint 21 22 // Open a channel with 100k atoms between Alice and Bob with Alice 23 // being the sole funder of the channel. 24 chanPointAlice := openChannelAndAssert( 25 t, net, net.Alice, net.Bob, 26 lntest.OpenChannelParams{ 27 Amt: chanAmt, 28 }, 29 ) 30 networkChans = append(networkChans, chanPointAlice) 31 32 aliceChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointAlice) 33 if err != nil { 34 t.Fatalf("unable to get txid: %v", err) 35 } 36 aliceFundPoint := wire.OutPoint{ 37 Hash: *aliceChanTXID, 38 Index: chanPointAlice.OutputIndex, 39 } 40 41 // As preliminary setup, we'll create two new nodes: Carol and Dave, 42 // such that we now have a 4 node, 3 channel topology. Dave will make a 43 // channel with Alice, and Carol with Dave. After this setup, the 44 // network topology should now look like: 45 // Carol -> Dave -> Alice -> Bob 46 // 47 // First, we'll create Dave and establish a channel to Alice. Dave will 48 // be running an older node that requires the legacy onion payload. 49 daveArgs := []string{"--protocol.legacy.onion"} 50 dave := net.NewNode(t.t, "Dave", daveArgs) 51 defer shutdownAndAssert(net, t, dave) 52 53 net.ConnectNodes(t.t, dave, net.Alice) 54 net.SendCoins(t.t, dcrutil.AtomsPerCoin, dave) 55 56 chanPointDave := openChannelAndAssert( 57 t, net, dave, net.Alice, 58 lntest.OpenChannelParams{ 59 Amt: chanAmt, 60 }, 61 ) 62 networkChans = append(networkChans, chanPointDave) 63 daveChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointDave) 64 if err != nil { 65 t.Fatalf("unable to get txid: %v", err) 66 } 67 daveFundPoint := wire.OutPoint{ 68 Hash: *daveChanTXID, 69 Index: chanPointDave.OutputIndex, 70 } 71 72 // Next, we'll create Carol and establish a channel to from her to 73 // Dave. 74 carol := net.NewNode(t.t, "Carol", nil) 75 defer shutdownAndAssert(net, t, carol) 76 77 net.ConnectNodes(t.t, carol, dave) 78 net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol) 79 80 chanPointCarol := openChannelAndAssert( 81 t, net, carol, dave, 82 lntest.OpenChannelParams{ 83 Amt: chanAmt, 84 }, 85 ) 86 networkChans = append(networkChans, chanPointCarol) 87 88 carolChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointCarol) 89 if err != nil { 90 t.Fatalf("unable to get txid: %v", err) 91 } 92 carolFundPoint := wire.OutPoint{ 93 Hash: *carolChanTXID, 94 Index: chanPointCarol.OutputIndex, 95 } 96 97 // Wait for all nodes to have seen all channels. 98 nodes := []*lntest.HarnessNode{net.Alice, net.Bob, carol, dave} 99 nodeNames := []string{"Alice", "Bob", "Carol", "Dave"} 100 for _, chanPoint := range networkChans { 101 for i, node := range nodes { 102 txid, err := lnrpc.GetChanPointFundingTxid(chanPoint) 103 if err != nil { 104 t.Fatalf("unable to get txid: %v", err) 105 } 106 point := wire.OutPoint{ 107 Hash: *txid, 108 Index: chanPoint.OutputIndex, 109 } 110 111 err = node.WaitForNetworkChannelOpen(chanPoint) 112 if err != nil { 113 t.Fatalf("%s(%d): timeout waiting for "+ 114 "channel(%s) open: %v", nodeNames[i], 115 node.NodeID, point, err) 116 } 117 } 118 } 119 120 // Create 5 invoices for Bob, which expect a payment from Carol for 1k 121 // atoms with a different preimage each time. 122 const numPayments = 5 123 const paymentAmt = 1000 124 payReqs, _, _, err := createPayReqs( 125 net.Bob, paymentAmt, numPayments, 126 ) 127 if err != nil { 128 t.Fatalf("unable to create pay reqs: %v", err) 129 } 130 131 // We'll wait for all parties to recognize the new channels within the 132 // network. 133 err = dave.WaitForNetworkChannelOpen(chanPointDave) 134 if err != nil { 135 t.Fatalf("dave didn't advertise his channel: %v", err) 136 } 137 err = carol.WaitForNetworkChannelOpen(chanPointCarol) 138 if err != nil { 139 t.Fatalf("carol didn't advertise her channel in time: %v", 140 err) 141 } 142 143 time.Sleep(time.Millisecond * 50) 144 145 // Set the fee policies of the Alice -> Bob and the Dave -> Alice 146 // channel edges to relatively large non default values. This makes it 147 // possible to pick up more subtle fee calculation errors. 148 maxHtlc := calculateMaxHtlc(chanAmt) 149 const aliceBaseFeeAtoms = 1 150 const aliceFeeRatePPM = 100000 151 updateChannelPolicy( 152 t, net.Alice, chanPointAlice, aliceBaseFeeAtoms*1000, 153 aliceFeeRatePPM, chainreg.DefaultDecredTimeLockDelta, maxHtlc, 154 carol, 155 ) 156 157 const daveBaseFeeAtoms = 5 158 const daveFeeRatePPM = 150000 159 updateChannelPolicy( 160 t, dave, chanPointDave, daveBaseFeeAtoms*1000, daveFeeRatePPM, 161 chainreg.DefaultDecredTimeLockDelta, maxHtlc, carol, 162 ) 163 164 // Before we start sending payments, subscribe to htlc events for each 165 // node. 166 ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) 167 defer cancel() 168 169 aliceEvents, err := net.Alice.RouterClient.SubscribeHtlcEvents( 170 ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, 171 ) 172 if err != nil { 173 t.Fatalf("could not subscribe events: %v", err) 174 } 175 176 bobEvents, err := net.Bob.RouterClient.SubscribeHtlcEvents( 177 ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, 178 ) 179 if err != nil { 180 t.Fatalf("could not subscribe events: %v", err) 181 } 182 183 carolEvents, err := carol.RouterClient.SubscribeHtlcEvents( 184 ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, 185 ) 186 if err != nil { 187 t.Fatalf("could not subscribe events: %v", err) 188 } 189 190 daveEvents, err := dave.RouterClient.SubscribeHtlcEvents( 191 ctxt, &routerrpc.SubscribeHtlcEventsRequest{}, 192 ) 193 if err != nil { 194 t.Fatalf("could not subscribe events: %v", err) 195 } 196 197 // Using Carol as the source, pay to the 5 invoices from Bob created 198 // above. 199 err = completePaymentRequests(carol, carol.RouterClient, payReqs, true) 200 if err != nil { 201 t.Fatalf("unable to send payments: %v", err) 202 } 203 204 // At this point all the channels within our proto network should be 205 // shifted by 5k atoms in the direction of Bob, the sink within the 206 // payment flow generated above. The order of asserts corresponds to 207 // increasing of time is needed to embed the HTLC in commitment 208 // transaction, in channel Carol->David->Alice->Bob, order is Bob, 209 // Alice, David, Carol. 210 211 // The final node bob expects to get paid five times 1000 atoms. 212 expectedAmountPaidAtoB := int64(numPayments * paymentAmt) 213 214 assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Bob, 215 aliceFundPoint, int64(0), expectedAmountPaidAtoB) 216 assertAmountPaid(t, "Alice(local) => Bob(remote)", net.Alice, 217 aliceFundPoint, expectedAmountPaidAtoB, int64(0)) 218 219 // To forward a payment of 1000 atoms, Alice is charging a fee of 1 220 // atom + 10% = 101 atoms. 221 const aliceFeePerPayment = aliceBaseFeeAtoms + 222 (paymentAmt * aliceFeeRatePPM / 1_000_000) 223 const expectedFeeAlice = numPayments * aliceFeePerPayment 224 225 // Dave needs to pay what Alice pays plus Alice's fee. 226 expectedAmountPaidDtoA := expectedAmountPaidAtoB + expectedFeeAlice 227 228 assertAmountPaid(t, "Dave(local) => Alice(remote)", net.Alice, 229 daveFundPoint, int64(0), expectedAmountPaidDtoA) 230 assertAmountPaid(t, "Dave(local) => Alice(remote)", dave, 231 daveFundPoint, expectedAmountPaidDtoA, int64(0)) 232 233 // To forward a payment of 1101 atom, Dave is charging a fee of 5 atoms 234 // + 15% = 170.15 atoms. This is rounded down in rpcserver to 170. 235 const davePaymentAmt = paymentAmt + aliceFeePerPayment 236 const daveFeePerPayment = daveBaseFeeAtoms + 237 (davePaymentAmt * daveFeeRatePPM / 1_000_000) 238 const expectedFeeDave = numPayments * daveFeePerPayment 239 240 // Carol needs to pay what Dave pays plus Dave's fee. 241 expectedAmountPaidCtoD := expectedAmountPaidDtoA + expectedFeeDave 242 243 assertAmountPaid(t, "Carol(local) => Dave(remote)", dave, 244 carolFundPoint, int64(0), expectedAmountPaidCtoD) 245 assertAmountPaid(t, "Carol(local) => Dave(remote)", carol, 246 carolFundPoint, expectedAmountPaidCtoD, int64(0)) 247 248 // Now that we know all the balances have been settled out properly, 249 // we'll ensure that our internal record keeping for completed circuits 250 // was properly updated. 251 252 // First, check that the FeeReport response shows the proper fees 253 // accrued over each time range. Dave should've earned 170 atoms for 254 // each of the forwarded payments. 255 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 256 feeReport, err := dave.FeeReport(ctxt, &lnrpc.FeeReportRequest{}) 257 if err != nil { 258 t.Fatalf("unable to query for fee report: %v", err) 259 } 260 261 if feeReport.DayFeeSum != uint64(expectedFeeDave) { 262 t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, 263 feeReport.DayFeeSum) 264 } 265 if feeReport.WeekFeeSum != uint64(expectedFeeDave) { 266 t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, 267 feeReport.WeekFeeSum) 268 } 269 if feeReport.MonthFeeSum != uint64(expectedFeeDave) { 270 t.Fatalf("fee mismatch: expected %v, got %v", expectedFeeDave, 271 feeReport.MonthFeeSum) 272 } 273 274 // Next, ensure that if we issue the vanilla query for the forwarding 275 // history, it returns 5 values, and each entry is formatted properly. 276 ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 277 fwdingHistory, err := dave.ForwardingHistory( 278 ctxt, &lnrpc.ForwardingHistoryRequest{}, 279 ) 280 if err != nil { 281 t.Fatalf("unable to query for fee report: %v", err) 282 } 283 if len(fwdingHistory.ForwardingEvents) != numPayments { 284 t.Fatalf("wrong number of forwarding event: expected %v, "+ 285 "got %v", numPayments, 286 len(fwdingHistory.ForwardingEvents)) 287 } 288 expectedForwardingFee := uint64(expectedFeeDave / numPayments) 289 for _, event := range fwdingHistory.ForwardingEvents { 290 // Each event should show a fee of 170 atoms. 291 if event.Fee != expectedForwardingFee { 292 t.Fatalf("fee mismatch: expected %v, got %v", 293 expectedForwardingFee, event.Fee) 294 } 295 } 296 297 // We expect Carol to have successful forwards and settles for 298 // her sends. 299 assertHtlcEvents( 300 t, numPayments, 0, numPayments, routerrpc.HtlcEvent_SEND, 301 carolEvents, 302 ) 303 304 // Dave and Alice should both have forwards and settles for 305 // their role as forwarding nodes. 306 assertHtlcEvents( 307 t, numPayments, 0, numPayments, routerrpc.HtlcEvent_FORWARD, 308 daveEvents, 309 ) 310 assertHtlcEvents( 311 t, numPayments, 0, numPayments, routerrpc.HtlcEvent_FORWARD, 312 aliceEvents, 313 ) 314 315 // Bob should only have settle events for his receives. 316 assertHtlcEvents( 317 t, 0, 0, numPayments, routerrpc.HtlcEvent_RECEIVE, bobEvents, 318 ) 319 320 closeChannelAndAssert(t, net, net.Alice, chanPointAlice, false) 321 closeChannelAndAssert(t, net, dave, chanPointDave, false) 322 closeChannelAndAssert(t, net, carol, chanPointCarol, false) 323 } 324 325 // assertHtlcEvents consumes events from a client and ensures that they are of 326 // the expected type and contain the expected number of forwards, forward 327 // failures and settles. 328 func assertHtlcEvents(t *harnessTest, fwdCount, fwdFailCount, settleCount int, 329 userType routerrpc.HtlcEvent_EventType, 330 client routerrpc.Router_SubscribeHtlcEventsClient) { 331 332 var forwards, forwardFails, settles int 333 334 numEvents := fwdCount + fwdFailCount + settleCount 335 for i := 0; i < numEvents; i++ { 336 event := assertEventAndType(t, userType, client) 337 338 switch event.Event.(type) { 339 case *routerrpc.HtlcEvent_ForwardEvent: 340 forwards++ 341 342 case *routerrpc.HtlcEvent_ForwardFailEvent: 343 forwardFails++ 344 345 case *routerrpc.HtlcEvent_SettleEvent: 346 settles++ 347 348 default: 349 t.Fatalf("unexpected event: %T", event.Event) 350 } 351 } 352 353 if forwards != fwdCount { 354 t.Fatalf("expected: %v forwards, got: %v", fwdCount, forwards) 355 } 356 357 if forwardFails != fwdFailCount { 358 t.Fatalf("expected: %v forward fails, got: %v", fwdFailCount, 359 forwardFails) 360 } 361 362 if settles != settleCount { 363 t.Fatalf("expected: %v settles, got: %v", settleCount, settles) 364 } 365 } 366 367 // assertEventAndType reads an event from the stream provided and ensures that 368 // it is associated with the correct user related type - a user initiated send, 369 // a receive to our node or a forward through our node. Note that this event 370 // type is different from the htlc event type (forward, link failure etc). 371 func assertEventAndType(t *harnessTest, eventType routerrpc.HtlcEvent_EventType, 372 client routerrpc.Router_SubscribeHtlcEventsClient) *routerrpc.HtlcEvent { 373 event, err := client.Recv() 374 if err != nil { 375 t.Fatalf("could not get event") 376 } 377 378 if event.EventType != eventType { 379 t.Fatalf("expected: %v, got: %v", eventType, 380 event.EventType) 381 } 382 383 return event 384 } 385 386 // updateChannelPolicy updates the channel policy of node to the 387 // given fees and timelock delta. This function blocks until 388 // listenerNode has received the policy update. 389 func updateChannelPolicy(t *harnessTest, node *lntest.HarnessNode, 390 chanPoint *lnrpc.ChannelPoint, baseFee int64, feeRate int64, 391 timeLockDelta uint32, maxHtlc uint64, listenerNode *lntest.HarnessNode) { 392 393 ctxb := context.Background() 394 395 expectedPolicy := &lnrpc.RoutingPolicy{ 396 FeeBaseMAtoms: baseFee, 397 FeeRateMilliMAtoms: feeRate, 398 TimeLockDelta: timeLockDelta, 399 MinHtlc: 1000, // default value 400 MaxHtlcMAtoms: maxHtlc, 401 } 402 403 updateFeeReq := &lnrpc.PolicyUpdateRequest{ 404 BaseFeeMAtoms: baseFee, 405 FeeRate: float64(feeRate) / testFeeBase, 406 TimeLockDelta: timeLockDelta, 407 Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{ 408 ChanPoint: chanPoint, 409 }, 410 MaxHtlcMAtoms: maxHtlc, 411 } 412 413 ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) 414 if _, err := node.UpdateChannelPolicy(ctxt, updateFeeReq); err != nil { 415 t.Fatalf("unable to update chan policy: %v", err) 416 } 417 418 // Wait for listener node to receive the channel update from node. 419 assertChannelPolicyUpdate( 420 t.t, listenerNode, node.PubKeyStr, 421 expectedPolicy, chanPoint, false, 422 ) 423 }