routing: add inbound fee support to pathfinding
Add sender-side support for inbound fees in pathfinding and route building.
This commit is contained in:
1 parent
d97e7d30fb
commit
0bae781785
13 files changed
+585
-131
No files matched your search
@@ -490,6 +490,16 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx,
|
||||
cachedInPolicy.ToNodeFeatures = toNodeFeatures
|
||||
}
|
||||
|
||||
var inboundFee lnwire.Fee
|
||||
if p1 != nil {
|
||||
// Extract inbound fee. If there is a decoding error,
|
||||
// skip this edge.
|
||||
_, err := p1.ExtraOpaqueData.ExtractRecords(&inboundFee)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
directedChannel := &DirectedChannel{
|
||||
ChannelID: e.ChannelID,
|
||||
IsNode1: node == e.NodeKey1Bytes,
|
||||
@@ -497,6 +507,7 @@ func (c *ChannelGraph) ForEachNodeDirectedChannel(tx kvdb.RTx,
|
||||
Capacity: e.Capacity,
|
||||
OutPolicySet: p1 != nil,
|
||||
InPolicy: cachedInPolicy,
|
||||
InboundFee: inboundFee,
|
||||
}
|
||||
|
||||
if node == e.NodeKey2Bytes {
|
||||
|
||||
@@ -59,6 +59,9 @@ type DirectedChannel struct {
|
||||
// source, so we're always interested in the edge that arrives to us
|
||||
// from the other node.
|
||||
InPolicy *models.CachedEdgePolicy
|
||||
|
||||
// Inbound fees of this node.
|
||||
InboundFee lnwire.Fee
|
||||
}
|
||||
|
||||
// DeepCopy creates a deep copy of the channel, including the incoming policy.
|
||||
@@ -220,6 +223,14 @@ func (c *GraphCache) updateOrAddEdge(node route.Vertex, edge *DirectedChannel) {
|
||||
func (c *GraphCache) UpdatePolicy(policy *models.ChannelEdgePolicy, fromNode,
|
||||
toNode route.Vertex, edge1 bool) {
|
||||
|
||||
// Extract inbound fee if possible and available. If there is a decoding
|
||||
// error, ignore this policy.
|
||||
var inboundFee lnwire.Fee
|
||||
_, err := policy.ExtraOpaqueData.ExtractRecords(&inboundFee)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
|
||||
@@ -240,11 +251,13 @@ func (c *GraphCache) UpdatePolicy(policy *models.ChannelEdgePolicy, fromNode,
|
||||
// policy for node 1.
|
||||
case channel.IsNode1 && edge1:
|
||||
channel.OutPolicySet = true
|
||||
channel.InboundFee = inboundFee
|
||||
|
||||
// This is node 2, and it is edge 2, so this is the outgoing
|
||||
// policy for node 2.
|
||||
case !channel.IsNode1 && !edge1:
|
||||
channel.OutPolicySet = true
|
||||
channel.InboundFee = inboundFee
|
||||
|
||||
// The other two cases left mean it's the inbound policy for the
|
||||
// node.
|
||||
|
||||
@@ -75,6 +75,10 @@ func TestGraphCacheAddNode(t *testing.T) {
|
||||
ChannelID: 1000,
|
||||
ChannelFlags: lnwire.ChanUpdateChanFlags(channelFlagA),
|
||||
ToNode: nodeB,
|
||||
// Define an inbound fee.
|
||||
ExtraOpaqueData: []byte{
|
||||
253, 217, 3, 8, 0, 0, 0, 10, 0, 0, 0, 20,
|
||||
},
|
||||
}
|
||||
inPolicy1 := &models.ChannelEdgePolicy{
|
||||
ChannelID: 1000,
|
||||
@@ -124,8 +128,18 @@ func TestGraphCacheAddNode(t *testing.T) {
|
||||
edges map[uint64]*DirectedChannel) error {
|
||||
|
||||
nodes[node] = struct{}{}
|
||||
for chanID := range edges {
|
||||
for chanID, directedChannel := range edges {
|
||||
chans[chanID] = struct{}{}
|
||||
|
||||
if node == nodeA {
|
||||
require.NotZero(
|
||||
t, directedChannel.InboundFee,
|
||||
)
|
||||
} else {
|
||||
require.Zero(
|
||||
t, directedChannel.InboundFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+35
-3
@@ -674,7 +674,7 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (
|
||||
FeeBaseMSat: 4352345,
|
||||
FeeProportionalMillionths: 3452352,
|
||||
ToNode: secondNode,
|
||||
ExtraOpaqueData: []byte("new unknown feature2"),
|
||||
ExtraOpaqueData: []byte{1, 0},
|
||||
}
|
||||
edge2 := &models.ChannelEdgePolicy{
|
||||
SigBytes: testSig.Serialize(),
|
||||
@@ -688,7 +688,7 @@ func createChannelEdge(db kvdb.Backend, node1, node2 *LightningNode) (
|
||||
FeeBaseMSat: 4352345,
|
||||
FeeProportionalMillionths: 90392423,
|
||||
ToNode: firstNode,
|
||||
ExtraOpaqueData: []byte("new unknown feature1"),
|
||||
ExtraOpaqueData: []byte{1, 0},
|
||||
}
|
||||
|
||||
return edgeInfo, edge1, edge2
|
||||
@@ -3929,7 +3929,17 @@ func TestGraphCacheForEachNodeChannel(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Create an edge and add it to the db.
|
||||
edgeInfo, _, _ := createChannelEdge(graph.db, node1, node2)
|
||||
edgeInfo, e1, e2 := createChannelEdge(graph.db, node1, node2)
|
||||
|
||||
// Because of lexigraphical sorting and the usage of random node keys in
|
||||
// this test, we need to determine which edge belongs to node 1 at
|
||||
// runtime.
|
||||
var edge1 *models.ChannelEdgePolicy
|
||||
if e1.ToNode == node2.PubKeyBytes {
|
||||
edge1 = e1
|
||||
} else {
|
||||
edge1 = e2
|
||||
}
|
||||
|
||||
// Add the channel, but only insert a single edge into the graph.
|
||||
require.NoError(t, graph.AddChannelEdge(edgeInfo))
|
||||
@@ -3952,6 +3962,28 @@ func TestGraphCacheForEachNodeChannel(t *testing.T) {
|
||||
// We should be able to accumulate the single channel added, even
|
||||
// though we have a nil edge policy here.
|
||||
require.NotNil(t, getSingleChannel())
|
||||
|
||||
// Set an inbound fee and check that it is properly returned.
|
||||
edge1.ExtraOpaqueData = []byte{
|
||||
253, 217, 3, 8, 0, 0, 0, 10, 0, 0, 0, 20,
|
||||
}
|
||||
require.NoError(t, graph.UpdateEdgePolicy(edge1))
|
||||
|
||||
directedChan := getSingleChannel()
|
||||
require.NotNil(t, directedChan)
|
||||
require.Equal(t, directedChan.InboundFee, lnwire.Fee{
|
||||
BaseFee: 10,
|
||||
FeeRate: 20,
|
||||
})
|
||||
|
||||
// Set an invalid inbound fee and check that the edge is no longer
|
||||
// returned.
|
||||
edge1.ExtraOpaqueData = []byte{
|
||||
253, 217, 3, 8, 0,
|
||||
}
|
||||
require.NoError(t, graph.UpdateEdgePolicy(edge1))
|
||||
|
||||
require.Nil(t, getSingleChannel())
|
||||
}
|
||||
|
||||
// TestGraphLoading asserts that the cache is properly reconstructed after a
|
||||
|
||||
Reference in new issue
Block a user