From 2be1051fb61ccd5ee879b8cb41f783e138000471 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Tue, 19 Feb 2019 09:09:01 +0100 Subject: [PATCH] zpay32: move HopHint and DefaultFinalCLTVDelta --- lnrpc/invoicesrpc/utils.go | 3 +-- routing/missioncontrol.go | 3 ++- routing/pathfind.go | 22 ---------------------- routing/pathfind_test.go | 21 +++++++++++---------- routing/router.go | 11 ++++------- routing/router_test.go | 9 +++++---- rpcserver.go | 7 +++---- zpay32/hophint.go | 31 +++++++++++++++++++++++++++++++ zpay32/invoice.go | 13 ++++++------- zpay32/invoice_internal_test.go | 5 ++--- zpay32/invoice_test.go | 11 +++++------ 11 files changed, 70 insertions(+), 66 deletions(-) create mode 100644 zpay32/hophint.go diff --git a/lnrpc/invoicesrpc/utils.go b/lnrpc/invoicesrpc/utils.go index 7f7c92bd..bbba240a 100644 --- a/lnrpc/invoicesrpc/utils.go +++ b/lnrpc/invoicesrpc/utils.go @@ -7,7 +7,6 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnrpc" - "github.com/lightningnetwork/lnd/routing" "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 // 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 for _, route := range routeHints { diff --git a/routing/missioncontrol.go b/routing/missioncontrol.go index 4864cab8..4ba96097 100644 --- a/routing/missioncontrol.go +++ b/routing/missioncontrol.go @@ -8,6 +8,7 @@ import ( "github.com/coreos/bbolt" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/zpay32" ) const ( @@ -152,7 +153,7 @@ func (m *missionControl) GraphPruneView() graphPruneView { // 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 // payment's destination. -func (m *missionControl) NewPaymentSession(routeHints [][]HopHint, +func (m *missionControl) NewPaymentSession(routeHints [][]zpay32.HopHint, target Vertex) (*paymentSession, error) { viewSnapshot := m.GraphPruneView() diff --git a/routing/pathfind.go b/routing/pathfind.go index 0aa4f800..8862c11e 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -39,28 +39,6 @@ const ( 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 // 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 diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index c9080175..c7fa4564 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -22,6 +22,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/zpay32" ) const ( @@ -1746,11 +1747,11 @@ func TestPathFindSpecExample(t *testing.T) { // The CLTV expiry should be the current height plus 9 (the expiry for // the B -> C channel. if firstRoute.TotalTimeLock != - startingHeight+DefaultFinalCLTVDelta { + startingHeight+zpay32.DefaultFinalCLTVDelta { t.Fatalf("wrong total time lock: got %v, expecting %v", firstRoute.TotalTimeLock, - startingHeight+DefaultFinalCLTVDelta) + startingHeight+zpay32.DefaultFinalCLTVDelta) } // 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 // to meet Carol's requirements. if routes[0].Hops[0].OutgoingTimeLock != - startingHeight+DefaultFinalCLTVDelta { + startingHeight+zpay32.DefaultFinalCLTVDelta { t.Fatalf("wrong total time lock: got %v, expecting %v", routes[0].Hops[0].OutgoingTimeLock, - startingHeight+DefaultFinalCLTVDelta) + startingHeight+zpay32.DefaultFinalCLTVDelta) } // 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) } if lastHop.OutgoingTimeLock != - startingHeight+DefaultFinalCLTVDelta { + startingHeight+zpay32.DefaultFinalCLTVDelta { t.Fatalf("wrong total time lock: got %v, expecting %v", lastHop.OutgoingTimeLock, - startingHeight+DefaultFinalCLTVDelta) + startingHeight+zpay32.DefaultFinalCLTVDelta) } // 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", secondRoute.TotalAmount, expectedAmt) } - expectedTimeLock := startingHeight + daveFinalCLTV + DefaultFinalCLTVDelta + expectedTimeLock := startingHeight + daveFinalCLTV + zpay32.DefaultFinalCLTVDelta if secondRoute.TotalTimeLock != uint32(expectedTimeLock) { t.Fatalf("wrong total time lock: got %v, expecting %v", secondRoute.TotalTimeLock, expectedTimeLock) @@ -1885,7 +1886,7 @@ func TestPathFindSpecExample(t *testing.T) { t.Fatalf("wrong forward amount: got %v, expected %v", onionPayload.AmtToForward, amt) } - expectedTimeLock = startingHeight + DefaultFinalCLTVDelta + expectedTimeLock = startingHeight + zpay32.DefaultFinalCLTVDelta if onionPayload.OutgoingTimeLock != uint32(expectedTimeLock) { t.Fatalf("wrong outgoing time lock: got %v, expecting %v", onionPayload.OutgoingTimeLock, @@ -1899,11 +1900,11 @@ func TestPathFindSpecExample(t *testing.T) { lastHop.AmtToForward, amt) } if lastHop.OutgoingTimeLock != - startingHeight+DefaultFinalCLTVDelta { + startingHeight+zpay32.DefaultFinalCLTVDelta { t.Fatalf("wrong total time lock: got %v, expecting %v", lastHop.OutgoingTimeLock, - startingHeight+DefaultFinalCLTVDelta) + startingHeight+zpay32.DefaultFinalCLTVDelta) } } diff --git a/routing/router.go b/routing/router.go index a31da444..ee0f621d 100644 --- a/routing/router.go +++ b/routing/router.go @@ -25,13 +25,10 @@ import ( "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/multimutex" "github.com/lightningnetwork/lnd/routing/chainview" + "github.com/lightningnetwork/lnd/zpay32" ) 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 // if we should give up on a payment attempt. This will be used if a // value isn't specified in the LightningNode struct. @@ -1331,7 +1328,7 @@ func (r *ChannelRouter) FindRoutes(source, target Vertex, var finalCLTVDelta uint16 if len(finalExpiry) == 0 { - finalCLTVDelta = DefaultFinalCLTVDelta + finalCLTVDelta = zpay32.DefaultFinalCLTVDelta } else { finalCLTVDelta = finalExpiry[0] } @@ -1551,7 +1548,7 @@ type LightningPayment struct { // multiple routes, ensure the hop hints within each route are chained // together and sorted in forward order in order to reach the // destination successfully. - RouteHints [][]HopHint + RouteHints [][]zpay32.HopHint // OutgoingChannelID is the channel that needs to be taken to the first // hop. If nil, any channel may be used. @@ -1628,7 +1625,7 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment, var finalCLTVDelta uint16 if payment.FinalCLTVDelta == nil { - finalCLTVDelta = DefaultFinalCLTVDelta + finalCLTVDelta = zpay32.DefaultFinalCLTVDelta } else { finalCLTVDelta = *payment.FinalCLTVDelta } diff --git a/routing/router_test.go b/routing/router_test.go index bcb0e4b1..a8249183 100644 --- a/routing/router_test.go +++ b/routing/router_test.go @@ -19,6 +19,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/zpay32" ) // 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( ctx.router.selfNode.PubKeyBytes, target, paymentAmt, noRestrictions, defaultNumRoutes, - DefaultFinalCLTVDelta, + zpay32.DefaultFinalCLTVDelta, ) if err != nil { t.Fatalf("unable to find any routes: %v", err) @@ -248,7 +249,7 @@ func TestFindRoutesWithFeeLimit(t *testing.T) { routes, err := ctx.router.FindRoutes( ctx.router.selfNode.PubKeyBytes, target, paymentAmt, restrictions, defaultNumRoutes, - DefaultFinalCLTVDelta, + zpay32.DefaultFinalCLTVDelta, ) if err != nil { t.Fatalf("unable to find any routes: %v", err) @@ -1345,7 +1346,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { routes, err := ctx.router.FindRoutes( ctx.router.selfNode.PubKeyBytes, targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes, - DefaultFinalCLTVDelta, + zpay32.DefaultFinalCLTVDelta, ) if err != nil { t.Fatalf("unable to find any routes: %v", err) @@ -1391,7 +1392,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) { routes, err = ctx.router.FindRoutes( ctx.router.selfNode.PubKeyBytes, targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes, - DefaultFinalCLTVDelta, + zpay32.DefaultFinalCLTVDelta, ) if err != nil { t.Fatalf("unable to find any routes: %v", err) diff --git a/rpcserver.go b/rpcserver.go index 8ef933b9..73cd59a0 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2796,7 +2796,7 @@ type rpcPaymentIntent struct { dest routing.Vertex rHash [32]byte cltvDelta uint16 - routeHints [][]routing.HopHint + routeHints [][]zpay32.HopHint outgoingChannelID *uint64 routes []*routing.Route @@ -3515,7 +3515,7 @@ func (r *rpcServer) AddInvoice(ctx context.Context, // Finally, create the routing hint for this channel and // add it to our list of route hints. - hint := routing.HopHint{ + hint := zpay32.HopHint{ NodeID: channel.IdentityPub, ChannelID: chanID, 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 // will be used when creating the invoice. - routeHint := []routing.HopHint{hint} + routeHint := []zpay32.HopHint{hint} options = append(options, zpay32.RouteHint(routeHint)) numHints++ } - } // Create and encode the payment request as a bech32 (zpay32) string. diff --git a/zpay32/hophint.go b/zpay32/hophint.go new file mode 100644 index 00000000..10dabda6 --- /dev/null +++ b/zpay32/hophint.go @@ -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 +} diff --git a/zpay32/invoice.go b/zpay32/invoice.go index 66ce3244..fb79e3cc 100644 --- a/zpay32/invoice.go +++ b/zpay32/invoice.go @@ -13,7 +13,6 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/bech32" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/routing" ) const ( @@ -146,7 +145,7 @@ type Invoice struct { // represent private routes. // // NOTE: This is optional. - RouteHints [][]routing.HopHint + RouteHints [][]HopHint } // 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 // 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) { i.RouteHints = append(i.RouteHints, routeHint) } @@ -476,7 +475,7 @@ func (invoice *Invoice) MinFinalCLTVExpiry() uint64 { return *invoice.minFinalCLTVExpiry } - return routing.DefaultFinalCLTVDelta + return DefaultFinalCLTVDelta } // 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 // 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) if err != nil { return nil, err @@ -854,10 +853,10 @@ func parseRouteHint(data []byte) ([]routing.HopHint, error) { "got %d", hopHintLen, len(base256Data)) } - var routeHint []routing.HopHint + var routeHint []HopHint for len(base256Data) > 0 { - hopHint := routing.HopHint{} + hopHint := HopHint{} hopHint.NodeID, err = btcec.ParsePubKey(base256Data[:33], btcec.S256()) if err != nil { return nil, err diff --git a/zpay32/invoice_internal_test.go b/zpay32/invoice_internal_test.go index 1311a46f..5d0c2cf1 100644 --- a/zpay32/invoice_internal_test.go +++ b/zpay32/invoice_internal_test.go @@ -12,7 +12,6 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/bech32" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/routing" ) // TestDecodeAmount ensures that the amount string in the hrp of the Invoice @@ -738,7 +737,7 @@ func TestParseRouteHint(t *testing.T) { tests := []struct { data []byte valid bool - result []routing.HopHint + result []HopHint }{ { data: []byte{0x0, 0x0, 0x0, 0x0}, @@ -747,7 +746,7 @@ func TestParseRouteHint(t *testing.T) { { data: []byte{}, valid: true, - result: []routing.HopHint{}, + result: []HopHint{}, }, { data: testSingleHopData, diff --git a/zpay32/invoice_test.go b/zpay32/invoice_test.go index 7b54e933..ce69e3a4 100644 --- a/zpay32/invoice_test.go +++ b/zpay32/invoice_test.go @@ -17,7 +17,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/routing" litecoinCfg "github.com/ltcsuite/ltcd/chaincfg" ) @@ -53,7 +52,7 @@ var ( testHopHintPubkeyBytes2, _ = hex.DecodeString("039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255") testHopHintPubkey2, _ = btcec.ParsePubKey(testHopHintPubkeyBytes2, btcec.S256()) - testSingleHop = []routing.HopHint{ + testSingleHop = []HopHint{ { NodeID: testHopHintPubkey1, ChannelID: 0x0102030405060708, @@ -62,7 +61,7 @@ var ( CLTVExpiryDelta: 3, }, } - testDoubleHop = []routing.HopHint{ + testDoubleHop = []HopHint{ { NodeID: testHopHintPubkey1, ChannelID: 0x0102030405060708, @@ -414,7 +413,7 @@ func TestDecodeEncode(t *testing.T) { DescriptionHash: &testDescriptionHash, Destination: testPubKey, FallbackAddr: testRustyAddr, - RouteHints: [][]routing.HopHint{testSingleHop}, + RouteHints: [][]HopHint{testSingleHop}, } }, beforeEncoding: func(i *Invoice) { @@ -437,7 +436,7 @@ func TestDecodeEncode(t *testing.T) { DescriptionHash: &testDescriptionHash, Destination: testPubKey, FallbackAddr: testRustyAddr, - RouteHints: [][]routing.HopHint{testDoubleHop}, + RouteHints: [][]HopHint{testDoubleHop}, } }, beforeEncoding: func(i *Invoice) { @@ -844,7 +843,7 @@ func compareHashes(a, b *[32]byte) bool { return bytes.Equal(a[:], b[:]) } -func compareRouteHints(a, b []routing.HopHint) error { +func compareRouteHints(a, b []HopHint) error { if len(a) != len(b) { return fmt.Errorf("expected len routingInfo %d, got %d", len(a), len(b))