mailbox_test.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. package htlcswitch
  2. import (
  3. prand "math/rand"
  4. "reflect"
  5. "testing"
  6. "time"
  7. "github.com/btcsuite/btcd/btcutil"
  8. "github.com/davecgh/go-spew/spew"
  9. "github.com/lightningnetwork/lnd/channeldb"
  10. "github.com/lightningnetwork/lnd/clock"
  11. "github.com/lightningnetwork/lnd/lnmock"
  12. "github.com/lightningnetwork/lnd/lnwallet/chainfee"
  13. "github.com/lightningnetwork/lnd/lnwire"
  14. "github.com/stretchr/testify/mock"
  15. "github.com/stretchr/testify/require"
  16. )
  17. const testExpiry = time.Minute
  18. // TestMailBoxCouriers tests that both aspects of the mailBox struct works
  19. // properly. Both packets and messages should be able to added to each
  20. // respective mailbox concurrently, and also messages/packets should also be
  21. // able to be received concurrently.
  22. func TestMailBoxCouriers(t *testing.T) {
  23. t.Parallel()
  24. // First, we'll create new instance of the current default mailbox
  25. // type.
  26. ctx := newMailboxContext(t, time.Now(), testExpiry)
  27. // We'll be adding 10 message of both types to the mailbox.
  28. const numPackets = 10
  29. const halfPackets = numPackets / 2
  30. // We'll add a set of random packets to the mailbox.
  31. sentPackets := make([]*htlcPacket, numPackets)
  32. for i := 0; i < numPackets; i++ {
  33. pkt := &htlcPacket{
  34. outgoingChanID: lnwire.NewShortChanIDFromInt(uint64(prand.Int63())),
  35. incomingChanID: lnwire.NewShortChanIDFromInt(uint64(prand.Int63())),
  36. amount: lnwire.MilliSatoshi(prand.Int63()),
  37. htlc: &lnwire.UpdateAddHTLC{
  38. ID: uint64(i),
  39. },
  40. }
  41. sentPackets[i] = pkt
  42. err := ctx.mailbox.AddPacket(pkt)
  43. if err != nil {
  44. t.Fatalf("unable to add packet: %v", err)
  45. }
  46. }
  47. // Next, we'll do the same, but this time adding wire messages.
  48. sentMessages := make([]lnwire.Message, numPackets)
  49. for i := 0; i < numPackets; i++ {
  50. msg := &lnwire.UpdateAddHTLC{
  51. ID: uint64(prand.Int63()),
  52. Amount: lnwire.MilliSatoshi(prand.Int63()),
  53. }
  54. sentMessages[i] = msg
  55. err := ctx.mailbox.AddMessage(msg)
  56. if err != nil {
  57. t.Fatalf("unable to add message: %v", err)
  58. }
  59. }
  60. // Now we'll attempt to read back the packets/messages we added to the
  61. // mailbox. We'll alternative reading from the message outbox vs the
  62. // packet outbox to ensure that they work concurrently properly.
  63. recvdPackets := make([]*htlcPacket, 0, numPackets)
  64. recvdMessages := make([]lnwire.Message, 0, numPackets)
  65. for i := 0; i < numPackets*2; i++ {
  66. timeout := time.After(time.Second * 5)
  67. if i%2 == 0 {
  68. select {
  69. case <-timeout:
  70. t.Fatalf("didn't recv pkt after timeout")
  71. case pkt := <-ctx.mailbox.PacketOutBox():
  72. recvdPackets = append(recvdPackets, pkt)
  73. }
  74. } else {
  75. select {
  76. case <-timeout:
  77. t.Fatalf("didn't recv message after timeout")
  78. case msg := <-ctx.mailbox.MessageOutBox():
  79. recvdMessages = append(recvdMessages, msg)
  80. }
  81. }
  82. }
  83. // The number of messages/packets we sent, and the number we received
  84. // should match exactly.
  85. if len(sentPackets) != len(recvdPackets) {
  86. t.Fatalf("expected %v packets instead got %v", len(sentPackets),
  87. len(recvdPackets))
  88. }
  89. if len(sentMessages) != len(recvdMessages) {
  90. t.Fatalf("expected %v messages instead got %v", len(sentMessages),
  91. len(recvdMessages))
  92. }
  93. // Additionally, the set of packets should match exactly, as we should
  94. // have received the packets in the exact same ordering that we added.
  95. if !reflect.DeepEqual(sentPackets, recvdPackets) {
  96. t.Fatalf("recvd packets mismatched: expected %v, got %v",
  97. spew.Sdump(sentPackets), spew.Sdump(recvdPackets))
  98. }
  99. if !reflect.DeepEqual(recvdMessages, recvdMessages) {
  100. t.Fatalf("recvd messages mismatched: expected %v, got %v",
  101. spew.Sdump(sentMessages), spew.Sdump(recvdMessages))
  102. }
  103. // Now that we've received all of the intended msgs/pkts, ack back half
  104. // of the packets.
  105. for _, recvdPkt := range recvdPackets[:halfPackets] {
  106. ctx.mailbox.AckPacket(recvdPkt.inKey())
  107. }
  108. // With the packets drained and partially acked, we reset the mailbox,
  109. // simulating a link shutting down and then coming back up.
  110. err := ctx.mailbox.ResetMessages()
  111. require.NoError(t, err, "unable to reset messages")
  112. err = ctx.mailbox.ResetPackets()
  113. require.NoError(t, err, "unable to reset packets")
  114. // Now, we'll use the same alternating strategy to read from our
  115. // mailbox. All wire messages are dropped on startup, but any unacked
  116. // packets will be replayed in the same order they were delivered
  117. // initially.
  118. recvdPackets2 := make([]*htlcPacket, 0, halfPackets)
  119. for i := 0; i < 2*halfPackets; i++ {
  120. timeout := time.After(time.Second * 5)
  121. if i%2 == 0 {
  122. select {
  123. case <-timeout:
  124. t.Fatalf("didn't recv pkt after timeout")
  125. case pkt := <-ctx.mailbox.PacketOutBox():
  126. recvdPackets2 = append(recvdPackets2, pkt)
  127. }
  128. } else {
  129. select {
  130. case <-ctx.mailbox.MessageOutBox():
  131. t.Fatalf("should not receive wire msg after reset")
  132. default:
  133. }
  134. }
  135. }
  136. // The number of packets we received should match the number of unacked
  137. // packets left in the mailbox.
  138. if halfPackets != len(recvdPackets2) {
  139. t.Fatalf("expected %v packets instead got %v", halfPackets,
  140. len(recvdPackets))
  141. }
  142. // Additionally, the set of packets should match exactly with the
  143. // unacked packets, and we should have received the packets in the exact
  144. // same ordering that we added.
  145. if !reflect.DeepEqual(recvdPackets[halfPackets:], recvdPackets2) {
  146. t.Fatalf("recvd packets mismatched: expected %v, got %v",
  147. spew.Sdump(sentPackets), spew.Sdump(recvdPackets))
  148. }
  149. }
  150. // TestMailBoxResetAfterShutdown tests that ResetMessages and ResetPackets
  151. // return ErrMailBoxShuttingDown after the mailbox has been stopped.
  152. func TestMailBoxResetAfterShutdown(t *testing.T) {
  153. t.Parallel()
  154. ctx := newMailboxContext(t, time.Now(), time.Second)
  155. // Stop the mailbox, then try to reset the message and packet couriers.
  156. ctx.mailbox.Stop()
  157. err := ctx.mailbox.ResetMessages()
  158. if err != ErrMailBoxShuttingDown {
  159. t.Fatalf("expected ErrMailBoxShuttingDown, got: %v", err)
  160. }
  161. err = ctx.mailbox.ResetPackets()
  162. if err != ErrMailBoxShuttingDown {
  163. t.Fatalf("expected ErrMailBoxShuttingDown, got: %v", err)
  164. }
  165. }
  166. type mailboxContext struct {
  167. t *testing.T
  168. mailbox MailBox
  169. clock *clock.TestClock
  170. forwards chan *htlcPacket
  171. }
  172. // newMailboxContextWithClock creates a new mailbox context with the given
  173. // mocked clock.
  174. //
  175. // TODO(yy): replace all usage of `newMailboxContext` with this method.
  176. func newMailboxContextWithClock(t *testing.T,
  177. clock clock.Clock) *mailboxContext {
  178. ctx := &mailboxContext{
  179. t: t,
  180. forwards: make(chan *htlcPacket, 1),
  181. }
  182. failMailboxUpdate := func(outScid,
  183. mboxScid lnwire.ShortChannelID) lnwire.FailureMessage {
  184. return &lnwire.FailTemporaryNodeFailure{}
  185. }
  186. ctx.mailbox = newMemoryMailBox(&mailBoxConfig{
  187. failMailboxUpdate: failMailboxUpdate,
  188. forwardPackets: ctx.forward,
  189. clock: clock,
  190. })
  191. ctx.mailbox.Start()
  192. t.Cleanup(ctx.mailbox.Stop)
  193. return ctx
  194. }
  195. func newMailboxContext(t *testing.T, startTime time.Time,
  196. expiry time.Duration) *mailboxContext {
  197. ctx := &mailboxContext{
  198. t: t,
  199. clock: clock.NewTestClock(startTime),
  200. forwards: make(chan *htlcPacket, 1),
  201. }
  202. failMailboxUpdate := func(outScid,
  203. mboxScid lnwire.ShortChannelID) lnwire.FailureMessage {
  204. return &lnwire.FailTemporaryNodeFailure{}
  205. }
  206. ctx.mailbox = newMemoryMailBox(&mailBoxConfig{
  207. failMailboxUpdate: failMailboxUpdate,
  208. forwardPackets: ctx.forward,
  209. clock: ctx.clock,
  210. expiry: expiry,
  211. })
  212. ctx.mailbox.Start()
  213. t.Cleanup(ctx.mailbox.Stop)
  214. return ctx
  215. }
  216. func (c *mailboxContext) forward(_ chan struct{},
  217. pkts ...*htlcPacket) error {
  218. for _, pkt := range pkts {
  219. c.forwards <- pkt
  220. }
  221. return nil
  222. }
  223. func (c *mailboxContext) sendAdds(start, num int) []*htlcPacket {
  224. c.t.Helper()
  225. sentPackets := make([]*htlcPacket, num)
  226. for i := 0; i < num; i++ {
  227. pkt := &htlcPacket{
  228. outgoingChanID: lnwire.NewShortChanIDFromInt(
  229. uint64(prand.Int63())),
  230. incomingChanID: lnwire.NewShortChanIDFromInt(
  231. uint64(prand.Int63())),
  232. incomingHTLCID: uint64(start + i),
  233. amount: lnwire.MilliSatoshi(prand.Int63()),
  234. htlc: &lnwire.UpdateAddHTLC{
  235. ID: uint64(start + i),
  236. },
  237. }
  238. sentPackets[i] = pkt
  239. err := c.mailbox.AddPacket(pkt)
  240. if err != nil {
  241. c.t.Fatalf("unable to add packet: %v", err)
  242. }
  243. }
  244. return sentPackets
  245. }
  246. func (c *mailboxContext) receivePkts(pkts []*htlcPacket) {
  247. c.t.Helper()
  248. for i, expPkt := range pkts {
  249. select {
  250. case pkt := <-c.mailbox.PacketOutBox():
  251. if reflect.DeepEqual(expPkt, pkt) {
  252. continue
  253. }
  254. c.t.Fatalf("inkey mismatch #%d, want: %v vs "+
  255. "got: %v", i, expPkt.inKey(), pkt.inKey())
  256. case <-time.After(50 * time.Millisecond):
  257. c.t.Fatalf("did not receive fail for index %d", i)
  258. }
  259. }
  260. }
  261. func (c *mailboxContext) checkFails(adds []*htlcPacket) {
  262. c.t.Helper()
  263. for i, add := range adds {
  264. select {
  265. case fail := <-c.forwards:
  266. if add.inKey() == fail.inKey() {
  267. continue
  268. }
  269. c.t.Fatalf("inkey mismatch #%d, add: %v vs fail: %v",
  270. i, add.inKey(), fail.inKey())
  271. case <-time.After(50 * time.Millisecond):
  272. c.t.Fatalf("did not receive fail for index %d", i)
  273. }
  274. }
  275. select {
  276. case pkt := <-c.forwards:
  277. c.t.Fatalf("unexpected forward: %v", pkt.keystone())
  278. case <-time.After(50 * time.Millisecond):
  279. }
  280. }
  281. // TestMailBoxFailAdd asserts that FailAdd returns a response to the switch
  282. // under various interleavings with other operations on the mailbox.
  283. func TestMailBoxFailAdd(t *testing.T) {
  284. var (
  285. batchDelay = time.Second
  286. expiry = time.Minute
  287. firstBatchStart = time.Now()
  288. secondBatchStart = time.Now().Add(batchDelay)
  289. thirdBatchStart = time.Now().Add(2 * batchDelay)
  290. thirdBatchExpiry = thirdBatchStart.Add(expiry)
  291. )
  292. ctx := newMailboxContext(t, firstBatchStart, expiry)
  293. failAdds := func(adds []*htlcPacket) {
  294. for _, add := range adds {
  295. ctx.mailbox.FailAdd(add)
  296. }
  297. }
  298. const numBatchPackets = 5
  299. // Send 10 adds, and pull them from the mailbox.
  300. firstBatch := ctx.sendAdds(0, numBatchPackets)
  301. ctx.receivePkts(firstBatch)
  302. // Fail all of these adds, simulating an error adding the HTLCs to the
  303. // commitment. We should see a failure message for each.
  304. go failAdds(firstBatch)
  305. ctx.checkFails(firstBatch)
  306. // As a sanity check, Fail all of them again and assert that no
  307. // duplicate fails are sent.
  308. go failAdds(firstBatch)
  309. ctx.checkFails(nil)
  310. // Now, send a second batch of adds after a short delay and deliver them
  311. // to the link.
  312. ctx.clock.SetTime(secondBatchStart)
  313. secondBatch := ctx.sendAdds(numBatchPackets, numBatchPackets)
  314. ctx.receivePkts(secondBatch)
  315. // Reset the packet queue w/o changing the current time. This simulates
  316. // the link flapping and coming back up before the second batch's
  317. // expiries have elapsed. We should see no failures sent back.
  318. err := ctx.mailbox.ResetPackets()
  319. require.NoError(t, err, "unable to reset packets")
  320. ctx.checkFails(nil)
  321. // Redeliver the second batch to the link and hold them there.
  322. ctx.receivePkts(secondBatch)
  323. // Send a third batch of adds shortly after the second batch.
  324. ctx.clock.SetTime(thirdBatchStart)
  325. thirdBatch := ctx.sendAdds(2*numBatchPackets, numBatchPackets)
  326. // Advance the clock so that the third batch expires. We expect to only
  327. // see fails for the third batch, since the second batch is still being
  328. // held by the link.
  329. ctx.clock.SetTime(thirdBatchExpiry)
  330. ctx.checkFails(thirdBatch)
  331. // Finally, reset the link which should cause the second batch to be
  332. // cancelled immediately.
  333. err = ctx.mailbox.ResetPackets()
  334. require.NoError(t, err, "unable to reset packets")
  335. ctx.checkFails(secondBatch)
  336. }
  337. // TestMailBoxPacketPrioritization asserts that the mailbox will prioritize
  338. // delivering Settle and Fail packets over Adds if both are available for
  339. // delivery at the same time.
  340. func TestMailBoxPacketPrioritization(t *testing.T) {
  341. t.Parallel()
  342. // First, we'll create new instance of the current default mailbox
  343. // type.
  344. ctx := newMailboxContext(t, time.Now(), testExpiry)
  345. const numPackets = 5
  346. _, _, aliceChanID, bobChanID := genIDs()
  347. // Next we'll send the following sequence of packets:
  348. // - Settle1
  349. // - Add1
  350. // - Add2
  351. // - Fail
  352. // - Settle2
  353. sentPackets := make([]*htlcPacket, numPackets)
  354. for i := 0; i < numPackets; i++ {
  355. pkt := &htlcPacket{
  356. outgoingChanID: aliceChanID,
  357. outgoingHTLCID: uint64(i),
  358. incomingChanID: bobChanID,
  359. incomingHTLCID: uint64(i),
  360. amount: lnwire.MilliSatoshi(prand.Int63()),
  361. }
  362. switch i {
  363. case 0, 4:
  364. // First and last packets are a Settle. A non-Add is
  365. // sent first to make the test deterministic w/o needing
  366. // to sleep.
  367. pkt.htlc = &lnwire.UpdateFulfillHTLC{ID: uint64(i)}
  368. case 1, 2:
  369. // Next two packets are Adds.
  370. pkt.htlc = &lnwire.UpdateAddHTLC{ID: uint64(i)}
  371. case 3:
  372. // Last packet is a Fail.
  373. pkt.htlc = &lnwire.UpdateFailHTLC{ID: uint64(i)}
  374. }
  375. sentPackets[i] = pkt
  376. err := ctx.mailbox.AddPacket(pkt)
  377. if err != nil {
  378. t.Fatalf("failed to add packet: %v", err)
  379. }
  380. }
  381. // When dequeueing the packets, we expect the following sequence:
  382. // - Settle1
  383. // - Fail
  384. // - Settle2
  385. // - Add1
  386. // - Add2
  387. //
  388. // We expect to see Fail and Settle2 to be delivered before either Add1
  389. // or Add2 due to the prioritization between the split queue.
  390. for i := 0; i < numPackets; i++ {
  391. select {
  392. case pkt := <-ctx.mailbox.PacketOutBox():
  393. var expPkt *htlcPacket
  394. switch i {
  395. case 0:
  396. // First packet should be Settle1.
  397. expPkt = sentPackets[0]
  398. case 1:
  399. // Second packet should be Fail.
  400. expPkt = sentPackets[3]
  401. case 2:
  402. // Third packet should be Settle2.
  403. expPkt = sentPackets[4]
  404. case 3:
  405. // Fourth packet should be Add1.
  406. expPkt = sentPackets[1]
  407. case 4:
  408. // Last packet should be Add2.
  409. expPkt = sentPackets[2]
  410. }
  411. if !reflect.DeepEqual(expPkt, pkt) {
  412. t.Fatalf("recvd packet mismatch %d, want: %v, got: %v",
  413. i, spew.Sdump(expPkt), spew.Sdump(pkt))
  414. }
  415. case <-time.After(50 * time.Millisecond):
  416. t.Fatalf("didn't receive packet %d before timeout", i)
  417. }
  418. }
  419. }
  420. // TestMailBoxAddExpiry asserts that the mailbox will cancel back Adds that
  421. // have reached their expiry time.
  422. func TestMailBoxAddExpiry(t *testing.T) {
  423. // Each batch will consist of 10 messages.
  424. const numBatchPackets = 10
  425. // deadline is the returned value from the `pktWithExpiry.deadline`.
  426. deadline := make(chan time.Time, numBatchPackets*2)
  427. // Create a mock clock and mock the methods.
  428. mockClock := &lnmock.MockClock{}
  429. mockClock.On("Now").Return(time.Now())
  430. // Mock TickAfter, which mounts the above `deadline` channel to the
  431. // returned value from `pktWithExpiry.deadline`.
  432. mockClock.On("TickAfter", mock.Anything).Return(deadline)
  433. // Create a test mailbox context.
  434. ctx := newMailboxContextWithClock(t, mockClock)
  435. // Send 10 packets and assert no failures are sent back.
  436. firstBatch := ctx.sendAdds(0, numBatchPackets)
  437. ctx.checkFails(nil)
  438. // Send another 10 packets and assert no failures are sent back.
  439. secondBatch := ctx.sendAdds(numBatchPackets, numBatchPackets)
  440. ctx.checkFails(nil)
  441. // Tick 10 times and we should see the first batch expired.
  442. for i := 0; i < numBatchPackets; i++ {
  443. deadline <- time.Now()
  444. }
  445. ctx.checkFails(firstBatch)
  446. // Tick another 10 times and we should see the second batch expired.
  447. for i := 0; i < numBatchPackets; i++ {
  448. deadline <- time.Now()
  449. }
  450. ctx.checkFails(secondBatch)
  451. }
  452. // TestMailBoxDuplicateAddPacket asserts that the mailbox returns an
  453. // ErrPacketAlreadyExists failure when two htlcPackets are added with identical
  454. // incoming circuit keys.
  455. func TestMailBoxDuplicateAddPacket(t *testing.T) {
  456. t.Parallel()
  457. ctx := newMailboxContext(t, time.Now(), testExpiry)
  458. ctx.mailbox.Start()
  459. addTwice := func(t *testing.T, pkt *htlcPacket) {
  460. // The first add should succeed.
  461. err := ctx.mailbox.AddPacket(pkt)
  462. if err != nil {
  463. t.Fatalf("unable to add packet: %v", err)
  464. }
  465. // Adding again with the same incoming circuit key should fail.
  466. err = ctx.mailbox.AddPacket(pkt)
  467. if err != ErrPacketAlreadyExists {
  468. t.Fatalf("expected ErrPacketAlreadyExists, got: %v", err)
  469. }
  470. }
  471. // Assert duplicate AddPacket calls fail for all types of HTLCs.
  472. addTwice(t, &htlcPacket{
  473. incomingHTLCID: 0,
  474. htlc: &lnwire.UpdateAddHTLC{},
  475. })
  476. addTwice(t, &htlcPacket{
  477. incomingHTLCID: 1,
  478. htlc: &lnwire.UpdateFulfillHTLC{},
  479. })
  480. addTwice(t, &htlcPacket{
  481. incomingHTLCID: 2,
  482. htlc: &lnwire.UpdateFailHTLC{},
  483. })
  484. }
  485. // TestMailBoxDustHandling tests that DustPackets returns the expected values
  486. // for the local and remote dust sum after calling SetFeeRate and
  487. // SetDustClosure.
  488. func TestMailBoxDustHandling(t *testing.T) {
  489. t.Run("tweakless mailbox dust", func(t *testing.T) {
  490. testMailBoxDust(t, channeldb.SingleFunderTweaklessBit)
  491. })
  492. t.Run("zero htlc fee anchors mailbox dust", func(t *testing.T) {
  493. testMailBoxDust(t, channeldb.SingleFunderTweaklessBit|
  494. channeldb.AnchorOutputsBit|
  495. channeldb.ZeroHtlcTxFeeBit,
  496. )
  497. })
  498. }
  499. func testMailBoxDust(t *testing.T, chantype channeldb.ChannelType) {
  500. t.Parallel()
  501. ctx := newMailboxContext(t, time.Now(), testExpiry)
  502. _, _, aliceID, bobID := genIDs()
  503. // It should not be the case that the MailBox has packets before the
  504. // feeRate or dustClosure is set. This is because the mailbox is always
  505. // created *with* its associated link and attached via AttachMailbox,
  506. // where these parameters will be set. Even though the lifetime is
  507. // longer than the link, the setting will persist across multiple link
  508. // creations.
  509. ctx.mailbox.SetFeeRate(chainfee.SatPerKWeight(253))
  510. localDustLimit := btcutil.Amount(400)
  511. remoteDustLimit := btcutil.Amount(500)
  512. isDust := dustHelper(chantype, localDustLimit, remoteDustLimit)
  513. ctx.mailbox.SetDustClosure(isDust)
  514. // The first packet will be dust according to the remote dust limit,
  515. // but not the local. We set a different amount if this is a zero fee
  516. // htlc channel type.
  517. firstAmt := lnwire.MilliSatoshi(600_000)
  518. if chantype.ZeroHtlcTxFee() {
  519. firstAmt = lnwire.MilliSatoshi(450_000)
  520. }
  521. firstPkt := &htlcPacket{
  522. outgoingChanID: aliceID,
  523. outgoingHTLCID: 0,
  524. incomingChanID: bobID,
  525. incomingHTLCID: 0,
  526. amount: firstAmt,
  527. htlc: &lnwire.UpdateAddHTLC{
  528. ID: uint64(0),
  529. },
  530. }
  531. err := ctx.mailbox.AddPacket(firstPkt)
  532. require.NoError(t, err)
  533. // Assert that the local sum is 0, and the remote sum accounts for this
  534. // added packet.
  535. localSum, remoteSum := ctx.mailbox.DustPackets()
  536. require.Equal(t, lnwire.MilliSatoshi(0), localSum)
  537. require.Equal(t, firstAmt, remoteSum)
  538. // The next packet will be dust according to both limits.
  539. secondAmt := lnwire.MilliSatoshi(300_000)
  540. secondPkt := &htlcPacket{
  541. outgoingChanID: aliceID,
  542. outgoingHTLCID: 1,
  543. incomingChanID: bobID,
  544. incomingHTLCID: 1,
  545. amount: secondAmt,
  546. htlc: &lnwire.UpdateAddHTLC{
  547. ID: uint64(1),
  548. },
  549. }
  550. err = ctx.mailbox.AddPacket(secondPkt)
  551. require.NoError(t, err)
  552. // Assert that both the local and remote sums have increased by the
  553. // second amount.
  554. localSum, remoteSum = ctx.mailbox.DustPackets()
  555. require.Equal(t, secondAmt, localSum)
  556. require.Equal(t, firstAmt+secondAmt, remoteSum)
  557. // Now we pull both packets off of the queue.
  558. for i := 0; i < 2; i++ {
  559. select {
  560. case <-ctx.mailbox.PacketOutBox():
  561. case <-time.After(50 * time.Millisecond):
  562. ctx.t.Fatalf("did not receive packet in time")
  563. }
  564. }
  565. // Assert that the sums haven't changed.
  566. localSum, remoteSum = ctx.mailbox.DustPackets()
  567. require.Equal(t, secondAmt, localSum)
  568. require.Equal(t, firstAmt+secondAmt, remoteSum)
  569. // Remove the first packet from the mailbox.
  570. removed := ctx.mailbox.AckPacket(firstPkt.inKey())
  571. require.True(t, removed)
  572. // Assert that the remote sum does not include the firstAmt.
  573. localSum, remoteSum = ctx.mailbox.DustPackets()
  574. require.Equal(t, secondAmt, localSum)
  575. require.Equal(t, secondAmt, remoteSum)
  576. // Remove the second packet from the mailbox.
  577. removed = ctx.mailbox.AckPacket(secondPkt.inKey())
  578. require.True(t, removed)
  579. // Assert that both sums are equal to 0.
  580. localSum, remoteSum = ctx.mailbox.DustPackets()
  581. require.Equal(t, lnwire.MilliSatoshi(0), localSum)
  582. require.Equal(t, lnwire.MilliSatoshi(0), remoteSum)
  583. }
  584. // TestMailOrchestrator asserts that the orchestrator properly buffers packets
  585. // for channels that haven't been made live, such that they are delivered
  586. // immediately after BindLiveShortChanID. It also tests that packets are delivered
  587. // readily to mailboxes for channels that are already in the live state.
  588. func TestMailOrchestrator(t *testing.T) {
  589. t.Parallel()
  590. failMailboxUpdate := func(outScid,
  591. mboxScid lnwire.ShortChannelID) lnwire.FailureMessage {
  592. return &lnwire.FailTemporaryNodeFailure{}
  593. }
  594. // First, we'll create a new instance of our orchestrator.
  595. mo := newMailOrchestrator(&mailOrchConfig{
  596. failMailboxUpdate: failMailboxUpdate,
  597. forwardPackets: func(_ chan struct{},
  598. pkts ...*htlcPacket) error {
  599. return nil
  600. },
  601. clock: clock.NewTestClock(time.Now()),
  602. expiry: testExpiry,
  603. })
  604. defer mo.Stop()
  605. // We'll be delivering 10 htlc packets via the orchestrator.
  606. const numPackets = 10
  607. const halfPackets = numPackets / 2
  608. // Before any mailbox is created or made live, we will deliver half of
  609. // the htlcs via the orchestrator.
  610. chanID1, chanID2, aliceChanID, bobChanID := genIDs()
  611. sentPackets := make([]*htlcPacket, halfPackets)
  612. for i := 0; i < halfPackets; i++ {
  613. pkt := &htlcPacket{
  614. outgoingChanID: aliceChanID,
  615. outgoingHTLCID: uint64(i),
  616. incomingChanID: bobChanID,
  617. incomingHTLCID: uint64(i),
  618. amount: lnwire.MilliSatoshi(prand.Int63()),
  619. htlc: &lnwire.UpdateAddHTLC{
  620. ID: uint64(i),
  621. },
  622. }
  623. sentPackets[i] = pkt
  624. mo.Deliver(pkt.outgoingChanID, pkt)
  625. }
  626. // Now, initialize a new mailbox for Alice's chanid.
  627. mailbox := mo.GetOrCreateMailBox(chanID1, aliceChanID)
  628. // Verify that no messages are received, since Alice's mailbox has not
  629. // been made live.
  630. for i := 0; i < halfPackets; i++ {
  631. timeout := time.After(50 * time.Millisecond)
  632. select {
  633. case <-mailbox.MessageOutBox():
  634. t.Fatalf("should not receive wire msg after reset")
  635. case <-timeout:
  636. }
  637. }
  638. // Assign a short chan id to the existing mailbox, make it available for
  639. // capturing incoming HTLCs. The HTLCs added above should be delivered
  640. // immediately.
  641. mo.BindLiveShortChanID(mailbox, chanID1, aliceChanID)
  642. // Verify that all of the packets are queued and delivered to Alice's
  643. // mailbox.
  644. recvdPackets := make([]*htlcPacket, 0, len(sentPackets))
  645. for i := 0; i < halfPackets; i++ {
  646. timeout := time.After(5 * time.Second)
  647. select {
  648. case <-timeout:
  649. t.Fatalf("didn't recv pkt %d after timeout", i)
  650. case pkt := <-mailbox.PacketOutBox():
  651. recvdPackets = append(recvdPackets, pkt)
  652. }
  653. }
  654. // We should have received half of the total number of packets.
  655. if len(recvdPackets) != halfPackets {
  656. t.Fatalf("expected %v packets instead got %v",
  657. halfPackets, len(recvdPackets))
  658. }
  659. // Check that the received packets are equal to the sent packets.
  660. if !reflect.DeepEqual(recvdPackets, sentPackets) {
  661. t.Fatalf("recvd packets mismatched: expected %v, got %v",
  662. spew.Sdump(sentPackets), spew.Sdump(recvdPackets))
  663. }
  664. // For the second half of the test, create a new mailbox for Bob and
  665. // immediately make it live with an assigned short chan id.
  666. mailbox = mo.GetOrCreateMailBox(chanID2, bobChanID)
  667. mo.BindLiveShortChanID(mailbox, chanID2, bobChanID)
  668. // Create the second half of our htlcs, and deliver them via the
  669. // orchestrator. We should be able to receive each of these in order.
  670. recvdPackets = make([]*htlcPacket, 0, len(sentPackets))
  671. for i := 0; i < halfPackets; i++ {
  672. pkt := &htlcPacket{
  673. outgoingChanID: aliceChanID,
  674. outgoingHTLCID: uint64(halfPackets + i),
  675. incomingChanID: bobChanID,
  676. incomingHTLCID: uint64(halfPackets + i),
  677. amount: lnwire.MilliSatoshi(prand.Int63()),
  678. htlc: &lnwire.UpdateAddHTLC{
  679. ID: uint64(halfPackets + i),
  680. },
  681. }
  682. sentPackets[i] = pkt
  683. mo.Deliver(pkt.incomingChanID, pkt)
  684. timeout := time.After(50 * time.Millisecond)
  685. select {
  686. case <-timeout:
  687. t.Fatalf("didn't recv pkt %d after timeout", halfPackets+i)
  688. case pkt := <-mailbox.PacketOutBox():
  689. recvdPackets = append(recvdPackets, pkt)
  690. }
  691. }
  692. // Again, we should have received half of the total number of packets.
  693. if len(recvdPackets) != halfPackets {
  694. t.Fatalf("expected %v packets instead got %v",
  695. halfPackets, len(recvdPackets))
  696. }
  697. // Check that the received packets are equal to the sent packets.
  698. if !reflect.DeepEqual(recvdPackets, sentPackets) {
  699. t.Fatalf("recvd packets mismatched: expected %v, got %v",
  700. spew.Sdump(sentPackets), spew.Sdump(recvdPackets))
  701. }
  702. }