zpay32: move HopHint and DefaultFinalCLTVDelta

This commit is contained in:
Joost Jager 2019-02-19 09:09:01 +01:00
parent 652ebb1652
commit 2be1051fb6
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
11 changed files with 70 additions and 66 deletions

@ -7,7 +7,6 @@ import (
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/zpay32" "github.com/lightningnetwork/lnd/zpay32"
) )
@ -93,7 +92,7 @@ func CreateRPCInvoice(invoice *channeldb.Invoice,
// CreateRPCRouteHints takes in the decoded form of an invoice's route hints // CreateRPCRouteHints takes in the decoded form of an invoice's route hints
// and converts them into the lnrpc type. // and converts them into the lnrpc type.
func CreateRPCRouteHints(routeHints [][]routing.HopHint) []*lnrpc.RouteHint { func CreateRPCRouteHints(routeHints [][]zpay32.HopHint) []*lnrpc.RouteHint {
var res []*lnrpc.RouteHint var res []*lnrpc.RouteHint
for _, route := range routeHints { for _, route := range routeHints {

@ -8,6 +8,7 @@ import (
"github.com/coreos/bbolt" "github.com/coreos/bbolt"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/zpay32"
) )
const ( const (
@ -152,7 +153,7 @@ func (m *missionControl) GraphPruneView() graphPruneView {
// view from Mission Control. An optional set of routing hints can be provided // view from Mission Control. An optional set of routing hints can be provided
// in order to populate additional edges to explore when finding a path to the // in order to populate additional edges to explore when finding a path to the
// payment's destination. // payment's destination.
func (m *missionControl) NewPaymentSession(routeHints [][]HopHint, func (m *missionControl) NewPaymentSession(routeHints [][]zpay32.HopHint,
target Vertex) (*paymentSession, error) { target Vertex) (*paymentSession, error) {
viewSnapshot := m.GraphPruneView() viewSnapshot := m.GraphPruneView()

@ -39,28 +39,6 @@ const (
RiskFactorBillionths = 15 RiskFactorBillionths = 15
) )
// HopHint is a routing hint that contains the minimum information of a channel
// required for an intermediate hop in a route to forward the payment to the
// next. This should be ideally used for private channels, since they are not
// publicly advertised to the network for routing.
type HopHint struct {
// NodeID is the public key of the node at the start of the channel.
NodeID *btcec.PublicKey
// ChannelID is the unique identifier of the channel.
ChannelID uint64
// FeeBaseMSat is the base fee of the channel in millisatoshis.
FeeBaseMSat uint32
// FeeProportionalMillionths is the fee rate, in millionths of a
// satoshi, for every satoshi sent through the channel.
FeeProportionalMillionths uint32
// CLTVExpiryDelta is the time-lock delta of the channel.
CLTVExpiryDelta uint16
}
// Hop represents an intermediate or final node of the route. This naming // Hop represents an intermediate or final node of the route. This naming
// is in line with the definition given in BOLT #4: Onion Routing Protocol. // is in line with the definition given in BOLT #4: Onion Routing Protocol.
// The struct houses the channel along which this hop can be reached and // The struct houses the channel along which this hop can be reached and

@ -22,6 +22,7 @@ import (
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/zpay32"
) )
const ( const (
@ -1746,11 +1747,11 @@ func TestPathFindSpecExample(t *testing.T) {
// The CLTV expiry should be the current height plus 9 (the expiry for // The CLTV expiry should be the current height plus 9 (the expiry for
// the B -> C channel. // the B -> C channel.
if firstRoute.TotalTimeLock != if firstRoute.TotalTimeLock !=
startingHeight+DefaultFinalCLTVDelta { startingHeight+zpay32.DefaultFinalCLTVDelta {
t.Fatalf("wrong total time lock: got %v, expecting %v", t.Fatalf("wrong total time lock: got %v, expecting %v",
firstRoute.TotalTimeLock, firstRoute.TotalTimeLock,
startingHeight+DefaultFinalCLTVDelta) startingHeight+zpay32.DefaultFinalCLTVDelta)
} }
// Next, we'll set A as the source node so we can assert that we create // Next, we'll set A as the source node so we can assert that we create
@ -1845,11 +1846,11 @@ func TestPathFindSpecExample(t *testing.T) {
// The outgoing CLTV value itself should be the current height plus 30 // The outgoing CLTV value itself should be the current height plus 30
// to meet Carol's requirements. // to meet Carol's requirements.
if routes[0].Hops[0].OutgoingTimeLock != if routes[0].Hops[0].OutgoingTimeLock !=
startingHeight+DefaultFinalCLTVDelta { startingHeight+zpay32.DefaultFinalCLTVDelta {
t.Fatalf("wrong total time lock: got %v, expecting %v", t.Fatalf("wrong total time lock: got %v, expecting %v",
routes[0].Hops[0].OutgoingTimeLock, routes[0].Hops[0].OutgoingTimeLock,
startingHeight+DefaultFinalCLTVDelta) startingHeight+zpay32.DefaultFinalCLTVDelta)
} }
// For B -> C, we assert that the final hop also has the proper // For B -> C, we assert that the final hop also has the proper
@ -1860,11 +1861,11 @@ func TestPathFindSpecExample(t *testing.T) {
lastHop.AmtToForward, amt) lastHop.AmtToForward, amt)
} }
if lastHop.OutgoingTimeLock != if lastHop.OutgoingTimeLock !=
startingHeight+DefaultFinalCLTVDelta { startingHeight+zpay32.DefaultFinalCLTVDelta {
t.Fatalf("wrong total time lock: got %v, expecting %v", t.Fatalf("wrong total time lock: got %v, expecting %v",
lastHop.OutgoingTimeLock, lastHop.OutgoingTimeLock,
startingHeight+DefaultFinalCLTVDelta) startingHeight+zpay32.DefaultFinalCLTVDelta)
} }
// We'll also make similar assertions for the second route from A to C // We'll also make similar assertions for the second route from A to C
@ -1875,7 +1876,7 @@ func TestPathFindSpecExample(t *testing.T) {
t.Fatalf("wrong amount: got %v, expected %v", t.Fatalf("wrong amount: got %v, expected %v",
secondRoute.TotalAmount, expectedAmt) secondRoute.TotalAmount, expectedAmt)
} }
expectedTimeLock := startingHeight + daveFinalCLTV + DefaultFinalCLTVDelta expectedTimeLock := startingHeight + daveFinalCLTV + zpay32.DefaultFinalCLTVDelta
if secondRoute.TotalTimeLock != uint32(expectedTimeLock) { if secondRoute.TotalTimeLock != uint32(expectedTimeLock) {
t.Fatalf("wrong total time lock: got %v, expecting %v", t.Fatalf("wrong total time lock: got %v, expecting %v",
secondRoute.TotalTimeLock, expectedTimeLock) secondRoute.TotalTimeLock, expectedTimeLock)
@ -1885,7 +1886,7 @@ func TestPathFindSpecExample(t *testing.T) {
t.Fatalf("wrong forward amount: got %v, expected %v", t.Fatalf("wrong forward amount: got %v, expected %v",
onionPayload.AmtToForward, amt) onionPayload.AmtToForward, amt)
} }
expectedTimeLock = startingHeight + DefaultFinalCLTVDelta expectedTimeLock = startingHeight + zpay32.DefaultFinalCLTVDelta
if onionPayload.OutgoingTimeLock != uint32(expectedTimeLock) { if onionPayload.OutgoingTimeLock != uint32(expectedTimeLock) {
t.Fatalf("wrong outgoing time lock: got %v, expecting %v", t.Fatalf("wrong outgoing time lock: got %v, expecting %v",
onionPayload.OutgoingTimeLock, onionPayload.OutgoingTimeLock,
@ -1899,11 +1900,11 @@ func TestPathFindSpecExample(t *testing.T) {
lastHop.AmtToForward, amt) lastHop.AmtToForward, amt)
} }
if lastHop.OutgoingTimeLock != if lastHop.OutgoingTimeLock !=
startingHeight+DefaultFinalCLTVDelta { startingHeight+zpay32.DefaultFinalCLTVDelta {
t.Fatalf("wrong total time lock: got %v, expecting %v", t.Fatalf("wrong total time lock: got %v, expecting %v",
lastHop.OutgoingTimeLock, lastHop.OutgoingTimeLock,
startingHeight+DefaultFinalCLTVDelta) startingHeight+zpay32.DefaultFinalCLTVDelta)
} }
} }

@ -25,13 +25,10 @@ import (
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/multimutex" "github.com/lightningnetwork/lnd/multimutex"
"github.com/lightningnetwork/lnd/routing/chainview" "github.com/lightningnetwork/lnd/routing/chainview"
"github.com/lightningnetwork/lnd/zpay32"
) )
const ( const (
// DefaultFinalCLTVDelta is the default value to be used as the final
// CLTV delta for a route if one is unspecified.
DefaultFinalCLTVDelta = 9
// defaultPayAttemptTimeout is a duration that we'll use to determine // defaultPayAttemptTimeout is a duration that we'll use to determine
// if we should give up on a payment attempt. This will be used if a // if we should give up on a payment attempt. This will be used if a
// value isn't specified in the LightningNode struct. // value isn't specified in the LightningNode struct.
@ -1331,7 +1328,7 @@ func (r *ChannelRouter) FindRoutes(source, target Vertex,
var finalCLTVDelta uint16 var finalCLTVDelta uint16
if len(finalExpiry) == 0 { if len(finalExpiry) == 0 {
finalCLTVDelta = DefaultFinalCLTVDelta finalCLTVDelta = zpay32.DefaultFinalCLTVDelta
} else { } else {
finalCLTVDelta = finalExpiry[0] finalCLTVDelta = finalExpiry[0]
} }
@ -1551,7 +1548,7 @@ type LightningPayment struct {
// multiple routes, ensure the hop hints within each route are chained // multiple routes, ensure the hop hints within each route are chained
// together and sorted in forward order in order to reach the // together and sorted in forward order in order to reach the
// destination successfully. // destination successfully.
RouteHints [][]HopHint RouteHints [][]zpay32.HopHint
// OutgoingChannelID is the channel that needs to be taken to the first // OutgoingChannelID is the channel that needs to be taken to the first
// hop. If nil, any channel may be used. // hop. If nil, any channel may be used.
@ -1628,7 +1625,7 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment,
var finalCLTVDelta uint16 var finalCLTVDelta uint16
if payment.FinalCLTVDelta == nil { if payment.FinalCLTVDelta == nil {
finalCLTVDelta = DefaultFinalCLTVDelta finalCLTVDelta = zpay32.DefaultFinalCLTVDelta
} else { } else {
finalCLTVDelta = *payment.FinalCLTVDelta finalCLTVDelta = *payment.FinalCLTVDelta
} }

@ -19,6 +19,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/zpay32"
) )
// defaultNumRoutes is the default value for the maximum number of routes to // defaultNumRoutes is the default value for the maximum number of routes to
@ -186,7 +187,7 @@ func TestFindRoutesFeeSorting(t *testing.T) {
routes, err := ctx.router.FindRoutes( routes, err := ctx.router.FindRoutes(
ctx.router.selfNode.PubKeyBytes, ctx.router.selfNode.PubKeyBytes,
target, paymentAmt, noRestrictions, defaultNumRoutes, target, paymentAmt, noRestrictions, defaultNumRoutes,
DefaultFinalCLTVDelta, zpay32.DefaultFinalCLTVDelta,
) )
if err != nil { if err != nil {
t.Fatalf("unable to find any routes: %v", err) t.Fatalf("unable to find any routes: %v", err)
@ -248,7 +249,7 @@ func TestFindRoutesWithFeeLimit(t *testing.T) {
routes, err := ctx.router.FindRoutes( routes, err := ctx.router.FindRoutes(
ctx.router.selfNode.PubKeyBytes, ctx.router.selfNode.PubKeyBytes,
target, paymentAmt, restrictions, defaultNumRoutes, target, paymentAmt, restrictions, defaultNumRoutes,
DefaultFinalCLTVDelta, zpay32.DefaultFinalCLTVDelta,
) )
if err != nil { if err != nil {
t.Fatalf("unable to find any routes: %v", err) t.Fatalf("unable to find any routes: %v", err)
@ -1345,7 +1346,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
routes, err := ctx.router.FindRoutes( routes, err := ctx.router.FindRoutes(
ctx.router.selfNode.PubKeyBytes, ctx.router.selfNode.PubKeyBytes,
targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes, targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes,
DefaultFinalCLTVDelta, zpay32.DefaultFinalCLTVDelta,
) )
if err != nil { if err != nil {
t.Fatalf("unable to find any routes: %v", err) t.Fatalf("unable to find any routes: %v", err)
@ -1391,7 +1392,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
routes, err = ctx.router.FindRoutes( routes, err = ctx.router.FindRoutes(
ctx.router.selfNode.PubKeyBytes, ctx.router.selfNode.PubKeyBytes,
targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes, targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes,
DefaultFinalCLTVDelta, zpay32.DefaultFinalCLTVDelta,
) )
if err != nil { if err != nil {
t.Fatalf("unable to find any routes: %v", err) t.Fatalf("unable to find any routes: %v", err)

@ -2796,7 +2796,7 @@ type rpcPaymentIntent struct {
dest routing.Vertex dest routing.Vertex
rHash [32]byte rHash [32]byte
cltvDelta uint16 cltvDelta uint16
routeHints [][]routing.HopHint routeHints [][]zpay32.HopHint
outgoingChannelID *uint64 outgoingChannelID *uint64
routes []*routing.Route routes []*routing.Route
@ -3515,7 +3515,7 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
// Finally, create the routing hint for this channel and // Finally, create the routing hint for this channel and
// add it to our list of route hints. // add it to our list of route hints.
hint := routing.HopHint{ hint := zpay32.HopHint{
NodeID: channel.IdentityPub, NodeID: channel.IdentityPub,
ChannelID: chanID, ChannelID: chanID,
FeeBaseMSat: uint32(remotePolicy.FeeBaseMSat), FeeBaseMSat: uint32(remotePolicy.FeeBaseMSat),
@ -3527,12 +3527,11 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
// Include the route hint in our set of options that // Include the route hint in our set of options that
// will be used when creating the invoice. // will be used when creating the invoice.
routeHint := []routing.HopHint{hint} routeHint := []zpay32.HopHint{hint}
options = append(options, zpay32.RouteHint(routeHint)) options = append(options, zpay32.RouteHint(routeHint))
numHints++ numHints++
} }
} }
// Create and encode the payment request as a bech32 (zpay32) string. // Create and encode the payment request as a bech32 (zpay32) string.

31
zpay32/hophint.go Normal file

@ -0,0 +1,31 @@
package zpay32
import "github.com/btcsuite/btcd/btcec"
const (
// DefaultFinalCLTVDelta is the default value to be used as the final
// CLTV delta for a route if one is unspecified.
DefaultFinalCLTVDelta = 9
)
// HopHint is a routing hint that contains the minimum information of a channel
// required for an intermediate hop in a route to forward the payment to the
// next. This should be ideally used for private channels, since they are not
// publicly advertised to the network for routing.
type HopHint struct {
// NodeID is the public key of the node at the start of the channel.
NodeID *btcec.PublicKey
// ChannelID is the unique identifier of the channel.
ChannelID uint64
// FeeBaseMSat is the base fee of the channel in millisatoshis.
FeeBaseMSat uint32
// FeeProportionalMillionths is the fee rate, in millionths of a
// satoshi, for every satoshi sent through the channel.
FeeProportionalMillionths uint32
// CLTVExpiryDelta is the time-lock delta of the channel.
CLTVExpiryDelta uint16
}

@ -13,7 +13,6 @@ import (
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/bech32" "github.com/btcsuite/btcutil/bech32"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing"
) )
const ( const (
@ -146,7 +145,7 @@ type Invoice struct {
// represent private routes. // represent private routes.
// //
// NOTE: This is optional. // NOTE: This is optional.
RouteHints [][]routing.HopHint RouteHints [][]HopHint
} }
// Amount is a functional option that allows callers of NewInvoice to set the // Amount is a functional option that allows callers of NewInvoice to set the
@ -214,7 +213,7 @@ func FallbackAddr(fallbackAddr btcutil.Address) func(*Invoice) {
// RouteHint is a functional option that allows callers of NewInvoice to add // RouteHint is a functional option that allows callers of NewInvoice to add
// one or more hop hints that represent a private route to the destination. // one or more hop hints that represent a private route to the destination.
func RouteHint(routeHint []routing.HopHint) func(*Invoice) { func RouteHint(routeHint []HopHint) func(*Invoice) {
return func(i *Invoice) { return func(i *Invoice) {
i.RouteHints = append(i.RouteHints, routeHint) i.RouteHints = append(i.RouteHints, routeHint)
} }
@ -476,7 +475,7 @@ func (invoice *Invoice) MinFinalCLTVExpiry() uint64 {
return *invoice.minFinalCLTVExpiry return *invoice.minFinalCLTVExpiry
} }
return routing.DefaultFinalCLTVDelta return DefaultFinalCLTVDelta
} }
// validateInvoice does a sanity check of the provided Invoice, making sure it // validateInvoice does a sanity check of the provided Invoice, making sure it
@ -843,7 +842,7 @@ func parseFallbackAddr(data []byte, net *chaincfg.Params) (btcutil.Address, erro
// parseRouteHint converts the data (encoded in base32) into an array containing // parseRouteHint converts the data (encoded in base32) into an array containing
// one or more routing hop hints that represent a single route hint. // one or more routing hop hints that represent a single route hint.
func parseRouteHint(data []byte) ([]routing.HopHint, error) { func parseRouteHint(data []byte) ([]HopHint, error) {
base256Data, err := bech32.ConvertBits(data, 5, 8, false) base256Data, err := bech32.ConvertBits(data, 5, 8, false)
if err != nil { if err != nil {
return nil, err return nil, err
@ -854,10 +853,10 @@ func parseRouteHint(data []byte) ([]routing.HopHint, error) {
"got %d", hopHintLen, len(base256Data)) "got %d", hopHintLen, len(base256Data))
} }
var routeHint []routing.HopHint var routeHint []HopHint
for len(base256Data) > 0 { for len(base256Data) > 0 {
hopHint := routing.HopHint{} hopHint := HopHint{}
hopHint.NodeID, err = btcec.ParsePubKey(base256Data[:33], btcec.S256()) hopHint.NodeID, err = btcec.ParsePubKey(base256Data[:33], btcec.S256())
if err != nil { if err != nil {
return nil, err return nil, err

@ -12,7 +12,6 @@ import (
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/bech32" "github.com/btcsuite/btcutil/bech32"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing"
) )
// TestDecodeAmount ensures that the amount string in the hrp of the Invoice // TestDecodeAmount ensures that the amount string in the hrp of the Invoice
@ -738,7 +737,7 @@ func TestParseRouteHint(t *testing.T) {
tests := []struct { tests := []struct {
data []byte data []byte
valid bool valid bool
result []routing.HopHint result []HopHint
}{ }{
{ {
data: []byte{0x0, 0x0, 0x0, 0x0}, data: []byte{0x0, 0x0, 0x0, 0x0},
@ -747,7 +746,7 @@ func TestParseRouteHint(t *testing.T) {
{ {
data: []byte{}, data: []byte{},
valid: true, valid: true,
result: []routing.HopHint{}, result: []HopHint{},
}, },
{ {
data: testSingleHopData, data: testSingleHopData,

@ -17,7 +17,6 @@ import (
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing"
litecoinCfg "github.com/ltcsuite/ltcd/chaincfg" litecoinCfg "github.com/ltcsuite/ltcd/chaincfg"
) )
@ -53,7 +52,7 @@ var (
testHopHintPubkeyBytes2, _ = hex.DecodeString("039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255") testHopHintPubkeyBytes2, _ = hex.DecodeString("039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255")
testHopHintPubkey2, _ = btcec.ParsePubKey(testHopHintPubkeyBytes2, btcec.S256()) testHopHintPubkey2, _ = btcec.ParsePubKey(testHopHintPubkeyBytes2, btcec.S256())
testSingleHop = []routing.HopHint{ testSingleHop = []HopHint{
{ {
NodeID: testHopHintPubkey1, NodeID: testHopHintPubkey1,
ChannelID: 0x0102030405060708, ChannelID: 0x0102030405060708,
@ -62,7 +61,7 @@ var (
CLTVExpiryDelta: 3, CLTVExpiryDelta: 3,
}, },
} }
testDoubleHop = []routing.HopHint{ testDoubleHop = []HopHint{
{ {
NodeID: testHopHintPubkey1, NodeID: testHopHintPubkey1,
ChannelID: 0x0102030405060708, ChannelID: 0x0102030405060708,
@ -414,7 +413,7 @@ func TestDecodeEncode(t *testing.T) {
DescriptionHash: &testDescriptionHash, DescriptionHash: &testDescriptionHash,
Destination: testPubKey, Destination: testPubKey,
FallbackAddr: testRustyAddr, FallbackAddr: testRustyAddr,
RouteHints: [][]routing.HopHint{testSingleHop}, RouteHints: [][]HopHint{testSingleHop},
} }
}, },
beforeEncoding: func(i *Invoice) { beforeEncoding: func(i *Invoice) {
@ -437,7 +436,7 @@ func TestDecodeEncode(t *testing.T) {
DescriptionHash: &testDescriptionHash, DescriptionHash: &testDescriptionHash,
Destination: testPubKey, Destination: testPubKey,
FallbackAddr: testRustyAddr, FallbackAddr: testRustyAddr,
RouteHints: [][]routing.HopHint{testDoubleHop}, RouteHints: [][]HopHint{testDoubleHop},
} }
}, },
beforeEncoding: func(i *Invoice) { beforeEncoding: func(i *Invoice) {
@ -844,7 +843,7 @@ func compareHashes(a, b *[32]byte) bool {
return bytes.Equal(a[:], b[:]) return bytes.Equal(a[:], b[:])
} }
func compareRouteHints(a, b []routing.HopHint) error { func compareRouteHints(a, b []HopHint) error {
if len(a) != len(b) { if len(a) != len(b) {
return fmt.Errorf("expected len routingInfo %d, got %d", return fmt.Errorf("expected len routingInfo %d, got %d",
len(a), len(b)) len(a), len(b))