You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

595 lines
17 KiB

  1. package loop
  2. import (
  3. "context"
  4. "errors"
  5. "reflect"
  6. "testing"
  7. "time"
  8. "github.com/btcsuite/btcd/blockchain"
  9. "github.com/btcsuite/btcd/wire"
  10. "github.com/btcsuite/btcutil"
  11. "github.com/lightninglabs/lndclient"
  12. "github.com/lightninglabs/loop/loopdb"
  13. "github.com/lightninglabs/loop/sweep"
  14. "github.com/lightninglabs/loop/test"
  15. "github.com/lightningnetwork/lnd/lnrpc"
  16. "github.com/lightningnetwork/lnd/lnwallet/chainfee"
  17. "github.com/stretchr/testify/require"
  18. )
  19. // TestLoopOutPaymentParameters tests the first part of the loop out process up
  20. // to the point where the off-chain payments are made.
  21. func TestLoopOutPaymentParameters(t *testing.T) {
  22. defer test.Guard(t)()
  23. // Set up test context objects.
  24. lnd := test.NewMockLnd()
  25. ctx := test.NewContext(t, lnd)
  26. server := newServerMock(lnd)
  27. store := newStoreMock(t)
  28. expiryChan := make(chan time.Time)
  29. timerFactory := func(_ time.Duration) <-chan time.Time {
  30. return expiryChan
  31. }
  32. height := int32(600)
  33. cfg := &swapConfig{
  34. lnd: &lnd.LndServices,
  35. store: store,
  36. server: server,
  37. }
  38. sweeper := &sweep.Sweeper{Lnd: &lnd.LndServices}
  39. blockEpochChan := make(chan interface{})
  40. statusChan := make(chan SwapInfo)
  41. const maxParts = 5
  42. // Initiate the swap.
  43. req := *testRequest
  44. req.OutgoingChanSet = loopdb.ChannelSet{2, 3}
  45. initResult, err := newLoopOutSwap(
  46. context.Background(), cfg, height, &req,
  47. )
  48. if err != nil {
  49. t.Fatal(err)
  50. }
  51. swap := initResult.swap
  52. // Execute the swap in its own goroutine.
  53. errChan := make(chan error)
  54. swapCtx, cancel := context.WithCancel(context.Background())
  55. go func() {
  56. err := swap.execute(swapCtx, &executeConfig{
  57. statusChan: statusChan,
  58. sweeper: sweeper,
  59. blockEpochChan: blockEpochChan,
  60. timerFactory: timerFactory,
  61. loopOutMaxParts: maxParts,
  62. }, height)
  63. if err != nil {
  64. log.Error(err)
  65. }
  66. errChan <- err
  67. }()
  68. store.assertLoopOutStored()
  69. state := <-statusChan
  70. if state.State != loopdb.StateInitiated {
  71. t.Fatal("unexpected state")
  72. }
  73. // Intercept the swap and prepay payments. Order is undefined.
  74. payments := []test.RouterPaymentChannelMessage{
  75. <-ctx.Lnd.RouterSendPaymentChannel,
  76. <-ctx.Lnd.RouterSendPaymentChannel,
  77. }
  78. // Find the swap payment.
  79. var swapPayment test.RouterPaymentChannelMessage
  80. for _, p := range payments {
  81. if p.Invoice == swap.SwapInvoice {
  82. swapPayment = p
  83. }
  84. }
  85. // Assert that it is sent as a multi-part payment.
  86. if swapPayment.MaxParts != maxParts {
  87. t.Fatalf("Expected %v parts, but got %v",
  88. maxParts, swapPayment.MaxParts)
  89. }
  90. // Verify the outgoing channel set restriction.
  91. if !reflect.DeepEqual(
  92. []uint64(req.OutgoingChanSet), swapPayment.OutgoingChanIds,
  93. ) {
  94. t.Fatalf("Unexpected outgoing channel set")
  95. }
  96. // Swap is expected to register for confirmation of the htlc. Assert
  97. // this to prevent a blocked channel in the mock.
  98. ctx.AssertRegisterConf(false, defaultConfirmations)
  99. // Cancel the swap. There is nothing else we need to assert. The payment
  100. // parameters don't play a role in the remainder of the swap process.
  101. cancel()
  102. // Expect the swap to signal that it was cancelled.
  103. err = <-errChan
  104. if err != context.Canceled {
  105. t.Fatal(err)
  106. }
  107. }
  108. // TestLateHtlcPublish tests that the client is not revealing the preimage if
  109. // there are not enough blocks left.
  110. func TestLateHtlcPublish(t *testing.T) {
  111. defer test.Guard(t)()
  112. lnd := test.NewMockLnd()
  113. ctx := test.NewContext(t, lnd)
  114. server := newServerMock(lnd)
  115. store := newStoreMock(t)
  116. expiryChan := make(chan time.Time)
  117. timerFactory := func(expiry time.Duration) <-chan time.Time {
  118. return expiryChan
  119. }
  120. height := int32(600)
  121. cfg := newSwapConfig(&lnd.LndServices, store, server)
  122. testRequest.Expiry = height + testLoopOutMinOnChainCltvDelta
  123. initResult, err := newLoopOutSwap(
  124. context.Background(), cfg, height, testRequest,
  125. )
  126. if err != nil {
  127. t.Fatal(err)
  128. }
  129. swap := initResult.swap
  130. sweeper := &sweep.Sweeper{Lnd: &lnd.LndServices}
  131. blockEpochChan := make(chan interface{})
  132. statusChan := make(chan SwapInfo)
  133. errChan := make(chan error)
  134. go func() {
  135. err := swap.execute(context.Background(), &executeConfig{
  136. statusChan: statusChan,
  137. sweeper: sweeper,
  138. blockEpochChan: blockEpochChan,
  139. timerFactory: timerFactory,
  140. }, height)
  141. if err != nil {
  142. log.Error(err)
  143. }
  144. errChan <- err
  145. }()
  146. store.assertLoopOutStored()
  147. state := <-statusChan
  148. if state.State != loopdb.StateInitiated {
  149. t.Fatal("unexpected state")
  150. }
  151. signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
  152. signalPrepaymentResult := ctx.AssertPaid(prepayInvoiceDesc)
  153. // Expect client to register for conf
  154. ctx.AssertRegisterConf(false, defaultConfirmations)
  155. // // Wait too long before publishing htlc.
  156. blockEpochChan <- int32(swap.CltvExpiry - 10)
  157. signalSwapPaymentResult(
  158. errors.New(lndclient.PaymentResultUnknownPaymentHash),
  159. )
  160. signalPrepaymentResult(
  161. errors.New(lndclient.PaymentResultUnknownPaymentHash),
  162. )
  163. store.assertStoreFinished(loopdb.StateFailTimeout)
  164. status := <-statusChan
  165. if status.State != loopdb.StateFailTimeout {
  166. t.Fatal("unexpected state")
  167. }
  168. err = <-errChan
  169. if err != nil {
  170. t.Fatal(err)
  171. }
  172. }
  173. // TestCustomSweepConfTarget ensures we are able to sweep a Loop Out HTLC with a
  174. // custom confirmation target.
  175. func TestCustomSweepConfTarget(t *testing.T) {
  176. defer test.Guard(t)()
  177. lnd := test.NewMockLnd()
  178. ctx := test.NewContext(t, lnd)
  179. server := newServerMock(lnd)
  180. // Use the highest sweep confirmation target before we attempt to use
  181. // the default.
  182. testReq := *testRequest
  183. testReq.SweepConfTarget = testLoopOutMinOnChainCltvDelta -
  184. DefaultSweepConfTargetDelta - 1
  185. // Set up custom fee estimates such that the lower confirmation target
  186. // yields a much higher fee rate.
  187. ctx.Lnd.SetFeeEstimate(testReq.SweepConfTarget, 250)
  188. ctx.Lnd.SetFeeEstimate(DefaultSweepConfTarget, 10000)
  189. cfg := newSwapConfig(
  190. &lnd.LndServices, newStoreMock(t), server,
  191. )
  192. initResult, err := newLoopOutSwap(
  193. context.Background(), cfg, ctx.Lnd.Height, &testReq,
  194. )
  195. if err != nil {
  196. t.Fatal(err)
  197. }
  198. swap := initResult.swap
  199. // Set up the required dependencies to execute the swap.
  200. //
  201. // TODO: create test context similar to loopInTestContext.
  202. sweeper := &sweep.Sweeper{Lnd: &lnd.LndServices}
  203. blockEpochChan := make(chan interface{})
  204. statusChan := make(chan SwapInfo)
  205. expiryChan := make(chan time.Time)
  206. timerFactory := func(expiry time.Duration) <-chan time.Time {
  207. return expiryChan
  208. }
  209. errChan := make(chan error)
  210. go func() {
  211. err := swap.execute(context.Background(), &executeConfig{
  212. statusChan: statusChan,
  213. blockEpochChan: blockEpochChan,
  214. timerFactory: timerFactory,
  215. sweeper: sweeper,
  216. }, ctx.Lnd.Height)
  217. if err != nil {
  218. log.Error(err)
  219. }
  220. errChan <- err
  221. }()
  222. // The swap should be found in its initial state.
  223. cfg.store.(*storeMock).assertLoopOutStored()
  224. state := <-statusChan
  225. if state.State != loopdb.StateInitiated {
  226. t.Fatal("unexpected state")
  227. }
  228. // We'll then pay both the swap and prepay invoice, which should trigger
  229. // the server to publish the on-chain HTLC.
  230. signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
  231. signalPrepaymentResult := ctx.AssertPaid(prepayInvoiceDesc)
  232. signalSwapPaymentResult(nil)
  233. signalPrepaymentResult(nil)
  234. // Notify the confirmation notification for the HTLC.
  235. ctx.AssertRegisterConf(false, defaultConfirmations)
  236. blockEpochChan <- ctx.Lnd.Height + 1
  237. htlcTx := wire.NewMsgTx(2)
  238. htlcTx.AddTxOut(&wire.TxOut{
  239. Value: int64(swap.AmountRequested),
  240. PkScript: swap.htlc.PkScript,
  241. })
  242. ctx.NotifyConf(htlcTx)
  243. // The client should then register for a spend of the HTLC and attempt
  244. // to sweep it using the custom confirmation target.
  245. ctx.AssertRegisterSpendNtfn(swap.htlc.PkScript)
  246. // Assert that we made a query to track our payment, as required for
  247. // preimage push tracking.
  248. trackPayment := ctx.AssertTrackPayment()
  249. expiryChan <- time.Now()
  250. // Expect a signing request for the HTLC success transaction.
  251. <-ctx.Lnd.SignOutputRawChannel
  252. cfg.store.(*storeMock).assertLoopOutState(loopdb.StatePreimageRevealed)
  253. status := <-statusChan
  254. if status.State != loopdb.StatePreimageRevealed {
  255. t.Fatalf("expected state %v, got %v",
  256. loopdb.StatePreimageRevealed, status.State)
  257. }
  258. // assertSweepTx performs some sanity checks on a sweep transaction to
  259. // ensure it was constructed correctly.
  260. assertSweepTx := func(expConfTarget int32) *wire.MsgTx {
  261. t.Helper()
  262. sweepTx := ctx.ReceiveTx()
  263. if sweepTx.TxIn[0].PreviousOutPoint.Hash != htlcTx.TxHash() {
  264. t.Fatalf("expected sweep tx to spend %v, got %v",
  265. htlcTx.TxHash(), sweepTx.TxIn[0].PreviousOutPoint)
  266. }
  267. // The fee used for the sweep transaction is an estimate based
  268. // on the maximum witness size, so we should expect to see a
  269. // lower fee when using the actual witness size of the
  270. // transaction.
  271. fee := btcutil.Amount(
  272. htlcTx.TxOut[0].Value - sweepTx.TxOut[0].Value,
  273. )
  274. weight := blockchain.GetTransactionWeight(btcutil.NewTx(sweepTx))
  275. feeRate, err := ctx.Lnd.WalletKit.EstimateFee(
  276. context.Background(), expConfTarget,
  277. )
  278. if err != nil {
  279. t.Fatalf("unable to retrieve fee estimate: %v", err)
  280. }
  281. minFee := feeRate.FeeForWeight(weight)
  282. maxFee := btcutil.Amount(float64(minFee) * 1.1)
  283. if fee < minFee && fee > maxFee {
  284. t.Fatalf("expected sweep tx to have fee between %v-%v, "+
  285. "got %v", minFee, maxFee, fee)
  286. }
  287. return sweepTx
  288. }
  289. // The sweep should have a fee that corresponds to the custom
  290. // confirmation target.
  291. _ = assertSweepTx(testReq.SweepConfTarget)
  292. // Once we have published an on chain sweep, we expect a preimage to
  293. // have been pushed to our server.
  294. preimage := <-server.preimagePush
  295. require.Equal(t, swap.Preimage, preimage)
  296. // Now that we have pushed our preimage to the sever, we send an update
  297. // indicating that our off chain htlc is settled. We do this so that
  298. // we don't have to keep consuming preimage pushes from our server mock
  299. // for every sweep attempt.
  300. trackPayment.Updates <- lndclient.PaymentStatus{
  301. State: lnrpc.Payment_SUCCEEDED,
  302. }
  303. // We'll then notify the height at which we begin using the default
  304. // confirmation target.
  305. defaultConfTargetHeight := ctx.Lnd.Height +
  306. testLoopOutMinOnChainCltvDelta - DefaultSweepConfTargetDelta
  307. blockEpochChan <- int32(defaultConfTargetHeight)
  308. expiryChan <- time.Now()
  309. // Expect another signing request.
  310. <-ctx.Lnd.SignOutputRawChannel
  311. // We should expect to see another sweep using the higher fee since the
  312. // spend hasn't been confirmed yet.
  313. sweepTx := assertSweepTx(DefaultSweepConfTarget)
  314. // Notify the spend so that the swap reaches its final state.
  315. ctx.NotifySpend(sweepTx, 0)
  316. cfg.store.(*storeMock).assertLoopOutState(loopdb.StateSuccess)
  317. status = <-statusChan
  318. if status.State != loopdb.StateSuccess {
  319. t.Fatalf("expected state %v, got %v", loopdb.StateSuccess,
  320. status.State)
  321. }
  322. if err := <-errChan; err != nil {
  323. t.Fatal(err)
  324. }
  325. }
  326. // TestPreimagePush tests or logic that decides whether to push our preimage to
  327. // the server. First, we test the case where we have not yet disclosed our
  328. // preimage with a sweep, so we do not want to push our preimage yet. Next, we
  329. // broadcast a sweep attempt and push our preimage to the server. In this stage
  330. // we mock a server failure by not sending a settle update for our payment.
  331. // Finally, we make a last sweep attempt, push the preimage (because we have
  332. // not detected our settle) and settle the off chain htlc, indicating that the
  333. // server successfully settled using the preimage push. In this test, we need
  334. // to start with a fee rate that will be too high, then progress to an
  335. // acceptable one. We do this by starting with a high confirmation target with
  336. // a high fee, and setting the default confirmation fee (which our swap will
  337. // drop down to if it is not confirming in time) to a lower fee. This is not
  338. // intuitive (lower confs having lower fees), but it allows up to mock fee
  339. // changes.
  340. func TestPreimagePush(t *testing.T) {
  341. defer test.Guard(t)()
  342. lnd := test.NewMockLnd()
  343. ctx := test.NewContext(t, lnd)
  344. server := newServerMock(lnd)
  345. // Start with a high confirmation delta which will have a very high fee
  346. // attached to it.
  347. testReq := *testRequest
  348. testReq.SweepConfTarget = testLoopOutMinOnChainCltvDelta -
  349. DefaultSweepConfTargetDelta - 1
  350. testReq.Expiry = ctx.Lnd.Height + testLoopOutMinOnChainCltvDelta
  351. // We set our mock fee estimate for our target sweep confs to be our
  352. // max miner fee *2, so that our fee will definitely be above what we
  353. // are willing to pay, and we will not sweep.
  354. ctx.Lnd.SetFeeEstimate(
  355. testReq.SweepConfTarget, chainfee.SatPerKWeight(
  356. testReq.MaxMinerFee*2,
  357. ),
  358. )
  359. // We set the fee estimate for our default confirmation target very
  360. // low, so that once we drop down to our default confs we will start
  361. // trying to sweep the preimage.
  362. ctx.Lnd.SetFeeEstimate(DefaultSweepConfTarget, 1)
  363. cfg := newSwapConfig(
  364. &lnd.LndServices, newStoreMock(t), server,
  365. )
  366. initResult, err := newLoopOutSwap(
  367. context.Background(), cfg, ctx.Lnd.Height, &testReq,
  368. )
  369. require.NoError(t, err)
  370. swap := initResult.swap
  371. // Set up the required dependencies to execute the swap.
  372. sweeper := &sweep.Sweeper{Lnd: &lnd.LndServices}
  373. blockEpochChan := make(chan interface{})
  374. statusChan := make(chan SwapInfo)
  375. expiryChan := make(chan time.Time)
  376. timerFactory := func(_ time.Duration) <-chan time.Time {
  377. return expiryChan
  378. }
  379. errChan := make(chan error)
  380. go func() {
  381. err := swap.execute(context.Background(), &executeConfig{
  382. statusChan: statusChan,
  383. blockEpochChan: blockEpochChan,
  384. timerFactory: timerFactory,
  385. sweeper: sweeper,
  386. }, ctx.Lnd.Height)
  387. if err != nil {
  388. log.Error(err)
  389. }
  390. errChan <- err
  391. }()
  392. // The swap should be found in its initial state.
  393. cfg.store.(*storeMock).assertLoopOutStored()
  394. state := <-statusChan
  395. require.Equal(t, loopdb.StateInitiated, state.State)
  396. // We'll then pay both the swap and prepay invoice, which should trigger
  397. // the server to publish the on-chain HTLC.
  398. signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
  399. signalPrepaymentResult := ctx.AssertPaid(prepayInvoiceDesc)
  400. signalSwapPaymentResult(nil)
  401. signalPrepaymentResult(nil)
  402. // Notify the confirmation notification for the HTLC.
  403. ctx.AssertRegisterConf(false, defaultConfirmations)
  404. blockEpochChan <- ctx.Lnd.Height + 1
  405. htlcTx := wire.NewMsgTx(2)
  406. htlcTx.AddTxOut(&wire.TxOut{
  407. Value: int64(swap.AmountRequested),
  408. PkScript: swap.htlc.PkScript,
  409. })
  410. ctx.NotifyConf(htlcTx)
  411. // The client should then register for a spend of the HTLC and attempt
  412. // to sweep it using the custom confirmation target.
  413. ctx.AssertRegisterSpendNtfn(swap.htlc.PkScript)
  414. // Assert that we made a query to track our payment, as required for
  415. // preimage push tracking.
  416. trackPayment := ctx.AssertTrackPayment()
  417. // Tick the expiry channel, we are still using our client confirmation
  418. // target at this stage which has fees higher than our max acceptable
  419. // fee. We do not expect a sweep attempt at this point. Since our
  420. // preimage is not revealed, we also do not expect a preimage push.
  421. expiryChan <- testTime
  422. // Now, we notify the height at which the client will start using the
  423. // default confirmation target. This has the effect of lowering our fees
  424. // so that the client still start sweeping.
  425. defaultConfTargetHeight := ctx.Lnd.Height + testLoopOutMinOnChainCltvDelta -
  426. DefaultSweepConfTargetDelta
  427. blockEpochChan <- defaultConfTargetHeight
  428. // This time when we tick the expiry chan, our fees are lower than the
  429. // swap max, so we expect it to prompt a sweep.
  430. expiryChan <- testTime
  431. // Expect a signing request for the HTLC success transaction.
  432. <-ctx.Lnd.SignOutputRawChannel
  433. // This is the first time we have swept, so we expect our preimage
  434. // revealed state to be set.
  435. cfg.store.(*storeMock).assertLoopOutState(loopdb.StatePreimageRevealed)
  436. status := <-statusChan
  437. require.Equal(
  438. t, status.State, loopdb.StatePreimageRevealed,
  439. )
  440. // We expect the sweep tx to have been published.
  441. ctx.ReceiveTx()
  442. // Once we have published an on chain sweep, we expect a preimage to
  443. // have been pushed to the server after the sweep.
  444. preimage := <-server.preimagePush
  445. require.Equal(t, swap.Preimage, preimage)
  446. // To mock a server failure, we do not send a payment settled update
  447. // for our off chain payment yet. We also do not confirm our sweep on
  448. // chain yet so we can test our preimage push retry logic. Instead, we
  449. // tick the expiry chan again to prompt another sweep.
  450. expiryChan <- testTime
  451. // We expect another signing request for out sweep, and publish of our
  452. // sweep transaction.
  453. <-ctx.Lnd.SignOutputRawChannel
  454. ctx.ReceiveTx()
  455. // Since we have not yet been notified of an off chain settle, and we
  456. // have attempted to sweep again, we expect another preimage push
  457. // attempt.
  458. preimage = <-server.preimagePush
  459. require.Equal(t, swap.Preimage, preimage)
  460. // This time, we send a payment succeeded update into our payment stream
  461. // to reflect that the server received our preimage push and settled off
  462. // chain.
  463. trackPayment.Updates <- lndclient.PaymentStatus{
  464. State: lnrpc.Payment_SUCCEEDED,
  465. }
  466. // We tick one last time, this time expecting a sweep but no preimage
  467. // push. The test's mocked preimage channel is un-buffered, so our test
  468. // would hang if we pushed the preimage here.
  469. expiryChan <- testTime
  470. <-ctx.Lnd.SignOutputRawChannel
  471. sweepTx := ctx.ReceiveTx()
  472. // Finally, we put this swap out of its misery and notify a successful
  473. // spend our our sweepTx and assert that the swap succeeds.
  474. ctx.NotifySpend(sweepTx, 0)
  475. cfg.store.(*storeMock).assertLoopOutState(loopdb.StateSuccess)
  476. status = <-statusChan
  477. require.Equal(
  478. t, status.State, loopdb.StateSuccess,
  479. )
  480. require.NoError(t, <-errChan)
  481. }