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`.
This commit is contained in:
7 files changed
+1612
-690
No files matched your search
@@ -11,27 +11,25 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const testMaxRecords = 2
|
||||
|
||||
var (
|
||||
// mcStoreTestRoute is a test route for the mission control store tests.
|
||||
mcStoreTestRoute = mcRoute{
|
||||
totalAmount: lnwire.MilliSatoshi(5),
|
||||
sourcePubKey: route.Vertex{1},
|
||||
hops: []*mcHop{
|
||||
{
|
||||
pubKeyBytes: route.Vertex{2},
|
||||
channelID: 4,
|
||||
amtToFwd: lnwire.MilliSatoshi(7),
|
||||
hasCustomRecords: true,
|
||||
hasBlindingPoint: false,
|
||||
},
|
||||
// mcStoreTestRoute is a test route for the mission control store tests.
|
||||
var mcStoreTestRoute = extractMCRoute(&route.Route{
|
||||
TotalAmount: lnwire.MilliSatoshi(5),
|
||||
SourcePubKey: route.Vertex{1},
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
PubKeyBytes: route.Vertex{2},
|
||||
ChannelID: 4,
|
||||
AmtToForward: lnwire.MilliSatoshi(7),
|
||||
CustomRecords: make(map[uint64][]byte),
|
||||
},
|
||||
}
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
// mcStoreTestHarness is the harness for a MissonControlStore test.
|
||||
type mcStoreTestHarness struct {
|
||||
@@ -84,28 +82,31 @@ func TestMissionControlStore(t *testing.T) {
|
||||
|
||||
failureSourceIdx := 1
|
||||
|
||||
result1 := paymentResult{
|
||||
route: &mcStoreTestRoute,
|
||||
failure: lnwire.NewFailIncorrectDetails(100, 1000),
|
||||
failureSourceIdx: &failureSourceIdx,
|
||||
id: 99,
|
||||
timeReply: testTime,
|
||||
timeFwd: testTime.Add(-time.Minute),
|
||||
}
|
||||
result1 := newPaymentResult(
|
||||
99, mcStoreTestRoute, testTime, testTime,
|
||||
newPaymentFailure(
|
||||
&failureSourceIdx,
|
||||
lnwire.NewFailIncorrectDetails(100, 1000),
|
||||
),
|
||||
)
|
||||
|
||||
result2 := result1
|
||||
result2.timeReply = result1.timeReply.Add(time.Hour)
|
||||
result2.timeFwd = result1.timeReply.Add(time.Hour)
|
||||
result2.id = 2
|
||||
result2 := newPaymentResult(
|
||||
2, mcStoreTestRoute, testTime.Add(time.Hour),
|
||||
testTime.Add(time.Hour),
|
||||
newPaymentFailure(
|
||||
&failureSourceIdx,
|
||||
lnwire.NewFailIncorrectDetails(100, 1000),
|
||||
),
|
||||
)
|
||||
|
||||
// Store result.
|
||||
store.AddResult(&result2)
|
||||
store.AddResult(result2)
|
||||
|
||||
// Store again to test idempotency.
|
||||
store.AddResult(&result2)
|
||||
store.AddResult(result2)
|
||||
|
||||
// Store second result which has an earlier timestamp.
|
||||
store.AddResult(&result1)
|
||||
store.AddResult(result1)
|
||||
require.NoError(t, store.storeResults())
|
||||
|
||||
results, err = store.fetchAll()
|
||||
@@ -113,8 +114,8 @@ func TestMissionControlStore(t *testing.T) {
|
||||
require.Len(t, results, 2)
|
||||
|
||||
// Check that results are stored in chronological order.
|
||||
require.Equal(t, &result1, results[0])
|
||||
require.Equal(t, &result2, results[1])
|
||||
require.Equal(t, result1, results[0])
|
||||
require.Equal(t, result2, results[1])
|
||||
|
||||
// Recreate store to test pruning.
|
||||
store, err = newMissionControlStore(
|
||||
@@ -124,12 +125,20 @@ func TestMissionControlStore(t *testing.T) {
|
||||
|
||||
// Add a newer result which failed due to mpp timeout.
|
||||
result3 := result1
|
||||
result3.timeReply = result1.timeReply.Add(2 * time.Hour)
|
||||
result3.timeFwd = result1.timeReply.Add(2 * time.Hour)
|
||||
result3.timeReply = tlv.NewPrimitiveRecord[tlv.TlvType1](
|
||||
uint64(testTime.Add(2 * time.Hour).UnixNano()),
|
||||
)
|
||||
result3.timeFwd = tlv.NewPrimitiveRecord[tlv.TlvType0](
|
||||
uint64(testTime.Add(2 * time.Hour).UnixNano()),
|
||||
)
|
||||
result3.id = 3
|
||||
result3.failure = &lnwire.FailMPPTimeout{}
|
||||
result3.failure = tlv.SomeRecordT(
|
||||
tlv.NewRecordT[tlv.TlvType3](*newPaymentFailure(
|
||||
&failureSourceIdx, &lnwire.FailMPPTimeout{},
|
||||
)),
|
||||
)
|
||||
|
||||
store.AddResult(&result3)
|
||||
store.AddResult(result3)
|
||||
require.NoError(t, store.storeResults())
|
||||
|
||||
// Check that results are pruned.
|
||||
@@ -137,8 +146,25 @@ func TestMissionControlStore(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results, 2)
|
||||
|
||||
require.Equal(t, &result2, results[0])
|
||||
require.Equal(t, &result3, results[1])
|
||||
require.Equal(t, result2, results[0])
|
||||
require.Equal(t, result3, results[1])
|
||||
|
||||
// Also demonstrate the persistence of a success result.
|
||||
result4 := newPaymentResult(
|
||||
5, mcStoreTestRoute, testTime.Add(3*time.Hour),
|
||||
testTime.Add(3*time.Hour), nil,
|
||||
)
|
||||
store.AddResult(result4)
|
||||
require.NoError(t, store.storeResults())
|
||||
|
||||
// We should still only have 2 results.
|
||||
results, err = store.fetchAll()
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results, 2)
|
||||
|
||||
// The two latest results should have been returned.
|
||||
require.Equal(t, result3, results[0])
|
||||
require.Equal(t, result4, results[1])
|
||||
}
|
||||
|
||||
// TestMissionControlStoreFlushing asserts the periodic flushing of the store
|
||||
@@ -156,14 +182,11 @@ func TestMissionControlStoreFlushing(t *testing.T) {
|
||||
)
|
||||
nextResult := func() *paymentResult {
|
||||
lastID += 1
|
||||
return &paymentResult{
|
||||
route: &mcStoreTestRoute,
|
||||
failure: failureDetails,
|
||||
failureSourceIdx: &failureSourceIdx,
|
||||
id: lastID,
|
||||
timeReply: testTime,
|
||||
timeFwd: testTime.Add(-time.Minute),
|
||||
}
|
||||
return newPaymentResult(
|
||||
lastID, mcStoreTestRoute, testTime.Add(-time.Hour),
|
||||
testTime,
|
||||
newPaymentFailure(&failureSourceIdx, failureDetails),
|
||||
)
|
||||
}
|
||||
|
||||
// Helper to assert the number of results is correct.
|
||||
@@ -260,14 +283,14 @@ func BenchmarkMissionControlStoreFlushing(b *testing.B) {
|
||||
var lastID uint64
|
||||
for i := 0; i < testMaxRecords; i++ {
|
||||
lastID++
|
||||
result := &paymentResult{
|
||||
route: &mcStoreTestRoute,
|
||||
failure: failureDetails,
|
||||
failureSourceIdx: &failureSourceIdx,
|
||||
id: lastID,
|
||||
timeReply: testTime,
|
||||
timeFwd: testTimeFwd,
|
||||
}
|
||||
result := newPaymentResult(
|
||||
lastID, mcStoreTestRoute, testTimeFwd,
|
||||
testTime,
|
||||
newPaymentFailure(
|
||||
&failureSourceIdx,
|
||||
failureDetails,
|
||||
),
|
||||
)
|
||||
store.AddResult(result)
|
||||
}
|
||||
|
||||
@@ -278,13 +301,14 @@ func BenchmarkMissionControlStoreFlushing(b *testing.B) {
|
||||
// Create the additional results.
|
||||
results := make([]*paymentResult, tc)
|
||||
for i := 0; i < len(results); i++ {
|
||||
results[i] = &paymentResult{
|
||||
route: &mcStoreTestRoute,
|
||||
failure: failureDetails,
|
||||
failureSourceIdx: &failureSourceIdx,
|
||||
timeReply: testTime,
|
||||
timeFwd: testTimeFwd,
|
||||
}
|
||||
results[i] = newPaymentResult(
|
||||
0, mcStoreTestRoute, testTimeFwd,
|
||||
testTime,
|
||||
newPaymentFailure(
|
||||
&failureSourceIdx,
|
||||
failureDetails,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// Run the actual benchmark.
|
||||
|
||||
Reference in new issue
Block a user