From 7ba18216960ea5213e3fcdfcb6a6c4286c8a0dee Mon Sep 17 00:00:00 2001 From: carla Date: Mon, 8 Feb 2021 09:38:23 +0200 Subject: [PATCH] liquidity: fail suggest swaps when no rules are set In an effort to surface more information about why autoloop is not executing, we add an error when suggest swaps is called with no rules. In other cases we can surface a reason enum with each rule that is set, but in the case where we have no rules, there are no results to accompany with reasons. --- cmd/loop/liquidity.go | 20 +++++++++++++++++--- liquidity/liquidity.go | 14 ++++++++++++-- liquidity/liquidity_test.go | 4 +++- loopd/swapclient_server.go | 10 +++++++++- release_notes.md | 3 +++ 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/cmd/loop/liquidity.go b/cmd/loop/liquidity.go index 57b48ec..dc6b9bb 100644 --- a/cmd/loop/liquidity.go +++ b/cmd/loop/liquidity.go @@ -2,12 +2,15 @@ package main import ( "context" + "errors" "fmt" "strconv" "github.com/lightninglabs/loop/liquidity" "github.com/lightninglabs/loop/looprpc" "github.com/urfave/cli" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) var getLiquidityParamsCommand = cli.Command{ @@ -411,11 +414,22 @@ func suggestSwap(ctx *cli.Context) error { resp, err := client.SuggestSwaps( context.Background(), &looprpc.SuggestSwapsRequest{}, ) - if err != nil { + if err == nil { + printJSON(resp) + return nil + } + + // If we got an error because no rules are set, we want to display a + // friendly message. + rpcErr, ok := status.FromError(err) + if !ok { return err } - printJSON(resp) + if rpcErr.Code() != codes.FailedPrecondition { + return err + } - return nil + return errors.New("no rules set for autolooper, please set rules " + + "using the setrule command") } diff --git a/liquidity/liquidity.go b/liquidity/liquidity.go index f70a08a..ab276a8 100644 --- a/liquidity/liquidity.go +++ b/liquidity/liquidity.go @@ -178,6 +178,9 @@ var ( // less than the server minimum. ErrMinLessThanServer = errors.New("minimum swap amount is less than " + "server minimum") + + // ErrNoRules is returned when no rules are set for swap suggestions. + ErrNoRules = errors.New("no rules set for autoloop") ) // Config contains the external functionality required to run the @@ -439,7 +442,14 @@ func (m *Manager) Run(ctx context.Context) error { for { select { case <-m.cfg.AutoloopTicker.Ticks(): - if err := m.autoloop(ctx); err != nil { + err := m.autoloop(ctx) + switch err { + case ErrNoRules: + log.Debugf("No rules configured for autoloop") + + case nil: + + default: log.Errorf("autoloop failed: %v", err) } @@ -562,7 +572,7 @@ func (m *Manager) SuggestSwaps(ctx context.Context, autoloop bool) ( // If we have no rules set, exit early to avoid unnecessary calls to // lnd and the server. if len(m.params.ChannelRules) == 0 { - return nil, nil + return nil, ErrNoRules } // If our start date is in the future, we interpret this as meaning that diff --git a/liquidity/liquidity_test.go b/liquidity/liquidity_test.go index 0872394..7bbe1f7 100644 --- a/liquidity/liquidity_test.go +++ b/liquidity/liquidity_test.go @@ -496,10 +496,12 @@ func TestSuggestSwaps(t *testing.T) { name string rules map[lnwire.ShortChannelID]*ThresholdRule swaps []loop.OutRequest + err error }{ { name: "no rules", rules: map[lnwire.ShortChannelID]*ThresholdRule{}, + err: ErrNoRules, }, { name: "loop out", @@ -534,7 +536,7 @@ func TestSuggestSwaps(t *testing.T) { testSuggestSwaps( t, newSuggestSwapsSetup(cfg, lnd, params), - testCase.swaps, nil, + testCase.swaps, testCase.err, ) }) } diff --git a/loopd/swapclient_server.go b/loopd/swapclient_server.go index abacd7a..ff310fc 100644 --- a/loopd/swapclient_server.go +++ b/loopd/swapclient_server.go @@ -21,6 +21,8 @@ import ( "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/routing/route" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) const ( @@ -703,7 +705,13 @@ func (s *swapClientServer) SuggestSwaps(ctx context.Context, _ *looprpc.SuggestSwapsRequest) (*looprpc.SuggestSwapsResponse, error) { swaps, err := s.liquidityMgr.SuggestSwaps(ctx, false) - if err != nil { + switch err { + case liquidity.ErrNoRules: + return nil, status.Error(codes.FailedPrecondition, err.Error()) + + case nil: + + default: return nil, err } diff --git a/release_notes.md b/release_notes.md index c5ee3dd..acc5120 100644 --- a/release_notes.md +++ b/release_notes.md @@ -31,5 +31,8 @@ This file tracks release notes for the loop client. been renamed to `Autoloop`, `AutoloopBudgetSat` and `AutoloopBudgetStartSec`. * The `autoout` flag for enabling automatic dispatch of loop out swaps has been renamed to `autoloop` so that it can cover loop out and loop in. +* The `SuggestSwaps` rpc call will now fail with a `FailedPrecondition` grpc + error code if no rules are configured for the autolooper. Previously the rpc + would return an empty response. #### Bug Fixes