routing: take Vertex types as path finding source and target nodes
Currently public keys are represented either as a 33-byte array (Vertex) or as a btcec.PublicKey struct. The latter isn't useable as index into maps and cannot be used easily in compares. Therefore the 33-byte array representation is used predominantly throughout the code base. This commit converts the argument types of source and target nodes for path finding to Vertex. Path finding executes no crypto operations and using Vertex simplifies the code. Additionally, it prepares for the path finding source parameter to be exposed over rpc in a follow up commit without requiring conversion back and forth between Vertex and btcec.PublicKey.
This commit is contained in:
parent
b09adc3219
commit
7719bc432f
@ -153,7 +153,7 @@ func (m *missionControl) GraphPruneView() graphPruneView {
|
||||
// in order to populate additional edges to explore when finding a path to the
|
||||
// payment's destination.
|
||||
func (m *missionControl) NewPaymentSession(routeHints [][]HopHint,
|
||||
target *btcec.PublicKey) (*paymentSession, error) {
|
||||
target Vertex) (*paymentSession, error) {
|
||||
|
||||
viewSnapshot := m.GraphPruneView()
|
||||
|
||||
@ -175,7 +175,13 @@ func (m *missionControl) NewPaymentSession(routeHints [][]HopHint,
|
||||
if i != len(routeHint)-1 {
|
||||
endNode.AddPubKey(routeHint[i+1].NodeID)
|
||||
} else {
|
||||
endNode.AddPubKey(target)
|
||||
targetPubKey, err := btcec.ParsePubKey(
|
||||
target[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endNode.AddPubKey(targetPubKey)
|
||||
}
|
||||
|
||||
// Finally, create the channel edge from the hop hint
|
||||
|
@ -1,7 +1,6 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
@ -429,8 +428,7 @@ type RestrictParams struct {
|
||||
// destination node back to source. This is to properly accumulate fees
|
||||
// that need to be paid along the path and accurately check the amount
|
||||
// to forward at every node against the available bandwidth.
|
||||
func findPath(g *graphParams, r *RestrictParams,
|
||||
sourceNode *channeldb.LightningNode, target *btcec.PublicKey,
|
||||
func findPath(g *graphParams, r *RestrictParams, source, target Vertex,
|
||||
amt lnwire.MilliSatoshi) ([]*channeldb.ChannelEdgePolicy, error) {
|
||||
|
||||
var err error
|
||||
@ -491,17 +489,14 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
}
|
||||
}
|
||||
|
||||
sourceVertex := Vertex(sourceNode.PubKeyBytes)
|
||||
|
||||
// We can't always assume that the end destination is publicly
|
||||
// advertised to the network and included in the graph.ForEachNode call
|
||||
// above, so we'll manually include the target node. The target node
|
||||
// charges no fee. Distance is set to 0, because this is the starting
|
||||
// point of the graph traversal. We are searching backwards to get the
|
||||
// fees first time right and correctly match channel bandwidth.
|
||||
targetVertex := NewVertex(target)
|
||||
targetNode := &channeldb.LightningNode{PubKeyBytes: targetVertex}
|
||||
distance[targetVertex] = nodeWithDist{
|
||||
targetNode := &channeldb.LightningNode{PubKeyBytes: target}
|
||||
distance[target] = nodeWithDist{
|
||||
dist: 0,
|
||||
node: targetNode,
|
||||
amountToReceive: amt,
|
||||
@ -534,7 +529,7 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
// skip it.
|
||||
// TODO(halseth): also ignore disable flags for non-local
|
||||
// channels if bandwidth hint is set?
|
||||
isSourceChan := fromVertex == sourceVertex
|
||||
isSourceChan := fromVertex == source
|
||||
|
||||
edgeFlags := edge.ChannelFlags
|
||||
isDisabled := edgeFlags&lnwire.ChanUpdateDisabled != 0
|
||||
@ -597,7 +592,7 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
// node, no additional timelock is required.
|
||||
var fee lnwire.MilliSatoshi
|
||||
var timeLockDelta uint16
|
||||
if fromVertex != sourceVertex {
|
||||
if fromVertex != source {
|
||||
fee = computeFee(amountToSend, edge)
|
||||
timeLockDelta = edge.TimeLockDelta
|
||||
}
|
||||
@ -666,7 +661,7 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
|
||||
// To start, our target node will the sole item within our distance
|
||||
// heap.
|
||||
heap.Push(&nodeHeap, distance[targetVertex])
|
||||
heap.Push(&nodeHeap, distance[target])
|
||||
|
||||
for nodeHeap.Len() != 0 {
|
||||
// Fetch the node within the smallest distance from our source
|
||||
@ -677,7 +672,7 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
// If we've reached our source (or we don't have any incoming
|
||||
// edges), then we're done here and can exit the graph
|
||||
// traversal early.
|
||||
if bytes.Equal(bestNode.PubKeyBytes[:], sourceVertex[:]) {
|
||||
if bestNode.PubKeyBytes == source {
|
||||
break
|
||||
}
|
||||
|
||||
@ -744,7 +739,7 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
|
||||
// If the source node isn't found in the next hop map, then a path
|
||||
// doesn't exist, so we terminate in an error.
|
||||
if _, ok := next[sourceVertex]; !ok {
|
||||
if _, ok := next[source]; !ok {
|
||||
return nil, newErrf(ErrNoPathFound, "unable to find a path to "+
|
||||
"destination")
|
||||
}
|
||||
@ -752,8 +747,8 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
// Use the nextHop map to unravel the forward path from source to
|
||||
// target.
|
||||
pathEdges := make([]*channeldb.ChannelEdgePolicy, 0, len(next))
|
||||
currentNode := sourceVertex
|
||||
for currentNode != targetVertex { // TODO(roasbeef): assumes no cycles
|
||||
currentNode := source
|
||||
for currentNode != target { // TODO(roasbeef): assumes no cycles
|
||||
// Determine the next hop forward using the next map.
|
||||
nextNode := next[currentNode]
|
||||
|
||||
@ -789,9 +784,10 @@ func findPath(g *graphParams, r *RestrictParams,
|
||||
// algorithm, rather than attempting to use an unmodified path finding
|
||||
// algorithm in a block box manner.
|
||||
func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
|
||||
source *channeldb.LightningNode, target *btcec.PublicKey,
|
||||
amt lnwire.MilliSatoshi, restrictions *RestrictParams, numPaths uint32,
|
||||
bandwidthHints map[uint64]lnwire.MilliSatoshi) ([][]*channeldb.ChannelEdgePolicy, error) {
|
||||
source, target Vertex, amt lnwire.MilliSatoshi,
|
||||
restrictions *RestrictParams, numPaths uint32,
|
||||
bandwidthHints map[uint64]lnwire.MilliSatoshi) (
|
||||
[][]*channeldb.ChannelEdgePolicy, error) {
|
||||
|
||||
// TODO(roasbeef): modifying ordering within heap to eliminate final
|
||||
// sorting step?
|
||||
@ -821,7 +817,7 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
|
||||
// function properly.
|
||||
firstPath := make([]*channeldb.ChannelEdgePolicy, 0, len(startingPath)+1)
|
||||
firstPath = append(firstPath, &channeldb.ChannelEdgePolicy{
|
||||
Node: source,
|
||||
Node: &channeldb.LightningNode{PubKeyBytes: source},
|
||||
})
|
||||
firstPath = append(firstPath, startingPath...)
|
||||
|
||||
@ -908,7 +904,8 @@ func findPaths(tx *bbolt.Tx, graph *channeldb.ChannelGraph,
|
||||
graph: graph,
|
||||
bandwidthHints: bandwidthHints,
|
||||
},
|
||||
spurRestrictions, spurNode, target, amt,
|
||||
spurRestrictions, spurNode.PubKeyBytes,
|
||||
target, amt,
|
||||
)
|
||||
|
||||
// If we weren't able to find a path, we'll continue to
|
||||
|
@ -162,7 +162,7 @@ func parseTestGraph(path string) (*testGraphInstance, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aliasMap := make(map[string]*btcec.PublicKey)
|
||||
aliasMap := make(map[string]Vertex)
|
||||
var source *channeldb.LightningNode
|
||||
|
||||
// First we insert all the nodes within the graph as vertexes.
|
||||
@ -189,14 +189,9 @@ func parseTestGraph(path string) (*testGraphInstance, error) {
|
||||
"must be unique!")
|
||||
}
|
||||
|
||||
pub, err := btcec.ParsePubKey(pubBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the alias is unique, then add the node to the
|
||||
// alias map for easy lookup.
|
||||
aliasMap[node.Alias] = pub
|
||||
aliasMap[node.Alias] = dbNode.PubKeyBytes
|
||||
|
||||
// If the node is tagged as the source, then we create a
|
||||
// pointer to is so we can mark the source in the graph
|
||||
@ -365,7 +360,7 @@ type testGraphInstance struct {
|
||||
// aliasMap is a map from a node's alias to its public key. This type is
|
||||
// provided in order to allow easily look up from the human memorable alias
|
||||
// to an exact node's public key.
|
||||
aliasMap map[string]*btcec.PublicKey
|
||||
aliasMap map[string]Vertex
|
||||
|
||||
// privKeyMap maps a node alias to its private key. This is used to be
|
||||
// able to mock a remote node's signing behaviour.
|
||||
@ -394,7 +389,7 @@ func createTestGraphFromChannels(testChannels []*testChannel) (*testGraphInstanc
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aliasMap := make(map[string]*btcec.PublicKey)
|
||||
aliasMap := make(map[string]Vertex)
|
||||
privKeyMap := make(map[string]*btcec.PrivateKey)
|
||||
|
||||
nodeIndex := byte(0)
|
||||
@ -429,7 +424,7 @@ func createTestGraphFromChannels(testChannels []*testChannel) (*testGraphInstanc
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aliasMap[alias] = pubKey
|
||||
aliasMap[alias] = dbNode.PubKeyBytes
|
||||
nodeIndex++
|
||||
|
||||
return dbNode, nil
|
||||
@ -482,16 +477,13 @@ func createTestGraphFromChannels(testChannels []*testChannel) (*testGraphInstanc
|
||||
AuthProof: &testAuthProof,
|
||||
ChannelPoint: *fundingPoint,
|
||||
Capacity: testChannel.Capacity,
|
||||
|
||||
NodeKey1Bytes: aliasMap[testChannel.Node1.Alias],
|
||||
BitcoinKey1Bytes: aliasMap[testChannel.Node1.Alias],
|
||||
NodeKey2Bytes: aliasMap[testChannel.Node2.Alias],
|
||||
BitcoinKey2Bytes: aliasMap[testChannel.Node2.Alias],
|
||||
}
|
||||
|
||||
node1Bytes := aliasMap[testChannel.Node1.Alias].SerializeCompressed()
|
||||
node2Bytes := aliasMap[testChannel.Node2.Alias].SerializeCompressed()
|
||||
|
||||
copy(edgeInfo.NodeKey1Bytes[:], node1Bytes)
|
||||
copy(edgeInfo.NodeKey2Bytes[:], node2Bytes)
|
||||
copy(edgeInfo.BitcoinKey1Bytes[:], node1Bytes)
|
||||
copy(edgeInfo.BitcoinKey2Bytes[:], node2Bytes)
|
||||
|
||||
err = graph.AddChannelEdge(&edgeInfo)
|
||||
if err != nil && err != channeldb.ErrEdgeAlreadyExist {
|
||||
return nil, err
|
||||
@ -618,7 +610,7 @@ func TestFindLowestFeePath(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, paymentAmt,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -631,20 +623,19 @@ func TestFindLowestFeePath(t *testing.T) {
|
||||
}
|
||||
|
||||
// Assert that the lowest fee route is returned.
|
||||
if !bytes.Equal(route.Hops[1].PubKeyBytes[:],
|
||||
testGraphInstance.aliasMap["b"].SerializeCompressed()) {
|
||||
if route.Hops[1].PubKeyBytes != testGraphInstance.aliasMap["b"] {
|
||||
t.Fatalf("expected route to pass through b, "+
|
||||
"but got a route through %v",
|
||||
getAliasFromPubKey(route.Hops[1].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[1].PubKeyBytes,
|
||||
testGraphInstance.aliasMap))
|
||||
}
|
||||
}
|
||||
|
||||
func getAliasFromPubKey(pubKey []byte,
|
||||
aliases map[string]*btcec.PublicKey) string {
|
||||
func getAliasFromPubKey(pubKey Vertex,
|
||||
aliases map[string]Vertex) string {
|
||||
|
||||
for alias, key := range aliases {
|
||||
if bytes.Equal(key.SerializeCompressed(), pubKey) {
|
||||
if key == pubKey {
|
||||
return alias
|
||||
}
|
||||
}
|
||||
@ -759,7 +750,7 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc
|
||||
&RestrictParams{
|
||||
FeeLimit: test.feeLimit,
|
||||
},
|
||||
sourceNode, target, paymentAmt,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
)
|
||||
if test.expectFailureNoPath {
|
||||
if err == nil {
|
||||
@ -786,12 +777,11 @@ func testBasicGraphPathFindingCase(t *testing.T, graphInstance *testGraphInstanc
|
||||
|
||||
// Check hop nodes
|
||||
for i := 0; i < len(expectedHops); i++ {
|
||||
if !bytes.Equal(route.Hops[i].PubKeyBytes[:],
|
||||
aliases[expectedHops[i].alias].SerializeCompressed()) {
|
||||
if route.Hops[i].PubKeyBytes != aliases[expectedHops[i].alias] {
|
||||
|
||||
t.Fatalf("%v-th hop should be %v, is instead: %v",
|
||||
i, expectedHops[i],
|
||||
getAliasFromPubKey(route.Hops[i].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[i].PubKeyBytes,
|
||||
aliases))
|
||||
}
|
||||
}
|
||||
@ -900,6 +890,8 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
|
||||
doge := &channeldb.LightningNode{}
|
||||
doge.AddPubKey(dogePubKey)
|
||||
doge.Alias = "doge"
|
||||
copy(doge.PubKeyBytes[:], dogePubKeyBytes)
|
||||
graph.aliasMap["doge"] = doge.PubKeyBytes
|
||||
|
||||
// Create the channel edge going from songoku to doge and include it in
|
||||
// our map of additional edges.
|
||||
@ -912,7 +904,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
|
||||
}
|
||||
|
||||
additionalEdges := map[Vertex][]*channeldb.ChannelEdgePolicy{
|
||||
NewVertex(graph.aliasMap["songoku"]): {songokuToDoge},
|
||||
graph.aliasMap["songoku"]: {songokuToDoge},
|
||||
}
|
||||
|
||||
// We should now be able to find a path from roasbeef to doge.
|
||||
@ -924,7 +916,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, dogePubKey, paymentAmt,
|
||||
sourceNode.PubKeyBytes, doge.PubKeyBytes, paymentAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find private path to doge: %v", err)
|
||||
@ -932,7 +924,7 @@ func TestPathFindingWithAdditionalEdges(t *testing.T) {
|
||||
|
||||
// The path should represent the following hops:
|
||||
// roasbeef -> songoku -> doge
|
||||
assertExpectedPath(t, path, "songoku", "doge")
|
||||
assertExpectedPath(t, graph.aliasMap, path, "songoku", "doge")
|
||||
}
|
||||
|
||||
func TestKShortestPathFinding(t *testing.T) {
|
||||
@ -963,8 +955,8 @@ func TestKShortestPathFinding(t *testing.T) {
|
||||
FeeLimit: noFeeLimit,
|
||||
}
|
||||
paths, err := findPaths(
|
||||
nil, graph.graph, sourceNode, target, paymentAmt, restrictions,
|
||||
100, nil,
|
||||
nil, graph.graph, sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
restrictions, 100, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find paths between roasbeef and "+
|
||||
@ -984,10 +976,12 @@ func TestKShortestPathFinding(t *testing.T) {
|
||||
}
|
||||
|
||||
// The first route should be a direct route to luo ji.
|
||||
assertExpectedPath(t, paths[0], "roasbeef", "luoji")
|
||||
assertExpectedPath(t, graph.aliasMap, paths[0], "roasbeef", "luoji")
|
||||
|
||||
// The second route should be a route to luo ji via satoshi.
|
||||
assertExpectedPath(t, paths[1], "roasbeef", "satoshi", "luoji")
|
||||
assertExpectedPath(
|
||||
t, graph.aliasMap, paths[1], "roasbeef", "satoshi", "luoji",
|
||||
)
|
||||
}
|
||||
|
||||
// TestNewRoute tests whether the construction of hop payloads by newRoute
|
||||
@ -1235,7 +1229,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, paymentAmt,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("path should have been found")
|
||||
@ -1251,7 +1245,7 @@ func TestNewRoutePathTooLong(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, paymentAmt,
|
||||
sourceNode.PubKeyBytes, target, paymentAmt,
|
||||
)
|
||||
if err == nil {
|
||||
t.Fatalf("should not have been able to find path, supposed to be "+
|
||||
@ -1283,10 +1277,8 @@ func TestPathNotAvailable(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse bytes: %v", err)
|
||||
}
|
||||
unknownNode, err := btcec.ParsePubKey(unknownNodeBytes, btcec.S256())
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse pubkey: %v", err)
|
||||
}
|
||||
var unknownNode Vertex
|
||||
copy(unknownNode[:], unknownNodeBytes)
|
||||
|
||||
_, err = findPath(
|
||||
&graphParams{
|
||||
@ -1295,7 +1287,7 @@ func TestPathNotAvailable(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, unknownNode, 100,
|
||||
sourceNode.PubKeyBytes, unknownNode, 100,
|
||||
)
|
||||
if !IsError(err, ErrNoPathFound) {
|
||||
t.Fatalf("path shouldn't have been found: %v", err)
|
||||
@ -1334,7 +1326,7 @@ func TestPathInsufficientCapacity(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if !IsError(err, ErrNoPathFound) {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1369,7 +1361,7 @@ func TestRouteFailMinHTLC(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if !IsError(err, ErrNoPathFound) {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1429,7 +1421,7 @@ func TestRouteFailMaxHTLC(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("graph should've been able to support payment: %v", err)
|
||||
@ -1453,7 +1445,7 @@ func TestRouteFailMaxHTLC(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if !IsError(err, ErrNoPathFound) {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1490,7 +1482,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -1520,7 +1512,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
@ -1547,7 +1539,7 @@ func TestRouteFailDisabledEdge(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if !IsError(err, ErrNoPathFound) {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1583,12 +1575,12 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
}
|
||||
assertExpectedPath(t, path, "songoku", "sophon")
|
||||
assertExpectedPath(t, graph.aliasMap, path, "songoku", "sophon")
|
||||
|
||||
// Now we'll set the bandwidth of the edge roasbeef->songoku and
|
||||
// roasbeef->phamnuwen to 0.
|
||||
@ -1609,7 +1601,7 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if !IsError(err, ErrNoPathFound) {
|
||||
t.Fatalf("graph shouldn't be able to support payment: %v", err)
|
||||
@ -1629,12 +1621,12 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
}
|
||||
assertExpectedPath(t, path, "phamnuwen", "sophon")
|
||||
assertExpectedPath(t, graph.aliasMap, path, "phamnuwen", "sophon")
|
||||
|
||||
// Finally, set the roasbeef->songoku bandwidth, but also set its
|
||||
// disable flag.
|
||||
@ -1662,12 +1654,12 @@ func TestPathSourceEdgesBandwidth(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, payAmt,
|
||||
sourceNode.PubKeyBytes, target, payAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
}
|
||||
assertExpectedPath(t, path, "songoku", "sophon")
|
||||
assertExpectedPath(t, graph.aliasMap, path, "songoku", "sophon")
|
||||
}
|
||||
|
||||
func TestPathInsufficientCapacityWithFee(t *testing.T) {
|
||||
@ -1704,7 +1696,11 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
// Carol, so we set "B" as the source node so path finding starts from
|
||||
// Bob.
|
||||
bob := ctx.aliases["B"]
|
||||
bobNode, err := ctx.graph.FetchLightningNode(bob)
|
||||
bobKey, err := btcec.ParsePubKey(bob[:], btcec.S256())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bobNode, err := ctx.graph.FetchLightningNode(bobKey)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find bob: %v", err)
|
||||
}
|
||||
@ -1715,7 +1711,9 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
// Query for a route of 4,999,999 mSAT to carol.
|
||||
carol := ctx.aliases["C"]
|
||||
const amt lnwire.MilliSatoshi = 4999999
|
||||
routes, err := ctx.router.FindRoutes(carol, amt, noRestrictions, 100)
|
||||
routes, err := ctx.router.FindRoutes(
|
||||
carol, amt, noRestrictions, 100,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find route: %v", err)
|
||||
}
|
||||
@ -1758,7 +1756,11 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
// Next, we'll set A as the source node so we can assert that we create
|
||||
// the proper route for any queries starting with Alice.
|
||||
alice := ctx.aliases["A"]
|
||||
aliceNode, err := ctx.graph.FetchLightningNode(alice)
|
||||
aliceKey, err := btcec.ParsePubKey(alice[:], btcec.S256())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aliceNode, err := ctx.graph.FetchLightningNode(aliceKey)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find alice: %v", err)
|
||||
}
|
||||
@ -1770,13 +1772,15 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unable to retrieve source node: %v", err)
|
||||
}
|
||||
if !bytes.Equal(source.PubKeyBytes[:], alice.SerializeCompressed()) {
|
||||
if source.PubKeyBytes != alice {
|
||||
t.Fatalf("source node not set")
|
||||
}
|
||||
|
||||
// We'll now request a route from A -> B -> C.
|
||||
ctx.router.routeCache = make(map[routeTuple][]*Route)
|
||||
routes, err = ctx.router.FindRoutes(carol, amt, noRestrictions, 100)
|
||||
routes, err = ctx.router.FindRoutes(
|
||||
carol, amt, noRestrictions, 100,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find routes: %v", err)
|
||||
}
|
||||
@ -1903,15 +1907,15 @@ func TestPathFindSpecExample(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func assertExpectedPath(t *testing.T, path []*channeldb.ChannelEdgePolicy,
|
||||
nodeAliases ...string) {
|
||||
func assertExpectedPath(t *testing.T, aliasMap map[string]Vertex,
|
||||
path []*channeldb.ChannelEdgePolicy, nodeAliases ...string) {
|
||||
|
||||
if len(path) != len(nodeAliases) {
|
||||
t.Fatal("number of hops and number of aliases do not match")
|
||||
}
|
||||
|
||||
for i, hop := range path {
|
||||
if hop.Node.Alias != nodeAliases[i] {
|
||||
if hop.Node.PubKeyBytes != aliasMap[nodeAliases[i]] {
|
||||
t.Fatalf("expected %v to be pos #%v in hop, instead "+
|
||||
"%v was", nodeAliases[i], i, hop.Node.Alias)
|
||||
}
|
||||
@ -1996,7 +2000,7 @@ func TestRestrictOutgoingChannel(t *testing.T) {
|
||||
FeeLimit: noFeeLimit,
|
||||
OutgoingChannelID: &outgoingChannelID,
|
||||
},
|
||||
sourceNode, target, paymentAmt,
|
||||
sourceVertex, target, paymentAmt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
|
@ -153,7 +153,8 @@ func (p *paymentSession) RequestRoute(payment *LightningPayment,
|
||||
FeeLimit: payment.FeeLimit,
|
||||
OutgoingChannelID: payment.OutgoingChannelID,
|
||||
},
|
||||
p.mc.selfNode, payment.Target, payment.Amount,
|
||||
p.mc.selfNode.PubKeyBytes, payment.Target,
|
||||
payment.Amount,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1325,9 +1325,9 @@ func pathsToFeeSortedRoutes(source Vertex, paths [][]*channeldb.ChannelEdgePolic
|
||||
// the required fee and time lock values running backwards along the route. The
|
||||
// route that will be ranked the highest is the one with the lowest cumulative
|
||||
// fee along the route.
|
||||
func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
||||
amt lnwire.MilliSatoshi, restrictions *RestrictParams, numPaths uint32,
|
||||
finalExpiry ...uint16) ([]*Route, error) {
|
||||
func (r *ChannelRouter) FindRoutes(target Vertex, amt lnwire.MilliSatoshi,
|
||||
restrictions *RestrictParams, numPaths uint32, finalExpiry ...uint16) (
|
||||
[]*Route, error) {
|
||||
|
||||
var finalCLTVDelta uint16
|
||||
if len(finalExpiry) == 0 {
|
||||
@ -1336,13 +1336,12 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
||||
finalCLTVDelta = finalExpiry[0]
|
||||
}
|
||||
|
||||
dest := target.SerializeCompressed()
|
||||
log.Debugf("Searching for path to %x, sending %v", dest, amt)
|
||||
log.Debugf("Searching for path to %x, sending %v", target, amt)
|
||||
|
||||
// Before attempting to perform a series of graph traversals to find
|
||||
// the k-shortest paths to the destination, we'll first consult our
|
||||
// path cache
|
||||
rt := newRouteTuple(amt, dest)
|
||||
rt := newRouteTuple(amt, target[:])
|
||||
r.routeCacheMtx.RLock()
|
||||
routes, ok := r.routeCache[rt]
|
||||
r.routeCacheMtx.RUnlock()
|
||||
@ -1361,11 +1360,10 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
||||
|
||||
// We can short circuit the routing by opportunistically checking to
|
||||
// see if the target vertex event exists in the current graph.
|
||||
targetVertex := NewVertex(target)
|
||||
if _, exists, err := r.cfg.Graph.HasLightningNode(targetVertex); err != nil {
|
||||
if _, exists, err := r.cfg.Graph.HasLightningNode(target); err != nil {
|
||||
return nil, err
|
||||
} else if !exists {
|
||||
log.Debugf("Target %x is not in known graph", dest)
|
||||
log.Debugf("Target %x is not in known graph", target)
|
||||
return nil, newErrf(ErrTargetNotInNetwork, "target not found")
|
||||
}
|
||||
|
||||
@ -1396,8 +1394,8 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
||||
// we'll execute our KSP algorithm to find the k-shortest paths from
|
||||
// our source to the destination.
|
||||
shortestPaths, err := findPaths(
|
||||
tx, r.cfg.Graph, r.selfNode, target, amt, restrictions,
|
||||
numPaths, bandwidthHints,
|
||||
tx, r.cfg.Graph, r.selfNode.PubKeyBytes, target, amt,
|
||||
restrictions, numPaths, bandwidthHints,
|
||||
)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
@ -1421,7 +1419,7 @@ func (r *ChannelRouter) FindRoutes(target *btcec.PublicKey,
|
||||
}
|
||||
|
||||
go log.Tracef("Obtained %v paths sending %v to %x: %v", len(validRoutes),
|
||||
amt, dest, newLogClosure(func() string {
|
||||
amt, target, newLogClosure(func() string {
|
||||
return spew.Sdump(validRoutes)
|
||||
}),
|
||||
)
|
||||
@ -1513,7 +1511,7 @@ func generateSphinxPacket(route *Route, paymentHash []byte) ([]byte,
|
||||
// final destination.
|
||||
type LightningPayment struct {
|
||||
// Target is the node in which the payment should be routed towards.
|
||||
Target *btcec.PublicKey
|
||||
Target Vertex
|
||||
|
||||
// Amount is the value of the payment to send through the network in
|
||||
// milli-satoshis.
|
||||
@ -1608,12 +1606,6 @@ func (r *ChannelRouter) sendPayment(payment *LightningPayment,
|
||||
|
||||
log.Tracef("Dispatching route for lightning payment: %v",
|
||||
newLogClosure(func() string {
|
||||
// Remove the public key curve parameters when logging
|
||||
// the route to prevent spamming the logs.
|
||||
if payment.Target != nil {
|
||||
payment.Target.Curve = nil
|
||||
}
|
||||
|
||||
for _, routeHint := range payment.RouteHints {
|
||||
for _, hopHint := range routeHint {
|
||||
hopHint.NodeID.Curve = nil
|
||||
|
@ -30,7 +30,7 @@ type testCtx struct {
|
||||
|
||||
graph *channeldb.ChannelGraph
|
||||
|
||||
aliases map[string]*btcec.PublicKey
|
||||
aliases map[string]Vertex
|
||||
|
||||
chain *mockChain
|
||||
|
||||
@ -265,11 +265,10 @@ func TestFindRoutesWithFeeLimit(t *testing.T) {
|
||||
t.Fatalf("expected 2 hops, got %d", len(hops))
|
||||
}
|
||||
|
||||
if !bytes.Equal(hops[0].PubKeyBytes[:],
|
||||
ctx.aliases["songoku"].SerializeCompressed()) {
|
||||
if hops[0].PubKeyBytes != ctx.aliases["songoku"] {
|
||||
|
||||
t.Fatalf("expected first hop through songoku, got %s",
|
||||
getAliasFromPubKey(hops[0].PubKeyBytes[:],
|
||||
getAliasFromPubKey(hops[0].PubKeyBytes,
|
||||
ctx.aliases))
|
||||
}
|
||||
}
|
||||
@ -347,12 +346,11 @@ func TestSendPaymentRouteFailureFallback(t *testing.T) {
|
||||
}
|
||||
|
||||
// The route should have satoshi as the first hop.
|
||||
if !bytes.Equal(route.Hops[0].PubKeyBytes[:],
|
||||
ctx.aliases["satoshi"].SerializeCompressed()) {
|
||||
if route.Hops[0].PubKeyBytes != ctx.aliases["satoshi"] {
|
||||
|
||||
t.Fatalf("route should go through satoshi as first hop, "+
|
||||
"instead passes through: %v",
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes,
|
||||
ctx.aliases))
|
||||
}
|
||||
}
|
||||
@ -410,11 +408,9 @@ func TestChannelUpdateValidation(t *testing.T) {
|
||||
// Setup a route from source a to destination c. The route will be used
|
||||
// in a call to SendToRoute. SendToRoute also applies channel updates,
|
||||
// but it saves us from including RequestRoute in the test scope too.
|
||||
var hop1 [33]byte
|
||||
copy(hop1[:], ctx.aliases["b"].SerializeCompressed())
|
||||
hop1 := ctx.aliases["b"]
|
||||
|
||||
var hop2 [33]byte
|
||||
copy(hop2[:], ctx.aliases["c"].SerializeCompressed())
|
||||
hop2 := ctx.aliases["c"]
|
||||
|
||||
hops := []*Hop{
|
||||
{
|
||||
@ -429,7 +425,7 @@ func TestChannelUpdateValidation(t *testing.T) {
|
||||
|
||||
route, err := NewRouteFromHops(
|
||||
lnwire.MilliSatoshi(10000), 100,
|
||||
NewVertex(ctx.aliases["a"]), hops,
|
||||
ctx.aliases["a"], hops,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create route: %v", err)
|
||||
@ -451,8 +447,16 @@ func TestChannelUpdateValidation(t *testing.T) {
|
||||
ctx.router.cfg.SendToSwitch = func(firstHop lnwire.ShortChannelID,
|
||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||
|
||||
v := ctx.aliases["b"]
|
||||
source, err := btcec.ParsePubKey(
|
||||
v[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
ErrorSource: ctx.aliases["b"],
|
||||
ErrorSource: source,
|
||||
FailureMessage: &lnwire.FailFeeInsufficient{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
@ -576,8 +580,15 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
||||
|
||||
roasbeefSongoku := lnwire.NewShortChanIDFromInt(chanID)
|
||||
if firstHop == roasbeefSongoku {
|
||||
sourceKey, err := btcec.ParsePubKey(
|
||||
sourceNode[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
ErrorSource: sourceNode,
|
||||
ErrorSource: sourceKey,
|
||||
|
||||
// Within our error, we'll add a channel update
|
||||
// which is meant to reflect he new fee
|
||||
@ -611,12 +622,11 @@ func TestSendPaymentErrorRepeatedFeeInsufficient(t *testing.T) {
|
||||
}
|
||||
|
||||
// The route should have pham nuwen as the first hop.
|
||||
if !bytes.Equal(route.Hops[0].PubKeyBytes[:],
|
||||
ctx.aliases["phamnuwen"].SerializeCompressed()) {
|
||||
if route.Hops[0].PubKeyBytes != ctx.aliases["phamnuwen"] {
|
||||
|
||||
t.Fatalf("route should go through satoshi as first hop, "+
|
||||
"instead passes through: %v",
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes,
|
||||
ctx.aliases))
|
||||
}
|
||||
}
|
||||
@ -684,8 +694,15 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||
|
||||
if firstHop == roasbeefSongoku {
|
||||
sourceKey, err := btcec.ParsePubKey(
|
||||
sourceNode[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
ErrorSource: sourceNode,
|
||||
ErrorSource: sourceKey,
|
||||
FailureMessage: &lnwire.FailExpiryTooSoon{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
@ -712,12 +729,11 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
// The route should have satoshi as the first hop.
|
||||
if !bytes.Equal(route.Hops[0].PubKeyBytes[:],
|
||||
ctx.aliases["phamnuwen"].SerializeCompressed()) {
|
||||
if route.Hops[0].PubKeyBytes != ctx.aliases["phamnuwen"] {
|
||||
|
||||
t.Fatalf("route should go through phamnuwen as first hop, "+
|
||||
"instead passes through: %v",
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes,
|
||||
ctx.aliases))
|
||||
}
|
||||
}
|
||||
@ -739,8 +755,15 @@ func TestSendPaymentErrorNonFinalTimeLockErrors(t *testing.T) {
|
||||
_ *lnwire.UpdateAddHTLC, _ *sphinx.Circuit) ([32]byte, error) {
|
||||
|
||||
if firstHop == roasbeefSongoku {
|
||||
sourceKey, err := btcec.ParsePubKey(
|
||||
sourceNode[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
ErrorSource: sourceNode,
|
||||
ErrorSource: sourceKey,
|
||||
FailureMessage: &lnwire.FailIncorrectCltvExpiry{
|
||||
Update: errChanUpdate,
|
||||
},
|
||||
@ -823,8 +846,16 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
||||
// prune out the rest of the routes.
|
||||
roasbeefSatoshi := lnwire.NewShortChanIDFromInt(2340213491)
|
||||
if firstHop == roasbeefSatoshi {
|
||||
vertex := ctx.aliases["satoshi"]
|
||||
key, err := btcec.ParsePubKey(
|
||||
vertex[:], btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return [32]byte{}, &htlcswitch.ForwardingError{
|
||||
ErrorSource: ctx.aliases["satoshi"],
|
||||
ErrorSource: key,
|
||||
FailureMessage: &lnwire.FailUnknownNextPeer{},
|
||||
}
|
||||
}
|
||||
@ -882,12 +913,11 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
||||
t.Fatalf("incorrect preimage used: expected %x got %x",
|
||||
preImage[:], paymentPreImage[:])
|
||||
}
|
||||
if !bytes.Equal(route.Hops[0].PubKeyBytes[:],
|
||||
ctx.aliases["satoshi"].SerializeCompressed()) {
|
||||
if route.Hops[0].PubKeyBytes != ctx.aliases["satoshi"] {
|
||||
|
||||
t.Fatalf("route should go through satoshi as first hop, "+
|
||||
"instead passes through: %v",
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes,
|
||||
ctx.aliases))
|
||||
}
|
||||
|
||||
@ -930,12 +960,11 @@ func TestSendPaymentErrorPathPruning(t *testing.T) {
|
||||
}
|
||||
|
||||
// The route should have satoshi as the first hop.
|
||||
if !bytes.Equal(route.Hops[0].PubKeyBytes[:],
|
||||
ctx.aliases["satoshi"].SerializeCompressed()) {
|
||||
if route.Hops[0].PubKeyBytes != ctx.aliases["satoshi"] {
|
||||
|
||||
t.Fatalf("route should go through satoshi as first hop, "+
|
||||
"instead passes through: %v",
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes[:],
|
||||
getAliasFromPubKey(route.Hops[0].PubKeyBytes,
|
||||
ctx.aliases))
|
||||
}
|
||||
}
|
||||
@ -1233,8 +1262,9 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
|
||||
// We will connect node 1 to "sophon"
|
||||
connectNode := ctx.aliases["sophon"]
|
||||
if connectNode == nil {
|
||||
t.Fatalf("could not find node to connect to")
|
||||
connectNodeKey, err := btcec.ParsePubKey(connectNode[:], btcec.S256())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var (
|
||||
@ -1242,12 +1272,12 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
pubKey2 *btcec.PublicKey
|
||||
)
|
||||
node1Bytes := priv1.PubKey().SerializeCompressed()
|
||||
node2Bytes := connectNode.SerializeCompressed()
|
||||
if bytes.Compare(node1Bytes, node2Bytes) == -1 {
|
||||
node2Bytes := connectNode
|
||||
if bytes.Compare(node1Bytes[:], node2Bytes[:]) == -1 {
|
||||
pubKey1 = priv1.PubKey()
|
||||
pubKey2 = connectNode
|
||||
pubKey2 = connectNodeKey
|
||||
} else {
|
||||
pubKey1 = connectNode
|
||||
pubKey1 = connectNodeKey
|
||||
pubKey2 = priv1.PubKey()
|
||||
}
|
||||
|
||||
@ -1267,9 +1297,9 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
AuthProof: nil,
|
||||
}
|
||||
copy(edge.NodeKey1Bytes[:], node1Bytes)
|
||||
copy(edge.NodeKey2Bytes[:], node2Bytes)
|
||||
edge.NodeKey2Bytes = node2Bytes
|
||||
copy(edge.BitcoinKey1Bytes[:], node1Bytes)
|
||||
copy(edge.BitcoinKey2Bytes[:], node2Bytes)
|
||||
edge.BitcoinKey2Bytes = node2Bytes
|
||||
|
||||
if err := ctx.router.AddEdge(edge); err != nil {
|
||||
t.Fatalf("unable to add edge to the channel graph: %v.", err)
|
||||
@ -1308,8 +1338,10 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
// We should now be able to find two routes to node 2.
|
||||
paymentAmt := lnwire.NewMSatFromSatoshis(100)
|
||||
targetNode := priv2.PubKey()
|
||||
var targetPubKeyBytes Vertex
|
||||
copy(targetPubKeyBytes[:], targetNode.SerializeCompressed())
|
||||
routes, err := ctx.router.FindRoutes(
|
||||
targetNode, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
DefaultFinalCLTVDelta,
|
||||
)
|
||||
if err != nil {
|
||||
@ -1354,7 +1386,7 @@ func TestAddEdgeUnknownVertexes(t *testing.T) {
|
||||
// Should still be able to find the routes, and the info should be
|
||||
// updated.
|
||||
routes, err = ctx.router.FindRoutes(
|
||||
targetNode, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
targetPubKeyBytes, paymentAmt, noRestrictions, defaultNumRoutes,
|
||||
DefaultFinalCLTVDelta,
|
||||
)
|
||||
if err != nil {
|
||||
@ -1954,9 +1986,6 @@ func TestFindPathFeeWeighting(t *testing.T) {
|
||||
amt := lnwire.MilliSatoshi(100)
|
||||
|
||||
target := ctx.aliases["luoji"]
|
||||
if target == nil {
|
||||
t.Fatalf("unable to find target node")
|
||||
}
|
||||
|
||||
// We'll now attempt a path finding attempt using this set up. Due to
|
||||
// the edge weighting, we should select the direct path over the 2 hop
|
||||
@ -1968,7 +1997,7 @@ func TestFindPathFeeWeighting(t *testing.T) {
|
||||
&RestrictParams{
|
||||
FeeLimit: noFeeLimit,
|
||||
},
|
||||
sourceNode, target, amt,
|
||||
sourceNode.PubKeyBytes, target, amt,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find path: %v", err)
|
||||
|
38
rpcserver.go
38
rpcserver.go
@ -2764,7 +2764,7 @@ func unmarshallSendToRouteRequest(req *lnrpc.SendToRouteRequest,
|
||||
type rpcPaymentIntent struct {
|
||||
msat lnwire.MilliSatoshi
|
||||
feeLimit lnwire.MilliSatoshi
|
||||
dest *btcec.PublicKey
|
||||
dest routing.Vertex
|
||||
rHash [32]byte
|
||||
cltvDelta uint16
|
||||
routeHints [][]routing.HopHint
|
||||
@ -2778,7 +2778,6 @@ type rpcPaymentIntent struct {
|
||||
// three ways a client can specify their payment details: a payment request,
|
||||
// via manual details, or via a complete route.
|
||||
func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error) {
|
||||
var err error
|
||||
payIntent := rpcPaymentIntent{}
|
||||
|
||||
// If a route was specified, then we can use that directly.
|
||||
@ -2849,7 +2848,8 @@ func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error
|
||||
)
|
||||
|
||||
copy(payIntent.rHash[:], payReq.PaymentHash[:])
|
||||
payIntent.dest = payReq.Destination
|
||||
destKey := payReq.Destination.SerializeCompressed()
|
||||
copy(payIntent.dest[:], destKey)
|
||||
payIntent.cltvDelta = uint16(payReq.MinFinalCLTVExpiry())
|
||||
payIntent.routeHints = payReq.RouteHints
|
||||
|
||||
@ -2859,24 +2859,20 @@ func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error
|
||||
// At this point, a destination MUST be specified, so we'll convert it
|
||||
// into the proper representation now. The destination will either be
|
||||
// encoded as raw bytes, or via a hex string.
|
||||
var pubBytes []byte
|
||||
if len(rpcPayReq.Dest) != 0 {
|
||||
payIntent.dest, err = btcec.ParsePubKey(
|
||||
rpcPayReq.Dest, btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return payIntent, err
|
||||
}
|
||||
|
||||
pubBytes = rpcPayReq.Dest
|
||||
} else {
|
||||
pubBytes, err := hex.DecodeString(rpcPayReq.DestString)
|
||||
if err != nil {
|
||||
return payIntent, err
|
||||
}
|
||||
payIntent.dest, err = btcec.ParsePubKey(pubBytes, btcec.S256())
|
||||
var err error
|
||||
pubBytes, err = hex.DecodeString(rpcPayReq.DestString)
|
||||
if err != nil {
|
||||
return payIntent, err
|
||||
}
|
||||
}
|
||||
if len(pubBytes) != 33 {
|
||||
return payIntent, errors.New("invalid key length")
|
||||
}
|
||||
copy(payIntent.dest[:], pubBytes)
|
||||
|
||||
// Otherwise, If the payment request field was not specified
|
||||
// (and a custom route wasn't specified), construct the payment
|
||||
@ -4001,17 +3997,19 @@ func (r *rpcServer) GetNodeInfo(ctx context.Context,
|
||||
func (r *rpcServer) QueryRoutes(ctx context.Context,
|
||||
in *lnrpc.QueryRoutesRequest) (*lnrpc.QueryRoutesResponse, error) {
|
||||
|
||||
// First parse the hex-encoded public key into a full public key object
|
||||
// we can properly manipulate.
|
||||
|
||||
pubKeyBytes, err := hex.DecodeString(in.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
if len(pubKeyBytes) != 33 {
|
||||
return nil, errors.New("invalid key length")
|
||||
}
|
||||
|
||||
var pubKey routing.Vertex
|
||||
copy(pubKey[:], pubKeyBytes)
|
||||
|
||||
// Currently, within the bootstrap phase of the network, we limit the
|
||||
// largest payment size allotted to (2^32) - 1 mSAT or 4.29 million
|
||||
// satoshis.
|
||||
|
Loading…
Reference in New Issue
Block a user