/ htlcswitch / test_utils.go
test_utils.go
1 package htlcswitch 2 3 import ( 4 "bytes" 5 "context" 6 crand "crypto/rand" 7 "crypto/sha256" 8 "encoding/binary" 9 "encoding/hex" 10 "errors" 11 "fmt" 12 "net" 13 "os" 14 "runtime" 15 "runtime/pprof" 16 "sync/atomic" 17 "testing" 18 "time" 19 20 "github.com/btcsuite/btcd/btcec/v2" 21 "github.com/btcsuite/btcd/btcec/v2/ecdsa" 22 "github.com/btcsuite/btcd/btcutil" 23 "github.com/btcsuite/btcd/chaincfg/chainhash" 24 "github.com/btcsuite/btcd/wire" 25 sphinx "github.com/lightningnetwork/lightning-onion" 26 "github.com/lightningnetwork/lnd/channeldb" 27 "github.com/lightningnetwork/lnd/contractcourt" 28 "github.com/lightningnetwork/lnd/graph/db/models" 29 "github.com/lightningnetwork/lnd/htlcswitch/hop" 30 "github.com/lightningnetwork/lnd/input" 31 "github.com/lightningnetwork/lnd/invoices" 32 "github.com/lightningnetwork/lnd/keychain" 33 "github.com/lightningnetwork/lnd/kvdb" 34 "github.com/lightningnetwork/lnd/lnpeer" 35 "github.com/lightningnetwork/lnd/lntest/channels" 36 "github.com/lightningnetwork/lnd/lntest/wait" 37 "github.com/lightningnetwork/lnd/lntypes" 38 "github.com/lightningnetwork/lnd/lnwallet" 39 "github.com/lightningnetwork/lnd/lnwallet/chainfee" 40 "github.com/lightningnetwork/lnd/lnwire" 41 "github.com/lightningnetwork/lnd/shachain" 42 "github.com/lightningnetwork/lnd/ticker" 43 "github.com/stretchr/testify/require" 44 ) 45 46 // maxInflightHtlcs specifies the max number of inflight HTLCs. This number is 47 // chosen to be smaller than the default 483 so the test can run faster. 48 const maxInflightHtlcs = 50 49 50 var ( 51 alicePrivKey = []byte("alice priv key") 52 bobPrivKey = []byte("bob priv key") 53 carolPrivKey = []byte("carol priv key") 54 55 testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571319d18e949ddfa2965fb6caa1bf0314f882d7") 56 testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a88121167221b6700d72a0ead154c03be696a292d24ae") 57 testRScalar = new(btcec.ModNScalar) 58 testSScalar = new(btcec.ModNScalar) 59 _ = testRScalar.SetByteSlice(testRBytes) 60 _ = testSScalar.SetByteSlice(testSBytes) 61 testSig = ecdsa.NewSignature(testRScalar, testSScalar) 62 63 wireSig, _ = lnwire.NewSigFromSignature(testSig) 64 65 testBatchTimeout = 50 * time.Millisecond 66 ) 67 68 var idSeqNum uint64 69 70 // genID generates a unique tuple to identify a test channel. 71 func genID() (lnwire.ChannelID, lnwire.ShortChannelID) { 72 id := atomic.AddUint64(&idSeqNum, 1) 73 74 var scratch [8]byte 75 76 binary.BigEndian.PutUint64(scratch[:], id) 77 hash1, _ := chainhash.NewHash(bytes.Repeat(scratch[:], 4)) 78 79 chanPoint1 := wire.NewOutPoint(hash1, uint32(id)) 80 chanID1 := lnwire.NewChanIDFromOutPoint(*chanPoint1) 81 aliceChanID := lnwire.NewShortChanIDFromInt(id) 82 83 return chanID1, aliceChanID 84 } 85 86 // genIDs generates ids for two test channels. 87 func genIDs() (lnwire.ChannelID, lnwire.ChannelID, lnwire.ShortChannelID, 88 lnwire.ShortChannelID) { 89 90 chanID1, aliceChanID := genID() 91 chanID2, bobChanID := genID() 92 93 return chanID1, chanID2, aliceChanID, bobChanID 94 } 95 96 // mockGetChanUpdateMessage helper function which returns topology update of 97 // the channel 98 func mockGetChanUpdateMessage(_ lnwire.ShortChannelID) (*lnwire.ChannelUpdate1, 99 error) { 100 101 return &lnwire.ChannelUpdate1{ 102 Signature: wireSig, 103 }, nil 104 } 105 106 // generateRandomBytes returns securely generated random bytes. 107 // It will return an error if the system's secure random 108 // number generator fails to function correctly, in which 109 // case the caller should not continue. 110 func generateRandomBytes(n int) ([]byte, error) { 111 b := make([]byte, n) 112 113 // TODO(roasbeef): should use counter in tests (atomic) rather than 114 // this 115 116 _, err := crand.Read(b) 117 // Note that Err == nil only if we read len(b) bytes. 118 if err != nil { 119 return nil, err 120 } 121 122 return b, nil 123 } 124 125 type testLightningChannel struct { 126 channel *lnwallet.LightningChannel 127 restore func() (*lnwallet.LightningChannel, error) 128 } 129 130 // createTestChannel creates the channel and returns our and remote channels 131 // representations. 132 // 133 // TODO(roasbeef): need to factor out, similar func re-used in many parts of codebase 134 func createTestChannel(t *testing.T, alicePrivKey, bobPrivKey []byte, 135 aliceAmount, bobAmount, aliceReserve, bobReserve btcutil.Amount, 136 chanID lnwire.ShortChannelID) (*testLightningChannel, 137 *testLightningChannel, error) { 138 139 aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(alicePrivKey) 140 bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(bobPrivKey) 141 142 channelCapacity := aliceAmount + bobAmount 143 csvTimeoutAlice := uint32(5) 144 csvTimeoutBob := uint32(4) 145 isAliceInitiator := true 146 147 aliceBounds := channeldb.ChannelStateBounds{ 148 MaxPendingAmount: lnwire.NewMSatFromSatoshis( 149 channelCapacity), 150 ChanReserve: aliceReserve, 151 MinHTLC: 0, 152 MaxAcceptedHtlcs: maxInflightHtlcs, 153 } 154 aliceCommitParams := channeldb.CommitmentParams{ 155 DustLimit: btcutil.Amount(200), 156 CsvDelay: uint16(csvTimeoutAlice), 157 } 158 159 bobBounds := channeldb.ChannelStateBounds{ 160 MaxPendingAmount: lnwire.NewMSatFromSatoshis( 161 channelCapacity), 162 ChanReserve: bobReserve, 163 MinHTLC: 0, 164 MaxAcceptedHtlcs: maxInflightHtlcs, 165 } 166 bobCommitParams := channeldb.CommitmentParams{ 167 DustLimit: btcutil.Amount(800), 168 CsvDelay: uint16(csvTimeoutBob), 169 } 170 171 var hash [sha256.Size]byte 172 randomSeed, err := generateRandomBytes(sha256.Size) 173 if err != nil { 174 return nil, nil, err 175 } 176 copy(hash[:], randomSeed) 177 178 prevOut := &wire.OutPoint{ 179 Hash: chainhash.Hash(hash), 180 Index: 0, 181 } 182 fundingTxIn := wire.NewTxIn(prevOut, nil, nil) 183 184 aliceCfg := channeldb.ChannelConfig{ 185 ChannelStateBounds: aliceBounds, 186 CommitmentParams: aliceCommitParams, 187 MultiSigKey: keychain.KeyDescriptor{ 188 PubKey: aliceKeyPub, 189 }, 190 RevocationBasePoint: keychain.KeyDescriptor{ 191 PubKey: aliceKeyPub, 192 }, 193 PaymentBasePoint: keychain.KeyDescriptor{ 194 PubKey: aliceKeyPub, 195 }, 196 DelayBasePoint: keychain.KeyDescriptor{ 197 PubKey: aliceKeyPub, 198 }, 199 HtlcBasePoint: keychain.KeyDescriptor{ 200 PubKey: aliceKeyPub, 201 }, 202 } 203 bobCfg := channeldb.ChannelConfig{ 204 ChannelStateBounds: bobBounds, 205 CommitmentParams: bobCommitParams, 206 MultiSigKey: keychain.KeyDescriptor{ 207 PubKey: bobKeyPub, 208 }, 209 RevocationBasePoint: keychain.KeyDescriptor{ 210 PubKey: bobKeyPub, 211 }, 212 PaymentBasePoint: keychain.KeyDescriptor{ 213 PubKey: bobKeyPub, 214 }, 215 DelayBasePoint: keychain.KeyDescriptor{ 216 PubKey: bobKeyPub, 217 }, 218 HtlcBasePoint: keychain.KeyDescriptor{ 219 PubKey: bobKeyPub, 220 }, 221 } 222 223 bobRoot, err := chainhash.NewHash(bobKeyPriv.Serialize()) 224 if err != nil { 225 return nil, nil, err 226 } 227 bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot) 228 bobFirstRevoke, err := bobPreimageProducer.AtIndex(0) 229 if err != nil { 230 return nil, nil, err 231 } 232 bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:]) 233 234 aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize()) 235 if err != nil { 236 return nil, nil, err 237 } 238 alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot) 239 aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0) 240 if err != nil { 241 return nil, nil, err 242 } 243 aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:]) 244 245 aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns( 246 aliceAmount, bobAmount, &aliceCfg, &bobCfg, aliceCommitPoint, 247 bobCommitPoint, *fundingTxIn, channeldb.SingleFunderTweaklessBit, 248 isAliceInitiator, 0, 249 ) 250 if err != nil { 251 return nil, nil, err 252 } 253 254 dbAlice := channeldb.OpenForTesting(t, t.TempDir()) 255 dbBob := channeldb.OpenForTesting(t, t.TempDir()) 256 257 estimator := chainfee.NewStaticEstimator(6000, 0) 258 feePerKw, err := estimator.EstimateFeePerKW(1) 259 if err != nil { 260 return nil, nil, err 261 } 262 commitFee := feePerKw.FeeForWeight(724) 263 264 const broadcastHeight = 1 265 bobAddr := &net.TCPAddr{ 266 IP: net.ParseIP("127.0.0.1"), 267 Port: 18555, 268 } 269 270 aliceAddr := &net.TCPAddr{ 271 IP: net.ParseIP("127.0.0.1"), 272 Port: 18556, 273 } 274 275 aliceCommit := channeldb.ChannelCommitment{ 276 CommitHeight: 0, 277 LocalBalance: lnwire.NewMSatFromSatoshis(aliceAmount - commitFee), 278 RemoteBalance: lnwire.NewMSatFromSatoshis(bobAmount), 279 CommitFee: commitFee, 280 FeePerKw: btcutil.Amount(feePerKw), 281 CommitTx: aliceCommitTx, 282 CommitSig: bytes.Repeat([]byte{1}, 71), 283 } 284 bobCommit := channeldb.ChannelCommitment{ 285 CommitHeight: 0, 286 LocalBalance: lnwire.NewMSatFromSatoshis(bobAmount), 287 RemoteBalance: lnwire.NewMSatFromSatoshis(aliceAmount - commitFee), 288 CommitFee: commitFee, 289 FeePerKw: btcutil.Amount(feePerKw), 290 CommitTx: bobCommitTx, 291 CommitSig: bytes.Repeat([]byte{1}, 71), 292 } 293 294 aliceChannelState := &channeldb.OpenChannel{ 295 LocalChanCfg: aliceCfg, 296 RemoteChanCfg: bobCfg, 297 IdentityPub: aliceKeyPub, 298 FundingOutpoint: *prevOut, 299 ChanType: channeldb.SingleFunderTweaklessBit, 300 IsInitiator: isAliceInitiator, 301 Capacity: channelCapacity, 302 RemoteCurrentRevocation: bobCommitPoint, 303 RevocationProducer: alicePreimageProducer, 304 RevocationStore: shachain.NewRevocationStore(), 305 LocalCommitment: aliceCommit, 306 RemoteCommitment: aliceCommit, 307 ShortChannelID: chanID, 308 Db: dbAlice.ChannelStateDB(), 309 Packager: channeldb.NewChannelPackager(chanID), 310 FundingTxn: channels.TestFundingTx, 311 } 312 313 bobChannelState := &channeldb.OpenChannel{ 314 LocalChanCfg: bobCfg, 315 RemoteChanCfg: aliceCfg, 316 IdentityPub: bobKeyPub, 317 FundingOutpoint: *prevOut, 318 ChanType: channeldb.SingleFunderTweaklessBit, 319 IsInitiator: !isAliceInitiator, 320 Capacity: channelCapacity, 321 RemoteCurrentRevocation: aliceCommitPoint, 322 RevocationProducer: bobPreimageProducer, 323 RevocationStore: shachain.NewRevocationStore(), 324 LocalCommitment: bobCommit, 325 RemoteCommitment: bobCommit, 326 ShortChannelID: chanID, 327 Db: dbBob.ChannelStateDB(), 328 Packager: channeldb.NewChannelPackager(chanID), 329 } 330 331 if err := aliceChannelState.SyncPending(bobAddr, broadcastHeight); err != nil { 332 return nil, nil, err 333 } 334 335 if err := bobChannelState.SyncPending(aliceAddr, broadcastHeight); err != nil { 336 return nil, nil, err 337 } 338 339 aliceSigner := input.NewMockSigner( 340 []*btcec.PrivateKey{aliceKeyPriv}, nil, 341 ) 342 bobSigner := input.NewMockSigner( 343 []*btcec.PrivateKey{bobKeyPriv}, nil, 344 ) 345 346 alicePool := lnwallet.NewSigPool(runtime.NumCPU(), aliceSigner) 347 signerMock := lnwallet.NewDefaultAuxSignerMock(t) 348 channelAlice, err := lnwallet.NewLightningChannel( 349 aliceSigner, aliceChannelState, alicePool, 350 lnwallet.WithLeafStore(&lnwallet.MockAuxLeafStore{}), 351 lnwallet.WithAuxSigner(signerMock), 352 ) 353 if err != nil { 354 return nil, nil, err 355 } 356 alicePool.Start() 357 358 bobPool := lnwallet.NewSigPool(runtime.NumCPU(), bobSigner) 359 channelBob, err := lnwallet.NewLightningChannel( 360 bobSigner, bobChannelState, bobPool, 361 lnwallet.WithLeafStore(&lnwallet.MockAuxLeafStore{}), 362 lnwallet.WithAuxSigner(signerMock), 363 ) 364 if err != nil { 365 return nil, nil, err 366 } 367 bobPool.Start() 368 369 // Now that the channel are open, simulate the start of a session by 370 // having Alice and Bob extend their revocation windows to each other. 371 aliceNextRevoke, err := channelAlice.NextRevocationKey() 372 if err != nil { 373 return nil, nil, err 374 } 375 if err := channelBob.InitNextRevocation(aliceNextRevoke); err != nil { 376 return nil, nil, err 377 } 378 379 bobNextRevoke, err := channelBob.NextRevocationKey() 380 if err != nil { 381 return nil, nil, err 382 } 383 if err := channelAlice.InitNextRevocation(bobNextRevoke); err != nil { 384 return nil, nil, err 385 } 386 387 restoreAlice := func() (*lnwallet.LightningChannel, error) { 388 aliceStoredChannels, err := dbAlice.ChannelStateDB(). 389 FetchOpenChannels(aliceKeyPub) 390 switch err { 391 case nil: 392 case kvdb.ErrDatabaseNotOpen: 393 dbAlice = channeldb.OpenForTesting(t, dbAlice.Path()) 394 395 aliceStoredChannels, err = dbAlice.ChannelStateDB(). 396 FetchOpenChannels(aliceKeyPub) 397 if err != nil { 398 return nil, fmt.Errorf("unable to fetch alice "+ 399 "channel: %w", err) 400 } 401 default: 402 return nil, fmt.Errorf("unable to fetch alice "+ 403 "channel: %w", err) 404 } 405 406 var aliceStoredChannel *channeldb.OpenChannel 407 for _, channel := range aliceStoredChannels { 408 if channel.FundingOutpoint.String() == prevOut.String() { 409 aliceStoredChannel = channel 410 break 411 } 412 } 413 414 if aliceStoredChannel == nil { 415 return nil, errors.New("unable to find stored alice channel") 416 } 417 418 newAliceChannel, err := lnwallet.NewLightningChannel( 419 aliceSigner, aliceStoredChannel, alicePool, 420 lnwallet.WithLeafStore(&lnwallet.MockAuxLeafStore{}), 421 lnwallet.WithAuxSigner(signerMock), 422 ) 423 if err != nil { 424 return nil, fmt.Errorf("unable to create new "+ 425 "channel: %w", err) 426 } 427 428 return newAliceChannel, nil 429 } 430 431 restoreBob := func() (*lnwallet.LightningChannel, error) { 432 bobStoredChannels, err := dbBob.ChannelStateDB(). 433 FetchOpenChannels(bobKeyPub) 434 switch err { 435 case nil: 436 case kvdb.ErrDatabaseNotOpen: 437 dbBob = channeldb.OpenForTesting(t, dbBob.Path()) 438 if err != nil { 439 return nil, fmt.Errorf("unable to reopen bob "+ 440 "db: %w", err) 441 } 442 443 bobStoredChannels, err = dbBob.ChannelStateDB(). 444 FetchOpenChannels(bobKeyPub) 445 if err != nil { 446 return nil, fmt.Errorf("unable to fetch bob "+ 447 "channel: %w", err) 448 } 449 default: 450 return nil, fmt.Errorf("unable to fetch bob channel: "+ 451 "%w", err) 452 } 453 454 var bobStoredChannel *channeldb.OpenChannel 455 for _, channel := range bobStoredChannels { 456 if channel.FundingOutpoint.String() == prevOut.String() { 457 bobStoredChannel = channel 458 break 459 } 460 } 461 462 if bobStoredChannel == nil { 463 return nil, errors.New("unable to find stored bob channel") 464 } 465 466 newBobChannel, err := lnwallet.NewLightningChannel( 467 bobSigner, bobStoredChannel, bobPool, 468 lnwallet.WithLeafStore(&lnwallet.MockAuxLeafStore{}), 469 lnwallet.WithAuxSigner(signerMock), 470 ) 471 if err != nil { 472 return nil, fmt.Errorf("unable to create new "+ 473 "channel: %w", err) 474 } 475 return newBobChannel, nil 476 } 477 478 testLightningChannelAlice := &testLightningChannel{ 479 channel: channelAlice, 480 restore: restoreAlice, 481 } 482 483 testLightningChannelBob := &testLightningChannel{ 484 channel: channelBob, 485 restore: restoreBob, 486 } 487 488 return testLightningChannelAlice, testLightningChannelBob, nil 489 } 490 491 // getChanID retrieves the channel point from an lnnwire message. 492 func getChanID(msg lnwire.Message) (lnwire.ChannelID, error) { 493 var chanID lnwire.ChannelID 494 switch msg := msg.(type) { 495 case *lnwire.UpdateAddHTLC: 496 chanID = msg.ChanID 497 case *lnwire.UpdateFulfillHTLC: 498 chanID = msg.ChanID 499 case *lnwire.UpdateFailHTLC: 500 chanID = msg.ChanID 501 case *lnwire.RevokeAndAck: 502 chanID = msg.ChanID 503 case *lnwire.CommitSig: 504 chanID = msg.ChanID 505 case *lnwire.ChannelReestablish: 506 chanID = msg.ChanID 507 case *lnwire.ChannelReady: 508 chanID = msg.ChanID 509 case *lnwire.UpdateFee: 510 chanID = msg.ChanID 511 default: 512 return chanID, fmt.Errorf("unknown type: %T", msg) 513 } 514 515 return chanID, nil 516 } 517 518 // generateHoldPayment generates the htlc add request by given path blob and 519 // invoice which should be added by destination peer. 520 func generatePaymentWithPreimage(invoiceAmt, htlcAmt lnwire.MilliSatoshi, 521 timelock uint32, blob [lnwire.OnionPacketSize]byte, 522 preimage *lntypes.Preimage, rhash, payAddr [32]byte) ( 523 *invoices.Invoice, *lnwire.UpdateAddHTLC, uint64, error) { 524 525 // Create the db invoice. Normally the payment requests needs to be set, 526 // because it is decoded in InvoiceRegistry to obtain the cltv expiry. 527 // But because the mock registry used in tests is mocking the decode 528 // step and always returning the value of testInvoiceCltvExpiry, we 529 // don't need to bother here with creating and signing a payment 530 // request. 531 532 invoice := &invoices.Invoice{ 533 CreationDate: time.Now(), 534 Terms: invoices.ContractTerm{ 535 FinalCltvDelta: testInvoiceCltvExpiry, 536 Value: invoiceAmt, 537 PaymentPreimage: preimage, 538 PaymentAddr: payAddr, 539 Features: lnwire.NewFeatureVector( 540 nil, lnwire.Features, 541 ), 542 }, 543 HodlInvoice: preimage == nil, 544 } 545 546 htlc := &lnwire.UpdateAddHTLC{ 547 PaymentHash: rhash, 548 Amount: htlcAmt, 549 Expiry: timelock, 550 OnionBlob: blob, 551 } 552 553 pid, err := generateRandomBytes(8) 554 if err != nil { 555 return nil, nil, 0, err 556 } 557 paymentID := binary.BigEndian.Uint64(pid) 558 559 return invoice, htlc, paymentID, nil 560 } 561 562 // generatePayment generates the htlc add request by given path blob and 563 // invoice which should be added by destination peer. 564 func generatePayment(invoiceAmt, htlcAmt lnwire.MilliSatoshi, timelock uint32, 565 blob [lnwire.OnionPacketSize]byte) (*invoices.Invoice, 566 *lnwire.UpdateAddHTLC, uint64, error) { 567 568 var preimage lntypes.Preimage 569 r, err := generateRandomBytes(sha256.Size) 570 if err != nil { 571 return nil, nil, 0, err 572 } 573 copy(preimage[:], r) 574 575 rhash := sha256.Sum256(preimage[:]) 576 577 var payAddr [sha256.Size]byte 578 r, err = generateRandomBytes(sha256.Size) 579 if err != nil { 580 return nil, nil, 0, err 581 } 582 copy(payAddr[:], r) 583 584 return generatePaymentWithPreimage( 585 invoiceAmt, htlcAmt, timelock, blob, &preimage, rhash, payAddr, 586 ) 587 } 588 589 // generateRoute generates the path blob by given array of peers. 590 func generateRoute(hops ...*hop.Payload) ( 591 [lnwire.OnionPacketSize]byte, error) { 592 593 var blob [lnwire.OnionPacketSize]byte 594 if len(hops) == 0 { 595 return blob, errors.New("empty path") 596 } 597 598 iterator := newMockHopIterator(hops...) 599 600 w := bytes.NewBuffer(blob[0:0]) 601 if err := iterator.EncodeNextHop(w); err != nil { 602 return blob, err 603 } 604 605 return blob, nil 606 607 } 608 609 // threeHopNetwork is used for managing the created cluster of 3 hops. 610 type threeHopNetwork struct { 611 aliceServer *mockServer 612 aliceChannelLink *channelLink 613 aliceOnionDecoder *mockIteratorDecoder 614 615 bobServer *mockServer 616 firstBobChannelLink *channelLink 617 secondBobChannelLink *channelLink 618 bobOnionDecoder *mockIteratorDecoder 619 620 carolServer *mockServer 621 carolChannelLink *channelLink 622 carolOnionDecoder *mockIteratorDecoder 623 624 hopNetwork 625 } 626 627 // generateHops creates the per hop payload, the total amount to be sent, and 628 // also the time lock value needed to route an HTLC with the target amount over 629 // the specified path. 630 func generateHops(payAmt lnwire.MilliSatoshi, startingHeight uint32, 631 path ...*channelLink) (lnwire.MilliSatoshi, uint32, []*hop.Payload) { 632 633 totalTimelock := startingHeight 634 runningAmt := payAmt 635 636 hops := make([]*hop.Payload, len(path)) 637 for i := len(path) - 1; i >= 0; i-- { 638 // If this is the last hop, then the next hop is the special 639 // "exit node". Otherwise, we look to the "prior" hop. 640 nextHop := hop.Exit 641 if i != len(path)-1 { 642 nextHop = path[i+1].channel.ShortChanID() 643 } 644 645 var timeLock uint32 646 // If this is the last, hop, then the time lock will be their 647 // specified delta policy plus our starting height. 648 if i == len(path)-1 { 649 totalTimelock += testInvoiceCltvExpiry 650 timeLock = totalTimelock 651 } else { 652 // Otherwise, the outgoing time lock should be the 653 // incoming timelock minus their specified delta. 654 delta := path[i+1].cfg.FwrdingPolicy.TimeLockDelta 655 totalTimelock += delta 656 timeLock = totalTimelock - delta 657 } 658 659 // Finally, we'll need to calculate the amount to forward. For 660 // the last hop, it's just the payment amount. 661 amount := payAmt 662 if i != len(path)-1 { 663 prevHop := hops[i+1] 664 prevAmount := prevHop.ForwardingInfo().AmountToForward 665 666 fee := ExpectedFee(path[i].cfg.FwrdingPolicy, prevAmount) 667 runningAmt += fee 668 669 // Otherwise, for a node to forward an HTLC, then 670 // following inequality most hold true: 671 // * amt_in - fee >= amt_to_forward 672 amount = runningAmt - fee 673 } 674 675 var nextHopBytes [8]byte 676 binary.BigEndian.PutUint64(nextHopBytes[:], nextHop.ToUint64()) 677 678 hops[i] = hop.NewLegacyPayload(&sphinx.HopData{ 679 Realm: [1]byte{}, // hop.BitcoinNetwork 680 NextAddress: nextHopBytes, 681 ForwardAmount: uint64(amount), 682 OutgoingCltv: timeLock, 683 }) 684 } 685 686 return runningAmt, totalTimelock, hops 687 } 688 689 type paymentResponse struct { 690 rhash lntypes.Hash 691 err chan error 692 } 693 694 func (r *paymentResponse) Wait(d time.Duration) (lntypes.Hash, error) { 695 return r.rhash, waitForPaymentResult(r.err, d) 696 } 697 698 // waitForPaymentResult waits for either an error to be received on c or a 699 // timeout. 700 func waitForPaymentResult(c chan error, d time.Duration) error { 701 select { 702 case err := <-c: 703 close(c) 704 return err 705 case <-time.After(d): 706 return errors.New("htlc was not settled in time") 707 } 708 } 709 710 // waitForPayFuncResult executes the given function and waits for a result with 711 // a timeout. 712 func waitForPayFuncResult(payFunc func() error, d time.Duration) error { 713 errChan := make(chan error) 714 go func() { 715 errChan <- payFunc() 716 }() 717 718 return waitForPaymentResult(errChan, d) 719 } 720 721 // makePayment takes the destination node and amount as input, sends the 722 // payment and returns the error channel to wait for error to be received and 723 // invoice in order to check its status after the payment finished. 724 // 725 // With this function you can send payments: 726 // * from Alice to Bob 727 // * from Alice to Carol through the Bob 728 // * from Alice to some another peer through the Bob 729 func makePayment(sendingPeer, receivingPeer lnpeer.Peer, 730 firstHop lnwire.ShortChannelID, hops []*hop.Payload, 731 invoiceAmt, htlcAmt lnwire.MilliSatoshi, 732 timelock uint32) *paymentResponse { 733 734 paymentErr := make(chan error, 1) 735 var rhash lntypes.Hash 736 737 invoice, payFunc, err := preparePayment(sendingPeer, receivingPeer, 738 firstHop, hops, invoiceAmt, htlcAmt, timelock, 739 ) 740 if err != nil { 741 paymentErr <- err 742 return &paymentResponse{ 743 rhash: rhash, 744 err: paymentErr, 745 } 746 } 747 748 rhash = invoice.Terms.PaymentPreimage.Hash() 749 750 // Send payment and expose err channel. 751 go func() { 752 paymentErr <- payFunc() 753 }() 754 755 return &paymentResponse{ 756 rhash: rhash, 757 err: paymentErr, 758 } 759 } 760 761 // preparePayment creates an invoice at the receivingPeer and returns a function 762 // that, when called, launches the payment from the sendingPeer. 763 func preparePayment(sendingPeer, receivingPeer lnpeer.Peer, 764 firstHop lnwire.ShortChannelID, hops []*hop.Payload, 765 invoiceAmt, htlcAmt lnwire.MilliSatoshi, 766 timelock uint32) (*invoices.Invoice, func() error, error) { 767 768 sender := sendingPeer.(*mockServer) 769 receiver := receivingPeer.(*mockServer) 770 771 // Generate route convert it to blob, and return next destination for 772 // htlc add request. 773 blob, err := generateRoute(hops...) 774 if err != nil { 775 return nil, nil, err 776 } 777 778 // Generate payment: invoice and htlc. 779 invoice, htlc, pid, err := generatePayment( 780 invoiceAmt, htlcAmt, timelock, blob, 781 ) 782 if err != nil { 783 return nil, nil, err 784 } 785 786 // Check who is last in the route and add invoice to server registry. 787 hash := invoice.Terms.PaymentPreimage.Hash() 788 if err := receiver.registry.AddInvoice( 789 context.Background(), *invoice, hash, 790 ); err != nil { 791 return nil, nil, err 792 } 793 794 // Send payment and expose err channel. 795 return invoice, func() error { 796 err := sender.htlcSwitch.SendHTLC( 797 firstHop, pid, htlc, 798 ) 799 if err != nil { 800 return err 801 } 802 resultChan, err := sender.htlcSwitch.GetAttemptResult( 803 pid, hash, newMockDeobfuscator(), 804 ) 805 if err != nil { 806 return err 807 } 808 809 result, ok := <-resultChan 810 if !ok { 811 return fmt.Errorf("shutting down") 812 } 813 814 if result.Error != nil { 815 return result.Error 816 } 817 818 return nil 819 }, nil 820 } 821 822 // start starts the three hop network alice,bob,carol servers. 823 func (n *threeHopNetwork) start() error { 824 if err := n.aliceServer.Start(); err != nil { 825 return err 826 } 827 if err := n.bobServer.Start(); err != nil { 828 return err 829 } 830 if err := n.carolServer.Start(); err != nil { 831 return err 832 } 833 834 return waitLinksEligible(map[string]*channelLink{ 835 "alice": n.aliceChannelLink, 836 "bob first": n.firstBobChannelLink, 837 "bob second": n.secondBobChannelLink, 838 "carol": n.carolChannelLink, 839 }) 840 } 841 842 // stop stops nodes and cleanup its databases. 843 func (n *threeHopNetwork) stop() { 844 done := make(chan struct{}) 845 go func() { 846 n.aliceServer.Stop() 847 done <- struct{}{} 848 }() 849 850 go func() { 851 n.bobServer.Stop() 852 done <- struct{}{} 853 }() 854 855 go func() { 856 n.carolServer.Stop() 857 done <- struct{}{} 858 }() 859 860 for i := 0; i < 3; i++ { 861 <-done 862 } 863 } 864 865 type clusterChannels struct { 866 aliceToBob *lnwallet.LightningChannel 867 bobToAlice *lnwallet.LightningChannel 868 bobToCarol *lnwallet.LightningChannel 869 carolToBob *lnwallet.LightningChannel 870 } 871 872 // createClusterChannels creates lightning channels which are needed for 873 // network cluster to be initialized. 874 func createClusterChannels(t *testing.T, aliceToBob, bobToCarol btcutil.Amount) ( 875 *clusterChannels, func() (*clusterChannels, error), error) { 876 877 _, _, firstChanID, secondChanID := genIDs() 878 879 // Create lightning channels between Alice<->Bob and Bob<->Carol 880 aliceChannel, firstBobChannel, err := createTestChannel(t, alicePrivKey, 881 bobPrivKey, aliceToBob, aliceToBob, 0, 0, firstChanID, 882 ) 883 if err != nil { 884 return nil, nil, fmt.Errorf("unable to create "+ 885 "alice<->bob channel: %w", err) 886 } 887 888 secondBobChannel, carolChannel, err := createTestChannel(t, bobPrivKey, 889 carolPrivKey, bobToCarol, bobToCarol, 0, 0, secondChanID, 890 ) 891 if err != nil { 892 return nil, nil, fmt.Errorf("unable to create "+ 893 "bob<->carol channel: %w", err) 894 } 895 896 restoreFromDb := func() (*clusterChannels, error) { 897 898 a2b, err := aliceChannel.restore() 899 if err != nil { 900 return nil, err 901 } 902 903 b2a, err := firstBobChannel.restore() 904 if err != nil { 905 return nil, err 906 } 907 908 b2c, err := secondBobChannel.restore() 909 if err != nil { 910 return nil, err 911 } 912 913 c2b, err := carolChannel.restore() 914 if err != nil { 915 return nil, err 916 } 917 918 return &clusterChannels{ 919 aliceToBob: a2b, 920 bobToAlice: b2a, 921 bobToCarol: b2c, 922 carolToBob: c2b, 923 }, nil 924 } 925 926 return &clusterChannels{ 927 aliceToBob: aliceChannel.channel, 928 bobToAlice: firstBobChannel.channel, 929 bobToCarol: secondBobChannel.channel, 930 carolToBob: carolChannel.channel, 931 }, restoreFromDb, nil 932 } 933 934 // newThreeHopNetwork function creates the following topology and returns the 935 // control object to manage this cluster: 936 // 937 // alice bob carol 938 // server - <-connection-> - server - - <-connection-> - - - server 939 // 940 // | | | 941 // 942 // alice htlc bob htlc carol htlc 943 // switch switch \ switch 944 // 945 // | | \ | 946 // | | \ | 947 // 948 // alice first bob second bob carol 949 // channel link channel link channel link channel link 950 // 951 // This function takes server options which can be used to apply custom 952 // settings to alice, bob and carol. 953 func newThreeHopNetwork(t testing.TB, aliceChannel, firstBobChannel, 954 secondBobChannel, carolChannel *lnwallet.LightningChannel, 955 startingHeight uint32, opts ...serverOption) *threeHopNetwork { 956 957 aliceDb := aliceChannel.State().Db.GetParentDB() 958 bobDb := firstBobChannel.State().Db.GetParentDB() 959 carolDb := carolChannel.State().Db.GetParentDB() 960 961 hopNetwork := newHopNetwork() 962 963 // Create three peers/servers. 964 aliceServer, err := newMockServer( 965 t, "alice", startingHeight, aliceDb, hopNetwork.defaultDelta, 966 ) 967 require.NoError(t, err, "unable to create alice server") 968 bobServer, err := newMockServer( 969 t, "bob", startingHeight, bobDb, hopNetwork.defaultDelta, 970 ) 971 require.NoError(t, err, "unable to create bob server") 972 carolServer, err := newMockServer( 973 t, "carol", startingHeight, carolDb, hopNetwork.defaultDelta, 974 ) 975 require.NoError(t, err, "unable to create carol server") 976 977 // Apply all additional functional options to the servers before 978 // creating any links. 979 for _, option := range opts { 980 option(aliceServer, bobServer, carolServer) 981 } 982 983 // Create mock decoder instead of sphinx one in order to mock the route 984 // which htlc should follow. 985 aliceDecoder := newMockIteratorDecoder() 986 bobDecoder := newMockIteratorDecoder() 987 carolDecoder := newMockIteratorDecoder() 988 989 aliceChannelLink, err := hopNetwork.createChannelLink(aliceServer, 990 bobServer, aliceChannel, aliceDecoder, 991 ) 992 if err != nil { 993 t.Fatal(err) 994 } 995 996 firstBobChannelLink, err := hopNetwork.createChannelLink(bobServer, 997 aliceServer, firstBobChannel, bobDecoder) 998 if err != nil { 999 t.Fatal(err) 1000 } 1001 1002 secondBobChannelLink, err := hopNetwork.createChannelLink(bobServer, 1003 carolServer, secondBobChannel, bobDecoder) 1004 if err != nil { 1005 t.Fatal(err) 1006 } 1007 1008 carolChannelLink, err := hopNetwork.createChannelLink(carolServer, 1009 bobServer, carolChannel, carolDecoder) 1010 if err != nil { 1011 t.Fatal(err) 1012 } 1013 1014 return &threeHopNetwork{ 1015 aliceServer: aliceServer, 1016 aliceChannelLink: aliceChannelLink.(*channelLink), 1017 aliceOnionDecoder: aliceDecoder, 1018 1019 bobServer: bobServer, 1020 firstBobChannelLink: firstBobChannelLink.(*channelLink), 1021 secondBobChannelLink: secondBobChannelLink.(*channelLink), 1022 bobOnionDecoder: bobDecoder, 1023 1024 carolServer: carolServer, 1025 carolChannelLink: carolChannelLink.(*channelLink), 1026 carolOnionDecoder: carolDecoder, 1027 1028 hopNetwork: *hopNetwork, 1029 } 1030 } 1031 1032 // serverOption is a function which alters the three servers created for 1033 // a three hop network to allow custom settings on each server. 1034 type serverOption func(aliceServer, bobServer, carolServer *mockServer) 1035 1036 // serverOptionWithHtlcNotifier is a functional option for the creation of 1037 // three hop network servers which allows setting of htlc notifiers. 1038 // Note that these notifiers should be started and stopped by the calling 1039 // function. 1040 func serverOptionWithHtlcNotifier(alice, bob, 1041 carol *HtlcNotifier) serverOption { 1042 1043 return func(aliceServer, bobServer, carolServer *mockServer) { 1044 aliceServer.htlcSwitch.cfg.HtlcNotifier = alice 1045 bobServer.htlcSwitch.cfg.HtlcNotifier = bob 1046 carolServer.htlcSwitch.cfg.HtlcNotifier = carol 1047 } 1048 } 1049 1050 // serverOptionRejectHtlc is the functional option for setting the reject 1051 // htlc config option in each server's switch. 1052 func serverOptionRejectHtlc(alice, bob, carol bool) serverOption { 1053 return func(aliceServer, bobServer, carolServer *mockServer) { 1054 aliceServer.htlcSwitch.cfg.RejectHTLC = alice 1055 bobServer.htlcSwitch.cfg.RejectHTLC = bob 1056 carolServer.htlcSwitch.cfg.RejectHTLC = carol 1057 } 1058 } 1059 1060 // createMirroredChannel creates two LightningChannel objects which represent 1061 // the state machines on either side of a single channel between alice and bob. 1062 func createMirroredChannel(t *testing.T, aliceToBob, 1063 bobToAlice btcutil.Amount) (*testLightningChannel, 1064 *testLightningChannel, error) { 1065 1066 _, _, firstChanID, _ := genIDs() 1067 1068 // Create lightning channels between Alice<->Bob for Alice and Bob 1069 alice, bob, err := createTestChannel(t, alicePrivKey, bobPrivKey, 1070 aliceToBob, bobToAlice, 0, 0, firstChanID, 1071 ) 1072 if err != nil { 1073 return nil, nil, fmt.Errorf("unable to create "+ 1074 "alice<->bob channel: %w", err) 1075 } 1076 1077 return alice, bob, nil 1078 } 1079 1080 // hopNetwork is the base struct for two and three hop networks 1081 type hopNetwork struct { 1082 feeEstimator *mockFeeEstimator 1083 globalPolicy models.ForwardingPolicy 1084 obfuscator hop.ErrorEncrypter 1085 1086 defaultDelta uint32 1087 } 1088 1089 func newHopNetwork() *hopNetwork { 1090 defaultDelta := uint32(6) 1091 1092 globalPolicy := models.ForwardingPolicy{ 1093 MinHTLCOut: lnwire.NewMSatFromSatoshis(5), 1094 BaseFee: lnwire.NewMSatFromSatoshis(1), 1095 TimeLockDelta: defaultDelta, 1096 } 1097 obfuscator := NewMockObfuscator() 1098 1099 return &hopNetwork{ 1100 feeEstimator: newMockFeeEstimator(), 1101 globalPolicy: globalPolicy, 1102 obfuscator: obfuscator, 1103 defaultDelta: defaultDelta, 1104 } 1105 } 1106 1107 func (h *hopNetwork) createChannelLink(server, peer *mockServer, 1108 channel *lnwallet.LightningChannel, 1109 decoder *mockIteratorDecoder) (ChannelLink, error) { 1110 1111 const ( 1112 fwdPkgTimeout = 15 * time.Second 1113 minFeeUpdateTimeout = 30 * time.Minute 1114 maxFeeUpdateTimeout = 40 * time.Minute 1115 ) 1116 1117 notifyUpdateChan := make(chan *contractcourt.ContractUpdate) 1118 doneChan := make(chan struct{}) 1119 notifyContractUpdate := func(u *contractcourt.ContractUpdate) error { 1120 select { 1121 case notifyUpdateChan <- u: 1122 case <-doneChan: 1123 } 1124 1125 return nil 1126 } 1127 1128 getAliases := func( 1129 base lnwire.ShortChannelID) []lnwire.ShortChannelID { 1130 1131 return nil 1132 } 1133 1134 forwardPackets := func(linkQuit <-chan struct{}, _ bool, 1135 packets ...*htlcPacket) error { 1136 1137 return server.htlcSwitch.ForwardPackets(linkQuit, packets...) 1138 } 1139 1140 //nolint:ll 1141 link := NewChannelLink( 1142 ChannelLinkConfig{ 1143 BestHeight: server.htlcSwitch.BestHeight, 1144 FwrdingPolicy: h.globalPolicy, 1145 Peer: peer, 1146 Circuits: server.htlcSwitch.CircuitModifier(), 1147 ForwardPackets: forwardPackets, 1148 DecodeHopIterators: decoder.DecodeHopIterators, 1149 ExtractErrorEncrypter: func(*btcec.PublicKey) ( 1150 hop.ErrorEncrypter, lnwire.FailCode) { 1151 return h.obfuscator, lnwire.CodeNone 1152 }, 1153 FetchLastChannelUpdate: mockGetChanUpdateMessage, 1154 Registry: server.registry, 1155 FeeEstimator: h.feeEstimator, 1156 PreimageCache: server.pCache, 1157 UpdateContractSignals: func(*contractcourt.ContractSignals) error { 1158 return nil 1159 }, 1160 NotifyContractUpdate: notifyContractUpdate, 1161 ChainEvents: &contractcourt.ChainEventSubscription{}, 1162 SyncStates: true, 1163 BatchSize: 10, 1164 BatchTicker: ticker.NewForce(testBatchTimeout), 1165 FwdPkgGCTicker: ticker.NewForce(fwdPkgTimeout), 1166 PendingCommitTicker: ticker.New(2 * time.Minute), 1167 MinUpdateTimeout: minFeeUpdateTimeout, 1168 MaxUpdateTimeout: maxFeeUpdateTimeout, 1169 OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {}, 1170 OutgoingCltvRejectDelta: 3, 1171 MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, 1172 MaxFeeAllocation: DefaultMaxLinkFeeAllocation, 1173 MaxAnchorsCommitFeeRate: chainfee.SatPerKVByte(10 * 1000).FeePerKWeight(), 1174 NotifyActiveLink: func(wire.OutPoint) {}, 1175 NotifyActiveChannel: func(wire.OutPoint) {}, 1176 NotifyInactiveChannel: func(wire.OutPoint) {}, 1177 NotifyInactiveLinkEvent: func(wire.OutPoint) {}, 1178 NotifyChannelUpdate: func(*channeldb.OpenChannel) {}, 1179 HtlcNotifier: server.htlcSwitch.cfg.HtlcNotifier, 1180 GetAliases: getAliases, 1181 ShouldFwdExpAccountability: func() bool { return true }, 1182 }, 1183 channel, 1184 ) 1185 if err := server.htlcSwitch.AddLink(link); err != nil { 1186 return nil, fmt.Errorf("unable to add channel link: %w", err) 1187 } 1188 1189 go func() { 1190 if chanLink, ok := link.(*channelLink); ok { 1191 for { 1192 select { 1193 case <-notifyUpdateChan: 1194 case <-chanLink.cg.Done(): 1195 close(doneChan) 1196 return 1197 } 1198 } 1199 } 1200 }() 1201 1202 return link, nil 1203 } 1204 1205 // twoHopNetwork is used for managing the created cluster of 2 hops. 1206 type twoHopNetwork struct { 1207 hopNetwork 1208 1209 aliceServer *mockServer 1210 aliceChannelLink *channelLink 1211 1212 bobServer *mockServer 1213 bobChannelLink *channelLink 1214 } 1215 1216 // newTwoHopNetwork function creates and starts the following topology and 1217 // returns the control object to manage this cluster: 1218 // 1219 // alice bob 1220 // server - <-connection-> - server 1221 // 1222 // | | 1223 // 1224 // alice htlc bob htlc 1225 // switch switch 1226 // 1227 // | | 1228 // | | 1229 // 1230 // alice bob 1231 // channel link channel link. 1232 func newTwoHopNetwork(t testing.TB, 1233 aliceChannel, bobChannel *lnwallet.LightningChannel, 1234 startingHeight uint32) *twoHopNetwork { 1235 1236 aliceDb := aliceChannel.State().Db.GetParentDB() 1237 bobDb := bobChannel.State().Db.GetParentDB() 1238 1239 hopNetwork := newHopNetwork() 1240 1241 // Create two peers/servers. 1242 aliceServer, err := newMockServer( 1243 t, "alice", startingHeight, aliceDb, hopNetwork.defaultDelta, 1244 ) 1245 require.NoError(t, err, "unable to create alice server") 1246 bobServer, err := newMockServer( 1247 t, "bob", startingHeight, bobDb, hopNetwork.defaultDelta, 1248 ) 1249 require.NoError(t, err, "unable to create bob server") 1250 1251 // Create mock decoder instead of sphinx one in order to mock the route 1252 // which htlc should follow. 1253 aliceDecoder := newMockIteratorDecoder() 1254 bobDecoder := newMockIteratorDecoder() 1255 1256 aliceChannelLink, err := hopNetwork.createChannelLink( 1257 aliceServer, bobServer, aliceChannel, aliceDecoder, 1258 ) 1259 if err != nil { 1260 t.Fatal(err) 1261 } 1262 1263 bobChannelLink, err := hopNetwork.createChannelLink( 1264 bobServer, aliceServer, bobChannel, bobDecoder, 1265 ) 1266 if err != nil { 1267 t.Fatal(err) 1268 } 1269 1270 n := &twoHopNetwork{ 1271 aliceServer: aliceServer, 1272 aliceChannelLink: aliceChannelLink.(*channelLink), 1273 1274 bobServer: bobServer, 1275 bobChannelLink: bobChannelLink.(*channelLink), 1276 1277 hopNetwork: *hopNetwork, 1278 } 1279 1280 require.NoError(t, n.start()) 1281 t.Cleanup(n.stop) 1282 1283 return n 1284 } 1285 1286 // start starts the two hop network alice,bob servers. 1287 func (n *twoHopNetwork) start() error { 1288 if err := n.aliceServer.Start(); err != nil { 1289 return err 1290 } 1291 if err := n.bobServer.Start(); err != nil { 1292 n.aliceServer.Stop() 1293 return err 1294 } 1295 1296 return waitLinksEligible(map[string]*channelLink{ 1297 "alice": n.aliceChannelLink, 1298 "bob": n.bobChannelLink, 1299 }) 1300 } 1301 1302 // stop stops nodes and cleanup its databases. 1303 func (n *twoHopNetwork) stop() { 1304 done := make(chan struct{}) 1305 go func() { 1306 n.aliceServer.Stop() 1307 done <- struct{}{} 1308 }() 1309 1310 go func() { 1311 n.bobServer.Stop() 1312 done <- struct{}{} 1313 }() 1314 1315 for i := 0; i < 2; i++ { 1316 <-done 1317 } 1318 } 1319 1320 func (n *twoHopNetwork) makeHoldPayment(sendingPeer, receivingPeer lnpeer.Peer, 1321 firstHop lnwire.ShortChannelID, hops []*hop.Payload, 1322 invoiceAmt, htlcAmt lnwire.MilliSatoshi, 1323 timelock uint32, preimage lntypes.Preimage) chan error { 1324 1325 paymentErr := make(chan error, 1) 1326 1327 sender := sendingPeer.(*mockServer) 1328 receiver := receivingPeer.(*mockServer) 1329 1330 // Generate route convert it to blob, and return next destination for 1331 // htlc add request. 1332 blob, err := generateRoute(hops...) 1333 if err != nil { 1334 paymentErr <- err 1335 return paymentErr 1336 } 1337 1338 rhash := preimage.Hash() 1339 1340 var payAddr [32]byte 1341 if _, err := crand.Read(payAddr[:]); err != nil { 1342 panic(err) 1343 } 1344 1345 // Generate payment: invoice and htlc. 1346 invoice, htlc, pid, err := generatePaymentWithPreimage( 1347 invoiceAmt, htlcAmt, timelock, blob, 1348 nil, rhash, payAddr, 1349 ) 1350 if err != nil { 1351 paymentErr <- err 1352 return paymentErr 1353 } 1354 1355 // Check who is last in the route and add invoice to server registry. 1356 if err := receiver.registry.AddInvoice( 1357 context.Background(), *invoice, rhash, 1358 ); err != nil { 1359 paymentErr <- err 1360 return paymentErr 1361 } 1362 1363 // Send payment and expose err channel. 1364 err = sender.htlcSwitch.SendHTLC(firstHop, pid, htlc) 1365 if err != nil { 1366 paymentErr <- err 1367 return paymentErr 1368 } 1369 1370 go func() { 1371 resultChan, err := sender.htlcSwitch.GetAttemptResult( 1372 pid, rhash, newMockDeobfuscator(), 1373 ) 1374 if err != nil { 1375 paymentErr <- err 1376 return 1377 } 1378 1379 result, ok := <-resultChan 1380 if !ok { 1381 paymentErr <- fmt.Errorf("shutting down") 1382 return 1383 } 1384 1385 if result.Error != nil { 1386 paymentErr <- result.Error 1387 return 1388 } 1389 paymentErr <- nil 1390 }() 1391 1392 return paymentErr 1393 } 1394 1395 // waitLinksEligible blocks until all links the provided name-to-link map are 1396 // eligible to forward HTLCs. 1397 func waitLinksEligible(links map[string]*channelLink) error { 1398 return wait.NoError(func() error { 1399 for name, link := range links { 1400 if link.EligibleToForward() { 1401 continue 1402 } 1403 return fmt.Errorf("%s channel link not eligible", name) 1404 } 1405 return nil 1406 }, 3*time.Second) 1407 } 1408 1409 // timeout implements a test level timeout. 1410 func timeout() func() { 1411 done := make(chan struct{}) 1412 go func() { 1413 select { 1414 case <-time.After(20 * time.Second): 1415 pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) 1416 1417 panic("test timeout") 1418 case <-done: 1419 } 1420 }() 1421 1422 return func() { 1423 close(done) 1424 } 1425 }