diff --git a/go.mod b/go.mod index 6a54778..987eb56 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index e0cdc39..281ae9a 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/loopd/run.go b/loopd/run.go index 724c99e..a694777 100644 --- a/loopd/run.go +++ b/loopd/run.go @@ -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", }, diff --git a/release_notes.md b/release_notes.md index c2befa0..c3bb955 100644 --- a/release_notes.md +++ b/release_notes.md @@ -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 diff --git a/routing_plugin.go b/routing_plugin.go index e30dd16..066a3c2 100644 --- a/routing_plugin.go +++ b/routing_plugin.go @@ -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 } diff --git a/routing_plugin_test.go b/routing_plugin_test.go index 4c2b69c..50df14c 100644 --- a/routing_plugin_test.go +++ b/routing_plugin_test.go @@ -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, }, }, diff --git a/test/router_mock.go b/test/router_mock.go index e14411a..e9998d6 100644 --- a/test/router_mock.go +++ b/test/router_mock.go @@ -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 }