Merge pull request #466 from bhandras/routing-plugin-force-mc-import

routing: integrate with the forced MC import to eliminate the "1 sec hack" when importing pair history
pull/467/head
András Bánki-Horváth 2 years ago committed by GitHub
commit a6350905d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,10 +11,10 @@ require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0
github.com/jessevdk/go-flags v1.4.0
github.com/lightninglabs/aperture v0.1.6-beta
github.com/lightninglabs/lndclient v0.14.0-8
github.com/lightninglabs/lndclient v0.14.2-3
github.com/lightninglabs/loop/swapserverrpc v1.0.0
github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display
github.com/lightningnetwork/lnd v0.14.2-beta.rc1
github.com/lightningnetwork/lnd v0.14.2-beta
github.com/lightningnetwork/lnd/cert v1.1.0
github.com/lightningnetwork/lnd/clock v1.1.0
github.com/lightningnetwork/lnd/queue v1.1.0
@ -32,5 +32,5 @@ go 1.15
replace github.com/lightninglabs/loop/swapserverrpc => ./swapserverrpc
// TODO(bhandras): remove once v0.14.2-beta is tagged.
// TODO(bhandras): remove once v0.14.3-beta or v0.15.0-beta is tagged.
replace github.com/lightningnetwork/lnd => github.com/lightningnetwork/lnd v0.14.1-beta.0.20220131141659-60625b6c1a0b

@ -548,8 +548,8 @@ github.com/lightninglabs/aperture v0.1.6-beta/go.mod h1:9xl4mx778ZAzrB87nLHMqk+X
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc=
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
github.com/lightninglabs/lndclient v0.11.0-4/go.mod h1:8/cTKNwgL87NX123gmlv3Xh6p1a7pvzu+40Un3PhHiI=
github.com/lightninglabs/lndclient v0.14.0-8 h1:vdwV6yFU4A7BjG2V8cpI8Kqdl2M0NSfsA+RWR+JGTko=
github.com/lightninglabs/lndclient v0.14.0-8/go.mod h1:YIE/Yac69hIMiq9cm/ZC2sP4F0Llv3tC4hZGfgOhdeY=
github.com/lightninglabs/lndclient v0.14.2-3 h1:19HWiGCUNejCAm9Ffl5Y56A8u6ZDhhfyjPSDbMDmjuw=
github.com/lightninglabs/lndclient v0.14.2-3/go.mod h1:8fu/+OAK1PqUx9oglz5p0WPOSAwKBUwrC3q3D1yi6Oo=
github.com/lightninglabs/neutrino v0.12.1/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E=
github.com/lightninglabs/neutrino v0.13.0 h1:j3PKWEJCwqwMn/qLASz2j0IuCF6AumS9DaM0i0pM/nY=
github.com/lightninglabs/neutrino v0.13.0/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E=
@ -568,7 +568,6 @@ github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ4
github.com/lightningnetwork/lnd/healthcheck v1.0.0/go.mod h1:u92p1JGFJNMSkMvztKEwmt1P3TRnLeJBXZ3M85xkU1E=
github.com/lightningnetwork/lnd/healthcheck v1.2.0 h1:00bkNn+hGJM9j3Ht+ulf8YNcSx1HEYSDv5pf4HB1/uQ=
github.com/lightningnetwork/lnd/healthcheck v1.2.0/go.mod h1:WSz3lsUjErJQZ3gb+zW32nM3WIHNiZ3A40GVoaQY5wU=
github.com/lightningnetwork/lnd/kvdb v1.2.0/go.mod h1:4DW7zc9AWqqJBvwhSE251VasYikTELItN70hESIt9RU=
github.com/lightningnetwork/lnd/kvdb v1.3.0 h1:0sadTsmfIoorGvd2zf09q/H7sxa/OU48NCpCQUPNN48=
github.com/lightningnetwork/lnd/kvdb v1.3.0/go.mod h1:x+IpsuDynubjokUofavLXroeGfS/WrqUXXTK6vN/gp4=
github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms=

@ -26,8 +26,8 @@ var (
// listed build tags/subservers need to be enabled.
LoopMinRequiredLndVersion = &verrpc.Version{
AppMajor: 0,
AppMinor: 11,
AppPatch: 1,
AppMinor: 14,
AppPatch: 2,
BuildTags: []string{
"signrpc", "walletrpc", "chainrpc", "invoicesrpc",
},

@ -19,6 +19,7 @@ This file tracks release notes for the loop client.
* Loop client now supports optional routing plugins to improve off-chain payment
reliability. One such plugin that the client implemenets will gradually prefer
increasingly more expensive routes in case payments using cheap routes time out.
Note that with this addition the minimum required LND version is LND 0.14.2-beta.
#### Breaking Changes

@ -5,7 +5,6 @@ import (
"fmt"
"sort"
"sync"
"time"
"github.com/btcsuite/btclog"
"github.com/btcsuite/btcutil"
@ -520,13 +519,10 @@ func (r *lowToHighRoutingPlugin) BeforePayment(ctx context.Context,
limit := minFee +
((maxFee-minFee)/int64(maxAttempts))*int64(currAttempt)
// Create a timestamp just slightly in the future as Mission Control
// stores timestamps with sub second precision where as we send a unix
// timestamp it may occur that we can't override the last entries as
// they have the same unix timestamp.
// TODO(bhandras): not very reliable, ideally we'd need a force import
// for MC.
now := r.clock.Now().Add(time.Second)
// With the forced MC import we can safely set the pair history
// timestamps to the current time as import will always just override
// current MC state.
now := r.clock.Now()
allowed := 0
entries := make(
@ -566,7 +562,7 @@ func (r *lowToHighRoutingPlugin) BeforePayment(ctx context.Context,
return ErrRoutingPluginNoMoreRetries
}
err := r.lnd.Router.ImportMissionControl(ctx, entries)
err := r.lnd.Router.ImportMissionControl(ctx, entries, true)
if err != nil {
return err
}
@ -606,10 +602,10 @@ func (r *lowToHighRoutingPlugin) Done(ctx context.Context) error {
return nil
}
// Roll the entry times forward (to be able to override recent updates).
// Use the "time travel" trick which is required to make overrides
// succeed.
now := r.clock.Now().Add(time.Second)
// With the forced import we're safe to just set the pair history
// timestamps to the current time as import will always succeed and
// override current MC state.
now := r.clock.Now()
entries := make(
[]lndclient.MissionControlEntry, 0, len(r.nodesByMaxFee),
)
@ -647,7 +643,7 @@ func (r *lowToHighRoutingPlugin) Done(ctx context.Context) error {
}
}
err := r.lnd.Router.ImportMissionControl(ctx, entries)
err := r.lnd.Router.ImportMissionControl(ctx, entries, true)
if err != nil {
return err
}

@ -81,8 +81,6 @@ func TestLowHighRoutingPlugin(t *testing.T) {
target := loopNode
amt := btcutil.Amount(50)
testTime := time.Now().UTC()
// We expect Mission Control entries to be set to now + 1 sec.
testTimeMc := testTime.Add(time.Second)
tests := []struct {
name string
@ -168,7 +166,7 @@ func TestLowHighRoutingPlugin(t *testing.T) {
NodeTo: dave,
FailTime: time.Time{},
FailAmt: 0,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 10000,
},
},
@ -210,14 +208,14 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: bob,
NodeTo: dave,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1,
},
// Encourage Charlie - Dave
{
NodeFrom: charlie,
NodeTo: dave,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},
@ -228,15 +226,15 @@ func TestLowHighRoutingPlugin(t *testing.T) {
NodeTo: dave,
FailTime: time.Time{},
FailAmt: 0,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 10000,
},
{
NodeFrom: charlie,
NodeTo: dave,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1000001,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},
@ -283,13 +281,13 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: bob,
NodeTo: dave,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 999000,
},
{
NodeFrom: charlie,
NodeTo: dave,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 999000,
},
},
@ -304,17 +302,17 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: bob,
NodeTo: dave,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 999000,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 999001,
},
{
NodeFrom: charlie,
NodeTo: dave,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 999000,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 999001,
},
},
@ -375,21 +373,21 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: bob,
NodeTo: eugene,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1,
},
// Encourage Charlie - Eugene
{
NodeFrom: charlie,
NodeTo: eugene,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
// Encourage Dave - Eugene
{
NodeFrom: dave,
NodeTo: eugene,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},
@ -399,21 +397,21 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: bob,
NodeTo: eugene,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1,
},
// Discourage Charlie - Eugene
{
NodeFrom: charlie,
NodeTo: eugene,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1,
},
// Encourage Dave - Eugene
{
NodeFrom: dave,
NodeTo: eugene,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},
@ -422,9 +420,9 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: bob,
NodeTo: eugene,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1000001,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
{
@ -432,15 +430,15 @@ func TestLowHighRoutingPlugin(t *testing.T) {
NodeTo: eugene,
FailTime: time.Time{},
FailAmt: 0,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 10000,
},
{
NodeFrom: dave,
NodeTo: eugene,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1000001,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},
@ -500,14 +498,14 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: frank,
NodeTo: george,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1,
},
// Encourage Dave - George
{
NodeFrom: dave,
NodeTo: george,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},
@ -522,17 +520,17 @@ func TestLowHighRoutingPlugin(t *testing.T) {
{
NodeFrom: frank,
NodeTo: george,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1000001,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
{
NodeFrom: dave,
NodeTo: george,
FailTime: testTimeMc,
FailTime: testTime,
FailAmt: 1000001,
SuccessTime: testTimeMc,
SuccessTime: testTime,
SuccessAmt: 1000000,
},
},

@ -52,7 +52,7 @@ func (r *mockRouter) QueryMissionControl(ctx context.Context) (
// ImpotMissionControl is a mocked reimplementation of the pair import.
// Reference: lnd/router/missioncontrol_state.go:importSnapshot().
func (r *mockRouter) ImportMissionControl(ctx context.Context,
entries []lndclient.MissionControlEntry) error {
entries []lndclient.MissionControlEntry, force bool) error {
for _, entry := range entries {
found := false
@ -79,12 +79,14 @@ func (r *mockRouter) ImportMissionControl(ctx context.Context,
// Import success result second.
current.SuccessTime = entry.SuccessTime
if entry.SuccessAmt > current.SuccessAmt {
if force ||
entry.SuccessAmt > current.SuccessAmt {
current.SuccessAmt = entry.SuccessAmt
}
if !current.FailTime.IsZero() &&
entry.SuccessAmt >= current.FailAmt {
if !force && (!current.FailTime.IsZero() &&
entry.SuccessAmt >= current.FailAmt) {
current.FailAmt = entry.SuccessAmt + 1
}

Loading…
Cancel
Save