2019-03-19 19:09:27 +03:00
|
|
|
package routing
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
"github.com/lightningnetwork/lnd/routing/route"
|
|
|
|
)
|
|
|
|
|
2019-06-03 21:32:07 +03:00
|
|
|
var (
|
|
|
|
mcTestNode = route.Vertex{}
|
|
|
|
mcTestEdge = EdgeLocator{
|
|
|
|
ChannelID: 123,
|
|
|
|
}
|
|
|
|
mcTestTime = time.Date(2018, time.January, 9, 14, 00, 00, 0, time.UTC)
|
|
|
|
)
|
|
|
|
|
|
|
|
type mcTestContext struct {
|
|
|
|
t *testing.T
|
|
|
|
mc *MissionControl
|
|
|
|
now time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
func createMcTestContext(t *testing.T) *mcTestContext {
|
|
|
|
ctx := &mcTestContext{
|
|
|
|
t: t,
|
|
|
|
now: mcTestTime,
|
|
|
|
}
|
2019-03-19 19:09:27 +03:00
|
|
|
|
2019-05-22 12:56:04 +03:00
|
|
|
mc := NewMissionControl(
|
2019-06-18 19:30:56 +03:00
|
|
|
&MissionControlConfig{
|
2019-05-22 12:56:04 +03:00
|
|
|
PenaltyHalfLife: 30 * time.Minute,
|
|
|
|
AprioriHopProbability: 0.8,
|
|
|
|
},
|
|
|
|
)
|
2019-06-03 21:32:07 +03:00
|
|
|
|
|
|
|
mc.now = func() time.Time { return ctx.now }
|
|
|
|
ctx.mc = mc
|
|
|
|
|
|
|
|
return ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assert that mission control returns a probability for an edge.
|
|
|
|
func (ctx *mcTestContext) expectP(amt lnwire.MilliSatoshi,
|
|
|
|
expected float64) {
|
|
|
|
|
|
|
|
ctx.t.Helper()
|
|
|
|
|
2019-06-18 19:30:56 +03:00
|
|
|
p := ctx.mc.GetEdgeProbability(mcTestNode, mcTestEdge, amt)
|
2019-06-03 21:32:07 +03:00
|
|
|
if p != expected {
|
|
|
|
ctx.t.Fatalf("unexpected probability %v", p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestMissionControl tests mission control probability estimation.
|
|
|
|
func TestMissionControl(t *testing.T) {
|
|
|
|
ctx := createMcTestContext(t)
|
|
|
|
|
|
|
|
ctx.now = testTime
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
testTime := time.Date(2018, time.January, 9, 14, 00, 00, 0, time.UTC)
|
|
|
|
|
|
|
|
testNode := route.Vertex{}
|
|
|
|
testEdge := edge{
|
|
|
|
channel: 123,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initial probability is expected to be 1.
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.expectP(1000, 0.8)
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
// Expect probability to be zero after reporting the edge as failed.
|
2019-06-18 19:30:56 +03:00
|
|
|
ctx.mc.ReportEdgeFailure(testEdge, 1000)
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.expectP(1000, 0)
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
// As we reported with a min penalization amt, a lower amt than reported
|
|
|
|
// should be unaffected.
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.expectP(500, 0.8)
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
// Edge decay started.
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.now = testTime.Add(30 * time.Minute)
|
|
|
|
ctx.expectP(1000, 0.4)
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
// Edge fails again, this time without a min penalization amt. The edge
|
|
|
|
// should be penalized regardless of amount.
|
2019-06-18 19:30:56 +03:00
|
|
|
ctx.mc.ReportEdgeFailure(testEdge, 0)
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.expectP(1000, 0)
|
|
|
|
ctx.expectP(500, 0)
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
// Edge decay started.
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.now = testTime.Add(60 * time.Minute)
|
|
|
|
ctx.expectP(1000, 0.4)
|
2019-03-19 19:09:27 +03:00
|
|
|
|
|
|
|
// A node level failure should bring probability of every channel back
|
|
|
|
// to zero.
|
2019-06-18 19:30:56 +03:00
|
|
|
ctx.mc.ReportVertexFailure(testNode)
|
2019-06-03 21:32:07 +03:00
|
|
|
ctx.expectP(1000, 0)
|
2019-05-10 11:38:31 +03:00
|
|
|
|
|
|
|
// Check whether history snapshot looks sane.
|
2019-06-03 21:32:07 +03:00
|
|
|
history := ctx.mc.GetHistorySnapshot()
|
2019-05-10 11:38:31 +03:00
|
|
|
if len(history.Nodes) != 1 {
|
|
|
|
t.Fatal("unexpected number of nodes")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(history.Nodes[0].Channels) != 1 {
|
|
|
|
t.Fatal("unexpected number of channels")
|
|
|
|
}
|
2019-03-19 19:09:27 +03:00
|
|
|
}
|
2019-06-26 09:39:34 +03:00
|
|
|
|
|
|
|
// TestMissionControlChannelUpdate tests that the first channel update is not
|
|
|
|
// penalizing the channel yet.
|
|
|
|
func TestMissionControlChannelUpdate(t *testing.T) {
|
|
|
|
ctx := createMcTestContext(t)
|
|
|
|
|
|
|
|
testEdge := edge{
|
|
|
|
channel: 123,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Report a policy related failure. Because it is the first, we don't
|
|
|
|
// expect a penalty.
|
|
|
|
ctx.mc.ReportEdgePolicyFailure(testEdge)
|
|
|
|
|
|
|
|
ctx.expectP(0, 0.8)
|
|
|
|
|
|
|
|
// Report another failure for the same channel. We expect it to be
|
|
|
|
// pruned.
|
|
|
|
ctx.mc.ReportEdgePolicyFailure(testEdge)
|
|
|
|
|
|
|
|
ctx.expectP(0, 0)
|
|
|
|
}
|