c8d11285f3
Add an entry to a payments index bucket which maps sequence number to payment hash when we initiate payments. This allows for more efficient paginated queries. We create the top level bucket in its own migration so that we do not need to create it on the fly. When we retry payments and provide them with a new sequence number, we delete the index for their existing payment so that we do not have an index that points to a non-existent payment. If we delete a payment, we also delete its index entry. This prevents us from looking up entries from indexes to payments that do not exist.
145 lines
3.3 KiB
Go
145 lines
3.3 KiB
Go
package migration16
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"testing"
|
|
|
|
"github.com/lightningnetwork/lnd/channeldb/kvdb"
|
|
"github.com/lightningnetwork/lnd/channeldb/migtest"
|
|
)
|
|
|
|
var (
|
|
hexStr = migtest.Hex
|
|
|
|
hash1Str = "02acee76ebd53d00824410cf6adecad4f50334dac702bd5a2d3ba01b91709f0e"
|
|
hash1 = hexStr(hash1Str)
|
|
paymentID1 = hexStr("0000000000000001")
|
|
|
|
hash2Str = "62eb3f0a48f954e495d0c14ac63df04a67cefa59dafdbcd3d5046d1f5647840c"
|
|
hash2 = hexStr(hash2Str)
|
|
paymentID2 = hexStr("0000000000000002")
|
|
|
|
paymentID3 = hexStr("0000000000000003")
|
|
|
|
// pre is the data in the payments root bucket in database version 13 format.
|
|
pre = map[string]interface{}{
|
|
// A payment without duplicates.
|
|
hash1: map[string]interface{}{
|
|
"payment-sequence-key": paymentID1,
|
|
},
|
|
|
|
// A payment with a duplicate.
|
|
hash2: map[string]interface{}{
|
|
"payment-sequence-key": paymentID2,
|
|
"payment-duplicate-bucket": map[string]interface{}{
|
|
paymentID3: map[string]interface{}{
|
|
"payment-sequence-key": paymentID3,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
preFails = map[string]interface{}{
|
|
// A payment without duplicates.
|
|
hash1: map[string]interface{}{
|
|
"payment-sequence-key": paymentID1,
|
|
"payment-duplicate-bucket": map[string]interface{}{
|
|
paymentID1: map[string]interface{}{
|
|
"payment-sequence-key": paymentID1,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// post is the expected data after migration.
|
|
post = map[string]interface{}{
|
|
paymentID1: paymentHashIndex(hash1Str),
|
|
paymentID2: paymentHashIndex(hash2Str),
|
|
paymentID3: paymentHashIndex(hash2Str),
|
|
}
|
|
)
|
|
|
|
// paymentHashIndex produces a string that represents the value we expect for
|
|
// our payment indexes from a hex encoded payment hash string.
|
|
func paymentHashIndex(hashStr string) string {
|
|
hash, err := hex.DecodeString(hashStr)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
bytes, err := serializePaymentIndexEntry(hash)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return string(bytes)
|
|
}
|
|
|
|
// MigrateSequenceIndex asserts that the database is properly migrated to
|
|
// contain a payments index.
|
|
func TestMigrateSequenceIndex(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
shouldFail bool
|
|
pre map[string]interface{}
|
|
post map[string]interface{}
|
|
}{
|
|
{
|
|
name: "migration ok",
|
|
shouldFail: false,
|
|
pre: pre,
|
|
post: post,
|
|
},
|
|
{
|
|
name: "duplicate sequence number",
|
|
shouldFail: true,
|
|
pre: preFails,
|
|
post: post,
|
|
},
|
|
{
|
|
name: "no payments",
|
|
shouldFail: false,
|
|
pre: nil,
|
|
post: nil,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
test := test
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
|
// Before the migration we have a payments bucket.
|
|
before := func(tx kvdb.RwTx) error {
|
|
return migtest.RestoreDB(
|
|
tx, paymentsRootBucket, test.pre,
|
|
)
|
|
}
|
|
|
|
// After the migration, we should have an untouched
|
|
// payments bucket and a new index bucket.
|
|
after := func(tx kvdb.RwTx) error {
|
|
if err := migtest.VerifyDB(
|
|
tx, paymentsRootBucket, test.pre,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
|
|
// If we expect our migration to fail, we don't
|
|
// expect an index bucket.
|
|
if test.shouldFail {
|
|
return nil
|
|
}
|
|
|
|
return migtest.VerifyDB(
|
|
tx, paymentsIndexBucket, test.post,
|
|
)
|
|
}
|
|
|
|
migtest.ApplyMigration(
|
|
t, before, after, MigrateSequenceIndex,
|
|
test.shouldFail,
|
|
)
|
|
})
|
|
}
|
|
}
|