lnd/routing/unified_policies_test.go
Joost Jager a347237e7a
routing: use unified policy for path finding
In this commit we change path finding to no longer consider all channels
between a pair of nodes individually. We assume that nodes forward
non-strict and when we attempt a connection between two nodes, we don't
want to try multiple channels because their policies may not be identical.
Having distinct policies for channel to the same peer is against the
recommendation in the spec, but it happens in the wild. Especially since
we recently changed the default cltv delta value.

What this commit introduces is a unified policy. This can be looked upon
as the greatest common denominator of all policies and should maximize
the probability of getting the payment forwarded.
2019-10-25 11:22:28 +02:00

92 lines
2.6 KiB
Go

package routing
import (
"testing"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
)
// TestUnifiedPolicies tests the composition of unified policies for nodes that
// have multiple channels between them.
func TestUnifiedPolicies(t *testing.T) {
source := route.Vertex{1}
toNode := route.Vertex{2}
fromNode := route.Vertex{3}
bandwidthHints := map[uint64]lnwire.MilliSatoshi{}
u := newUnifiedPolicies(source, toNode, nil)
// Add two channels between the pair of nodes.
p1 := channeldb.ChannelEdgePolicy{
FeeProportionalMillionths: 100000,
FeeBaseMSat: 30,
TimeLockDelta: 60,
MessageFlags: lnwire.ChanUpdateOptionMaxHtlc,
MaxHTLC: 500,
MinHTLC: 100,
}
p2 := channeldb.ChannelEdgePolicy{
FeeProportionalMillionths: 190000,
FeeBaseMSat: 10,
TimeLockDelta: 40,
MessageFlags: lnwire.ChanUpdateOptionMaxHtlc,
MaxHTLC: 400,
MinHTLC: 100,
}
u.addPolicy(fromNode, &p1, 7)
u.addPolicy(fromNode, &p2, 7)
checkPolicy := func(policy *channeldb.ChannelEdgePolicy,
feeBase lnwire.MilliSatoshi, feeRate lnwire.MilliSatoshi,
timeLockDelta uint16) {
t.Helper()
if policy.FeeBaseMSat != feeBase {
t.Fatalf("expected fee base %v, got %v",
feeBase, policy.FeeBaseMSat)
}
if policy.TimeLockDelta != timeLockDelta {
t.Fatalf("expected fee base %v, got %v",
timeLockDelta, policy.TimeLockDelta)
}
if policy.FeeProportionalMillionths != feeRate {
t.Fatalf("expected fee rate %v, got %v",
feeRate, policy.FeeProportionalMillionths)
}
}
policy := u.policies[fromNode].getPolicy(50, bandwidthHints)
if policy != nil {
t.Fatal("expected no policy for amt below min htlc")
}
policy = u.policies[fromNode].getPolicy(550, bandwidthHints)
if policy != nil {
t.Fatal("expected no policy for amt above max htlc")
}
// For 200 sat, p1 yields the highest fee. Use that policy to forward,
// because it will also match p2 in case p1 does not have enough
// balance.
policy = u.policies[fromNode].getPolicy(200, bandwidthHints)
checkPolicy(
policy, p1.FeeBaseMSat, p1.FeeProportionalMillionths,
p1.TimeLockDelta,
)
// For 400 sat, p2 yields the highest fee. Use that policy to forward,
// because it will also match p1 in case p2 does not have enough
// balance. In order to match p1, it needs to have p1's time lock delta.
policy = u.policies[fromNode].getPolicy(400, bandwidthHints)
checkPolicy(
policy, p2.FeeBaseMSat, p2.FeeProportionalMillionths,
p1.TimeLockDelta,
)
}