lnd/channeldb/migration32/migration_test.go
Elle Mouton 5370c90906
routing+migration32: update MC encoding to use pure TLV
In this commit, we update an existing migration which at the time of
writing has not been included in a release. We update it so that it
converts the format used for MissionControl result encoding to use pure
TLV instead. The 3 structs that have been updated are: `mcHop`,
`mcRoute` and `paymentResult`.
2024-11-01 12:28:06 +02:00

276 lines
7 KiB
Go

package migration32
import (
"encoding/hex"
"testing"
"time"
"github.com/btcsuite/btcd/btcec/v2"
lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
"github.com/lightningnetwork/lnd/channeldb/migtest"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/tlv"
)
var (
failureIndex = 8
testPub = Vertex{2, 202, 4}
testPub2 = Vertex{22, 202, 4}
pubkeyBytes, _ = hex.DecodeString(
"598ec453728e0ffe0ae2f5e174243cf58f2" +
"a3f2c83d2457b43036db568b11093",
)
pubKeyY = new(btcec.FieldVal)
_ = pubKeyY.SetByteSlice(pubkeyBytes)
pubkey = btcec.NewPublicKey(new(btcec.FieldVal).SetInt(4), pubKeyY)
customRecord = map[uint64][]byte{
65536: {4, 2, 2},
}
resultOld1 = paymentResultOld{
id: 0,
timeFwd: time.Unix(0, 1),
timeReply: time.Unix(0, 2),
success: false,
failureSourceIdx: &failureIndex,
failure: &lnwire.FailFeeInsufficient{},
route: &Route{
TotalTimeLock: 100,
TotalAmount: 400,
SourcePubKey: testPub,
Hops: []*Hop{
// A hop with MPP, AMP and custom
// records.
{
PubKeyBytes: testPub,
ChannelID: 100,
OutgoingTimeLock: 300,
AmtToForward: 500,
MPP: &MPP{
paymentAddr: [32]byte{4, 5},
totalMsat: 900,
},
AMP: &AMP{
rootShare: [32]byte{0, 0},
setID: [32]byte{5, 5, 5},
childIndex: 90,
},
CustomRecords: customRecord,
Metadata: []byte{6, 7, 7},
},
// A legacy hop.
{
PubKeyBytes: testPub,
ChannelID: 800,
OutgoingTimeLock: 4,
AmtToForward: 4,
LegacyPayload: true,
},
// A hop with a blinding key.
{
PubKeyBytes: testPub,
ChannelID: 800,
OutgoingTimeLock: 4,
AmtToForward: 4,
BlindingPoint: pubkey,
EncryptedData: []byte{1, 2, 3},
TotalAmtMsat: 600,
},
// A hop with a blinding key and custom
// records.
{
PubKeyBytes: testPub,
ChannelID: 800,
OutgoingTimeLock: 4,
AmtToForward: 4,
CustomRecords: customRecord,
BlindingPoint: pubkey,
EncryptedData: []byte{1, 2, 3},
TotalAmtMsat: 600,
},
},
},
}
resultOld2 = paymentResultOld{
id: 2,
timeFwd: time.Unix(0, 4),
timeReply: time.Unix(0, 7),
success: true,
route: &Route{
TotalTimeLock: 101,
TotalAmount: 401,
SourcePubKey: testPub2,
Hops: []*Hop{
{
PubKeyBytes: testPub,
ChannelID: 800,
OutgoingTimeLock: 4,
AmtToForward: 4,
BlindingPoint: pubkey,
EncryptedData: []byte{1, 2, 3},
CustomRecords: customRecord,
TotalAmtMsat: 600,
},
},
},
}
//nolint:lll
resultNew1Hop1 = &mcHop{
channelID: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](100),
pubKeyBytes: tlv.NewRecordT[tlv.TlvType1](testPub),
amtToFwd: tlv.NewPrimitiveRecord[tlv.TlvType2, lnwire.MilliSatoshi](500),
hasCustomRecords: tlv.SomeRecordT(
tlv.ZeroRecordT[tlv.TlvType4, lnwire.TrueBoolean](),
),
}
//nolint:lll
resultNew1Hop2 = &mcHop{
channelID: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](800),
pubKeyBytes: tlv.NewRecordT[tlv.TlvType1](testPub),
amtToFwd: tlv.NewPrimitiveRecord[tlv.TlvType2, lnwire.MilliSatoshi](4),
}
//nolint:lll
resultNew1Hop3 = &mcHop{
channelID: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](800),
pubKeyBytes: tlv.NewRecordT[tlv.TlvType1](testPub),
amtToFwd: tlv.NewPrimitiveRecord[tlv.TlvType2, lnwire.MilliSatoshi](4),
hasBlindingPoint: tlv.SomeRecordT(
tlv.ZeroRecordT[tlv.TlvType3, lnwire.TrueBoolean](),
),
}
//nolint:lll
resultNew1Hop4 = &mcHop{
channelID: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](800),
pubKeyBytes: tlv.NewRecordT[tlv.TlvType1](testPub),
amtToFwd: tlv.NewPrimitiveRecord[tlv.TlvType2, lnwire.MilliSatoshi](4),
hasCustomRecords: tlv.SomeRecordT(
tlv.ZeroRecordT[tlv.TlvType4, lnwire.TrueBoolean](),
),
hasBlindingPoint: tlv.SomeRecordT(
tlv.ZeroRecordT[tlv.TlvType3, lnwire.TrueBoolean](),
),
}
//nolint:lll
resultNew2Hop1 = &mcHop{
channelID: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](800),
pubKeyBytes: tlv.NewRecordT[tlv.TlvType1](testPub),
amtToFwd: tlv.NewPrimitiveRecord[tlv.TlvType2, lnwire.MilliSatoshi](4),
hasCustomRecords: tlv.SomeRecordT(
tlv.ZeroRecordT[tlv.TlvType4, lnwire.TrueBoolean](),
),
hasBlindingPoint: tlv.SomeRecordT(
tlv.ZeroRecordT[tlv.TlvType3, lnwire.TrueBoolean](),
),
}
//nolint:lll
resultNew1 = paymentResultNew{
id: 0,
timeFwd: tlv.NewPrimitiveRecord[tlv.TlvType0](
uint64(time.Unix(0, 1).UnixNano()),
),
timeReply: tlv.NewPrimitiveRecord[tlv.TlvType1](
uint64(time.Unix(0, 2).UnixNano()),
),
failure: tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType3](
*newPaymentFailure(
&failureIndex,
&lnwire.FailFeeInsufficient{},
),
),
),
route: tlv.NewRecordT[tlv.TlvType2](mcRoute{
sourcePubKey: tlv.NewRecordT[tlv.TlvType0](testPub),
totalAmount: tlv.NewRecordT[tlv.TlvType1, lnwire.MilliSatoshi](400),
hops: tlv.NewRecordT[tlv.TlvType2, mcHops](mcHops{
resultNew1Hop1,
resultNew1Hop2,
resultNew1Hop3,
resultNew1Hop4,
}),
}),
}
//nolint:lll
resultNew2 = paymentResultNew{
id: 2,
timeFwd: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](
uint64(time.Unix(0, 4).UnixNano()),
),
timeReply: tlv.NewPrimitiveRecord[tlv.TlvType1, uint64](
uint64(time.Unix(0, 7).UnixNano()),
),
route: tlv.NewRecordT[tlv.TlvType2](mcRoute{
sourcePubKey: tlv.NewRecordT[tlv.TlvType0](testPub2),
totalAmount: tlv.NewRecordT[tlv.TlvType1, lnwire.MilliSatoshi](401),
hops: tlv.NewRecordT[tlv.TlvType2](mcHops{
resultNew2Hop1,
}),
}),
}
)
// TestMigrateMCRouteSerialisation tests that the MigrateMCRouteSerialisation
// migration function correctly migrates the MC store from using the old route
// encoding to using the newer, more minimal route encoding.
func TestMigrateMCRouteSerialisation(t *testing.T) {
var (
resultsOld = []*paymentResultOld{
&resultOld1, &resultOld2,
}
expectedResultsNew = []*paymentResultNew{
&resultNew1, &resultNew2,
}
)
// Prime the database with some mission control data that uses the
// old route encoding.
before := func(tx kvdb.RwTx) error {
resultBucket, err := tx.CreateTopLevelBucket(resultsKey)
if err != nil {
return err
}
for _, result := range resultsOld {
k, v, err := serializeOldResult(result)
if err != nil {
return err
}
if err := resultBucket.Put(k, v); err != nil {
return err
}
}
return nil
}
// After the migration, ensure that all the relevant info was
// maintained.
after := func(tx kvdb.RwTx) error {
m := make(map[string]interface{})
for _, result := range expectedResultsNew {
k, v, err := serializeNewResult(result)
if err != nil {
return err
}
m[string(k)] = string(v)
}
return migtest.VerifyDB(tx, resultsKey, m)
}
migtest.ApplyMigration(
t, before, after, MigrateMCRouteSerialisation, false,
)
}