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
@@ -4,7 +4,9 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
)
|
||||
@@ -14,110 +16,170 @@ var (
|
||||
{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4},
|
||||
}
|
||||
|
||||
routeOneHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
routeOneHop = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 99,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
routeTwoHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{pubKeyBytes: hops[2], amtToFwd: 97},
|
||||
routeTwoHop = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 99,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 97,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
routeThreeHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{pubKeyBytes: hops[2], amtToFwd: 97},
|
||||
{pubKeyBytes: hops[3], amtToFwd: 94},
|
||||
routeThreeHop = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 99,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 97,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[3],
|
||||
AmtToForward: 94,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
routeFourHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{pubKeyBytes: hops[2], amtToFwd: 97},
|
||||
{pubKeyBytes: hops[3], amtToFwd: 94},
|
||||
{pubKeyBytes: hops[4], amtToFwd: 90},
|
||||
routeFourHop = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 99,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 97,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[3],
|
||||
AmtToForward: 94,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[4],
|
||||
AmtToForward: 90,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// blindedMultiHop is a blinded path where there are cleartext hops
|
||||
// before the introduction node, and an intermediate blinded hop before
|
||||
// the recipient after it.
|
||||
blindedMultiHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
blindedMultiHop = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
pubKeyBytes: hops[2],
|
||||
amtToFwd: 95,
|
||||
hasBlindingPoint: true,
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 99,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 95,
|
||||
BlindingPoint: genTestPubKey(),
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[3],
|
||||
AmtToForward: 88,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[4],
|
||||
AmtToForward: 77,
|
||||
},
|
||||
{pubKeyBytes: hops[3], amtToFwd: 88},
|
||||
{pubKeyBytes: hops[4], amtToFwd: 77},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// blindedSingleHop is a blinded path with a single blinded hop after
|
||||
// the introduction node.
|
||||
blindedSingleHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
blindedSingleHop = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
pubKeyBytes: hops[2],
|
||||
amtToFwd: 95,
|
||||
hasBlindingPoint: true,
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 99,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 95,
|
||||
BlindingPoint: genTestPubKey(),
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[3],
|
||||
AmtToForward: 88,
|
||||
},
|
||||
{pubKeyBytes: hops[3], amtToFwd: 88},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// blindedMultiToIntroduction is a blinded path which goes directly
|
||||
// to the introduction node, with multiple blinded hops after it.
|
||||
blindedMultiToIntroduction = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
blindedMultiToIntroduction = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
pubKeyBytes: hops[1],
|
||||
amtToFwd: 90,
|
||||
hasBlindingPoint: true,
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 90,
|
||||
BlindingPoint: genTestPubKey(),
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 75,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[3],
|
||||
AmtToForward: 58,
|
||||
},
|
||||
{pubKeyBytes: hops[2], amtToFwd: 75},
|
||||
{pubKeyBytes: hops[3], amtToFwd: 58},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// blindedIntroReceiver is a blinded path where the introduction node
|
||||
// is the recipient.
|
||||
blindedIntroReceiver = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 95},
|
||||
blindedIntroReceiver = extractMCRoute(&route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{
|
||||
pubKeyBytes: hops[2],
|
||||
amtToFwd: 90,
|
||||
hasBlindingPoint: true,
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 95,
|
||||
},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 90,
|
||||
BlindingPoint: genTestPubKey(),
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
func genTestPubKey() *btcec.PublicKey {
|
||||
key, _ := btcec.NewPrivateKey()
|
||||
|
||||
return key.PubKey()
|
||||
}
|
||||
|
||||
func getTestPair(from, to int) DirectedNodePair {
|
||||
return NewDirectedNodePair(hops[from], hops[to])
|
||||
}
|
||||
@@ -142,7 +204,7 @@ var resultTestCases = []resultTestCase{
|
||||
// interpreted.
|
||||
{
|
||||
name: "fail",
|
||||
route: &routeTwoHop,
|
||||
route: routeTwoHop,
|
||||
failureSrcIdx: 1,
|
||||
failure: lnwire.NewTemporaryChannelFailure(nil),
|
||||
|
||||
@@ -157,7 +219,7 @@ var resultTestCases = []resultTestCase{
|
||||
// Tests that an expiry too soon failure result is properly interpreted.
|
||||
{
|
||||
name: "fail expiry too soon",
|
||||
route: &routeFourHop,
|
||||
route: routeFourHop,
|
||||
failureSrcIdx: 3,
|
||||
failure: lnwire.NewExpiryTooSoon(lnwire.ChannelUpdate1{}),
|
||||
|
||||
@@ -177,7 +239,7 @@ var resultTestCases = []resultTestCase{
|
||||
// failure, but mark all pairs along the route as successful.
|
||||
{
|
||||
name: "fail incorrect details",
|
||||
route: &routeTwoHop,
|
||||
route: routeTwoHop,
|
||||
failureSrcIdx: 2,
|
||||
failure: lnwire.NewFailIncorrectDetails(97, 0),
|
||||
|
||||
@@ -193,7 +255,7 @@ var resultTestCases = []resultTestCase{
|
||||
// Tests a successful direct payment.
|
||||
{
|
||||
name: "success direct",
|
||||
route: &routeOneHop,
|
||||
route: routeOneHop,
|
||||
success: true,
|
||||
|
||||
expectedResult: &interpretedResult{
|
||||
@@ -206,7 +268,7 @@ var resultTestCases = []resultTestCase{
|
||||
// Tests a successful two hop payment.
|
||||
{
|
||||
name: "success",
|
||||
route: &routeTwoHop,
|
||||
route: routeTwoHop,
|
||||
success: true,
|
||||
|
||||
expectedResult: &interpretedResult{
|
||||
@@ -220,7 +282,7 @@ var resultTestCases = []resultTestCase{
|
||||
// Tests a malformed htlc from a direct peer.
|
||||
{
|
||||
name: "fail malformed htlc from direct peer",
|
||||
route: &routeTwoHop,
|
||||
route: routeTwoHop,
|
||||
failureSrcIdx: 0,
|
||||
failure: lnwire.NewInvalidOnionKey(nil),
|
||||
|
||||
@@ -239,7 +301,7 @@ var resultTestCases = []resultTestCase{
|
||||
// destination.
|
||||
{
|
||||
name: "fail malformed htlc from direct final peer",
|
||||
route: &routeOneHop,
|
||||
route: routeOneHop,
|
||||
failureSrcIdx: 0,
|
||||
failure: lnwire.NewInvalidOnionKey(nil),
|
||||
|
||||
@@ -259,7 +321,7 @@ var resultTestCases = []resultTestCase{
|
||||
// in a policy failure for the outgoing hop.
|
||||
{
|
||||
name: "fail fee insufficient intermediate",
|
||||
route: &routeFourHop,
|
||||
route: routeFourHop,
|
||||
failureSrcIdx: 2,
|
||||
failure: lnwire.NewFeeInsufficient(
|
||||
0, lnwire.ChannelUpdate1{},
|
||||
@@ -282,7 +344,7 @@ var resultTestCases = []resultTestCase{
|
||||
// failure is terminal since the receiver can't process our onion.
|
||||
{
|
||||
name: "fail invalid onion payload final hop four",
|
||||
route: &routeFourHop,
|
||||
route: routeFourHop,
|
||||
failureSrcIdx: 4,
|
||||
failure: lnwire.NewInvalidOnionPayload(0, 0),
|
||||
|
||||
@@ -311,7 +373,7 @@ var resultTestCases = []resultTestCase{
|
||||
// Tests an invalid onion payload from a final hop on a three hop route.
|
||||
{
|
||||
name: "fail invalid onion payload final hop three",
|
||||
route: &routeThreeHop,
|
||||
route: routeThreeHop,
|
||||
failureSrcIdx: 3,
|
||||
failure: lnwire.NewInvalidOnionPayload(0, 0),
|
||||
|
||||
@@ -338,7 +400,7 @@ var resultTestCases = []resultTestCase{
|
||||
// can still try other paths.
|
||||
{
|
||||
name: "fail invalid onion payload intermediate",
|
||||
route: &routeFourHop,
|
||||
route: routeFourHop,
|
||||
failureSrcIdx: 3,
|
||||
failure: lnwire.NewInvalidOnionPayload(0, 0),
|
||||
|
||||
@@ -366,7 +428,7 @@ var resultTestCases = []resultTestCase{
|
||||
// since the remote node can't process our onion.
|
||||
{
|
||||
name: "fail invalid onion payload direct",
|
||||
route: &routeOneHop,
|
||||
route: routeOneHop,
|
||||
failureSrcIdx: 1,
|
||||
failure: lnwire.NewInvalidOnionPayload(0, 0),
|
||||
|
||||
@@ -385,7 +447,7 @@ var resultTestCases = []resultTestCase{
|
||||
// penalize mpp timeouts.
|
||||
{
|
||||
name: "one hop mpp timeout",
|
||||
route: &routeOneHop,
|
||||
route: routeOneHop,
|
||||
failureSrcIdx: 1,
|
||||
failure: &lnwire.FailMPPTimeout{},
|
||||
|
||||
@@ -402,7 +464,7 @@ var resultTestCases = []resultTestCase{
|
||||
// temporary measure while we decide how to penalize mpp timeouts.
|
||||
{
|
||||
name: "two hop mpp timeout",
|
||||
route: &routeTwoHop,
|
||||
route: routeTwoHop,
|
||||
failureSrcIdx: 2,
|
||||
failure: &lnwire.FailMPPTimeout{},
|
||||
|
||||
@@ -419,7 +481,7 @@ var resultTestCases = []resultTestCase{
|
||||
// disabled channel should be penalized for any amount.
|
||||
{
|
||||
name: "two hop channel disabled",
|
||||
route: &routeTwoHop,
|
||||
route: routeTwoHop,
|
||||
failureSrcIdx: 1,
|
||||
failure: &lnwire.FailChannelDisabled{},
|
||||
|
||||
@@ -437,7 +499,7 @@ var resultTestCases = []resultTestCase{
|
||||
// has not followed the specification properly.
|
||||
{
|
||||
name: "error after introduction",
|
||||
route: &blindedMultiToIntroduction,
|
||||
route: blindedMultiToIntroduction,
|
||||
failureSrcIdx: 2,
|
||||
// Note that the failure code doesn't matter in this case -
|
||||
// all we're worried about is errors originating after the
|
||||
@@ -460,7 +522,7 @@ var resultTestCases = []resultTestCase{
|
||||
// hop when we expected the introduction node to convert.
|
||||
{
|
||||
name: "final failure expected intro",
|
||||
route: &blindedMultiHop,
|
||||
route: blindedMultiHop,
|
||||
failureSrcIdx: 4,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -482,7 +544,7 @@ var resultTestCases = []resultTestCase{
|
||||
// introduction point.
|
||||
{
|
||||
name: "blinded multi-hop introduction",
|
||||
route: &blindedMultiHop,
|
||||
route: blindedMultiHop,
|
||||
failureSrcIdx: 2,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -498,7 +560,7 @@ var resultTestCases = []resultTestCase{
|
||||
// introduction point, which is a direct peer.
|
||||
{
|
||||
name: "blinded multi-hop introduction peer",
|
||||
route: &blindedMultiToIntroduction,
|
||||
route: blindedMultiToIntroduction,
|
||||
failureSrcIdx: 1,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -513,7 +575,7 @@ var resultTestCases = []resultTestCase{
|
||||
// connected to the introduction node.
|
||||
{
|
||||
name: "blinded single hop introduction failure",
|
||||
route: &blindedSingleHop,
|
||||
route: blindedSingleHop,
|
||||
failureSrcIdx: 2,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -529,7 +591,7 @@ var resultTestCases = []resultTestCase{
|
||||
// blinding error and is penalized for returning the wrong error.
|
||||
{
|
||||
name: "error before introduction",
|
||||
route: &blindedMultiHop,
|
||||
route: blindedMultiHop,
|
||||
failureSrcIdx: 1,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -549,7 +611,7 @@ var resultTestCases = []resultTestCase{
|
||||
// successful hop before the incorrect error.
|
||||
{
|
||||
name: "intermediate unexpected blinding",
|
||||
route: &routeThreeHop,
|
||||
route: routeThreeHop,
|
||||
failureSrcIdx: 2,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -570,7 +632,7 @@ var resultTestCases = []resultTestCase{
|
||||
// hops before the erring incoming link (the erring node if our peer).
|
||||
{
|
||||
name: "peer unexpected blinding",
|
||||
route: &routeThreeHop,
|
||||
route: routeThreeHop,
|
||||
failureSrcIdx: 1,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -588,7 +650,7 @@ var resultTestCases = []resultTestCase{
|
||||
// A node in a non-blinded route returns a blinding related error.
|
||||
{
|
||||
name: "final node unexpected blinding",
|
||||
route: &routeThreeHop,
|
||||
route: routeThreeHop,
|
||||
failureSrcIdx: 3,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -606,7 +668,7 @@ var resultTestCases = []resultTestCase{
|
||||
// Introduction node returns invalid blinding erroneously.
|
||||
{
|
||||
name: "final node intro blinding",
|
||||
route: &blindedIntroReceiver,
|
||||
route: blindedIntroReceiver,
|
||||
failureSrcIdx: 2,
|
||||
failure: &lnwire.FailInvalidBlinding{},
|
||||
|
||||
@@ -629,10 +691,15 @@ func TestResultInterpretation(t *testing.T) {
|
||||
|
||||
for _, testCase := range resultTestCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
i := interpretResult(
|
||||
testCase.route, testCase.success,
|
||||
&testCase.failureSrcIdx, testCase.failure,
|
||||
)
|
||||
var failure fn.Option[paymentFailure]
|
||||
if !testCase.success {
|
||||
failure = fn.Some(*newPaymentFailure(
|
||||
&testCase.failureSrcIdx,
|
||||
testCase.failure,
|
||||
))
|
||||
}
|
||||
|
||||
i := interpretResult(testCase.route, failure)
|
||||
|
||||
expected := testCase.expectedResult
|
||||
|
||||
|
||||
Reference in new issue
Block a user