payments_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. package channeldb
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math"
  6. "reflect"
  7. "testing"
  8. "time"
  9. "github.com/btcsuite/btcd/btcec/v2"
  10. "github.com/btcsuite/btcwallet/walletdb"
  11. "github.com/davecgh/go-spew/spew"
  12. "github.com/lightningnetwork/lnd/kvdb"
  13. "github.com/lightningnetwork/lnd/lntypes"
  14. "github.com/lightningnetwork/lnd/record"
  15. "github.com/lightningnetwork/lnd/routing/route"
  16. "github.com/stretchr/testify/require"
  17. )
  18. var (
  19. priv, _ = btcec.NewPrivateKey()
  20. pub = priv.PubKey()
  21. vertex = route.NewVertex(pub)
  22. testHop1 = &route.Hop{
  23. PubKeyBytes: vertex,
  24. ChannelID: 12345,
  25. OutgoingTimeLock: 111,
  26. AmtToForward: 555,
  27. CustomRecords: record.CustomSet{
  28. 65536: []byte{},
  29. 80001: []byte{},
  30. },
  31. MPP: record.NewMPP(32, [32]byte{0x42}),
  32. Metadata: []byte{1, 2, 3},
  33. }
  34. testHop2 = &route.Hop{
  35. PubKeyBytes: vertex,
  36. ChannelID: 12345,
  37. OutgoingTimeLock: 111,
  38. AmtToForward: 555,
  39. LegacyPayload: true,
  40. }
  41. testHop3 = &route.Hop{
  42. PubKeyBytes: route.NewVertex(pub),
  43. ChannelID: 12345,
  44. OutgoingTimeLock: 111,
  45. AmtToForward: 555,
  46. CustomRecords: record.CustomSet{
  47. 65536: []byte{},
  48. 80001: []byte{},
  49. },
  50. AMP: record.NewAMP([32]byte{0x69}, [32]byte{0x42}, 1),
  51. Metadata: []byte{1, 2, 3},
  52. }
  53. testRoute = route.Route{
  54. TotalTimeLock: 123,
  55. TotalAmount: 1234567,
  56. SourcePubKey: vertex,
  57. Hops: []*route.Hop{
  58. testHop3,
  59. testHop2,
  60. testHop1,
  61. },
  62. }
  63. testBlindedRoute = route.Route{
  64. TotalTimeLock: 150,
  65. TotalAmount: 1000,
  66. SourcePubKey: vertex,
  67. Hops: []*route.Hop{
  68. {
  69. PubKeyBytes: vertex,
  70. ChannelID: 9876,
  71. OutgoingTimeLock: 120,
  72. AmtToForward: 900,
  73. EncryptedData: []byte{1, 3, 3},
  74. BlindingPoint: pub,
  75. },
  76. {
  77. PubKeyBytes: vertex,
  78. EncryptedData: []byte{3, 2, 1},
  79. },
  80. {
  81. PubKeyBytes: vertex,
  82. Metadata: []byte{4, 5, 6},
  83. AmtToForward: 500,
  84. OutgoingTimeLock: 100,
  85. TotalAmtMsat: 500,
  86. },
  87. },
  88. }
  89. )
  90. func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) {
  91. var preimg lntypes.Preimage
  92. copy(preimg[:], rev[:])
  93. hash := preimg.Hash()
  94. c := &PaymentCreationInfo{
  95. PaymentIdentifier: hash,
  96. Value: 1000,
  97. // Use single second precision to avoid false positive test
  98. // failures due to the monotonic time component.
  99. CreationTime: time.Unix(time.Now().Unix(), 0),
  100. PaymentRequest: []byte(""),
  101. }
  102. a := NewHtlcAttempt(
  103. 44, priv, testRoute, time.Unix(100, 0), &hash,
  104. )
  105. return c, &a.HTLCAttemptInfo
  106. }
  107. func TestSentPaymentSerialization(t *testing.T) {
  108. t.Parallel()
  109. c, s := makeFakeInfo()
  110. var b bytes.Buffer
  111. if err := serializePaymentCreationInfo(&b, c); err != nil {
  112. t.Fatalf("unable to serialize creation info: %v", err)
  113. }
  114. newCreationInfo, err := deserializePaymentCreationInfo(&b)
  115. require.NoError(t, err, "unable to deserialize creation info")
  116. if !reflect.DeepEqual(c, newCreationInfo) {
  117. t.Fatalf("Payments do not match after "+
  118. "serialization/deserialization %v vs %v",
  119. spew.Sdump(c), spew.Sdump(newCreationInfo),
  120. )
  121. }
  122. b.Reset()
  123. if err := serializeHTLCAttemptInfo(&b, s); err != nil {
  124. t.Fatalf("unable to serialize info: %v", err)
  125. }
  126. newWireInfo, err := deserializeHTLCAttemptInfo(&b)
  127. require.NoError(t, err, "unable to deserialize info")
  128. newWireInfo.AttemptID = s.AttemptID
  129. // First we verify all the records match up porperly, as they aren't
  130. // able to be properly compared using reflect.DeepEqual.
  131. err = assertRouteEqual(&s.Route, &newWireInfo.Route)
  132. if err != nil {
  133. t.Fatalf("Routes do not match after "+
  134. "serialization/deserialization: %v", err)
  135. }
  136. // Clear routes to allow DeepEqual to compare the remaining fields.
  137. newWireInfo.Route = route.Route{}
  138. s.Route = route.Route{}
  139. // Call session key method to set our cached session key so we can use
  140. // DeepEqual, and assert that our key equals the original key.
  141. require.Equal(t, s.cachedSessionKey, newWireInfo.SessionKey())
  142. if !reflect.DeepEqual(s, newWireInfo) {
  143. t.Fatalf("Payments do not match after "+
  144. "serialization/deserialization %v vs %v",
  145. spew.Sdump(s), spew.Sdump(newWireInfo),
  146. )
  147. }
  148. }
  149. // assertRouteEquals compares to routes for equality and returns an error if
  150. // they are not equal.
  151. func assertRouteEqual(a, b *route.Route) error {
  152. if !reflect.DeepEqual(a, b) {
  153. return fmt.Errorf("HTLCAttemptInfos don't match: %v vs %v",
  154. spew.Sdump(a), spew.Sdump(b))
  155. }
  156. return nil
  157. }
  158. // TestRouteSerialization tests serialization of a regular and blinded route.
  159. func TestRouteSerialization(t *testing.T) {
  160. t.Parallel()
  161. testSerializeRoute(t, testRoute)
  162. testSerializeRoute(t, testBlindedRoute)
  163. }
  164. func testSerializeRoute(t *testing.T, route route.Route) {
  165. var b bytes.Buffer
  166. err := SerializeRoute(&b, route)
  167. require.NoError(t, err)
  168. r := bytes.NewReader(b.Bytes())
  169. route2, err := DeserializeRoute(r)
  170. require.NoError(t, err)
  171. reflect.DeepEqual(route, route2)
  172. }
  173. // deletePayment removes a payment with paymentHash from the payments database.
  174. func deletePayment(t *testing.T, db *DB, paymentHash lntypes.Hash, seqNr uint64) {
  175. t.Helper()
  176. err := kvdb.Update(db, func(tx kvdb.RwTx) error {
  177. payments := tx.ReadWriteBucket(paymentsRootBucket)
  178. // Delete the payment bucket.
  179. err := payments.DeleteNestedBucket(paymentHash[:])
  180. if err != nil {
  181. return err
  182. }
  183. key := make([]byte, 8)
  184. byteOrder.PutUint64(key, seqNr)
  185. // Delete the index that references this payment.
  186. indexes := tx.ReadWriteBucket(paymentsIndexBucket)
  187. return indexes.Delete(key)
  188. }, func() {})
  189. if err != nil {
  190. t.Fatalf("could not delete "+
  191. "payment: %v", err)
  192. }
  193. }
  194. // TestQueryPayments tests retrieval of payments with forwards and reversed
  195. // queries.
  196. func TestQueryPayments(t *testing.T) {
  197. // Define table driven test for QueryPayments.
  198. // Test payments have sequence indices [1, 3, 4, 5, 6, 7].
  199. // Note that the payment with index 7 has the same payment hash as 6,
  200. // and is stored in a nested bucket within payment 6 rather than being
  201. // its own entry in the payments bucket. We do this to test retrieval
  202. // of legacy payments.
  203. tests := []struct {
  204. name string
  205. query PaymentsQuery
  206. firstIndex uint64
  207. lastIndex uint64
  208. // expectedSeqNrs contains the set of sequence numbers we expect
  209. // our query to return.
  210. expectedSeqNrs []uint64
  211. }{
  212. {
  213. name: "IndexOffset at the end of the payments range",
  214. query: PaymentsQuery{
  215. IndexOffset: 7,
  216. MaxPayments: 7,
  217. Reversed: false,
  218. IncludeIncomplete: true,
  219. },
  220. firstIndex: 0,
  221. lastIndex: 0,
  222. expectedSeqNrs: nil,
  223. },
  224. {
  225. name: "query in forwards order, start at beginning",
  226. query: PaymentsQuery{
  227. IndexOffset: 0,
  228. MaxPayments: 2,
  229. Reversed: false,
  230. IncludeIncomplete: true,
  231. },
  232. firstIndex: 1,
  233. lastIndex: 3,
  234. expectedSeqNrs: []uint64{1, 3},
  235. },
  236. {
  237. name: "query in forwards order, start at end, overflow",
  238. query: PaymentsQuery{
  239. IndexOffset: 6,
  240. MaxPayments: 2,
  241. Reversed: false,
  242. IncludeIncomplete: true,
  243. },
  244. firstIndex: 7,
  245. lastIndex: 7,
  246. expectedSeqNrs: []uint64{7},
  247. },
  248. {
  249. name: "start at offset index outside of payments",
  250. query: PaymentsQuery{
  251. IndexOffset: 20,
  252. MaxPayments: 2,
  253. Reversed: false,
  254. IncludeIncomplete: true,
  255. },
  256. firstIndex: 0,
  257. lastIndex: 0,
  258. expectedSeqNrs: nil,
  259. },
  260. {
  261. name: "overflow in forwards order",
  262. query: PaymentsQuery{
  263. IndexOffset: 4,
  264. MaxPayments: math.MaxUint64,
  265. Reversed: false,
  266. IncludeIncomplete: true,
  267. },
  268. firstIndex: 5,
  269. lastIndex: 7,
  270. expectedSeqNrs: []uint64{5, 6, 7},
  271. },
  272. {
  273. name: "start at offset index outside of payments, " +
  274. "reversed order",
  275. query: PaymentsQuery{
  276. IndexOffset: 9,
  277. MaxPayments: 2,
  278. Reversed: true,
  279. IncludeIncomplete: true,
  280. },
  281. firstIndex: 6,
  282. lastIndex: 7,
  283. expectedSeqNrs: []uint64{6, 7},
  284. },
  285. {
  286. name: "query in reverse order, start at end",
  287. query: PaymentsQuery{
  288. IndexOffset: 0,
  289. MaxPayments: 2,
  290. Reversed: true,
  291. IncludeIncomplete: true,
  292. },
  293. firstIndex: 6,
  294. lastIndex: 7,
  295. expectedSeqNrs: []uint64{6, 7},
  296. },
  297. {
  298. name: "query in reverse order, starting in middle",
  299. query: PaymentsQuery{
  300. IndexOffset: 4,
  301. MaxPayments: 2,
  302. Reversed: true,
  303. IncludeIncomplete: true,
  304. },
  305. firstIndex: 1,
  306. lastIndex: 3,
  307. expectedSeqNrs: []uint64{1, 3},
  308. },
  309. {
  310. name: "query in reverse order, starting in middle, " +
  311. "with underflow",
  312. query: PaymentsQuery{
  313. IndexOffset: 4,
  314. MaxPayments: 5,
  315. Reversed: true,
  316. IncludeIncomplete: true,
  317. },
  318. firstIndex: 1,
  319. lastIndex: 3,
  320. expectedSeqNrs: []uint64{1, 3},
  321. },
  322. {
  323. name: "all payments in reverse, order maintained",
  324. query: PaymentsQuery{
  325. IndexOffset: 0,
  326. MaxPayments: 7,
  327. Reversed: true,
  328. IncludeIncomplete: true,
  329. },
  330. firstIndex: 1,
  331. lastIndex: 7,
  332. expectedSeqNrs: []uint64{1, 3, 4, 5, 6, 7},
  333. },
  334. {
  335. name: "exclude incomplete payments",
  336. query: PaymentsQuery{
  337. IndexOffset: 0,
  338. MaxPayments: 7,
  339. Reversed: false,
  340. IncludeIncomplete: false,
  341. },
  342. firstIndex: 7,
  343. lastIndex: 7,
  344. expectedSeqNrs: []uint64{7},
  345. },
  346. {
  347. name: "query payments at index gap",
  348. query: PaymentsQuery{
  349. IndexOffset: 1,
  350. MaxPayments: 7,
  351. Reversed: false,
  352. IncludeIncomplete: true,
  353. },
  354. firstIndex: 3,
  355. lastIndex: 7,
  356. expectedSeqNrs: []uint64{3, 4, 5, 6, 7},
  357. },
  358. {
  359. name: "query payments reverse before index gap",
  360. query: PaymentsQuery{
  361. IndexOffset: 3,
  362. MaxPayments: 7,
  363. Reversed: true,
  364. IncludeIncomplete: true,
  365. },
  366. firstIndex: 1,
  367. lastIndex: 1,
  368. expectedSeqNrs: []uint64{1},
  369. },
  370. {
  371. name: "query payments reverse on index gap",
  372. query: PaymentsQuery{
  373. IndexOffset: 2,
  374. MaxPayments: 7,
  375. Reversed: true,
  376. IncludeIncomplete: true,
  377. },
  378. firstIndex: 1,
  379. lastIndex: 1,
  380. expectedSeqNrs: []uint64{1},
  381. },
  382. {
  383. name: "query payments forward on index gap",
  384. query: PaymentsQuery{
  385. IndexOffset: 2,
  386. MaxPayments: 2,
  387. Reversed: false,
  388. IncludeIncomplete: true,
  389. },
  390. firstIndex: 3,
  391. lastIndex: 4,
  392. expectedSeqNrs: []uint64{3, 4},
  393. },
  394. {
  395. name: "query in forwards order, with start creation " +
  396. "time",
  397. query: PaymentsQuery{
  398. IndexOffset: 0,
  399. MaxPayments: 2,
  400. Reversed: false,
  401. IncludeIncomplete: true,
  402. CreationDateStart: 5,
  403. },
  404. firstIndex: 5,
  405. lastIndex: 6,
  406. expectedSeqNrs: []uint64{5, 6},
  407. },
  408. {
  409. name: "query in forwards order, with start creation " +
  410. "time at end, overflow",
  411. query: PaymentsQuery{
  412. IndexOffset: 0,
  413. MaxPayments: 2,
  414. Reversed: false,
  415. IncludeIncomplete: true,
  416. CreationDateStart: 7,
  417. },
  418. firstIndex: 7,
  419. lastIndex: 7,
  420. expectedSeqNrs: []uint64{7},
  421. },
  422. {
  423. name: "query with start and end creation time",
  424. query: PaymentsQuery{
  425. IndexOffset: 9,
  426. MaxPayments: math.MaxUint64,
  427. Reversed: true,
  428. IncludeIncomplete: true,
  429. CreationDateStart: 3,
  430. CreationDateEnd: 5,
  431. },
  432. firstIndex: 3,
  433. lastIndex: 5,
  434. expectedSeqNrs: []uint64{3, 4, 5},
  435. },
  436. }
  437. for _, tt := range tests {
  438. tt := tt
  439. t.Run(tt.name, func(t *testing.T) {
  440. t.Parallel()
  441. db, err := MakeTestDB(t)
  442. if err != nil {
  443. t.Fatalf("unable to init db: %v", err)
  444. }
  445. // Make a preliminary query to make sure it's ok to
  446. // query when we have no payments.
  447. resp, err := db.QueryPayments(tt.query)
  448. require.NoError(t, err)
  449. require.Len(t, resp.Payments, 0)
  450. // Populate the database with a set of test payments.
  451. // We create 6 original payments, deleting the payment
  452. // at index 2 so that we cover the case where sequence
  453. // numbers are missing. We also add a duplicate payment
  454. // to the last payment added to test the legacy case
  455. // where we have duplicates in the nested duplicates
  456. // bucket.
  457. nonDuplicatePayments := 6
  458. pControl := NewPaymentControl(db)
  459. for i := 0; i < nonDuplicatePayments; i++ {
  460. // Generate a test payment.
  461. info, _, preimg, err := genInfo()
  462. if err != nil {
  463. t.Fatalf("unable to create test "+
  464. "payment: %v", err)
  465. }
  466. // Override creation time to allow for testing
  467. // of CreationDateStart and CreationDateEnd.
  468. info.CreationTime = time.Unix(int64(i+1), 0)
  469. // Create a new payment entry in the database.
  470. err = pControl.InitPayment(info.PaymentIdentifier, info)
  471. if err != nil {
  472. t.Fatalf("unable to initialize "+
  473. "payment in database: %v", err)
  474. }
  475. // Immediately delete the payment with index 2.
  476. if i == 1 {
  477. pmt, err := pControl.FetchPayment(
  478. info.PaymentIdentifier,
  479. )
  480. require.NoError(t, err)
  481. deletePayment(t, db, info.PaymentIdentifier,
  482. pmt.SequenceNum)
  483. }
  484. // If we are on the last payment entry, add a
  485. // duplicate payment with sequence number equal
  486. // to the parent payment + 1. Note that
  487. // duplicate payments will always be succeeded.
  488. if i == (nonDuplicatePayments - 1) {
  489. pmt, err := pControl.FetchPayment(
  490. info.PaymentIdentifier,
  491. )
  492. require.NoError(t, err)
  493. appendDuplicatePayment(
  494. t, pControl.db,
  495. info.PaymentIdentifier,
  496. pmt.SequenceNum+1,
  497. preimg,
  498. )
  499. }
  500. }
  501. // Fetch all payments in the database.
  502. allPayments, err := db.FetchPayments()
  503. if err != nil {
  504. t.Fatalf("payments could not be fetched from "+
  505. "database: %v", err)
  506. }
  507. if len(allPayments) != 6 {
  508. t.Fatalf("Number of payments received does not "+
  509. "match expected one. Got %v, want %v.",
  510. len(allPayments), 6)
  511. }
  512. querySlice, err := db.QueryPayments(tt.query)
  513. if err != nil {
  514. t.Fatalf("unexpected error: %v", err)
  515. }
  516. if tt.firstIndex != querySlice.FirstIndexOffset ||
  517. tt.lastIndex != querySlice.LastIndexOffset {
  518. t.Errorf("First or last index does not match "+
  519. "expected index. Want (%d, %d), got (%d, %d).",
  520. tt.firstIndex, tt.lastIndex,
  521. querySlice.FirstIndexOffset,
  522. querySlice.LastIndexOffset)
  523. }
  524. if len(querySlice.Payments) != len(tt.expectedSeqNrs) {
  525. t.Errorf("expected: %v payments, got: %v",
  526. len(tt.expectedSeqNrs), len(querySlice.Payments))
  527. }
  528. for i, seqNr := range tt.expectedSeqNrs {
  529. q := querySlice.Payments[i]
  530. if seqNr != q.SequenceNum {
  531. t.Errorf("sequence numbers do not match, "+
  532. "got %v, want %v", q.SequenceNum, seqNr)
  533. }
  534. }
  535. })
  536. }
  537. }
  538. // TestFetchPaymentWithSequenceNumber tests lookup of payments with their
  539. // sequence number. It sets up one payment with no duplicates, and another with
  540. // two duplicates in its duplicates bucket then uses these payments to test the
  541. // case where a specific duplicate is not found and the duplicates bucket is not
  542. // present when we expect it to be.
  543. func TestFetchPaymentWithSequenceNumber(t *testing.T) {
  544. db, err := MakeTestDB(t)
  545. require.NoError(t, err)
  546. pControl := NewPaymentControl(db)
  547. // Generate a test payment which does not have duplicates.
  548. noDuplicates, _, _, err := genInfo()
  549. require.NoError(t, err)
  550. // Create a new payment entry in the database.
  551. err = pControl.InitPayment(noDuplicates.PaymentIdentifier, noDuplicates)
  552. require.NoError(t, err)
  553. // Fetch the payment so we can get its sequence nr.
  554. noDuplicatesPayment, err := pControl.FetchPayment(
  555. noDuplicates.PaymentIdentifier,
  556. )
  557. require.NoError(t, err)
  558. // Generate a test payment which we will add duplicates to.
  559. hasDuplicates, _, preimg, err := genInfo()
  560. require.NoError(t, err)
  561. // Create a new payment entry in the database.
  562. err = pControl.InitPayment(hasDuplicates.PaymentIdentifier, hasDuplicates)
  563. require.NoError(t, err)
  564. // Fetch the payment so we can get its sequence nr.
  565. hasDuplicatesPayment, err := pControl.FetchPayment(
  566. hasDuplicates.PaymentIdentifier,
  567. )
  568. require.NoError(t, err)
  569. // We declare the sequence numbers used here so that we can reference
  570. // them in tests.
  571. var (
  572. duplicateOneSeqNr = hasDuplicatesPayment.SequenceNum + 1
  573. duplicateTwoSeqNr = hasDuplicatesPayment.SequenceNum + 2
  574. )
  575. // Add two duplicates to our second payment.
  576. appendDuplicatePayment(
  577. t, db, hasDuplicates.PaymentIdentifier, duplicateOneSeqNr, preimg,
  578. )
  579. appendDuplicatePayment(
  580. t, db, hasDuplicates.PaymentIdentifier, duplicateTwoSeqNr, preimg,
  581. )
  582. tests := []struct {
  583. name string
  584. paymentHash lntypes.Hash
  585. sequenceNumber uint64
  586. expectedErr error
  587. }{
  588. {
  589. name: "lookup payment without duplicates",
  590. paymentHash: noDuplicates.PaymentIdentifier,
  591. sequenceNumber: noDuplicatesPayment.SequenceNum,
  592. expectedErr: nil,
  593. },
  594. {
  595. name: "lookup payment with duplicates",
  596. paymentHash: hasDuplicates.PaymentIdentifier,
  597. sequenceNumber: hasDuplicatesPayment.SequenceNum,
  598. expectedErr: nil,
  599. },
  600. {
  601. name: "lookup first duplicate",
  602. paymentHash: hasDuplicates.PaymentIdentifier,
  603. sequenceNumber: duplicateOneSeqNr,
  604. expectedErr: nil,
  605. },
  606. {
  607. name: "lookup second duplicate",
  608. paymentHash: hasDuplicates.PaymentIdentifier,
  609. sequenceNumber: duplicateTwoSeqNr,
  610. expectedErr: nil,
  611. },
  612. {
  613. name: "lookup non-existent duplicate",
  614. paymentHash: hasDuplicates.PaymentIdentifier,
  615. sequenceNumber: 999999,
  616. expectedErr: ErrDuplicateNotFound,
  617. },
  618. {
  619. name: "lookup duplicate, no duplicates bucket",
  620. paymentHash: noDuplicates.PaymentIdentifier,
  621. sequenceNumber: duplicateTwoSeqNr,
  622. expectedErr: ErrNoDuplicateBucket,
  623. },
  624. }
  625. for _, test := range tests {
  626. test := test
  627. t.Run(test.name, func(t *testing.T) {
  628. err := kvdb.Update(
  629. db, func(tx walletdb.ReadWriteTx) error {
  630. var seqNrBytes [8]byte
  631. byteOrder.PutUint64(
  632. seqNrBytes[:], test.sequenceNumber,
  633. )
  634. _, err := fetchPaymentWithSequenceNumber(
  635. tx, test.paymentHash, seqNrBytes[:],
  636. )
  637. return err
  638. }, func() {},
  639. )
  640. require.Equal(t, test.expectedErr, err)
  641. })
  642. }
  643. }
  644. // appendDuplicatePayment adds a duplicate payment to an existing payment. Note
  645. // that this function requires a unique sequence number.
  646. //
  647. // This code is *only* intended to replicate legacy duplicate payments in lnd,
  648. // our current schema does not allow duplicates.
  649. func appendDuplicatePayment(t *testing.T, db *DB, paymentHash lntypes.Hash,
  650. seqNr uint64, preImg lntypes.Preimage) {
  651. err := kvdb.Update(db, func(tx walletdb.ReadWriteTx) error {
  652. bucket, err := fetchPaymentBucketUpdate(
  653. tx, paymentHash,
  654. )
  655. if err != nil {
  656. return err
  657. }
  658. // Create the duplicates bucket if it is not
  659. // present.
  660. dup, err := bucket.CreateBucketIfNotExists(
  661. duplicatePaymentsBucket,
  662. )
  663. if err != nil {
  664. return err
  665. }
  666. var sequenceKey [8]byte
  667. byteOrder.PutUint64(sequenceKey[:], seqNr)
  668. // Create duplicate payments for the two dup
  669. // sequence numbers we've setup.
  670. putDuplicatePayment(t, dup, sequenceKey[:], paymentHash, preImg)
  671. // Finally, once we have created our entry we add an index for
  672. // it.
  673. err = createPaymentIndexEntry(tx, sequenceKey[:], paymentHash)
  674. require.NoError(t, err)
  675. return nil
  676. }, func() {})
  677. require.NoError(t, err, "could not create payment")
  678. }
  679. // putDuplicatePayment creates a duplicate payment in the duplicates bucket
  680. // provided with the minimal information required for successful reading.
  681. func putDuplicatePayment(t *testing.T, duplicateBucket kvdb.RwBucket,
  682. sequenceKey []byte, paymentHash lntypes.Hash,
  683. preImg lntypes.Preimage) {
  684. paymentBucket, err := duplicateBucket.CreateBucketIfNotExists(
  685. sequenceKey,
  686. )
  687. require.NoError(t, err)
  688. err = paymentBucket.Put(duplicatePaymentSequenceKey, sequenceKey)
  689. require.NoError(t, err)
  690. // Generate fake information for the duplicate payment.
  691. info, _, _, err := genInfo()
  692. require.NoError(t, err)
  693. // Write the payment info to disk under the creation info key. This code
  694. // is copied rather than using serializePaymentCreationInfo to ensure
  695. // we always write in the legacy format used by duplicate payments.
  696. var b bytes.Buffer
  697. var scratch [8]byte
  698. _, err = b.Write(paymentHash[:])
  699. require.NoError(t, err)
  700. byteOrder.PutUint64(scratch[:], uint64(info.Value))
  701. _, err = b.Write(scratch[:])
  702. require.NoError(t, err)
  703. err = serializeTime(&b, info.CreationTime)
  704. require.NoError(t, err)
  705. byteOrder.PutUint32(scratch[:4], 0)
  706. _, err = b.Write(scratch[:4])
  707. require.NoError(t, err)
  708. // Get the PaymentCreationInfo.
  709. err = paymentBucket.Put(duplicatePaymentCreationInfoKey, b.Bytes())
  710. require.NoError(t, err)
  711. // Duolicate payments are only stored for successes, so add the
  712. // preimage.
  713. err = paymentBucket.Put(duplicatePaymentSettleInfoKey, preImg[:])
  714. require.NoError(t, err)
  715. }