Merge pull request #1058 from hieblmi/minor-fixes

multi: fix `staticcheck` flags
This commit is contained in:
Slyghtning 2025-12-20 06:49:08 +01:00 committed by GitHub
commit 1bdaff887c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 1291 additions and 4367 deletions

View file

@ -306,7 +306,7 @@ func getClientConn(config *TapdConfig) (*grpc.ClientConn, error) {
}
// Dial the gRPC server.
conn, err := grpc.Dial(config.Host, opts...)
conn, err := grpc.NewClient(config.Host, opts...)
if err != nil {
return nil, err
}

View file

@ -48,7 +48,7 @@ func getDebugClient(ctx context.Context, cmd *cli.Command) (looprpc.DebugClient,
if err != nil {
return nil, nil, err
}
conn, err := getClientConn(ctx, rpcServer, tlsCertPath, macaroonPath)
conn, err := getClientConn(rpcServer, tlsCertPath, macaroonPath)
if err != nil {
return nil, nil, err
}

View file

@ -17,7 +17,7 @@ var getInfoCommand = &cli.Command{
}
func getInfo(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -53,7 +53,7 @@ func instantOut(ctx context.Context, cmd *cli.Command) error {
}
// First set up the swap client itself.
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -213,7 +213,7 @@ var listInstantOutsCommand = &cli.Command{
func listInstantOuts(ctx context.Context, cmd *cli.Command) error {
// First set up the swap client itself.
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -32,7 +32,7 @@ var listAuthCommand = &cli.Command{
}
func listAuth(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -85,7 +85,7 @@ var fetchL402Command = &cli.Command{
}
func fetchL402(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -25,7 +25,7 @@ var getLiquidityParamsCommand = &cli.Command{
}
func getParams(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -98,7 +98,7 @@ func setRule(ctx context.Context, cmd *cli.Command) error {
pubkeyRule = true
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -106,7 +106,7 @@ func setRule(ctx context.Context, cmd *cli.Command) error {
// We need to set the full set of current parameters every time we call
// SetParameters. To allow users to set only individual fields on the
// cli, we lookup our current params, then update individual values.
// cli, we look up our current params, then update individual values.
params, err := client.GetLiquidityParams(
ctx, &looprpc.GetLiquidityParamsRequest{},
)
@ -395,7 +395,7 @@ var setParamsCommand = &cli.Command{
}
func setParams(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -403,7 +403,7 @@ func setParams(ctx context.Context, cmd *cli.Command) error {
// We need to set the full set of current parameters every time we call
// SetParameters. To allow users to set only individual fields on the
// cli, we lookup our current params, then update individual values.
// cli, we look up our current params, then update individual values.
params, err := client.GetLiquidityParams(
ctx, &looprpc.GetLiquidityParamsRequest{},
)
@ -693,7 +693,7 @@ var suggestSwapCommand = &cli.Command{
}
func suggestSwap(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -108,7 +108,7 @@ func loopIn(ctx context.Context, cmd *cli.Command) error {
return err
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -237,7 +237,7 @@ func loopOut(ctx context.Context, cmd *cli.Command) error {
}
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -192,10 +192,10 @@ func main() {
// getClient establishes a SwapClient RPC connection and returns the client and
// a cleanup handler.
func getClient(ctx context.Context, cmd *cli.Command) (looprpc.SwapClientClient,
func getClient(cmd *cli.Command) (looprpc.SwapClientClient,
func(), error) {
client, _, cleanup, err := getClientWithConn(ctx, cmd)
client, _, cleanup, err := getClientWithConn(cmd)
if err != nil {
return nil, nil, err
}
@ -205,15 +205,15 @@ func getClient(ctx context.Context, cmd *cli.Command) (looprpc.SwapClientClient,
// getClientWithConn returns both the SwapClient RPC client and the underlying
// gRPC connection so callers can perform connection-aware actions.
func getClientWithConn(ctx context.Context, cmd *cli.Command) (
looprpc.SwapClientClient, *grpc.ClientConn, func(), error) {
func getClientWithConn(cmd *cli.Command) (looprpc.SwapClientClient,
*grpc.ClientConn, func(), error) {
rpcServer := cmd.String("rpcserver")
tlsCertPath, macaroonPath, err := extractPathArgs(cmd)
if err != nil {
return nil, nil, nil, err
}
conn, err := getClientConn(ctx, rpcServer, tlsCertPath, macaroonPath)
conn, err := getClientConn(rpcServer, tlsCertPath, macaroonPath)
if err != nil {
return nil, nil, nil, err
}
@ -432,7 +432,7 @@ func logSwap(swap *looprpc.SwapStatus) {
fmt.Println()
}
func getClientConn(ctx context.Context, address, tlsCertPath, macaroonPath string) (*grpc.ClientConn,
func getClientConn(address, tlsCertPath, macaroonPath string) (*grpc.ClientConn,
error) {
// We always need to send a macaroon.
@ -446,7 +446,7 @@ func getClientConn(ctx context.Context, address, tlsCertPath, macaroonPath strin
macOption,
}
// TLS cannot be disabled, we'll always have a cert file to read.
// Since TLS cannot be disabled, we'll always have a cert file to read.
creds, err := credentials.NewClientTLSFromFile(tlsCertPath, "")
if err != nil {
return nil, err
@ -454,9 +454,9 @@ func getClientConn(ctx context.Context, address, tlsCertPath, macaroonPath strin
opts = append(opts, grpc.WithTransportCredentials(creds))
conn, err := grpc.DialContext(ctx, address, opts...)
conn, err := grpc.NewClient(address, opts...)
if err != nil {
return nil, fmt.Errorf("unable to connect to RPC server: %v",
return nil, fmt.Errorf("unable to create RPC client: %v",
err)
}

View file

@ -16,7 +16,7 @@ var monitorCommand = &cli.Command{
}
func monitor(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -72,7 +72,7 @@ func quoteIn(ctx context.Context, cmd *cli.Command) error {
}
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -199,7 +199,7 @@ func quoteOut(ctx context.Context, cmd *cli.Command) error {
return err
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -37,7 +37,7 @@ var (
)
func listReservations(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -62,7 +62,7 @@ func newStaticAddress(ctx context.Context, cmd *cli.Command) error {
return err
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -107,7 +107,7 @@ func listUnspent(ctx context.Context, cmd *cli.Command) error {
return showCommandHelp(ctx, cmd)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -173,7 +173,7 @@ func withdraw(ctx context.Context, cmd *cli.Command) error {
return showCommandHelp(ctx, cmd)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -251,7 +251,7 @@ func listDeposits(ctx context.Context, cmd *cli.Command) error {
return showCommandHelp(ctx, cmd)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -323,7 +323,7 @@ func listWithdrawals(ctx context.Context, cmd *cli.Command) error {
return showCommandHelp(ctx, cmd)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -354,7 +354,7 @@ func listStaticAddressSwaps(ctx context.Context, cmd *cli.Command) error {
return showCommandHelp(ctx, cmd)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -388,7 +388,7 @@ func summary(ctx context.Context, cmd *cli.Command) error {
return showCommandHelp(ctx, cmd)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -519,7 +519,7 @@ func staticAddressLoopIn(ctx context.Context, cmd *cli.Command) error {
selectedAmount = int64(cmd.Uint64("amt"))
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -29,7 +29,7 @@ func stopDaemon(ctx context.Context, cmd *cli.Command) error {
waitForShutdown := cmd.Bool("wait")
// Establish a client connection to loopd.
client, conn, cleanup, err := getClientWithConn(ctx, cmd)
client, conn, cleanup, err := getClientWithConn(cmd)
if err != nil {
return err
}

View file

@ -48,7 +48,7 @@ var listSwapsCommand = &cli.Command{
}
func listSwaps(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -164,7 +164,7 @@ func swapInfo(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("cannot hex decode id: %v", err)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}
@ -226,7 +226,7 @@ func abandonSwap(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("cannot hex decode id: %v", err)
}
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

View file

@ -16,7 +16,7 @@ var termsCommand = &cli.Command{
}
func terms(ctx context.Context, cmd *cli.Command) error {
client, cleanup, err := getClient(ctx, cmd)
client, cleanup, err := getClient(cmd)
if err != nil {
return err
}

3
go.mod
View file

@ -39,7 +39,7 @@ require (
go.etcd.io/bbolt v1.4.3
golang.org/x/sync v0.18.0
google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.36.5
google.golang.org/protobuf v1.36.11
gopkg.in/macaroon-bakery.v2 v2.3.0
gopkg.in/macaroon.v2 v2.1.0
modernc.org/sqlite v1.34.5
@ -150,7 +150,6 @@ require (
github.com/prometheus/procfs v0.8.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect

View file

@ -47,6 +47,13 @@ var (
errOnlyStartOnce = fmt.Errorf("daemon can only be started once")
)
// shouldReportManagerErr determines whether a manager error should be forwarded
// to the internal error channel. Context cancellations are treated as
// non-fatal.
func shouldReportManagerErr(err error) bool {
return err != nil && !errors.Is(err, context.Canceled)
}
// ListenerCfg holds closures used to retrieve listeners for the gRPC services.
type ListenerCfg struct {
// grpcListener returns a TLS listener to use for the gRPC server, based
@ -892,7 +899,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
defer infof("Static address manager stopped")
err := staticAddressManager.Run(d.mainCtx, initChan)
if err != nil && !errors.Is(context.Canceled, err) {
if shouldReportManagerErr(err) {
d.internalErrChan <- err
}
}()
@ -924,7 +931,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
defer infof("Static address deposit manager stopped")
err := depositManager.Run(d.mainCtx, initChan)
if err != nil && !errors.Is(context.Canceled, err) {
if shouldReportManagerErr(err) {
d.internalErrChan <- err
}
}()
@ -956,7 +963,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
defer infof("Static address withdrawal manager stopped")
err := withdrawalManager.Run(d.mainCtx, initChan)
if err != nil && !errors.Is(context.Canceled, err) {
if shouldReportManagerErr(err) {
d.internalErrChan <- err
}
}()
@ -992,7 +999,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
infof("Starting static address loop-in manager...")
defer infof("Static address loop-in manager stopped")
err := staticLoopInManager.Run(d.mainCtx, initChan)
if err != nil && !errors.Is(context.Canceled, err) {
if shouldReportManagerErr(err) {
d.internalErrChan <- err
}
}()

50
loopd/daemon_test.go Normal file
View file

@ -0,0 +1,50 @@
package loopd
import (
"context"
"errors"
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
// TestShouldReportManagerErr verifies that context cancellations are treated as
// non-fatal while other errors are reported.
func TestShouldReportManagerErr(t *testing.T) {
t.Parallel()
tests := []struct {
name string
err error
expected bool
}{
{
name: "nil error",
err: nil,
expected: false,
},
{
name: "context canceled",
err: context.Canceled,
expected: false,
},
{
name: "wrapped context canceled",
err: fmt.Errorf("wrap: %w", context.Canceled),
expected: false,
},
{
name: "other error",
err: errors.New("boom"),
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := shouldReportManagerErr(tt.err)
require.Equal(t, tt.expected, got)
})
}
}

View file

@ -18,6 +18,9 @@ import (
)
var (
// bboltOpen allows overriding the open function in tests.
bboltOpen = bbolt.Open
// dbFileName is the default file name of the client-side loop sub-swap
// database.
dbFileName = "loop.db"
@ -191,10 +194,10 @@ func NewBoltSwapStore(dbPath string, chainParams *chaincfg.Params) (
// Now that we know that path exists, we'll open up bolt, which
// implements our default swap store.
path := filepath.Join(dbPath, dbFileName)
bdb, err := bbolt.Open(path, 0600, &bbolt.Options{
bdb, err := bboltOpen(path, 0600, &bbolt.Options{
Timeout: DefaultLoopDBTimeout,
})
if err == bbolt.ErrTimeout {
if errors.Is(err, bbolt.ErrTimeout) {
return nil, fmt.Errorf("%w: couldn't obtain exclusive lock on "+
"%s, timed out after %v", bbolt.ErrTimeout, path,
DefaultLoopDBTimeout)

View file

@ -3,6 +3,7 @@ package loopdb
import (
"context"
"crypto/sha256"
"fmt"
"io/ioutil"
"os"
"path/filepath"
@ -50,6 +51,33 @@ var (
testTime = time.Date(2018, time.January, 9, 14, 00, 00, 0, time.UTC)
)
// TestNewBoltSwapStoreTimeout ensures a wrapped bbolt timeout is detected
// correctly when opening the store.
func TestNewBoltSwapStoreTimeout(t *testing.T) {
tempDir := t.TempDir()
// Override the bbolt open function to return a wrapped timeout.
origOpen := bboltOpen
t.Cleanup(func() {
bboltOpen = origOpen
})
wrappedErr := fmt.Errorf("wrapped: %w", bbolt.ErrTimeout)
bboltOpen = func(path string, mode os.FileMode,
options *bbolt.Options) (*bbolt.DB, error) {
require.NotNil(t, options)
require.Equal(t, filepath.Join(tempDir, dbFileName), path)
return nil, wrappedErr
}
store, err := NewBoltSwapStore(tempDir, &chaincfg.MainNetParams)
require.Nil(t, store)
require.ErrorIs(t, err, bbolt.ErrTimeout)
require.ErrorContains(t, err, "couldn't obtain exclusive lock")
}
// TestLoopOutStore tests all the basic functionality of the current bbolt
// swap store.
func TestLoopOutStore(t *testing.T) {

View file

@ -593,7 +593,7 @@ func TestAbandonPublishedHtlcState(t *testing.T) {
height := int32(600)
cfg, err, inSwap := startNewLoopIn(t, ctx, height)
cfg, inSwap, err := startNewLoopIn(t, ctx, height)
require.NoError(t, err)
advanceToPublishedHtlc(t, ctx)
@ -663,7 +663,7 @@ func TestAbandonSettledInvoiceState(t *testing.T) {
height := int32(600)
cfg, err, inSwap := startNewLoopIn(t, ctx, height)
cfg, inSwap, err := startNewLoopIn(t, ctx, height)
require.NoError(t, err)
advanceToPublishedHtlc(t, ctx)
@ -760,7 +760,7 @@ func advanceToPublishedHtlc(t *testing.T, ctx *loopInTestContext) SwapInfo {
}
func startNewLoopIn(t *testing.T, ctx *loopInTestContext, height int32) (
*swapConfig, error, *loopInSwap) {
*swapConfig, *loopInSwap, error) {
cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil)
@ -783,5 +783,6 @@ func startNewLoopIn(t *testing.T, ctx *loopInTestContext, height int32) (
}
ctx.errChan <- err
}()
return cfg, err, inSwap
return cfg, inSwap, err
}

View file

@ -1,4 +1,4 @@
FROM golang:1.21.9-bookworm
FROM golang:1.24-bookworm
RUN apt-get update && apt-get install -y \
git \

File diff suppressed because it is too large Load diff

View file

@ -35,11 +35,7 @@ func request_SwapClient_LoopOut_0(ctx context.Context, marshaler runtime.Marshal
var protoReq LoopOutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -52,11 +48,7 @@ func local_request_SwapClient_LoopOut_0(ctx context.Context, marshaler runtime.M
var protoReq LoopOutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -69,11 +61,7 @@ func request_SwapClient_LoopIn_0(ctx context.Context, marshaler runtime.Marshale
var protoReq LoopInRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -86,11 +74,7 @@ func local_request_SwapClient_LoopIn_0(ctx context.Context, marshaler runtime.Ma
var protoReq LoopInRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -527,11 +511,7 @@ func request_SwapClient_SetLiquidityParams_0(ctx context.Context, marshaler runt
var protoReq SetLiquidityParamsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -544,11 +524,7 @@ func local_request_SwapClient_SetLiquidityParams_0(ctx context.Context, marshale
var protoReq SetLiquidityParamsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -597,11 +573,7 @@ func request_SwapClient_InstantOut_0(ctx context.Context, marshaler runtime.Mars
var protoReq InstantOutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -614,11 +586,7 @@ func local_request_SwapClient_InstantOut_0(ctx context.Context, marshaler runtim
var protoReq InstantOutRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -631,11 +599,7 @@ func request_SwapClient_InstantOutQuote_0(ctx context.Context, marshaler runtime
var protoReq InstantOutQuoteRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -648,11 +612,7 @@ func local_request_SwapClient_InstantOutQuote_0(ctx context.Context, marshaler r
var protoReq InstantOutQuoteRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -683,11 +643,7 @@ func request_SwapClient_NewStaticAddress_0(ctx context.Context, marshaler runtim
var protoReq NewStaticAddressRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -700,11 +656,7 @@ func local_request_SwapClient_NewStaticAddress_0(ctx context.Context, marshaler
var protoReq NewStaticAddressRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -753,11 +705,7 @@ func request_SwapClient_WithdrawDeposits_0(ctx context.Context, marshaler runtim
var protoReq WithdrawDepositsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -770,11 +718,7 @@ func local_request_SwapClient_WithdrawDeposits_0(ctx context.Context, marshaler
var protoReq WithdrawDepositsRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -877,11 +821,7 @@ func request_SwapClient_StaticAddressLoopIn_0(ctx context.Context, marshaler run
var protoReq StaticAddressLoopInRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -894,11 +834,7 @@ func local_request_SwapClient_StaticAddressLoopIn_0(ctx context.Context, marshal
var protoReq StaticAddressLoopInRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@ -1619,21 +1555,21 @@ func RegisterSwapClientHandlerServer(ctx context.Context, mux *runtime.ServeMux,
// RegisterSwapClientHandlerFromEndpoint is same as RegisterSwapClientHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterSwapClientHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
conn, err := grpc.NewClient(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()

View file

@ -1663,6 +1663,7 @@
"rules": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcLiquidityRule"
},
"description": "A set of liquidity rules that describe the desired liquidity balance."
@ -1845,6 +1846,7 @@
"swaps": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcInstantOut"
},
"description": "The list of all currently known instant out swaps and their status."
@ -1857,6 +1859,7 @@
"reservations": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcClientReservation"
},
"description": "The list of all currently known reservations and their status."
@ -1869,6 +1872,7 @@
"filtered_deposits": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcDeposit"
},
"description": "A list of all deposits that match the filtered state."
@ -1881,6 +1885,7 @@
"swaps": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcStaticAddressLoopInSwap"
},
"description": "A list of all swaps known static address loop-in swaps."
@ -1893,6 +1898,7 @@
"withdrawals": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcStaticAddressWithdrawal"
},
"description": "A list of all static address withdrawals."
@ -1944,6 +1950,7 @@
"swaps": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcSwapStatus"
},
"description": "The list of all currently known swaps and their status."
@ -1961,6 +1968,7 @@
"utxos": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcUtxo"
},
"description": "A list of utxos behind the static address."
@ -2010,6 +2018,7 @@
"route_hints": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcRouteHint"
},
"description": "Optional route hints to reach the destination through private channels."
@ -2274,6 +2283,7 @@
"hop_hints": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcHopHint"
},
"description": "A list of hop hints that when chained together can assist in reaching a\nspecific destination."
@ -2323,6 +2333,7 @@
"route_hints": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcRouteHint"
},
"description": "Optional route hints to reach the destination through private channels."
@ -2404,6 +2415,7 @@
"used_deposits": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcDeposit"
},
"description": "The deposits that are used for this swap."
@ -2454,6 +2466,7 @@
"deposits": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcDeposit"
},
"description": "The deposits that were used for this swap."
@ -2537,6 +2550,7 @@
"deposits": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcDeposit"
},
"description": "The selected deposits that is withdrawn from."
@ -2572,6 +2586,7 @@
"loop_out": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcLoopOutRequest"
},
"description": "The set of recommended loop outs."
@ -2579,6 +2594,7 @@
"loop_in": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcLoopInRequest"
},
"title": "The set of recommended loop in swaps"
@ -2586,6 +2602,7 @@
"disqualified": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcDisqualified"
},
"description": "Disqualified contains the set of channels that swaps are not recommended\nfor."
@ -2739,6 +2756,7 @@
"tokens": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcL402Token"
},
"description": "List of all tokens the daemon knows of, including old/expired tokens."
@ -2774,6 +2792,7 @@
"outpoints": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/looprpcOutPoint"
},
"description": "The outpoints of the deposits to withdraw."
@ -2833,6 +2852,7 @@
"details": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/protobufAny"
}
}

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.2
// protoc-gen-go v1.36.11
// protoc v3.21.12
// source: debug.proto
@ -11,6 +11,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@ -21,18 +22,16 @@ const (
)
type ForceAutoLoopRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ForceAutoLoopRequest) Reset() {
*x = ForceAutoLoopRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_debug_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_debug_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ForceAutoLoopRequest) String() string {
@ -43,7 +42,7 @@ func (*ForceAutoLoopRequest) ProtoMessage() {}
func (x *ForceAutoLoopRequest) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -59,18 +58,16 @@ func (*ForceAutoLoopRequest) Descriptor() ([]byte, []int) {
}
type ForceAutoLoopResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ForceAutoLoopResponse) Reset() {
*x = ForceAutoLoopResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_debug_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_debug_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ForceAutoLoopResponse) String() string {
@ -81,7 +78,7 @@ func (*ForceAutoLoopResponse) ProtoMessage() {}
func (x *ForceAutoLoopResponse) ProtoReflect() protoreflect.Message {
mi := &file_debug_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -98,31 +95,22 @@ func (*ForceAutoLoopResponse) Descriptor() ([]byte, []int) {
var File_debug_proto protoreflect.FileDescriptor
var file_debug_proto_rawDesc = []byte{
0x0a, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6c,
0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x22, 0x16, 0x0a, 0x14, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x41,
0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17,
0x0a, 0x15, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x6f, 0x70, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x57, 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, 0x67,
0x12, 0x4e, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x6f,
0x70, 0x12, 0x1d, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x63,
0x65, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x1e, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65,
0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c,
0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6c, 0x6f, 0x6f,
0x70, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
const file_debug_proto_rawDesc = "" +
"\n" +
"\vdebug.proto\x12\alooprpc\"\x16\n" +
"\x14ForceAutoLoopRequest\"\x17\n" +
"\x15ForceAutoLoopResponse2W\n" +
"\x05Debug\x12N\n" +
"\rForceAutoLoop\x12\x1d.looprpc.ForceAutoLoopRequest\x1a\x1e.looprpc.ForceAutoLoopResponseB'Z%github.com/lightninglabs/loop/looprpcb\x06proto3"
var (
file_debug_proto_rawDescOnce sync.Once
file_debug_proto_rawDescData = file_debug_proto_rawDesc
file_debug_proto_rawDescData []byte
)
func file_debug_proto_rawDescGZIP() []byte {
file_debug_proto_rawDescOnce.Do(func() {
file_debug_proto_rawDescData = protoimpl.X.CompressGZIP(file_debug_proto_rawDescData)
file_debug_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_debug_proto_rawDesc), len(file_debug_proto_rawDesc)))
})
return file_debug_proto_rawDescData
}
@ -147,37 +135,11 @@ func file_debug_proto_init() {
if File_debug_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_debug_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*ForceAutoLoopRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_debug_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*ForceAutoLoopResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_debug_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_debug_proto_rawDesc), len(file_debug_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@ -188,7 +150,6 @@ func file_debug_proto_init() {
MessageInfos: file_debug_proto_msgTypes,
}.Build()
File_debug_proto = out.File
file_debug_proto_rawDesc = nil
file_debug_proto_goTypes = nil
file_debug_proto_depIdxs = nil
}

View file

@ -3,10 +3,10 @@ module github.com/lightninglabs/loop/looprpc
go 1.24.9
require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3
github.com/lightninglabs/loop/swapserverrpc v1.0.13
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
github.com/lightninglabs/loop/swapserverrpc v1.0.14
google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.34.2
google.golang.org/protobuf v1.36.11
gopkg.in/macaroon-bakery.v2 v2.3.0
)
@ -14,11 +14,11 @@ require (
github.com/go-macaroon-bakery/macaroonpb v1.0.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/sys v0.38.0 // indirect
golang.org/x/text v0.31.0 // indirect
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240730163845-b1a4ccb954bf // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect
gopkg.in/errgo.v1 v1.0.1 // indirect

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
)
@ -896,7 +897,7 @@ func rpcRouteCancel(details *outCancelDetails) (
// getSwapServerConn returns a connection to the swap server. A non-empty
// proxyAddr indicates that a SOCKS proxy found at the address should be used to
// establish the connection.
func getSwapServerConn(address, proxyAddress string, insecure bool,
func getSwapServerConn(address, proxyAddress string, skipCertCheck bool,
tlsPath string, interceptor *l402.ClientInterceptor) (*grpc.ClientConn,
error) {
@ -914,8 +915,9 @@ func getSwapServerConn(address, proxyAddress string, insecure bool,
// using a self-signed certificate or with a certificate signed by a
// public CA.
switch {
case insecure:
opts = append(opts, grpc.WithInsecure())
case skipCertCheck:
creds := insecure.NewCredentials()
opts = append(opts, grpc.WithTransportCredentials(creds))
case tlsPath != "":
// Load the specified TLS certificate and build
@ -945,7 +947,7 @@ func getSwapServerConn(address, proxyAddress string, insecure bool,
opts = append(opts, grpc.WithContextDialer(torDialer))
}
conn, err := grpc.Dial(address, opts...)
conn, err := grpc.NewClient(address, opts...)
if err != nil {
return nil, fmt.Errorf("unable to connect to RPC server: %v",
err)

View file

@ -638,7 +638,7 @@ type testTransactionPublisher struct {
attempts int
}
var testPublishError = errors.New("test publish error")
var errTestPublish = errors.New("test publish error")
// PublishTransaction publishes the transaction or fails it's the first attempt.
func (p *testTransactionPublisher) PublishTransaction(ctx context.Context,
@ -646,7 +646,7 @@ func (p *testTransactionPublisher) PublishTransaction(ctx context.Context,
p.attempts++
if p.attempts == 1 {
return testPublishError
return errTestPublish
}
return p.WalletKitClient.PublishTransaction(ctx, tx, label)
@ -733,7 +733,7 @@ func testPublishErrorHandler(t *testing.T, store testStore,
}, test.Timeout, eventuallyCheckFrequency)
// The first attempt to publish the batch tx is expected to fail.
require.ErrorIs(t, <-publishErrorChan, testPublishError)
require.ErrorIs(t, <-publishErrorChan, errTestPublish)
// Mine a block to trigger another publishing attempt.
err = lnd.NotifyHeight(601)
@ -4072,8 +4072,8 @@ func testSweepBatcherHandleSweepRace(t *testing.T, store testStore,
<-batcher.initDone
const (
sweepValue btcutil.Amount = 1_000_000
confHeight = 605
sweepValue = btcutil.Amount(1_000_000)
confHeight = 605
)
sweepOutpoint := wire.OutPoint{
@ -4534,8 +4534,8 @@ func TestSweepBatcherConfirmedBatchIncompleteSweeps(t *testing.T) {
swapStore := newLoopdbStore(t, sqlDB)
const (
sweepValue btcutil.Amount = 1_000_000
confHeight = 777
sweepValue = btcutil.Amount(1_000_000)
confHeight = 777
)
ctx := context.Background()

View file

@ -1 +0,0 @@
package loop