Merge pull request #407 from carlaKC/355-surfaceloopingrpcerr

multi: surface grpc error codes from server to client
pull/409/head
Carla Kirk-Cohen 3 years ago committed by GitHub
commit 478f242f91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -15,6 +15,7 @@ import (
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/sweep"
"google.golang.org/grpc/status"
)
var (
@ -610,3 +611,17 @@ func (s *Client) LoopInTerms(ctx context.Context) (
return s.Server.GetLoopInTerms(ctx)
}
// wrapGrpcError wraps the non-nil error provided with a message providing
// additional context, preserving the grpc code returned with the original
// error. If the original error has no grpc code, then codes.Unknown is used.
func wrapGrpcError(message string, err error) error {
// Since our error is non-nil, we don't need to worry about a nil
// grpcStatus, we'll just get an unknown one if no code was passed back.
grpcStatus, _ := status.FromError(err)
return status.Error(
grpcStatus.Code(), fmt.Sprintf("%v: %v", message,
grpcStatus.Message()),
)
}

@ -17,6 +17,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var (
@ -372,3 +374,39 @@ func testSuccess(ctx *testContext, amt btcutil.Amount, hash lntypes.Hash,
ctx.finish()
}
// TestWrapGrpcError tests grpc error wrapping in the case where a grpc error
// code is present, and when it is absent.
func TestWrapGrpcError(t *testing.T) {
tests := []struct {
name string
original error
expectedCode codes.Code
}{
{
name: "out of range error",
original: status.Error(
codes.OutOfRange, "err string",
),
expectedCode: codes.OutOfRange,
},
{
name: "no grpc code",
original: errors.New("no error code"),
expectedCode: codes.Unknown,
},
}
for _, testCase := range tests {
testCase := testCase
t.Run(testCase.name, func(t *testing.T) {
err := wrapGrpcError("", testCase.original)
require.Error(t, err, "test only expects errors")
status, ok := status.FromError(err)
require.True(t, ok, "test expects grpc code")
require.Equal(t, testCase.expectedCode, status.Code())
})
}
}

@ -9,11 +9,10 @@ import (
"sync"
"time"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/labels"
"github.com/lightninglabs/loop/loopdb"
@ -86,7 +85,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
// request that we send to the server.
quote, err := cfg.server.GetLoopInQuote(globalCtx, request.Amount)
if err != nil {
return nil, fmt.Errorf("loop in terms: %v", err)
return nil, wrapGrpcError("loop in terms", err)
}
swapFee := quote.SwapFee
@ -172,7 +171,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
)
probeWaitCancel()
if err != nil {
return nil, fmt.Errorf("cannot initiate swap: %v", err)
return nil, wrapGrpcError("cannot initiate swap", err)
}
// Because the context is cancelled, it is guaranteed that we will be

@ -4,15 +4,14 @@ import (
"context"
"testing"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/stretchr/testify/require"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
)
var (

@ -128,7 +128,7 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig,
receiverKey, request.SwapPublicationDeadline, request.Initiator,
)
if err != nil {
return nil, fmt.Errorf("cannot initiate swap: %v", err)
return nil, wrapGrpcError("cannot initiate swap", err)
}
err = validateLoopOutContract(

@ -19,3 +19,7 @@ This file tracks release notes for the loop client.
#### Breaking Changes
#### Bug Fixes
* Grpc error codes returned by the swap server when swap initiation fails are
now surfaced to the client. Previously these error codes would be returned
as a string.

Loading…
Cancel
Save