routing+channeldb: migrate MC store to use minimal Route encoding
Add a new mcRoute type that houses the data about a route that MC actually uses. Then add a migration (channeldb/migration32) that migrates the existing store from its current serialisation to the new, more minimal serialisation.
This commit is contained in:
9 files changed
+873
-136
No files matched your search
@@ -208,7 +208,7 @@ type MissionControlPairSnapshot struct {
|
||||
type paymentResult struct {
|
||||
id uint64
|
||||
timeFwd, timeReply time.Time
|
||||
route *route.Route
|
||||
route *mcRoute
|
||||
success bool
|
||||
failureSourceIdx *int
|
||||
failure lnwire.FailureMessage
|
||||
@@ -438,7 +438,7 @@ func (m *MissionControl) ReportPaymentFail(paymentID uint64, rt *route.Route,
|
||||
id: paymentID,
|
||||
failureSourceIdx: failureSourceIdx,
|
||||
failure: failure,
|
||||
route: rt,
|
||||
route: extractMCRoute(rt),
|
||||
}
|
||||
|
||||
return m.processPaymentResult(result)
|
||||
@@ -456,7 +456,7 @@ func (m *MissionControl) ReportPaymentSuccess(paymentID uint64,
|
||||
timeReply: timestamp,
|
||||
id: paymentID,
|
||||
success: true,
|
||||
route: rt,
|
||||
route: extractMCRoute(rt),
|
||||
}
|
||||
|
||||
_, err := m.processPaymentResult(result)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"container/list"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -187,7 +188,7 @@ func serializeResult(rp *paymentResult) ([]byte, []byte, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := channeldb.SerializeRoute(&b, *rp.route); err != nil {
|
||||
if err := serializeRoute(&b, rp.route); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -211,6 +212,90 @@ func serializeResult(rp *paymentResult) ([]byte, []byte, error) {
|
||||
return key, b.Bytes(), nil
|
||||
}
|
||||
|
||||
// deserializeRoute deserializes the mcRoute from the given io.Reader.
|
||||
func deserializeRoute(r io.Reader) (*mcRoute, error) {
|
||||
var rt mcRoute
|
||||
if err := channeldb.ReadElements(r, &rt.totalAmount); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var pub []byte
|
||||
if err := channeldb.ReadElements(r, &pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(rt.sourcePubKey[:], pub)
|
||||
|
||||
var numHops uint32
|
||||
if err := channeldb.ReadElements(r, &numHops); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var hops []*mcHop
|
||||
for i := uint32(0); i < numHops; i++ {
|
||||
hop, err := deserializeHop(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hops = append(hops, hop)
|
||||
}
|
||||
rt.hops = hops
|
||||
|
||||
return &rt, nil
|
||||
}
|
||||
|
||||
// deserializeHop deserializes the mcHop from the given io.Reader.
|
||||
func deserializeHop(r io.Reader) (*mcHop, error) {
|
||||
var h mcHop
|
||||
|
||||
var pub []byte
|
||||
if err := channeldb.ReadElements(r, &pub); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(h.pubKeyBytes[:], pub)
|
||||
|
||||
if err := channeldb.ReadElements(r,
|
||||
&h.channelID, &h.amtToFwd, &h.hasBlindingPoint,
|
||||
&h.hasCustomRecords,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &h, nil
|
||||
}
|
||||
|
||||
// serializeRoute serializes a mcRoute and writes the resulting bytes to the
|
||||
// given io.Writer.
|
||||
func serializeRoute(w io.Writer, r *mcRoute) error {
|
||||
err := channeldb.WriteElements(w, r.totalAmount, r.sourcePubKey[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := channeldb.WriteElements(w, uint32(len(r.hops))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, h := range r.hops {
|
||||
if err := serializeHop(w, h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serializeHop serializes a mcHop and writes the resulting bytes to the given
|
||||
// io.Writer.
|
||||
func serializeHop(w io.Writer, h *mcHop) error {
|
||||
return channeldb.WriteElements(w,
|
||||
h.pubKeyBytes[:],
|
||||
h.channelID,
|
||||
h.amtToFwd,
|
||||
h.hasBlindingPoint,
|
||||
h.hasCustomRecords,
|
||||
)
|
||||
}
|
||||
|
||||
// deserializeResult deserializes a payment result.
|
||||
func deserializeResult(k, v []byte) (*paymentResult, error) {
|
||||
// Parse payment id.
|
||||
@@ -244,11 +329,11 @@ func deserializeResult(k, v []byte) (*paymentResult, error) {
|
||||
}
|
||||
|
||||
// Read route.
|
||||
route, err := channeldb.DeserializeRoute(r)
|
||||
route, err := deserializeRoute(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.route = &route
|
||||
result.route = route
|
||||
|
||||
// Read failure.
|
||||
failureBytes, err := wire.ReadVarBytes(
|
||||
@@ -499,7 +584,7 @@ func getResultKey(rp *paymentResult) []byte {
|
||||
// chronologically.
|
||||
byteOrder.PutUint64(keyBytes[:], uint64(rp.timeReply.UnixNano()))
|
||||
byteOrder.PutUint64(keyBytes[8:], rp.id)
|
||||
copy(keyBytes[16:], rp.route.SourcePubKey[:])
|
||||
copy(keyBytes[16:], rp.route.sourcePubKey[:])
|
||||
|
||||
return keyBytes[:]
|
||||
}
|
||||
@@ -18,12 +18,16 @@ const testMaxRecords = 2
|
||||
|
||||
var (
|
||||
// mcStoreTestRoute is a test route for the mission control store tests.
|
||||
mcStoreTestRoute = route.Route{
|
||||
SourcePubKey: route.Vertex{1},
|
||||
Hops: []*route.Hop{
|
||||
mcStoreTestRoute = mcRoute{
|
||||
totalAmount: lnwire.MilliSatoshi(5),
|
||||
sourcePubKey: route.Vertex{1},
|
||||
hops: []*mcHop{
|
||||
{
|
||||
PubKeyBytes: route.Vertex{2},
|
||||
LegacyPayload: true,
|
||||
pubKeyBytes: route.Vertex{2},
|
||||
channelID: 4,
|
||||
amtToFwd: lnwire.MilliSatoshi(7),
|
||||
hasCustomRecords: true,
|
||||
hasBlindingPoint: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ type interpretedResult struct {
|
||||
|
||||
// interpretResult interprets a payment outcome and returns an object that
|
||||
// contains information required to update mission control.
|
||||
func interpretResult(rt *route.Route, success bool, failureSrcIdx *int,
|
||||
func interpretResult(rt *mcRoute, success bool, failureSrcIdx *int,
|
||||
failure lnwire.FailureMessage) *interpretedResult {
|
||||
|
||||
i := &interpretedResult{
|
||||
@@ -92,15 +92,14 @@ func interpretResult(rt *route.Route, success bool, failureSrcIdx *int,
|
||||
}
|
||||
|
||||
// processSuccess processes a successful payment attempt.
|
||||
func (i *interpretedResult) processSuccess(route *route.Route) {
|
||||
func (i *interpretedResult) processSuccess(route *mcRoute) {
|
||||
// For successes, all nodes must have acted in the right way. Therefore
|
||||
// we mark all of them with a success result.
|
||||
i.successPairRange(route, 0, len(route.Hops)-1)
|
||||
i.successPairRange(route, 0, len(route.hops)-1)
|
||||
}
|
||||
|
||||
// processFail processes a failed payment attempt.
|
||||
func (i *interpretedResult) processFail(
|
||||
rt *route.Route, errSourceIdx *int,
|
||||
func (i *interpretedResult) processFail(rt *mcRoute, errSourceIdx *int,
|
||||
failure lnwire.FailureMessage) {
|
||||
|
||||
if errSourceIdx == nil {
|
||||
@@ -125,10 +124,8 @@ func (i *interpretedResult) processFail(
|
||||
i.processPaymentOutcomeSelf(rt, failure)
|
||||
|
||||
// A failure from the final hop was received.
|
||||
case len(rt.Hops):
|
||||
i.processPaymentOutcomeFinal(
|
||||
rt, failure,
|
||||
)
|
||||
case len(rt.hops):
|
||||
i.processPaymentOutcomeFinal(rt, failure)
|
||||
|
||||
// An intermediate hop failed. Interpret the outcome, update reputation
|
||||
// and try again.
|
||||
@@ -144,7 +141,7 @@ func (i *interpretedResult) processFail(
|
||||
// node. This indicates that the introduction node is not obeying the route
|
||||
// blinding specification, as we expect all errors from the introduction node
|
||||
// to be source from it.
|
||||
func (i *interpretedResult) processPaymentOutcomeBadIntro(route *route.Route,
|
||||
func (i *interpretedResult) processPaymentOutcomeBadIntro(route *mcRoute,
|
||||
introIdx, errSourceIdx int) {
|
||||
|
||||
// We fail the introduction node for not obeying the specification.
|
||||
@@ -161,14 +158,14 @@ func (i *interpretedResult) processPaymentOutcomeBadIntro(route *route.Route,
|
||||
// a final failure reason because the recipient can't process the
|
||||
// payment (independent of the introduction failing to convert the
|
||||
// error, we can't complete the payment if the last hop fails).
|
||||
if errSourceIdx == len(route.Hops) {
|
||||
if errSourceIdx == len(route.hops) {
|
||||
i.finalFailureReason = &reasonError
|
||||
}
|
||||
}
|
||||
|
||||
// processPaymentOutcomeSelf handles failures sent by ourselves.
|
||||
func (i *interpretedResult) processPaymentOutcomeSelf(
|
||||
rt *route.Route, failure lnwire.FailureMessage) {
|
||||
func (i *interpretedResult) processPaymentOutcomeSelf(rt *mcRoute,
|
||||
failure lnwire.FailureMessage) {
|
||||
|
||||
switch failure.(type) {
|
||||
|
||||
@@ -181,7 +178,7 @@ func (i *interpretedResult) processPaymentOutcomeSelf(
|
||||
i.failNode(rt, 1)
|
||||
|
||||
// If this was a payment to a direct peer, we can stop trying.
|
||||
if len(rt.Hops) == 1 {
|
||||
if len(rt.hops) == 1 {
|
||||
i.finalFailureReason = &reasonError
|
||||
}
|
||||
|
||||
@@ -191,15 +188,15 @@ func (i *interpretedResult) processPaymentOutcomeSelf(
|
||||
// available in the link has been updated.
|
||||
default:
|
||||
log.Warnf("Routing failure for local channel %v occurred",
|
||||
rt.Hops[0].ChannelID)
|
||||
rt.hops[0].channelID)
|
||||
}
|
||||
}
|
||||
|
||||
// processPaymentOutcomeFinal handles failures sent by the final hop.
|
||||
func (i *interpretedResult) processPaymentOutcomeFinal(
|
||||
route *route.Route, failure lnwire.FailureMessage) {
|
||||
func (i *interpretedResult) processPaymentOutcomeFinal(route *mcRoute,
|
||||
failure lnwire.FailureMessage) {
|
||||
|
||||
n := len(route.Hops)
|
||||
n := len(route.hops)
|
||||
|
||||
failNode := func() {
|
||||
i.failNode(route, n)
|
||||
@@ -292,9 +289,10 @@ func (i *interpretedResult) processPaymentOutcomeFinal(
|
||||
|
||||
// processPaymentOutcomeIntermediate handles failures sent by an intermediate
|
||||
// hop.
|
||||
func (i *interpretedResult) processPaymentOutcomeIntermediate(
|
||||
route *route.Route, errorSourceIdx int,
|
||||
failure lnwire.FailureMessage) {
|
||||
//
|
||||
//nolint:funlen
|
||||
func (i *interpretedResult) processPaymentOutcomeIntermediate(route *mcRoute,
|
||||
errorSourceIdx int, failure lnwire.FailureMessage) {
|
||||
|
||||
reportOutgoing := func() {
|
||||
i.failPair(
|
||||
@@ -398,8 +396,8 @@ func (i *interpretedResult) processPaymentOutcomeIntermediate(
|
||||
// Set the node pair for which a channel update may be out of
|
||||
// date. The second chance logic uses the policyFailure field.
|
||||
i.policyFailure = &DirectedNodePair{
|
||||
From: route.Hops[errorSourceIdx-1].PubKeyBytes,
|
||||
To: route.Hops[errorSourceIdx].PubKeyBytes,
|
||||
From: route.hops[errorSourceIdx-1].pubKeyBytes,
|
||||
To: route.hops[errorSourceIdx].pubKeyBytes,
|
||||
}
|
||||
|
||||
reportOutgoing()
|
||||
@@ -427,8 +425,8 @@ func (i *interpretedResult) processPaymentOutcomeIntermediate(
|
||||
// Set the node pair for which a channel update may be out of
|
||||
// date. The second chance logic uses the policyFailure field.
|
||||
i.policyFailure = &DirectedNodePair{
|
||||
From: route.Hops[errorSourceIdx-1].PubKeyBytes,
|
||||
To: route.Hops[errorSourceIdx].PubKeyBytes,
|
||||
From: route.hops[errorSourceIdx-1].pubKeyBytes,
|
||||
To: route.hops[errorSourceIdx].pubKeyBytes,
|
||||
}
|
||||
|
||||
// We report incoming channel. If a second pair is granted in
|
||||
@@ -502,16 +500,14 @@ func (i *interpretedResult) processPaymentOutcomeIntermediate(
|
||||
// Note that if LND is extended to support multiple blinded
|
||||
// routes, this will terminate the payment without re-trying
|
||||
// the other routes.
|
||||
if introIdx == len(route.Hops)-1 {
|
||||
if introIdx == len(route.hops)-1 {
|
||||
i.finalFailureReason = &reasonError
|
||||
} else {
|
||||
// If there are other hops between the recipient and
|
||||
// introduction node, then we just penalize the last
|
||||
// hop in the blinded route to minimize the storage of
|
||||
// results for ephemeral keys.
|
||||
i.failPairBalance(
|
||||
route, len(route.Hops)-1,
|
||||
)
|
||||
i.failPairBalance(route, len(route.hops)-1)
|
||||
}
|
||||
|
||||
// In all other cases, we penalize the reporting node. These are all
|
||||
@@ -525,9 +521,9 @@ func (i *interpretedResult) processPaymentOutcomeIntermediate(
|
||||
// route, using the same indexing in the route that we use for errorSourceIdx
|
||||
// (i.e., that we consider our own node to be at index zero). A boolean is
|
||||
// returned to indicate whether the route contains a blinded portion at all.
|
||||
func introductionPointIndex(route *route.Route) (int, bool) {
|
||||
for i, hop := range route.Hops {
|
||||
if hop.BlindingPoint != nil {
|
||||
func introductionPointIndex(route *mcRoute) (int, bool) {
|
||||
for i, hop := range route.hops {
|
||||
if hop.hasBlindingPoint {
|
||||
return i + 1, true
|
||||
}
|
||||
}
|
||||
@@ -537,8 +533,8 @@ func introductionPointIndex(route *route.Route) (int, bool) {
|
||||
|
||||
// processPaymentOutcomeUnknown processes a payment outcome for which no failure
|
||||
// message or source is available.
|
||||
func (i *interpretedResult) processPaymentOutcomeUnknown(route *route.Route) {
|
||||
n := len(route.Hops)
|
||||
func (i *interpretedResult) processPaymentOutcomeUnknown(route *mcRoute) {
|
||||
n := len(route.hops)
|
||||
|
||||
// If this is a direct payment, the destination must be at fault.
|
||||
if n == 1 {
|
||||
@@ -553,12 +549,62 @@ func (i *interpretedResult) processPaymentOutcomeUnknown(route *route.Route) {
|
||||
i.failPairRange(route, 0, n-1)
|
||||
}
|
||||
|
||||
// extractMCRoute extracts the fields required by MC from the Route struct to
|
||||
// create the more minimal mcRoute struct.
|
||||
func extractMCRoute(route *route.Route) *mcRoute {
|
||||
return &mcRoute{
|
||||
sourcePubKey: route.SourcePubKey,
|
||||
totalAmount: route.TotalAmount,
|
||||
hops: extractMCHops(route.Hops),
|
||||
}
|
||||
}
|
||||
|
||||
// extractMCHops extracts the Hop fields that MC actually uses from a slice of
|
||||
// Hops.
|
||||
func extractMCHops(hops []*route.Hop) []*mcHop {
|
||||
mcHops := make([]*mcHop, len(hops))
|
||||
for i, hop := range hops {
|
||||
mcHops[i] = extractMCHop(hop)
|
||||
}
|
||||
|
||||
return mcHops
|
||||
}
|
||||
|
||||
// extractMCHop extracts the Hop fields that MC actually uses from a Hop.
|
||||
func extractMCHop(hop *route.Hop) *mcHop {
|
||||
return &mcHop{
|
||||
channelID: hop.ChannelID,
|
||||
pubKeyBytes: hop.PubKeyBytes,
|
||||
amtToFwd: hop.AmtToForward,
|
||||
hasBlindingPoint: hop.BlindingPoint != nil,
|
||||
hasCustomRecords: len(hop.CustomRecords) > 0,
|
||||
}
|
||||
}
|
||||
|
||||
// mcRoute holds the bare minimum info about a payment attempt route that MC
|
||||
// requires.
|
||||
type mcRoute struct {
|
||||
sourcePubKey route.Vertex
|
||||
totalAmount lnwire.MilliSatoshi
|
||||
hops []*mcHop
|
||||
}
|
||||
|
||||
// mcHop holds the bare minimum info about a payment attempt route hop that MC
|
||||
// requires.
|
||||
type mcHop struct {
|
||||
channelID uint64
|
||||
pubKeyBytes route.Vertex
|
||||
amtToFwd lnwire.MilliSatoshi
|
||||
hasBlindingPoint bool
|
||||
hasCustomRecords bool
|
||||
}
|
||||
|
||||
// failNode marks the node indicated by idx in the route as failed. It also
|
||||
// marks the incoming and outgoing channels of the node as failed. This function
|
||||
// intentionally panics when the self node is failed.
|
||||
func (i *interpretedResult) failNode(rt *route.Route, idx int) {
|
||||
func (i *interpretedResult) failNode(rt *mcRoute, idx int) {
|
||||
// Mark the node as failing.
|
||||
i.nodeFailure = &rt.Hops[idx-1].PubKeyBytes
|
||||
i.nodeFailure = &rt.hops[idx-1].pubKeyBytes
|
||||
|
||||
// Mark the incoming connection as failed for the node. We intent to
|
||||
// penalize as much as we can for a node level failure, including future
|
||||
@@ -574,7 +620,7 @@ func (i *interpretedResult) failNode(rt *route.Route, idx int) {
|
||||
|
||||
// If not the ultimate node, mark the outgoing connection as failed for
|
||||
// the node.
|
||||
if idx < len(rt.Hops) {
|
||||
if idx < len(rt.hops) {
|
||||
outgoingChannelIdx := idx
|
||||
outPair, _ := getPair(rt, outgoingChannelIdx)
|
||||
i.pairResults[outPair] = failPairResult(0)
|
||||
@@ -584,18 +630,14 @@ func (i *interpretedResult) failNode(rt *route.Route, idx int) {
|
||||
|
||||
// failPairRange marks the node pairs from node fromIdx to node toIdx as failed
|
||||
// in both direction.
|
||||
func (i *interpretedResult) failPairRange(
|
||||
rt *route.Route, fromIdx, toIdx int) {
|
||||
|
||||
func (i *interpretedResult) failPairRange(rt *mcRoute, fromIdx, toIdx int) {
|
||||
for idx := fromIdx; idx <= toIdx; idx++ {
|
||||
i.failPair(rt, idx)
|
||||
}
|
||||
}
|
||||
|
||||
// failPair marks a pair as failed in both directions.
|
||||
func (i *interpretedResult) failPair(
|
||||
rt *route.Route, idx int) {
|
||||
|
||||
func (i *interpretedResult) failPair(rt *mcRoute, idx int) {
|
||||
pair, _ := getPair(rt, idx)
|
||||
|
||||
// Report pair in both directions without a minimum penalization amount.
|
||||
@@ -604,9 +646,7 @@ func (i *interpretedResult) failPair(
|
||||
}
|
||||
|
||||
// failPairBalance marks a pair as failed with a minimum penalization amount.
|
||||
func (i *interpretedResult) failPairBalance(
|
||||
rt *route.Route, channelIdx int) {
|
||||
|
||||
func (i *interpretedResult) failPairBalance(rt *mcRoute, channelIdx int) {
|
||||
pair, amt := getPair(rt, channelIdx)
|
||||
|
||||
i.pairResults[pair] = failPairResult(amt)
|
||||
@@ -614,9 +654,7 @@ func (i *interpretedResult) failPairBalance(
|
||||
|
||||
// successPairRange marks the node pairs from node fromIdx to node toIdx as
|
||||
// succeeded.
|
||||
func (i *interpretedResult) successPairRange(
|
||||
rt *route.Route, fromIdx, toIdx int) {
|
||||
|
||||
func (i *interpretedResult) successPairRange(rt *mcRoute, fromIdx, toIdx int) {
|
||||
for idx := fromIdx; idx <= toIdx; idx++ {
|
||||
pair, amt := getPair(rt, idx)
|
||||
|
||||
@@ -626,21 +664,21 @@ func (i *interpretedResult) successPairRange(
|
||||
|
||||
// getPair returns a node pair from the route and the amount passed between that
|
||||
// pair.
|
||||
func getPair(rt *route.Route, channelIdx int) (DirectedNodePair,
|
||||
func getPair(rt *mcRoute, channelIdx int) (DirectedNodePair,
|
||||
lnwire.MilliSatoshi) {
|
||||
|
||||
nodeTo := rt.Hops[channelIdx].PubKeyBytes
|
||||
nodeTo := rt.hops[channelIdx].pubKeyBytes
|
||||
var (
|
||||
nodeFrom route.Vertex
|
||||
amt lnwire.MilliSatoshi
|
||||
)
|
||||
|
||||
if channelIdx == 0 {
|
||||
nodeFrom = rt.SourcePubKey
|
||||
amt = rt.TotalAmount
|
||||
nodeFrom = rt.sourcePubKey
|
||||
amt = rt.totalAmount
|
||||
} else {
|
||||
nodeFrom = rt.Hops[channelIdx-1].PubKeyBytes
|
||||
amt = rt.Hops[channelIdx-1].AmtToForward
|
||||
nodeFrom = rt.hops[channelIdx-1].pubKeyBytes
|
||||
amt = rt.hops[channelIdx-1].amtToFwd
|
||||
}
|
||||
|
||||
pair := NewDirectedNodePair(nodeFrom, nodeTo)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
@@ -15,109 +14,105 @@ var (
|
||||
{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4},
|
||||
}
|
||||
|
||||
// blindingPoint provides a non-nil blinding point (value is never
|
||||
// used).
|
||||
blindingPoint = &btcec.PublicKey{}
|
||||
|
||||
routeOneHop = route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{PubKeyBytes: hops[1], AmtToForward: 99},
|
||||
routeOneHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
},
|
||||
}
|
||||
|
||||
routeTwoHop = route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{PubKeyBytes: hops[1], AmtToForward: 99},
|
||||
{PubKeyBytes: hops[2], AmtToForward: 97},
|
||||
routeTwoHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{pubKeyBytes: hops[2], amtToFwd: 97},
|
||||
},
|
||||
}
|
||||
|
||||
routeThreeHop = 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},
|
||||
routeThreeHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{pubKeyBytes: hops[2], amtToFwd: 97},
|
||||
{pubKeyBytes: hops[3], amtToFwd: 94},
|
||||
},
|
||||
}
|
||||
|
||||
routeFourHop = 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},
|
||||
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},
|
||||
},
|
||||
}
|
||||
|
||||
// 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 = route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{PubKeyBytes: hops[1], AmtToForward: 99},
|
||||
blindedMultiHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 95,
|
||||
BlindingPoint: blindingPoint,
|
||||
pubKeyBytes: hops[2],
|
||||
amtToFwd: 95,
|
||||
hasBlindingPoint: true,
|
||||
},
|
||||
{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 = route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{PubKeyBytes: hops[1], AmtToForward: 99},
|
||||
blindedSingleHop = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 99},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 95,
|
||||
BlindingPoint: blindingPoint,
|
||||
pubKeyBytes: hops[2],
|
||||
amtToFwd: 95,
|
||||
hasBlindingPoint: true,
|
||||
},
|
||||
{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 = route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
blindedMultiToIntroduction = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{
|
||||
PubKeyBytes: hops[1],
|
||||
AmtToForward: 90,
|
||||
BlindingPoint: blindingPoint,
|
||||
pubKeyBytes: hops[1],
|
||||
amtToFwd: 90,
|
||||
hasBlindingPoint: true,
|
||||
},
|
||||
{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 = route.Route{
|
||||
SourcePubKey: hops[0],
|
||||
TotalAmount: 100,
|
||||
Hops: []*route.Hop{
|
||||
{PubKeyBytes: hops[1], AmtToForward: 95},
|
||||
blindedIntroReceiver = mcRoute{
|
||||
sourcePubKey: hops[0],
|
||||
totalAmount: 100,
|
||||
hops: []*mcHop{
|
||||
{pubKeyBytes: hops[1], amtToFwd: 95},
|
||||
{
|
||||
PubKeyBytes: hops[2],
|
||||
AmtToForward: 90,
|
||||
BlindingPoint: blindingPoint,
|
||||
pubKeyBytes: hops[2],
|
||||
amtToFwd: 90,
|
||||
hasBlindingPoint: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -134,7 +129,7 @@ func getPolicyFailure(from, to int) *DirectedNodePair {
|
||||
|
||||
type resultTestCase struct {
|
||||
name string
|
||||
route *route.Route
|
||||
route *mcRoute
|
||||
success bool
|
||||
failureSrcIdx int
|
||||
failure lnwire.FailureMessage
|
||||
@@ -159,7 +154,7 @@ var resultTestCases = []resultTestCase{
|
||||
},
|
||||
},
|
||||
|
||||
// Tests that a expiry too soon failure result is properly interpreted.
|
||||
// Tests that an expiry too soon failure result is properly interpreted.
|
||||
{
|
||||
name: "fail expiry too soon",
|
||||
route: &routeFourHop,
|
||||
|
||||
Reference in new issue
Block a user