channeldb: update TestQueryPayments to cover duplicate payments
Update our current tests to include lookup of duplicate payments. We do so in preparation for changing our lookup to be based on a new payments index. We add an append duplicate function which will add a duplicate payment with the minimum information required to successfully read it from disk in tests.
This commit is contained in:
parent
38b8e54ba7
commit
6c4a1f4f99
@ -9,11 +9,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/btcsuite/btcwallet/walletdb"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/record"
|
"github.com/lightningnetwork/lnd/record"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -188,6 +190,10 @@ func deletePayment(t *testing.T, db *DB, paymentHash lntypes.Hash) {
|
|||||||
func TestQueryPayments(t *testing.T) {
|
func TestQueryPayments(t *testing.T) {
|
||||||
// Define table driven test for QueryPayments.
|
// Define table driven test for QueryPayments.
|
||||||
// Test payments have sequence indices [1, 3, 4, 5, 6, 7].
|
// Test payments have sequence indices [1, 3, 4, 5, 6, 7].
|
||||||
|
// Note that the payment with index 7 has the same payment hash as 6,
|
||||||
|
// and is stored in a nested bucket within payment 6 rather than being
|
||||||
|
// its own entry in the payments bucket. We do this to test retrieval
|
||||||
|
// of legacy payments.
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
query PaymentsQuery
|
query PaymentsQuery
|
||||||
@ -359,10 +365,16 @@ func TestQueryPayments(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Populate the database with a set of test payments.
|
// Populate the database with a set of test payments.
|
||||||
numberOfPayments := 7
|
// We create 6 original payments, deleting the payment
|
||||||
|
// at index 2 so that we cover the case where sequence
|
||||||
|
// numbers are missing. We also add a duplicate payment
|
||||||
|
// to the last payment added to test the legacy case
|
||||||
|
// where we have duplicates in the nested duplicates
|
||||||
|
// bucket.
|
||||||
|
nonDuplicatePayments := 6
|
||||||
pControl := NewPaymentControl(db)
|
pControl := NewPaymentControl(db)
|
||||||
|
|
||||||
for i := 0; i < numberOfPayments; i++ {
|
for i := 0; i < nonDuplicatePayments; i++ {
|
||||||
// Generate a test payment.
|
// Generate a test payment.
|
||||||
info, _, _, err := genInfo()
|
info, _, _, err := genInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -381,6 +393,22 @@ func TestQueryPayments(t *testing.T) {
|
|||||||
if i == 1 {
|
if i == 1 {
|
||||||
deletePayment(t, db, info.PaymentHash)
|
deletePayment(t, db, info.PaymentHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are on the last payment entry, add a
|
||||||
|
// duplicate payment with sequence number equal
|
||||||
|
// to the parent payment + 1.
|
||||||
|
if i == (nonDuplicatePayments - 1) {
|
||||||
|
pmt, err := pControl.FetchPayment(
|
||||||
|
info.PaymentHash,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
appendDuplicatePayment(
|
||||||
|
t, pControl.db,
|
||||||
|
info.PaymentHash,
|
||||||
|
pmt.SequenceNum+1,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all payments in the database.
|
// Fetch all payments in the database.
|
||||||
@ -424,3 +452,83 @@ func TestQueryPayments(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appendDuplicatePayment adds a duplicate payment to an existing payment. Note
|
||||||
|
// that this function requires a unique sequence number.
|
||||||
|
//
|
||||||
|
// This code is *only* intended to replicate legacy duplicate payments in lnd,
|
||||||
|
// our current schema does not allow duplicates.
|
||||||
|
func appendDuplicatePayment(t *testing.T, db *DB, paymentHash lntypes.Hash,
|
||||||
|
seqNr uint64) {
|
||||||
|
|
||||||
|
err := kvdb.Update(db, func(tx walletdb.ReadWriteTx) error {
|
||||||
|
bucket, err := fetchPaymentBucketUpdate(
|
||||||
|
tx, paymentHash,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the duplicates bucket if it is not
|
||||||
|
// present.
|
||||||
|
dup, err := bucket.CreateBucketIfNotExists(
|
||||||
|
duplicatePaymentsBucket,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var sequenceKey [8]byte
|
||||||
|
byteOrder.PutUint64(sequenceKey[:], seqNr)
|
||||||
|
|
||||||
|
// Create duplicate payments for the two dup
|
||||||
|
// sequence numbers we've setup.
|
||||||
|
putDuplicatePayment(t, dup, sequenceKey[:], paymentHash)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not create payment: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// putDuplicatePayment creates a duplicate payment in the duplicates bucket
|
||||||
|
// provided with the minimal information required for successful reading.
|
||||||
|
func putDuplicatePayment(t *testing.T, duplicateBucket kvdb.RwBucket,
|
||||||
|
sequenceKey []byte, paymentHash lntypes.Hash) {
|
||||||
|
|
||||||
|
paymentBucket, err := duplicateBucket.CreateBucketIfNotExists(
|
||||||
|
sequenceKey,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = paymentBucket.Put(duplicatePaymentSequenceKey, sequenceKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Generate fake information for the duplicate payment.
|
||||||
|
info, _, _, err := genInfo()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Write the payment info to disk under the creation info key. This code
|
||||||
|
// is copied rather than using serializePaymentCreationInfo to ensure
|
||||||
|
// we always write in the legacy format used by duplicate payments.
|
||||||
|
var b bytes.Buffer
|
||||||
|
var scratch [8]byte
|
||||||
|
_, err = b.Write(paymentHash[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
byteOrder.PutUint64(scratch[:], uint64(info.Value))
|
||||||
|
_, err = b.Write(scratch[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = serializeTime(&b, info.CreationTime)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
byteOrder.PutUint32(scratch[:4], 0)
|
||||||
|
_, err = b.Write(scratch[:4])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Get the PaymentCreationInfo.
|
||||||
|
err = paymentBucket.Put(duplicatePaymentCreationInfoKey, b.Bytes())
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user