Compare commits

..

No commits in common. 'master' and 'v0.27.1-beta' have entirely different histories.

@ -20,7 +20,7 @@ env:
# If you change this value, please change it in the following files as well: # If you change this value, please change it in the following files as well:
# /Dockerfile # /Dockerfile
GO_VERSION: 1.21.10 GO_VERSION: 1.20.4
jobs: jobs:
######################## ########################

@ -1,4 +1,4 @@
FROM --platform=${BUILDPLATFORM} golang:1.22-alpine as builder FROM --platform=${BUILDPLATFORM} golang:1.20.4-alpine as builder
# Copy in the local repository to build from. # Copy in the local repository to build from.
COPY . /go/src/github.com/lightningnetwork/loop COPY . /go/src/github.com/lightningnetwork/loop

@ -34,11 +34,7 @@ ifneq ($(workers),)
LINT_WORKERS = --concurrency=$(workers) LINT_WORKERS = --concurrency=$(workers)
endif endif
DOCKER_TOOLS = docker run \ DOCKER_TOOLS = docker run -v $$(pwd):/build loop-tools
--rm \
-v $(shell bash -c "go env GOCACHE || (mkdir -p /tmp/go-cache; echo /tmp/go-cache)"):/tmp/build/.cache \
-v $(shell bash -c "go env GOMODCACHE || (mkdir -p /tmp/go-modcache; echo /tmp/go-modcache)"):/tmp/build/.modcache \
-v $$(pwd):/build loop-tools
GREEN := "\\033[0;32m" GREEN := "\\033[0;32m"
NC := "\\033[0m" NC := "\\033[0m"

@ -12,7 +12,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/swap"
@ -56,8 +56,8 @@ var (
// globalCallTimeout is the maximum time any call of the client to the // globalCallTimeout is the maximum time any call of the client to the
// server is allowed to take, including the time it may take to get // server is allowed to take, including the time it may take to get
// and pay for an L402 token. // and pay for an LSAT token.
globalCallTimeout = serverRPCTimeout + l402.PaymentTimeout globalCallTimeout = serverRPCTimeout + lsat.PaymentTimeout
// probeTimeout is the maximum time until a probe is allowed to take. // probeTimeout is the maximum time until a probe is allowed to take.
probeTimeout = 3 * time.Minute probeTimeout = 3 * time.Minute
@ -111,13 +111,13 @@ type ClientConfig struct {
// Lnd is an instance of the lnd proxy. // Lnd is an instance of the lnd proxy.
Lnd *lndclient.LndServices Lnd *lndclient.LndServices
// MaxL402Cost is the maximum price we are willing to pay to the server // MaxLsatCost is the maximum price we are willing to pay to the server
// for the token. // for the token.
MaxL402Cost btcutil.Amount MaxLsatCost btcutil.Amount
// MaxL402Fee is the maximum that we are willing to pay in routing fees // MaxLsatFee is the maximum that we are willing to pay in routing fees
// to obtain the token. // to obtain the token.
MaxL402Fee btcutil.Amount MaxLsatFee btcutil.Amount
// LoopOutMaxParts defines the maximum number of parts that may be used // LoopOutMaxParts defines the maximum number of parts that may be used
// for a loop out swap. When greater than one, a multi-part payment may // for a loop out swap. When greater than one, a multi-part payment may
@ -138,12 +138,12 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
sweeperDb sweepbatcher.BatcherStore, cfg *ClientConfig) ( sweeperDb sweepbatcher.BatcherStore, cfg *ClientConfig) (
*Client, func(), error) { *Client, func(), error) {
l402Store, err := l402.NewFileStore(dbDir) lsatStore, err := lsat.NewFileStore(dbDir)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
swapServerClient, err := newSwapServerClient(cfg, l402Store) swapServerClient, err := newSwapServerClient(cfg, lsatStore)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -153,7 +153,7 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
Server: swapServerClient, Server: swapServerClient,
Store: loopDB, Store: loopDB,
Conn: swapServerClient.conn, Conn: swapServerClient.conn,
L402Store: l402Store, LsatStore: lsatStore,
CreateExpiryTimer: func(d time.Duration) <-chan time.Time { CreateExpiryTimer: func(d time.Duration) <-chan time.Time {
return time.NewTimer(d).C return time.NewTimer(d).C
}, },
@ -177,18 +177,10 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
return nil return nil
} }
sweepStore, err := sweepbatcher.NewSweepFetcherFromSwapStore(
loopDB, cfg.Lnd.ChainParams,
)
if err != nil {
return nil, nil, fmt.Errorf("sweepbatcher."+
"NewSweepFetcherFromSwapStore failed: %w", err)
}
batcher := sweepbatcher.NewBatcher( batcher := sweepbatcher.NewBatcher(
cfg.Lnd.WalletKit, cfg.Lnd.ChainNotifier, cfg.Lnd.Signer, cfg.Lnd.WalletKit, cfg.Lnd.ChainNotifier, cfg.Lnd.Signer,
swapServerClient.MultiMuSig2SignSweep, verifySchnorrSig, swapServerClient.MultiMuSig2SignSweep, verifySchnorrSig,
cfg.Lnd.ChainParams, sweeperDb, sweepStore, cfg.Lnd.ChainParams, sweeperDb, loopDB,
) )
executor := newExecutor(&executorConfig{ executor := newExecutor(&executorConfig{
@ -683,8 +675,7 @@ func (s *Client) LoopInQuote(ctx context.Context,
// Because the Private flag is set, we'll generate our own // Because the Private flag is set, we'll generate our own
// set of hop hints and use that // set of hop hints and use that
request.RouteHints, err = SelectHopHints( request.RouteHints, err = SelectHopHints(
ctx, s.lndServices.Client, request.Amount, ctx, s.lndServices, request.Amount, DefaultMaxHopHints, includeNodes,
DefaultMaxHopHints, includeNodes,
) )
if err != nil { if err != nil {
return nil, err return nil, err

@ -106,7 +106,7 @@ func TestLoopOutFailOffchain(t *testing.T) {
ctx.finish() ctx.finish()
} }
// TestLoopOutFailWrongAmount asserts that the client checks the server invoice // TestLoopOutWrongAmount asserts that the client checks the server invoice
// amounts. // amounts.
func TestLoopOutFailWrongAmount(t *testing.T) { func TestLoopOutFailWrongAmount(t *testing.T) {
defer test.Guard(t)() defer test.Guard(t)()

@ -25,12 +25,6 @@ var instantOutCommand = cli.Command{
Usage: "the comma-separated list of short " + Usage: "the comma-separated list of short " +
"channel IDs of the channels to loop out", "channel IDs of the channels to loop out",
}, },
cli.StringFlag{
Name: "addr",
Usage: "the optional address that the looped out funds " +
"should be sent to, if let blank the funds " +
"will go to lnd's wallet",
},
}, },
Action: instantOut, Action: instantOut,
} }
@ -89,10 +83,7 @@ func instantOut(ctx *cli.Context) error {
fmt.Printf("Available reservations: \n\n") fmt.Printf("Available reservations: \n\n")
for _, res := range confirmedReservations { for _, res := range confirmedReservations {
idx++ idx++
fmt.Printf("Reservation %v: shortid %x, amt %v, expiry "+ fmt.Printf("Reservation %v: %v \n", idx, res.Amount)
"height %v \n", idx, res.ReservationId[:3], res.Amount,
res.Expiry)
totalAmt += int64(res.Amount) totalAmt += int64(res.Amount)
} }
@ -184,7 +175,6 @@ func instantOut(ctx *cli.Context) error {
&looprpc.InstantOutRequest{ &looprpc.InstantOutRequest{
ReservationIds: selectedReservations, ReservationIds: selectedReservations,
OutgoingChanSet: outgoingChanSet, OutgoingChanSet: outgoingChanSet,
DestAddr: ctx.String("addr"),
}, },
) )
@ -202,31 +192,3 @@ func instantOut(ctx *cli.Context) error {
return nil return nil
} }
var listInstantOutsCommand = cli.Command{
Name: "listinstantouts",
Usage: "list all instant out swaps",
Description: `
List all instant out swaps.
`,
Action: listInstantOuts,
}
func listInstantOuts(ctx *cli.Context) error {
// First set up the swap client itself.
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
resp, err := client.ListInstantOuts(
context.Background(), &looprpc.ListInstantOutsRequest{},
)
if err != nil {
return err
}
printRespJSON(resp)
return nil
}

@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"math"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -93,14 +92,6 @@ var loopOutCommand = cli.Command{
"Not setting this flag therefore might " + "Not setting this flag therefore might " +
"result in a lower swap fee", "result in a lower swap fee",
}, },
cli.DurationFlag{
Name: "payment_timeout",
Usage: "the timeout for each individual off-chain " +
"payment attempt. If not set, the default " +
"timeout of 1 hour will be used. As the " +
"payment might be retried, the actual total " +
"time may be longer",
},
forceFlag, forceFlag,
labelFlag, labelFlag,
verboseFlag, verboseFlag,
@ -244,25 +235,6 @@ func loopOut(ctx *cli.Context) error {
} }
} }
var paymentTimeout int64
if ctx.IsSet("payment_timeout") {
parsedTimeout := ctx.Duration("payment_timeout")
if parsedTimeout.Truncate(time.Second) != parsedTimeout {
return fmt.Errorf("payment timeout must be a " +
"whole number of seconds")
}
paymentTimeout = int64(parsedTimeout.Seconds())
if paymentTimeout <= 0 {
return fmt.Errorf("payment timeout must be a " +
"positive value")
}
if paymentTimeout > math.MaxUint32 {
return fmt.Errorf("payment timeout is too large")
}
}
resp, err := client.LoopOut(context.Background(), &looprpc.LoopOutRequest{ resp, err := client.LoopOut(context.Background(), &looprpc.LoopOutRequest{
Amt: int64(amt), Amt: int64(amt),
Dest: destAddr, Dest: destAddr,
@ -280,7 +252,6 @@ func loopOut(ctx *cli.Context) error {
SwapPublicationDeadline: uint64(swapDeadline.Unix()), SwapPublicationDeadline: uint64(swapDeadline.Unix()),
Label: label, Label: label,
Initiator: defaultInitiator, Initiator: defaultInitiator,
PaymentTimeout: uint32(paymentTimeout),
}) })
if err != nil { if err != nil {
return err return err

@ -26,8 +26,8 @@ type printableToken struct {
var listAuthCommand = cli.Command{ var listAuthCommand = cli.Command{
Name: "listauth", Name: "listauth",
Usage: "list all L402 tokens", Usage: "list all LSAT tokens",
Description: "Shows a list of all L402 tokens that loopd has paid for", Description: "Shows a list of all LSAT tokens that loopd has paid for",
Action: listAuth, Action: listAuth,
} }
@ -38,7 +38,7 @@ func listAuth(ctx *cli.Context) error {
} }
defer cleanup() defer cleanup()
resp, err := client.GetL402Tokens( resp, err := client.GetLsatTokens(
context.Background(), &looprpc.TokensRequest{}, context.Background(), &looprpc.TokensRequest{},
) )
if err != nil { if err != nil {

@ -148,7 +148,7 @@ func main() {
listSwapsCommand, swapInfoCommand, getLiquidityParamsCommand, listSwapsCommand, swapInfoCommand, getLiquidityParamsCommand,
setLiquidityRuleCommand, suggestSwapCommand, setParamsCommand, setLiquidityRuleCommand, suggestSwapCommand, setParamsCommand,
getInfoCommand, abandonSwapCommand, reservationsCommands, getInfoCommand, abandonSwapCommand, reservationsCommands,
instantOutCommand, listInstantOutsCommand, instantOutCommand,
} }
err := app.Run(os.Args) err := app.Run(os.Args)

@ -3,7 +3,7 @@ package loop
import ( import (
"time" "time"
"github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -15,7 +15,7 @@ type clientConfig struct {
Server swapServerClient Server swapServerClient
Conn *grpc.ClientConn Conn *grpc.ClientConn
Store loopdb.SwapStore Store loopdb.SwapStore
L402Store l402.Store LsatStore lsat.Store
CreateExpiryTimer func(expiry time.Duration) <-chan time.Time CreateExpiryTimer func(expiry time.Duration) <-chan time.Time
LoopOutMaxParts uint32 LoopOutMaxParts uint32
} }

@ -1,204 +0,0 @@
package loop
import (
"context"
"fmt"
"time"
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
)
const (
// costMigrationID is the identifier for the cost migration.
costMigrationID = "cost_migration"
// paymentBatchSize is the maximum number of payments we'll fetch in
// one go.
paymentBatchSize = 1000
)
// CalculateLoopOutCost calculates the total cost of a loop out swap. It will
// correctly account for the on-chain and off-chain fees that were paid and
// make sure that all costs are positive.
func CalculateLoopOutCost(params *chaincfg.Params, loopOutSwap *loopdb.LoopOut,
paymentFees map[lntypes.Hash]lnwire.MilliSatoshi) (loopdb.SwapCost,
error) {
// First make sure that this swap is actually finished.
if loopOutSwap.State().State.IsPending() {
return loopdb.SwapCost{}, fmt.Errorf("swap is not yet finished")
}
// We first need to decode the prepay invoice to get the prepay hash and
// the prepay amount.
_, _, hash, prepayAmount, err := swap.DecodeInvoice(
params, loopOutSwap.Contract.PrepayInvoice,
)
if err != nil {
return loopdb.SwapCost{}, fmt.Errorf("unable to decode the "+
"prepay invoice: %v", err)
}
// The swap hash is given and we don't need to get it from the
// swap invoice, however we'll decode it anyway to get the invoice amount
// that was paid in case we don't have the payment anymore.
_, _, swapHash, swapPaymentAmount, err := swap.DecodeInvoice(
params, loopOutSwap.Contract.SwapInvoice,
)
if err != nil {
return loopdb.SwapCost{}, fmt.Errorf("unable to decode the "+
"swap invoice: %v", err)
}
var (
cost loopdb.SwapCost
swapPaid, prepayPaid bool
)
// Now that we have the prepay and swap amount, we can calculate the
// total cost of the swap. Note that we only need to account for the
// server cost in case the swap was successful or if the sweep timed
// out. Otherwise the server didn't pull the off-chain htlc nor the
// prepay.
switch loopOutSwap.State().State {
case loopdb.StateSuccess:
cost.Server = swapPaymentAmount + prepayAmount -
loopOutSwap.Contract.AmountRequested
swapPaid = true
prepayPaid = true
case loopdb.StateFailSweepTimeout:
cost.Server = prepayAmount
prepayPaid = true
default:
cost.Server = 0
}
// Now attempt to look up the actual payments so we can calculate the
// total routing costs.
prepayPaymentFee, ok := paymentFees[hash]
if prepayPaid && ok {
cost.Offchain += prepayPaymentFee.ToSatoshis()
} else {
log.Debugf("Prepay payment %s is missing, won't account for "+
"routing fees", hash)
}
swapPaymentFee, ok := paymentFees[swapHash]
if swapPaid && ok {
cost.Offchain += swapPaymentFee.ToSatoshis()
} else {
log.Debugf("Swap payment %s is missing, won't account for "+
"routing fees", swapHash)
}
// For the on-chain cost, just make sure that the cost is positive.
cost.Onchain = loopOutSwap.State().Cost.Onchain
if cost.Onchain < 0 {
cost.Onchain *= -1
}
return cost, nil
}
// MigrateLoopOutCosts will calculate the correct cost for all loop out swaps
// and override the cost values of the last update in the database.
func MigrateLoopOutCosts(ctx context.Context, lnd lndclient.LndServices,
db loopdb.SwapStore) error {
migrationDone, err := db.HasMigration(ctx, costMigrationID)
if err != nil {
return err
}
if migrationDone {
log.Infof("Cost cleanup migration already done, skipping")
return nil
}
log.Infof("Starting cost cleanup migration")
startTs := time.Now()
defer func() {
log.Infof("Finished cost cleanup migration in %v",
time.Since(startTs))
}()
// First we'll fetch all loop out swaps from the database.
loopOutSwaps, err := db.FetchLoopOutSwaps(ctx)
if err != nil {
return err
}
// Gather payment fees to a map for easier lookup.
paymentFees := make(map[lntypes.Hash]lnwire.MilliSatoshi)
offset := uint64(0)
for {
payments, err := lnd.Client.ListPayments(
ctx, lndclient.ListPaymentsRequest{
Offset: offset,
MaxPayments: paymentBatchSize,
},
)
if err != nil {
return err
}
if len(payments.Payments) == 0 {
break
}
for _, payment := range payments.Payments {
paymentFees[payment.Hash] = payment.Fee
}
offset = payments.LastIndexOffset + 1
}
// Now we'll calculate the cost for each swap and finally update the
// costs in the database.
updatedCosts := make(map[lntypes.Hash]loopdb.SwapCost)
for _, loopOutSwap := range loopOutSwaps {
if loopOutSwap.State().State.IsPending() {
continue
}
cost, err := CalculateLoopOutCost(
lnd.ChainParams, loopOutSwap, paymentFees,
)
if err != nil {
// We don't want to fail loopd because of any old swap
// that we're unable to calculate the cost for. We'll
// warn though so that we can investigate further.
log.Warnf("Unable to calculate cost for swap %v: %v",
loopOutSwap.Hash, err)
continue
}
_, ok := updatedCosts[loopOutSwap.Hash]
if ok {
return fmt.Errorf("found a duplicate swap %v while "+
"updating costs", loopOutSwap.Hash)
}
updatedCosts[loopOutSwap.Hash] = cost
}
log.Infof("Updating costs for %d loop out swaps", len(updatedCosts))
err = db.BatchUpdateLoopOutSwapCosts(ctx, updatedCosts)
if err != nil {
return err
}
// Finally mark the migration as done.
return db.SetMigration(ctx, costMigrationID)
}

@ -1,184 +0,0 @@
package loop
import (
"context"
"testing"
"time"
"github.com/btcsuite/btcd/btcutil"
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
// TestCalculateLoopOutCost tests the CalculateLoopOutCost function.
func TestCalculateLoopOutCost(t *testing.T) {
// Set up test context objects.
lnd := test.NewMockLnd()
server := newServerMock(lnd)
store := loopdb.NewStoreMock(t)
cfg := &swapConfig{
lnd: &lnd.LndServices,
store: store,
server: server,
}
height := int32(600)
req := *testRequest
initResult, err := newLoopOutSwap(
context.Background(), cfg, height, &req,
)
require.NoError(t, err)
swap, err := store.FetchLoopOutSwap(
context.Background(), initResult.swap.hash,
)
require.NoError(t, err)
// Override the chain cost so it's negative.
const expectedChainCost = btcutil.Amount(1000)
// Now we have the swap and prepay invoices so let's calculate the
// costs without providing the payments first, so we don't account for
// any routing fees.
paymentFees := make(map[lntypes.Hash]lnwire.MilliSatoshi)
_, err = CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
// We expect that the call fails as the swap isn't finished yet.
require.Error(t, err)
// Override the swap state to make it look like the swap is finished
// and make the chain cost negative too, so we can test that it'll be
// corrected to be positive in the cost calculation.
swap.Events = append(
swap.Events, &loopdb.LoopEvent{
SwapStateData: loopdb.SwapStateData{
State: loopdb.StateSuccess,
Cost: loopdb.SwapCost{
Onchain: -expectedChainCost,
},
},
},
)
costs, err := CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
require.NoError(t, err)
expectedServerCost := server.swapInvoiceAmt + server.prepayInvoiceAmt -
swap.Contract.AmountRequested
require.Equal(t, expectedServerCost, costs.Server)
require.Equal(t, btcutil.Amount(0), costs.Offchain)
require.Equal(t, expectedChainCost, costs.Onchain)
// Now add the two payments to the payments map and calculate the costs
// again. We expect that the routng fees are now accounted for.
paymentFees[server.swapHash] = lnwire.NewMSatFromSatoshis(44)
paymentFees[server.prepayHash] = lnwire.NewMSatFromSatoshis(11)
costs, err = CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
require.NoError(t, err)
expectedOffchainCost := btcutil.Amount(44 + 11)
require.Equal(t, expectedServerCost, costs.Server)
require.Equal(t, expectedOffchainCost, costs.Offchain)
require.Equal(t, expectedChainCost, costs.Onchain)
// Now override the last update to make the swap timed out at the HTLC
// sweep. We expect that the chain cost won't change, and only the
// prepay will be accounted for.
swap.Events[0] = &loopdb.LoopEvent{
SwapStateData: loopdb.SwapStateData{
State: loopdb.StateFailSweepTimeout,
Cost: loopdb.SwapCost{
Onchain: 0,
},
},
}
costs, err = CalculateLoopOutCost(lnd.ChainParams, swap, paymentFees)
require.NoError(t, err)
expectedServerCost = server.prepayInvoiceAmt
expectedOffchainCost = btcutil.Amount(11)
require.Equal(t, expectedServerCost, costs.Server)
require.Equal(t, expectedOffchainCost, costs.Offchain)
require.Equal(t, btcutil.Amount(0), costs.Onchain)
}
// TestCostMigration tests the cost migration for loop out swaps.
func TestCostMigration(t *testing.T) {
// Set up test context objects.
lnd := test.NewMockLnd()
server := newServerMock(lnd)
store := loopdb.NewStoreMock(t)
cfg := &swapConfig{
lnd: &lnd.LndServices,
store: store,
server: server,
}
height := int32(600)
req := *testRequest
initResult, err := newLoopOutSwap(
context.Background(), cfg, height, &req,
)
require.NoError(t, err)
// Override the chain cost so it's negative.
const expectedChainCost = btcutil.Amount(1000)
// Override the swap state to make it look like the swap is finished
// and make the chain cost negative too, so we can test that it'll be
// corrected to be positive in the cost calculation.
err = store.UpdateLoopOut(
context.Background(), initResult.swap.hash, time.Now(),
loopdb.SwapStateData{
State: loopdb.StateSuccess,
Cost: loopdb.SwapCost{
Onchain: -expectedChainCost,
},
},
)
require.NoError(t, err)
// Add the two mocked payment to LND. Note that we only care about the
// fees here, so we don't need to provide the full payment details.
lnd.Payments = []lndclient.Payment{
{
Hash: server.swapHash,
Fee: lnwire.NewMSatFromSatoshis(44),
},
{
Hash: server.prepayHash,
Fee: lnwire.NewMSatFromSatoshis(11),
},
}
// Now we can run the migration.
err = MigrateLoopOutCosts(context.Background(), lnd.LndServices, store)
require.NoError(t, err)
// Finally check that the swap cost has been updated correctly.
swap, err := store.FetchLoopOutSwap(
context.Background(), initResult.swap.hash,
)
require.NoError(t, err)
expectedServerCost := server.swapInvoiceAmt + server.prepayInvoiceAmt -
swap.Contract.AmountRequested
costs := swap.Events[0].Cost
expectedOffchainCost := btcutil.Amount(44 + 11)
require.Equal(t, expectedServerCost, costs.Server)
require.Equal(t, expectedOffchainCost, costs.Offchain)
require.Equal(t, expectedChainCost, costs.Onchain)
// Now run the migration again to make sure it doesn't fail. This also
// indicates that the migration did not run the second time as
// otherwise the store mocks SetMigration function would fail.
err = MigrateLoopOutCosts(context.Background(), lnd.LndServices, store)
require.NoError(t, err)
}

@ -243,82 +243,3 @@ func TestExampleFSMFlow(t *testing.T) {
}) })
} }
} }
// TestObserverAsyncWait tests the observer's WaitForStateAsync function.
func TestObserverAsyncWait(t *testing.T) {
testCases := []struct {
name string
waitTime time.Duration
blockTime time.Duration
expectTimeout bool
}{
{
name: "success",
waitTime: time.Second,
blockTime: time.Millisecond,
expectTimeout: false,
},
{
name: "timeout",
waitTime: time.Millisecond,
blockTime: time.Second,
expectTimeout: true,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
service := &mockService{
respondChan: make(chan bool),
}
store := &mockStore{}
exampleContext := NewExampleFSMContext(service, store)
cachedObserver := NewCachedObserver(100)
exampleContext.RegisterObserver(cachedObserver)
t0 := time.Now()
timeoutCtx, cancel := context.WithTimeout(
context.Background(), tc.waitTime,
)
defer cancel()
// Wait for the final state.
errChan := cachedObserver.WaitForStateAsync(
timeoutCtx, StuffSuccess, true,
)
go func() {
err := exampleContext.SendEvent(
OnRequestStuff,
newInitStuffRequest(),
)
require.NoError(t, err)
time.Sleep(tc.blockTime)
service.respondChan <- true
}()
timeout := false
select {
case <-timeoutCtx.Done():
timeout = true
case <-errChan:
}
require.Equal(t, tc.expectTimeout, timeout)
t1 := time.Now()
diff := t1.Sub(t0)
if tc.expectTimeout {
require.Less(t, diff, tc.blockTime)
} else {
require.Less(t, diff, tc.waitTime)
}
})
}
}

@ -306,36 +306,23 @@ func NoOpAction(_ EventContext) EventType {
} }
// ErrConfigError is an error returned when the state machine is misconfigured. // ErrConfigError is an error returned when the state machine is misconfigured.
type ErrConfigError struct { type ErrConfigError error
msg string
}
// Error returns the error message.
func (e ErrConfigError) Error() string {
return fmt.Sprintf("config error: %s", e.msg)
}
// NewErrConfigError creates a new ErrConfigError. // NewErrConfigError creates a new ErrConfigError.
func NewErrConfigError(msg string) ErrConfigError { func NewErrConfigError(msg string) ErrConfigError {
return ErrConfigError{ return (ErrConfigError)(fmt.Errorf("config error: %s", msg))
msg: msg,
}
} }
// ErrWaitingForStateTimeout is an error returned when the state machine times // ErrWaitingForStateTimeout is an error returned when the state machine times
// out while waiting for a state. // out while waiting for a state.
type ErrWaitingForStateTimeout struct { type ErrWaitingForStateTimeout error
expected StateType
}
// Error returns the error message.
func (e ErrWaitingForStateTimeout) Error() string {
return fmt.Sprintf("waiting for state timed out: %s", e.expected)
}
// NewErrWaitingForStateTimeout creates a new ErrWaitingForStateTimeout. // NewErrWaitingForStateTimeout creates a new ErrWaitingForStateTimeout.
func NewErrWaitingForStateTimeout(expected StateType) ErrWaitingForStateTimeout { func NewErrWaitingForStateTimeout(expected,
return ErrWaitingForStateTimeout{ actual StateType) ErrWaitingForStateTimeout {
expected: expected,
} return (ErrWaitingForStateTimeout)(fmt.Errorf(
"waiting for state timeout: expected %s, actual: %s",
expected, actual,
))
} }

@ -100,11 +100,12 @@ func WithAbortEarlyOnErrorOption() WaitForStateOption {
// the given duration before checking the state. This is useful if the // the given duration before checking the state. This is useful if the
// function is called immediately after sending an event to the state machine // function is called immediately after sending an event to the state machine
// and the state machine needs some time to process the event. // and the state machine needs some time to process the event.
func (c *CachedObserver) WaitForState(ctx context.Context, func (s *CachedObserver) WaitForState(ctx context.Context,
timeout time.Duration, state StateType, timeout time.Duration, state StateType,
opts ...WaitForStateOption) error { opts ...WaitForStateOption) error {
var options fsmOptions var options fsmOptions
for _, opt := range opts { for _, opt := range opts {
opt.apply(&options) opt.apply(&options)
} }
@ -119,77 +120,61 @@ func (c *CachedObserver) WaitForState(ctx context.Context,
} }
} }
// Create a new context with a timeout.
timeoutCtx, cancel := context.WithTimeout(ctx, timeout) timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel() defer cancel()
ch := c.WaitForStateAsync(timeoutCtx, state, options.abortEarlyOnError) // Channel to notify when the desired state is reached
// or an error occurred.
// Wait for either the condition to be met or for a timeout. ch := make(chan error)
select {
case <-timeoutCtx.Done():
return NewErrWaitingForStateTimeout(state)
case err := <-ch: // Goroutine to wait on condition variable
return err
}
}
// WaitForStateAsync waits asynchronously until the passed context is canceled
// or the expected state is reached. The function returns a channel that will
// receive an error if the expected state is reached or an error occurred. If
// the context is canceled before the expected state is reached, the channel
// will receive an ErrWaitingForStateTimeout error.
func (c *CachedObserver) WaitForStateAsync(ctx context.Context, state StateType,
abortOnEarlyError bool) chan error {
// Channel to notify when the desired state is reached or an error
// occurred.
ch := make(chan error, 1)
// Wait on the notification condition variable asynchronously to avoid
// blocking the caller.
go func() { go func() {
c.notificationMx.Lock() s.notificationMx.Lock()
defer c.notificationMx.Unlock() defer s.notificationMx.Unlock()
// writeResult writes the result to the channel. If the context
// is canceled, an ErrWaitingForStateTimeout error is written
// to the channel.
writeResult := func(err error) {
select {
case <-ctx.Done():
ch <- NewErrWaitingForStateTimeout(
state,
)
case ch <- err:
}
}
for { for {
// Check if the last state is the desired state. // Check if the last state is the desired state
if c.lastNotification.NextState == state { if s.lastNotification.NextState == state {
writeResult(nil) select {
return case <-timeoutCtx.Done():
} return
// Check if an error has occurred. case ch <- nil:
if c.lastNotification.Event == OnError {
lastErr := c.lastNotification.LastActionError
if abortOnEarlyError {
writeResult(lastErr)
return return
} }
} }
// Otherwise use the conditional variable to wait for // Check if an error occurred
// the next notification. if s.lastNotification.Event == OnError {
c.notificationCond.Wait() if options.abortEarlyOnError {
select {
case <-timeoutCtx.Done():
return
case ch <- s.lastNotification.LastActionError:
return
}
}
}
// Otherwise, wait for the next notification
s.notificationCond.Wait()
} }
}() }()
return ch // Wait for either the condition to be met or for a timeout
select {
case <-timeoutCtx.Done():
return NewErrWaitingForStateTimeout(
state, s.lastNotification.NextState,
)
case lastActionErr := <-ch:
if lastActionErr != nil {
return lastActionErr
}
return nil
}
} }
// FixedSizeSlice is a slice with a fixed size. // FixedSizeSlice is a slice with a fixed size.

136
go.mod

@ -1,42 +1,42 @@
module github.com/lightninglabs/loop module github.com/lightninglabs/loop
require ( require (
github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46 github.com/btcsuite/btcd v0.24.1-0.20240123000108-62e6af035ec5
github.com/btcsuite/btcd/btcec/v2 v2.3.3 github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/btcutil v1.1.5
github.com/btcsuite/btcd/btcutil/psbt v1.1.8 github.com/btcsuite/btcd/btcutil/psbt v1.1.8
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb github.com/btcsuite/btcwallet v0.16.10-0.20240127010340-16b422a2e8bf
github.com/btcsuite/btcwallet/wtxmgr v1.5.3 github.com/btcsuite/btcwallet/wtxmgr v1.5.0
github.com/coreos/bbolt v1.3.3 github.com/coreos/bbolt v1.3.3
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
github.com/fortytw2/leaktest v1.3.0 github.com/fortytw2/leaktest v1.3.0
github.com/golang-migrate/migrate/v4 v4.17.0 github.com/golang-migrate/migrate/v4 v4.16.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3
github.com/jackc/pgconn v1.14.3 github.com/jackc/pgconn v1.14.0
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
github.com/jessevdk/go-flags v1.4.0 github.com/jessevdk/go-flags v1.4.0
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.7
github.com/lightninglabs/aperture v0.3.2-beta github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030
github.com/lightninglabs/lndclient v0.18.0-1 github.com/lightninglabs/lndclient v0.17.4-1
github.com/lightninglabs/loop/swapserverrpc v1.0.5 github.com/lightninglabs/loop/swapserverrpc v1.0.5
github.com/lightningnetwork/lnd v0.18.0-beta.1 github.com/lightningnetwork/lnd v0.17.4-beta
github.com/lightningnetwork/lnd/cert v1.2.2 github.com/lightningnetwork/lnd/cert v1.2.2
github.com/lightningnetwork/lnd/clock v1.1.1 github.com/lightningnetwork/lnd/clock v1.1.1
github.com/lightningnetwork/lnd/queue v1.1.1 github.com/lightningnetwork/lnd/queue v1.1.1
github.com/lightningnetwork/lnd/ticker v1.1.1 github.com/lightningnetwork/lnd/ticker v1.1.1
github.com/lightningnetwork/lnd/tor v1.1.2 github.com/lightningnetwork/lnd/tor v1.1.2
github.com/ory/dockertest/v3 v3.10.0 github.com/ory/dockertest/v3 v3.10.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.8.4
github.com/urfave/cli v1.22.9 github.com/urfave/cli v1.22.9
golang.org/x/net v0.23.0 golang.org/x/net v0.17.0
google.golang.org/grpc v1.59.0 google.golang.org/grpc v1.59.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.31.0
gopkg.in/macaroon-bakery.v2 v2.1.0 gopkg.in/macaroon-bakery.v2 v2.1.0
gopkg.in/macaroon.v2 v2.1.0 gopkg.in/macaroon.v2 v2.1.0
modernc.org/sqlite v1.29.8 modernc.org/sqlite v1.20.3
) )
require ( require (
@ -48,11 +48,12 @@ require (
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/siphash v1.0.1 // indirect github.com/aead/siphash v1.0.1 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 // indirect github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 // indirect github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 // indirect
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 // indirect github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 // indirect
github.com/btcsuite/btcwallet/walletdb v1.4.2 // indirect github.com/btcsuite/btcwallet/walletdb v1.4.0 // indirect
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
github.com/btcsuite/winsvc v1.0.0 // indirect github.com/btcsuite/winsvc v1.0.0 // indirect
@ -63,84 +64,88 @@ require (
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/decred/dcrd/lru v1.1.2 // indirect github.com/decred/dcrd/lru v1.0.0 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/docker v24.0.9+incompatible // indirect github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dsnet/compress v0.0.1 // indirect
github.com/fergusstrange/embedded-postgres v1.25.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fergusstrange/embedded-postgres v1.10.0 // indirect
github.com/go-errors/errors v1.0.1 // indirect github.com/go-errors/errors v1.0.1 // indirect
github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect github.com/google/btree v1.0.1 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/imdario/mergo v0.3.13 // indirect github.com/imdario/mergo v0.3.13 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.2 // indirect github.com/jackc/pgx/v4 v4.18.1 // indirect
github.com/jackpal/gateway v1.0.5 // indirect github.com/jackpal/gateway v1.0.5 // indirect
github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad // indirect github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/jrick/logrotate v1.0.0 // indirect github.com/jrick/logrotate v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 // indirect github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/kkdai/bstream v1.0.0 // indirect github.com/kkdai/bstream v1.0.0 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd // indirect github.com/lightninglabs/neutrino v0.16.0 // indirect
github.com/lightninglabs/neutrino/cache v1.1.2 // indirect github.com/lightninglabs/neutrino/cache v1.1.1 // indirect
github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f // indirect github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f // indirect
github.com/lightningnetwork/lnd/fn v1.0.5 // indirect github.com/lightningnetwork/lnd/healthcheck v1.2.3 // indirect
github.com/lightningnetwork/lnd/healthcheck v1.2.4 // indirect github.com/lightningnetwork/lnd/kvdb v1.4.4 // indirect
github.com/lightningnetwork/lnd/kvdb v1.4.8 // indirect github.com/lightningnetwork/lnd/tlv v1.1.1 // indirect
github.com/lightningnetwork/lnd/sqldb v1.0.2 // indirect
github.com/lightningnetwork/lnd/tlv v1.2.3 // indirect
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.17 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mholt/archiver/v3 v3.5.0 // indirect
github.com/miekg/dns v1.1.43 // indirect github.com/miekg/dns v1.1.43 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/moby/term v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nwaples/rardecode v1.1.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.12 // indirect github.com/opencontainers/runc v1.1.12 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.11.1 // indirect github.com/prometheus/client_golang v1.11.1 // indirect
github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.30.0 // indirect github.com/prometheus/common v0.30.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.7.3 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.2 // indirect github.com/sirupsen/logrus v1.9.2 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 // indirect github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect
@ -155,47 +160,50 @@ require (
go.etcd.io/etcd/pkg/v3 v3.5.7 // indirect go.etcd.io/etcd/pkg/v3 v3.5.7 // indirect
go.etcd.io/etcd/raft/v3 v3.5.7 // indirect go.etcd.io/etcd/raft/v3 v3.5.7 // indirect
go.etcd.io/etcd/server/v3 v3.5.7 // indirect go.etcd.io/etcd/server/v3 v3.5.7 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect
go.opentelemetry.io/otel v1.21.0 // indirect go.opentelemetry.io/otel v1.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 // indirect
go.opentelemetry.io/otel/metric v1.21.0 // indirect go.opentelemetry.io/otel/metric v1.20.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect go.opentelemetry.io/otel/sdk v1.3.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.20.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.7.0 // indirect go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.17.0 // indirect go.uber.org/zap v1.17.0 // indirect
golang.org/x/crypto v0.22.0 // indirect golang.org/x/crypto v0.17.0 // indirect
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect
golang.org/x/mod v0.16.0 // indirect golang.org/x/mod v0.10.0 // indirect
golang.org/x/sync v0.6.0 // indirect golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.19.0 // indirect golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.19.0 // indirect golang.org/x/tools v0.9.1 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
gopkg.in/errgo.v1 v1.0.1 // indirect gopkg.in/errgo.v1 v1.0.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/libc v1.49.3 // indirect modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/mathutil v1.6.0 // indirect modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/memory v1.8.0 // indirect modernc.org/libc v1.22.2 // indirect
modernc.org/strutil v1.2.0 // indirect modernc.org/mathutil v1.5.0 // indirect
modernc.org/token v1.1.0 // indirect modernc.org/memory v1.4.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect sigs.k8s.io/yaml v1.2.0 // indirect
) )
// We want to format raw bytes as hex instead of base64. The forked version // We want to format raw bytes as hex instead of base64. The forked version
// allows us to specify that as an option. // allows us to specify that as an option.
replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.33.0-hex-display replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display
replace github.com/lightninglabs/loop/swapserverrpc => ./swapserverrpc replace github.com/lightninglabs/loop/swapserverrpc => ./swapserverrpc
go 1.22.3 go 1.19

334
go.sum

@ -36,7 +36,7 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY
cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o=
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
@ -173,8 +173,7 @@ cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
@ -607,7 +606,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e h1:n+DcnTNkQnHlwpsrHoQtkrJIO7CBx029fw6oR4vIob4= github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e h1:n+DcnTNkQnHlwpsrHoQtkrJIO7CBx029fw6oR4vIob4=
@ -632,6 +630,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
@ -645,15 +645,19 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
github.com/btcsuite/btcd v0.22.0-beta.0.20220204213055-eaf0459ff879/go.mod h1:osu7EoKiL36UThEgzYPqdRaxeo0NU8VoXqgcnwpey0g=
github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A=
github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46 h1:tjpNTdZNQqE14menwDGAxWfzN0DFHVTXFEyEL8yvA/4= github.com/btcsuite/btcd v0.24.1-0.20240123000108-62e6af035ec5 h1:8BHBWvtP6kkzvmCpyWEznq4eS0gfLOSVuXLesv413Xs=
github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd v0.24.1-0.20240123000108-62e6af035ec5/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg=
github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA=
github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A=
github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE=
github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34=
github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8=
github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00=
github.com/btcsuite/btcd/btcutil/psbt v1.1.8 h1:4voqtT8UppT7nmKQkXV+T9K8UyQjKOn2z/ycpmJK8wg= github.com/btcsuite/btcd/btcutil/psbt v1.1.8 h1:4voqtT8UppT7nmKQkXV+T9K8UyQjKOn2z/ycpmJK8wg=
@ -665,18 +669,20 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb h1:qoIOlBPRZWtfpcbQlNFf67Wz8ZlXo+mxQc9Pnbm/iqU= github.com/btcsuite/btcwallet v0.16.10-0.20240127010340-16b422a2e8bf h1:eNjj5R0tKP48NQxDkuKr+C9frZsdzTAemEwu75ZDQg0=
github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb/go.mod h1:2C3Q/MhYAKmk7F+Tey6LfKtKRTdQsrCf8AAAzzDPmH4= github.com/btcsuite/btcwallet v0.16.10-0.20240127010340-16b422a2e8bf/go.mod h1:LzcW/LYkQLgDufv6Ouw4cOIW0YsY+A60MTtc61/OZTU=
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 h1:etuLgGEojecsDOYTII8rYiGHjGyV5xTqsXi+ZQ715UU=
github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2/go.mod h1:Zpk/LOb2sKqwP2lmHjaZT9AdaKsHPSbNLm2Uql5IQ/0=
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk= github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 h1:BtEN5Empw62/RVnZ0VcJaVtVlBijnLlJY+dwjAye2Bg=
github.com/btcsuite/btcwallet/wallet/txrules v1.2.1/go.mod h1:MVSqRkju/IGxImXYPfBkG65FgEZYA4fXchheILMVl8g= github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0=
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4 h1:nmcKAVTv/cmYrs0A4hbiC6Qw+WTLYy/14SmTt3mLnCo= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.2/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448=
github.com/btcsuite/btcwallet/wallet/txsizes v1.2.4/go.mod h1:YqJR8WAAHiKIPesZTr9Cx9Az4fRhRLcJ6GcxzRUZCAc= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 h1:PszOub7iXVYbtGybym5TGCp9Dv1h1iX4rIC3HICZGLg=
github.com/btcsuite/btcwallet/walletdb v1.4.2 h1:zwZZ+zaHo4mK+FAN6KeK85S3oOm+92x2avsHvFAhVBE= github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448=
github.com/btcsuite/btcwallet/walletdb v1.4.2/go.mod h1:7ZQ+BvOEre90YT7eSq8bLoxTsgXidUzA/mqbRS114CQ= github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
github.com/btcsuite/btcwallet/wtxmgr v1.5.3 h1:QrWCio9Leh3DwkWfp+A1SURj8pYn3JuTLv3waP5uEro= github.com/btcsuite/btcwallet/walletdb v1.4.0 h1:/C5JRF+dTuE2CNMCO/or5N8epsrhmSM4710uBQoYPTQ=
github.com/btcsuite/btcwallet/wtxmgr v1.5.3/go.mod h1:M4nQpxGTXiDlSOODKXboXX7NFthmiBNjzAKKNS7Fhjg= github.com/btcsuite/btcwallet/walletdb v1.4.0/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
github.com/btcsuite/btcwallet/wtxmgr v1.5.0 h1:WO0KyN4l6H3JWnlFxfGR7r3gDnlGT7W2cL8vl6av4SU=
github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc=
@ -695,7 +701,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
@ -716,17 +721,13 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY=
github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY=
@ -744,36 +745,32 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY= github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw=
github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8=
github.com/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M=
github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78=
github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M=
github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@ -790,9 +787,8 @@ github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg=
github.com/fergusstrange/embedded-postgres v1.25.0 h1:sa+k2Ycrtz40eCRPOzI7Ry7TtkWXXJ+YRsxpKMDhxK0= github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c=
github.com/fergusstrange/embedded-postgres v1.25.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
@ -800,13 +796,10 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu
github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBavT6B6CuGq2k= github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBavT6B6CuGq2k=
github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
@ -837,26 +830,23 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYND2gB4p7xcaU= github.com/golang-migrate/migrate/v4 v4.16.1 h1:O+0C55RbMN66pWm5MjO6mw0px6usGpY0+bkSGW9zCo0=
github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= github.com/golang-migrate/migrate/v4 v4.16.1/go.mod h1:qXiwa/3Zeqaltm1MxOCZDYysW/F6folYiBgBG03l9hc=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -882,9 +872,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@ -910,7 +900,6 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -932,15 +921,14 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
@ -977,8 +965,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -995,10 +981,10 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q=
github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw=
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
@ -1014,8 +1000,8 @@ github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvW
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0=
github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
@ -1029,11 +1015,12 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0=
github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc=
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsNCekUlsFhO2jstxO4b5iQ665LjwM5mDc= github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad h1:heFfj7z0pGsNCekUlsFhO2jstxO4b5iQ665LjwM5mDc=
@ -1055,27 +1042,20 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/juju/clock v0.0.0-20220203021603-d9deb868a28a h1:Az/6CM/P5guGHNy7r6TkOCctv3lDmN3W1uhku7QMupk= github.com/juju/clock v0.0.0-20220203021603-d9deb868a28a h1:Az/6CM/P5guGHNy7r6TkOCctv3lDmN3W1uhku7QMupk=
github.com/juju/clock v0.0.0-20220203021603-d9deb868a28a/go.mod h1:GZ/FY8Cqw3KHG6DwRVPUKbSPTAwyrU28xFi5cqZnLsc=
github.com/juju/collections v0.0.0-20220203020748-febd7cad8a7a h1:d7eZO8OS/ZXxdP0uq3E8CdoA1qNFaecAv90UxrxaY2k= github.com/juju/collections v0.0.0-20220203020748-febd7cad8a7a h1:d7eZO8OS/ZXxdP0uq3E8CdoA1qNFaecAv90UxrxaY2k=
github.com/juju/collections v0.0.0-20220203020748-febd7cad8a7a/go.mod h1:JWeZdyttIEbkR51z2S13+J+aCuHVe0F6meRy+P0YGDo=
github.com/juju/errors v0.0.0-20220331221717-b38fca44723b h1:AxFeSQJfcm2O3ov1wqAkTKYFsnMw2g1B4PkYujfAdkY= github.com/juju/errors v0.0.0-20220331221717-b38fca44723b h1:AxFeSQJfcm2O3ov1wqAkTKYFsnMw2g1B4PkYujfAdkY=
github.com/juju/errors v0.0.0-20220331221717-b38fca44723b/go.mod h1:jMGj9DWF/qbo91ODcfJq6z/RYc3FX3taCBZMCcpI4Ls=
github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY=
github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg=
github.com/juju/mgo/v2 v2.0.0-20220111072304-f200228f1090 h1:zX5GoH3Jp8k1EjUFkApu/YZAYEn0PYQfg/U6IDyNyYs= github.com/juju/mgo/v2 v2.0.0-20220111072304-f200228f1090 h1:zX5GoH3Jp8k1EjUFkApu/YZAYEn0PYQfg/U6IDyNyYs=
github.com/juju/mgo/v2 v2.0.0-20220111072304-f200228f1090/go.mod h1:N614SE0a4e+ih2rg96Vi2PeC3cTpUOWgCTv3Cgk974c=
github.com/juju/retry v0.0.0-20220204093819-62423bf33287 h1:U+7oMWEglXfiikIppNexButZRwKPlzLBGKYSNCXzXf8= github.com/juju/retry v0.0.0-20220204093819-62423bf33287 h1:U+7oMWEglXfiikIppNexButZRwKPlzLBGKYSNCXzXf8=
github.com/juju/retry v0.0.0-20220204093819-62423bf33287/go.mod h1:SssN1eYeK3A2qjnFGTiVMbdzGJ2BfluaJblJXvuvgqA=
github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 h1:XEDzpuZb8Ma7vLja3+5hzUqVTvAqm5Y+ygvnDs5iTMM= github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 h1:XEDzpuZb8Ma7vLja3+5hzUqVTvAqm5Y+ygvnDs5iTMM=
github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494/go.mod h1:rUquetT0ALL48LHZhyRGvjjBH8xZaZ8dFClulKK5wK4=
github.com/juju/utils/v3 v3.0.0-20220203023959-c3fbc78a33b0 h1:bn+2Adl1yWqYjm3KSFlFqsvfLg2eq+XNL7GGMYApdVw= github.com/juju/utils/v3 v3.0.0-20220203023959-c3fbc78a33b0 h1:bn+2Adl1yWqYjm3KSFlFqsvfLg2eq+XNL7GGMYApdVw=
github.com/juju/utils/v3 v3.0.0-20220203023959-c3fbc78a33b0/go.mod h1:8csUcj1VRkfjNIRzBFWzLFCMLwLqsRWvkmhfVAUwbC4=
github.com/juju/version/v2 v2.0.0-20220204124744-fc9915e3d935 h1:6YoyzXVW1XkqN86y2s/rz365Jm7EiAy39v2G5ikzvHU= github.com/juju/version/v2 v2.0.0-20220204124744-fc9915e3d935 h1:6YoyzXVW1XkqN86y2s/rz365Jm7EiAy39v2G5ikzvHU=
github.com/juju/version/v2 v2.0.0-20220204124744-fc9915e3d935/go.mod h1:ZeFjNy+UFEWJDDPdzW7Cm9NeU6dsViGaFYhXzycLQrw=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@ -1083,8 +1063,15 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6
github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -1094,7 +1081,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@ -1103,43 +1089,41 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightninglabs/aperture v0.3.2-beta h1:J2GQwBmSHxpr5VOatXbgrTogF/qN2l6UWLPHfIowq10= github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030 h1:q/BBO2awQdy/dCILXXZbBsstQ+1DpSQ/c8B8EgKqg+g=
github.com/lightninglabs/aperture v0.3.2-beta/go.mod h1:M/5dPzHjHvuYXQuxzicqaGiCclHUvKW6N0ay1t/HGiM= github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030/go.mod h1:Jvoen+fgoaGQZIHdchiGigu0Lwuwz8S5u5wad9IhVDU=
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= 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/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk=
github.com/lightninglabs/lndclient v0.18.0-1 h1:b9ur24NTbNRUOfotkhio6SAlkvXADLz9k7QLIlLYpSk= github.com/lightninglabs/lndclient v0.17.4-1 h1:uCLBYf1f1nOoagHuiPK9anERA86dNSlYK9/QGb410RQ=
github.com/lightninglabs/lndclient v0.18.0-1/go.mod h1:GBIttLpj+W82XrZrFvQ1gpQH074aTcwisP/zvdGbqE4= github.com/lightninglabs/lndclient v0.17.4-1/go.mod h1:2krqTDgp3W3DLSDx9bYaT0MDrMVslGMXETViKE8J1pk=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s= github.com/lightninglabs/neutrino v0.16.0 h1:YNTQG32fPR/Zg0vvJVI65OBH8l3U18LSXXtX91hx0q0=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk= github.com/lightninglabs/neutrino v0.16.0/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk=
github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3shmlu5hIQ798g= github.com/lightninglabs/neutrino/cache v1.1.1 h1:TllWOSlkABhpgbWJfzsrdUaDH2fBy/54VSIB4vVqV8M=
github.com/lightninglabs/neutrino/cache v1.1.2/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= github.com/lightninglabs/neutrino/cache v1.1.1/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo=
github.com/lightninglabs/protobuf-go-hex-display v1.33.0-hex-display h1:Y2WiPkBS/00EiEg0qp0FhehxnQfk3vv8U6Xt3nN+rTY= github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display h1:pRdza2wleRN1L2fJXd6ZoQ9ZegVFTAb2bOQfruJPKcY=
github.com/lightninglabs/protobuf-go-hex-display v1.33.0-hex-display/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f h1:Pua7+5TcFEJXIIZ1I2YAUapmbcttmLj4TTi786bIi3s= github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f h1:Pua7+5TcFEJXIIZ1I2YAUapmbcttmLj4TTi786bIi3s=
github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI=
github.com/lightningnetwork/lnd v0.18.0-beta.1 h1:7DpRre4rtUmLim4JC5oPd3KEd1Q3QpWTH6jQgSOGNYM= github.com/lightningnetwork/lnd v0.17.4-beta h1:BXYbETYZWtcNrYcAosGGXnWsq4Nr5R9PRqlRuEA9AUs=
github.com/lightningnetwork/lnd v0.18.0-beta.1/go.mod h1:1SA9iv9rZddNAcfP38SN9lNSVT1zf5aqmukLUoomjDU= github.com/lightningnetwork/lnd v0.17.4-beta/go.mod h1:S5hugoB/FWyF9Up9sjEnOsA/ohmhXzIqRHHMLlrtyFk=
github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI= github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI=
github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U= github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U=
github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg=
github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0=
github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ= github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ=
github.com/lightningnetwork/lnd/fn v1.0.5 h1:ffDgMSn83avw6rNzxhbt6w5/2oIrwQKTPGfyaLupZtE= github.com/lightningnetwork/lnd/healthcheck v1.2.3 h1:oqhOOy8WmIEa6RBkYKC0mmYZkhl8T2kGD97n9jpML8o=
github.com/lightningnetwork/lnd/fn v1.0.5/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U= github.com/lightningnetwork/lnd/healthcheck v1.2.3/go.mod h1:eDxH3dEwV9DeBW/6inrmlVh1qBOFV0AI14EEPnGt9gc=
github.com/lightningnetwork/lnd/healthcheck v1.2.4 h1:lLPLac+p/TllByxGSlkCwkJlkddqMP5UCoawCj3mgFQ= github.com/lightningnetwork/lnd/kvdb v1.4.4 h1:bCv63rVCvzqj1BkagN/EWTov6NDDgYEG/t0z2HepRMk=
github.com/lightningnetwork/lnd/healthcheck v1.2.4/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I= github.com/lightningnetwork/lnd/kvdb v1.4.4/go.mod h1:9SuaIqMA9ugrVkdvgQkYXa8CAKYNYd4vsEYORP4V698=
github.com/lightningnetwork/lnd/kvdb v1.4.8 h1:xH0a5Vi1yrcZ5BEeF2ba3vlKBRxrL9uYXlWTjOjbNTY=
github.com/lightningnetwork/lnd/kvdb v1.4.8/go.mod h1:J2diNABOoII9UrMnxXS5w7vZwP7CA1CStrl8MnIrb3A=
github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI=
github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4=
github.com/lightningnetwork/lnd/sqldb v1.0.2 h1:PfuYzScYMD9/QonKo/QvgsbXfTnH5DfldIimkfdW4Bk=
github.com/lightningnetwork/lnd/sqldb v1.0.2/go.mod h1:V2Xl6JNWLTKE97WJnwfs0d0TYJdIQTqK8/3aAwkd3qI=
github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM=
github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA=
github.com/lightningnetwork/lnd/tlv v1.2.3 h1:If5ibokA/UoCBGuCKaY6Vn2SJU0l9uAbehCnhTZjEP8= github.com/lightningnetwork/lnd/tlv v1.1.1 h1:BW1u9+uHLRA9sm+8FBkAg1H9rPjrj3S9KvXYiCYjQWk=
github.com/lightningnetwork/lnd/tlv v1.2.3/go.mod h1:zDkmqxOczP6LaLTvSFDQ1SJUfHcQRCMKFj93dn3eMB8= github.com/lightningnetwork/lnd/tlv v1.1.1/go.mod h1:292dSXpZ+BNnSJFjS1qvHden9LEbulmECglSgfg+4lw=
github.com/lightningnetwork/lnd/tor v1.1.2 h1:3zv9z/EivNFaMF89v3ciBjCS7kvCj4ZFG7XvD2Qq0/k= github.com/lightningnetwork/lnd/tor v1.1.2 h1:3zv9z/EivNFaMF89v3ciBjCS7kvCj4ZFG7XvD2Qq0/k=
github.com/lightningnetwork/lnd/tor v1.1.2/go.mod h1:j7T9uJ2NLMaHwE7GiBGnpYLn4f7NRoTM6qj+ul6/ycA= github.com/lightningnetwork/lnd/tor v1.1.2/go.mod h1:j7T9uJ2NLMaHwE7GiBGnpYLn4f7NRoTM6qj+ul6/ycA=
github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw=
@ -1157,14 +1141,15 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE=
github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
@ -1181,26 +1166,23 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M=
github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
@ -1213,6 +1195,8 @@ github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnz
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -1246,9 +1230,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -1266,7 +1249,6 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -1287,9 +1269,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@ -1300,18 +1281,21 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02 h1:tcJ6OjwOMvExLlzrAVZute09ocAGa7KqOON60++Gz4E=
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw=
github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
@ -1334,6 +1318,7 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo=
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ=
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY=
@ -1358,25 +1343,24 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M=
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc=
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 h1:R/OBkMoGgfy2fLhs2QhkCI1w4HLEQX92GCcJB6SSdNk= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 h1:R/OBkMoGgfy2fLhs2QhkCI1w4HLEQX92GCcJB6SSdNk=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 h1:giGm8w67Ja7amYNfYMdme7xSp2pIxThWopw8+QP51Yk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 h1:giGm8w67Ja7amYNfYMdme7xSp2pIxThWopw8+QP51Yk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 h1:VQbUHoJqytHHSJ1OZodPH9tvZZSVzUHjPHpkO85sT6k= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0 h1:VQbUHoJqytHHSJ1OZodPH9tvZZSVzUHjPHpkO85sT6k=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY=
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA=
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM=
go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI=
go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ=
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
@ -1417,8 +1401,9 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1434,8 +1419,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -1478,8 +1463,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1546,8 +1531,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1577,8 +1562,7 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1595,8 +1579,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1695,8 +1679,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1706,8 +1690,8 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1801,8 +1785,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -2019,12 +2003,12 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl
google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY=
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -2104,7 +2088,6 @@ gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@ -2114,27 +2097,24 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws=
modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
@ -2143,35 +2123,33 @@ modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0=
modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s=
modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0=
modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4=
modernc.org/sqlite v1.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8= modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs=
modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk= modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

@ -19,7 +19,6 @@ import (
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
) )
const ( const (
@ -60,7 +59,6 @@ type InitInstantOutCtx struct {
initationHeight int32 initationHeight int32
outgoingChanSet loopdb.ChannelSet outgoingChanSet loopdb.ChannelSet
protocolVersion ProtocolVersion protocolVersion ProtocolVersion
sweepAddress btcutil.Address
} }
// InitInstantOutAction is the first action that is executed when the instant // InitInstantOutAction is the first action that is executed when the instant
@ -109,7 +107,7 @@ func (f *FSM) InitInstantOutAction(eventCtx fsm.EventContext) fsm.EventType {
if int32(res.Expiry) < initCtx.cltvExpiry+htlcExpiryDelta { if int32(res.Expiry) < initCtx.cltvExpiry+htlcExpiryDelta {
return f.HandleError(fmt.Errorf("reservation %x has "+ return f.HandleError(fmt.Errorf("reservation %x has "+
"expiry %v which is less than the swap expiry %v", "expiry %v which is less than the swap expiry %v",
resId, res.Expiry, initCtx.cltvExpiry+htlcExpiryDelta)) resId, res.Expiry, initCtx.cltvExpiry))
} }
} }
@ -167,15 +165,11 @@ func (f *FSM) InitInstantOutAction(eventCtx fsm.EventContext) fsm.EventType {
} }
// Create the address that we'll send the funds to. // Create the address that we'll send the funds to.
sweepAddress := initCtx.sweepAddress sweepAddress, err := f.cfg.Wallet.NextAddr(
if sweepAddress == nil { f.ctx, "", walletrpc.AddressType_TAPROOT_PUBKEY, false,
sweepAddress, err = f.cfg.Wallet.NextAddr( )
f.ctx, lnwallet.DefaultAccountName, if err != nil {
walletrpc.AddressType_TAPROOT_PUBKEY, false, return f.HandleError(err)
)
if err != nil {
return f.HandleError(err)
}
} }
// Now we can create the instant out. // Now we can create the instant out.
@ -185,13 +179,13 @@ func (f *FSM) InitInstantOutAction(eventCtx fsm.EventContext) fsm.EventType {
protocolVersion: ProtocolVersionFullReservation, protocolVersion: ProtocolVersionFullReservation,
initiationHeight: initCtx.initationHeight, initiationHeight: initCtx.initationHeight,
outgoingChanSet: initCtx.outgoingChanSet, outgoingChanSet: initCtx.outgoingChanSet,
CltvExpiry: initCtx.cltvExpiry, cltvExpiry: initCtx.cltvExpiry,
clientPubkey: keyRes.PubKey, clientPubkey: keyRes.PubKey,
serverPubkey: serverPubkey, serverPubkey: serverPubkey,
Value: btcutil.Amount(reservationAmt), value: btcutil.Amount(reservationAmt),
htlcFeeRate: feeRate, htlcFeeRate: feeRate,
swapInvoice: instantOutResponse.SwapInvoice, swapInvoice: instantOutResponse.SwapInvoice,
Reservations: reservations, reservations: reservations,
keyLocator: keyRes.KeyLocator, keyLocator: keyRes.KeyLocator,
sweepAddress: sweepAddress, sweepAddress: sweepAddress,
} }
@ -211,7 +205,7 @@ func (f *FSM) InitInstantOutAction(eventCtx fsm.EventContext) fsm.EventType {
func (f *FSM) PollPaymentAcceptedAction(_ fsm.EventContext) fsm.EventType { func (f *FSM) PollPaymentAcceptedAction(_ fsm.EventContext) fsm.EventType {
// Now that we're doing the swap, we first lock the reservations // Now that we're doing the swap, we first lock the reservations
// so that they can't be used for other swaps. // so that they can't be used for other swaps.
for _, reservation := range f.InstantOut.Reservations { for _, reservation := range f.InstantOut.reservations {
err := f.cfg.ReservationManager.LockReservation( err := f.cfg.ReservationManager.LockReservation(
f.ctx, reservation.ID, f.ctx, reservation.ID,
) )
@ -227,7 +221,7 @@ func (f *FSM) PollPaymentAcceptedAction(_ fsm.EventContext) fsm.EventType {
Invoice: f.InstantOut.swapInvoice, Invoice: f.InstantOut.swapInvoice,
Timeout: defaultSendpaymentTimeout, Timeout: defaultSendpaymentTimeout,
MaxParts: defaultMaxParts, MaxParts: defaultMaxParts,
MaxFee: getMaxRoutingFee(f.InstantOut.Value), MaxFee: getMaxRoutingFee(f.InstantOut.value),
}, },
) )
if err != nil { if err != nil {
@ -301,7 +295,7 @@ func (f *FSM) BuildHTLCAction(eventCtx fsm.EventContext) fsm.EventType {
return f.handleErrorAndUnlockReservations(err) return f.handleErrorAndUnlockReservations(err)
} }
if len(htlcInitRes.HtlcServerNonces) != len(f.InstantOut.Reservations) { if len(htlcInitRes.HtlcServerNonces) != len(f.InstantOut.reservations) {
return f.handleErrorAndUnlockReservations( return f.handleErrorAndUnlockReservations(
errors.New("invalid number of server nonces"), errors.New("invalid number of server nonces"),
) )
@ -435,8 +429,8 @@ func (f *FSM) PushPreimageAction(eventCtx fsm.EventContext) fsm.EventType {
return OnErrorPublishHtlc return OnErrorPublishHtlc
} }
f.InstantOut.FinalizedSweeplessSweepTx = sweepTx f.InstantOut.finalizedSweeplessSweepTx = sweepTx
txHash := f.InstantOut.FinalizedSweeplessSweepTx.TxHash() txHash := f.InstantOut.finalizedSweeplessSweepTx.TxHash()
f.InstantOut.SweepTxHash = &txHash f.InstantOut.SweepTxHash = &txHash
@ -598,7 +592,7 @@ func (f *FSM) handleErrorAndUnlockReservations(err error) fsm.EventType {
defer cancel() defer cancel()
// Unlock the reservations. // Unlock the reservations.
for _, reservation := range f.InstantOut.Reservations { for _, reservation := range f.InstantOut.reservations {
err := f.cfg.ReservationManager.UnlockReservation( err := f.cfg.ReservationManager.UnlockReservation(
ctx, reservation.ID, ctx, reservation.ID,
) )

@ -35,16 +35,16 @@ type InstantOut struct {
// State is the current state of the swap. // State is the current state of the swap.
State fsm.StateType State fsm.StateType
// CltvExpiry is the expiry of the swap. // cltvExpiry is the expiry of the swap.
CltvExpiry int32 cltvExpiry int32
// outgoingChanSet optionally specifies the short channel ids of the // outgoingChanSet optionally specifies the short channel ids of the
// channels that may be used to loop out. // channels that may be used to loop out.
outgoingChanSet loopdb.ChannelSet outgoingChanSet loopdb.ChannelSet
// Reservations are the Reservations that are used in as inputs for the // reservations are the reservations that are used in as inputs for the
// instant out swap. // instant out swap.
Reservations []*reservation.Reservation reservations []*reservation.Reservation
// protocolVersion is the version of the protocol that is used for the // protocolVersion is the version of the protocol that is used for the
// swap. // swap.
@ -53,8 +53,8 @@ type InstantOut struct {
// initiationHeight is the height at which the swap was initiated. // initiationHeight is the height at which the swap was initiated.
initiationHeight int32 initiationHeight int32
// Value is the amount that is swapped. // value is the amount that is swapped.
Value btcutil.Amount value btcutil.Amount
// keyLocator is the key locator that is used for the swap. // keyLocator is the key locator that is used for the swap.
keyLocator keychain.KeyLocator keyLocator keychain.KeyLocator
@ -81,9 +81,9 @@ type InstantOut struct {
// SweepTxHash is the hash of the sweep transaction. // SweepTxHash is the hash of the sweep transaction.
SweepTxHash *chainhash.Hash SweepTxHash *chainhash.Hash
// FinalizedSweeplessSweepTx is the transaction that is used to sweep // finalizedSweeplessSweepTx is the transaction that is used to sweep
// the funds in the cooperative path. // the funds in the cooperative path.
FinalizedSweeplessSweepTx *wire.MsgTx finalizedSweeplessSweepTx *wire.MsgTx
// sweepConfirmationHeight is the height at which the sweep // sweepConfirmationHeight is the height at which the sweep
// transaction was confirmed. // transaction was confirmed.
@ -93,7 +93,7 @@ type InstantOut struct {
// getHtlc returns the swap.htlc for the instant out. // getHtlc returns the swap.htlc for the instant out.
func (i *InstantOut) getHtlc(chainParams *chaincfg.Params) (*swap.Htlc, error) { func (i *InstantOut) getHtlc(chainParams *chaincfg.Params) (*swap.Htlc, error) {
return swap.NewHtlcV2( return swap.NewHtlcV2(
i.CltvExpiry, pubkeyTo33ByteSlice(i.serverPubkey), i.cltvExpiry, pubkeyTo33ByteSlice(i.serverPubkey),
pubkeyTo33ByteSlice(i.clientPubkey), i.SwapHash, chainParams, pubkeyTo33ByteSlice(i.clientPubkey), i.SwapHash, chainParams,
) )
} }
@ -104,11 +104,11 @@ func (i *InstantOut) createMusig2Session(ctx context.Context,
[][]byte, error) { [][]byte, error) {
// Create the htlc musig2 context. // Create the htlc musig2 context.
musig2Sessions := make([]*input.MuSig2SessionInfo, len(i.Reservations)) musig2Sessions := make([]*input.MuSig2SessionInfo, len(i.reservations))
clientNonces := make([][]byte, len(i.Reservations)) clientNonces := make([][]byte, len(i.reservations))
// Create the sessions and nonces from the reservations. // Create the sessions and nonces from the reservations.
for idx, reservation := range i.Reservations { for idx, reservation := range i.reservations {
session, err := reservation.Musig2CreateSession(ctx, signer) session, err := reservation.Musig2CreateSession(ctx, signer)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -123,12 +123,12 @@ func (i *InstantOut) createMusig2Session(ctx context.Context,
// getInputReservation returns the input reservation for the instant out. // getInputReservation returns the input reservation for the instant out.
func (i *InstantOut) getInputReservations() (InputReservations, error) { func (i *InstantOut) getInputReservations() (InputReservations, error) {
if len(i.Reservations) == 0 { if len(i.reservations) == 0 {
return nil, errors.New("no reservations") return nil, errors.New("no reservations")
} }
inputs := make(InputReservations, len(i.Reservations)) inputs := make(InputReservations, len(i.reservations))
for idx, reservation := range i.Reservations { for idx, reservation := range i.reservations {
pkScript, err := reservation.GetPkScript() pkScript, err := reservation.GetPkScript()
if err != nil { if err != nil {
return nil, err return nil, err
@ -170,7 +170,7 @@ func (i *InstantOut) createHtlcTransaction(network *chaincfg.Params) (
// Estimate the fee // Estimate the fee
weight := htlcWeight(len(inputReservations)) weight := htlcWeight(len(inputReservations))
fee := i.htlcFeeRate.FeeForWeight(weight) fee := i.htlcFeeRate.FeeForWeight(weight)
if fee > i.Value/5 { if fee > i.value/5 {
return nil, errors.New("fee is higher than 20% of " + return nil, errors.New("fee is higher than 20% of " +
"sweep value") "sweep value")
} }
@ -182,7 +182,7 @@ func (i *InstantOut) createHtlcTransaction(network *chaincfg.Params) (
// Create the sweep output // Create the sweep output
sweepOutput := &wire.TxOut{ sweepOutput := &wire.TxOut{
Value: int64(i.Value) - int64(fee), Value: int64(i.value) - int64(fee),
PkScript: htlc.PkScript, PkScript: htlc.PkScript,
} }
@ -214,7 +214,7 @@ func (i *InstantOut) createSweeplessSweepTx(feerate chainfee.SatPerKWeight) (
// Estimate the fee // Estimate the fee
weight := sweeplessSweepWeight(len(inputReservations)) weight := sweeplessSweepWeight(len(inputReservations))
fee := feerate.FeeForWeight(weight) fee := feerate.FeeForWeight(weight)
if fee > i.Value/5 { if fee > i.value/5 {
return nil, errors.New("fee is higher than 20% of " + return nil, errors.New("fee is higher than 20% of " +
"sweep value") "sweep value")
} }
@ -226,7 +226,7 @@ func (i *InstantOut) createSweeplessSweepTx(feerate chainfee.SatPerKWeight) (
// Create the sweep output // Create the sweep output
sweepOutput := &wire.TxOut{ sweepOutput := &wire.TxOut{
Value: int64(i.Value) - int64(fee), Value: int64(i.value) - int64(fee),
PkScript: pkscript, PkScript: pkscript,
} }
@ -381,7 +381,7 @@ func (i *InstantOut) generateHtlcSweepTx(ctx context.Context,
return nil, err return nil, err
} }
fee := feeRate.FeeForWeight(weightEstimator.Weight()) fee := feeRate.FeeForWeight(int64(weightEstimator.Weight()))
htlcOutValue := i.finalizedHtlcTx.TxOut[0].Value htlcOutValue := i.finalizedHtlcTx.TxOut[0].Value
output := &wire.TxOut{ output := &wire.TxOut{
@ -424,7 +424,7 @@ func (i *InstantOut) generateHtlcSweepTx(ctx context.Context,
} }
// htlcWeight returns the weight for the htlc transaction. // htlcWeight returns the weight for the htlc transaction.
func htlcWeight(numInputs int) lntypes.WeightUnit { func htlcWeight(numInputs int) int64 {
var weightEstimator input.TxWeightEstimator var weightEstimator input.TxWeightEstimator
for i := 0; i < numInputs; i++ { for i := 0; i < numInputs; i++ {
weightEstimator.AddTaprootKeySpendInput( weightEstimator.AddTaprootKeySpendInput(
@ -434,11 +434,11 @@ func htlcWeight(numInputs int) lntypes.WeightUnit {
weightEstimator.AddP2WSHOutput() weightEstimator.AddP2WSHOutput()
return weightEstimator.Weight() return int64(weightEstimator.Weight())
} }
// sweeplessSweepWeight returns the weight for the sweepless sweep transaction. // sweeplessSweepWeight returns the weight for the sweepless sweep transaction.
func sweeplessSweepWeight(numInputs int) lntypes.WeightUnit { func sweeplessSweepWeight(numInputs int) int64 {
var weightEstimator input.TxWeightEstimator var weightEstimator input.TxWeightEstimator
for i := 0; i < numInputs; i++ { for i := 0; i < numInputs; i++ {
weightEstimator.AddTaprootKeySpendInput( weightEstimator.AddTaprootKeySpendInput(
@ -448,7 +448,7 @@ func sweeplessSweepWeight(numInputs int) lntypes.WeightUnit {
weightEstimator.AddP2TROutput() weightEstimator.AddP2TROutput()
return weightEstimator.Weight() return int64(weightEstimator.Weight())
} }
// pubkeyTo33ByteSlice converts a pubkey to a 33 byte slice. // pubkeyTo33ByteSlice converts a pubkey to a 33 byte slice.

@ -137,20 +137,7 @@ func (m *Manager) recoverInstantOuts(ctx context.Context) error {
// NewInstantOut creates a new instantout. // NewInstantOut creates a new instantout.
func (m *Manager) NewInstantOut(ctx context.Context, func (m *Manager) NewInstantOut(ctx context.Context,
reservations []reservation.ID, sweepAddress string) (*FSM, error) { reservations []reservation.ID) (*FSM, error) {
var (
sweepAddr btcutil.Address
err error
)
if sweepAddress != "" {
sweepAddr, err = btcutil.DecodeAddress(
sweepAddress, m.cfg.Network,
)
if err != nil {
return nil, err
}
}
m.Lock() m.Lock()
// Create the instantout request. // Create the instantout request.
@ -159,7 +146,6 @@ func (m *Manager) NewInstantOut(ctx context.Context,
reservations: reservations, reservations: reservations,
initationHeight: m.currentHeight, initationHeight: m.currentHeight,
protocolVersion: CurrentProtocolVersion(), protocolVersion: CurrentProtocolVersion(),
sweepAddress: sweepAddr,
} }
instantOut, err := NewFSM( instantOut, err := NewFSM(
@ -258,8 +244,3 @@ func (m *Manager) GetInstantOutQuote(ctx context.Context,
OnChainFee: chainFee, OnChainFee: chainFee,
}, nil }, nil
} }
// ListInstantOuts returns all instant outs from the database.
func (m *Manager) ListInstantOuts(ctx context.Context) ([]*InstantOut, error) {
return m.cfg.Store.ListInstantLoopOuts(ctx)
}

@ -9,6 +9,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/lightninglabs/loop/fsm" "github.com/lightninglabs/loop/fsm"
reservationrpc "github.com/lightninglabs/loop/swapserverrpc" reservationrpc "github.com/lightninglabs/loop/swapserverrpc"
) )
@ -185,7 +186,7 @@ func (m *Manager) fetchL402(ctx context.Context) {
func (m *Manager) RegisterReservationNotifications( func (m *Manager) RegisterReservationNotifications(
reservationChan chan *reservationrpc.ServerReservationNotification) error { reservationChan chan *reservationrpc.ServerReservationNotification) error {
// In order to create a valid l402 we first are going to call // In order to create a valid lsat we first are going to call
// the FetchL402 method. As a client might not have outbound capacity // the FetchL402 method. As a client might not have outbound capacity
// yet, we'll retry until we get a valid response. // yet, we'll retry until we get a valid response.
if !m.hasL402 { if !m.hasL402 {

@ -112,7 +112,7 @@ func newManagerTestContext(t *testing.T) *ManagerTestContext {
dbFixture := loopdb.NewTestDB(t) dbFixture := loopdb.NewTestDB(t)
store := NewSQLStore(loopdb.NewTypedStore[Querier](dbFixture)) store := NewSQLStore(dbFixture)
mockReservationClient := new(mockReservationClient) mockReservationClient := new(mockReservationClient)

@ -16,9 +16,9 @@ import (
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
) )
// Querier is the interface that contains all the queries generated // BaseDB is the interface that contains all the queries generated
// by sqlc for the reservation table. // by sqlc for the reservation table.
type Querier interface { type BaseDB interface {
// CreateReservation stores the reservation in the database. // CreateReservation stores the reservation in the database.
CreateReservation(ctx context.Context, CreateReservation(ctx context.Context,
arg sqlc.CreateReservationParams) error arg sqlc.CreateReservationParams) error
@ -35,24 +35,14 @@ type Querier interface {
// made. // made.
GetReservations(ctx context.Context) ([]sqlc.Reservation, error) GetReservations(ctx context.Context) ([]sqlc.Reservation, error)
// InsertReservationUpdate inserts a new reservation update. // UpdateReservation inserts a new reservation update.
InsertReservationUpdate(ctx context.Context,
arg sqlc.InsertReservationUpdateParams) error
// UpdateReservation updates a reservation.
UpdateReservation(ctx context.Context, UpdateReservation(ctx context.Context,
arg sqlc.UpdateReservationParams) error arg sqlc.UpdateReservationParams) error
}
// BaseDB is the interface that contains all the queries generated
// by sqlc for the reservation table and transaction functionality.
type BaseDB interface {
Querier
// ExecTx allows for executing a function in the context of a database // ExecTx allows for executing a function in the context of a database
// transaction. // transaction.
ExecTx(ctx context.Context, txOptions loopdb.TxOptions, ExecTx(ctx context.Context, txOptions loopdb.TxOptions,
txBody func(Querier) error) error txBody func(*sqlc.Queries) error) error
} }
// SQLStore manages the reservations in the database. // SQLStore manages the reservations in the database.
@ -91,8 +81,8 @@ func (r *SQLStore) CreateReservation(ctx context.Context,
UpdateState: string(reservation.State), UpdateState: string(reservation.State),
} }
return r.baseDb.ExecTx(ctx, loopdb.NewSqlWriteOpts(), return r.baseDb.ExecTx(ctx, &loopdb.SqliteTxOptions{},
func(q Querier) error { func(q *sqlc.Queries) error {
err := q.CreateReservation(ctx, args) err := q.CreateReservation(ctx, args)
if err != nil { if err != nil {
return err return err
@ -131,8 +121,8 @@ func (r *SQLStore) UpdateReservation(ctx context.Context,
), ),
} }
return r.baseDb.ExecTx(ctx, loopdb.NewSqlWriteOpts(), return r.baseDb.ExecTx(ctx, &loopdb.SqliteTxOptions{},
func(q Querier) error { func(q *sqlc.Queries) error {
err := q.UpdateReservation(ctx, updateArgs) err := q.UpdateReservation(ctx, updateArgs)
if err != nil { if err != nil {
return err return err
@ -148,7 +138,7 @@ func (r *SQLStore) GetReservation(ctx context.Context,
var reservation *Reservation var reservation *Reservation
err := r.baseDb.ExecTx(ctx, loopdb.NewSqlReadOpts(), err := r.baseDb.ExecTx(ctx, loopdb.NewSqlReadOpts(),
func(q Querier) error { func(q *sqlc.Queries) error {
var err error var err error
reservationRow, err := q.GetReservation( reservationRow, err := q.GetReservation(
ctx, reservationId[:], ctx, reservationId[:],
@ -192,7 +182,7 @@ func (r *SQLStore) ListReservations(ctx context.Context) ([]*Reservation,
var result []*Reservation var result []*Reservation
err := r.baseDb.ExecTx(ctx, loopdb.NewSqlReadOpts(), err := r.baseDb.ExecTx(ctx, loopdb.NewSqlReadOpts(),
func(q Querier) error { func(q *sqlc.Queries) error {
var err error var err error
reservations, err := q.GetReservations(ctx) reservations, err := q.GetReservations(ctx)

@ -19,7 +19,7 @@ func TestSqlStore(t *testing.T) {
testDb := loopdb.NewTestDB(t) testDb := loopdb.NewTestDB(t)
defer testDb.Close() defer testDb.Close()
store := NewSQLStore(loopdb.NewTypedStore[Querier](testDb)) store := NewSQLStore(testDb)
// Create a reservation and store it. // Create a reservation and store it.
reservation := &Reservation{ reservation := &Reservation{

@ -21,9 +21,9 @@ import (
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
) )
// Querier is the interface that contains all the queries generated // InstantOutBaseDB is the interface that contains all the queries generated
// by sqlc for the instantout table. // by sqlc for the instantout table.
type Querier interface { type InstantOutBaseDB interface {
// InsertSwap inserts a new base swap. // InsertSwap inserts a new base swap.
InsertSwap(ctx context.Context, arg sqlc.InsertSwapParams) error InsertSwap(ctx context.Context, arg sqlc.InsertSwapParams) error
@ -53,17 +53,11 @@ type Querier interface {
// GetInstantOutSwaps retrieves all instant out swaps. // GetInstantOutSwaps retrieves all instant out swaps.
GetInstantOutSwaps(ctx context.Context) ([]sqlc.GetInstantOutSwapsRow, GetInstantOutSwaps(ctx context.Context) ([]sqlc.GetInstantOutSwapsRow,
error) error)
}
// InstantOutBaseDB is the interface that contains all the queries generated
// by sqlc for the instantout table and transaction functionality.
type InstantOutBaseDB interface {
Querier
// ExecTx allows for executing a function in the context of a database // ExecTx allows for executing a function in the context of a database
// transaction. // transaction.
ExecTx(ctx context.Context, txOptions loopdb.TxOptions, ExecTx(ctx context.Context, txOptions loopdb.TxOptions,
txBody func(Querier) error) error txBody func(*sqlc.Queries) error) error
} }
// ReservationStore is the interface that is required to load the reservations // ReservationStore is the interface that is required to load the reservations
@ -100,8 +94,8 @@ func (s *SQLStore) CreateInstantLoopOut(ctx context.Context,
SwapHash: instantOut.SwapHash[:], SwapHash: instantOut.SwapHash[:],
Preimage: instantOut.swapPreimage[:], Preimage: instantOut.swapPreimage[:],
InitiationTime: s.clock.Now(), InitiationTime: s.clock.Now(),
AmountRequested: int64(instantOut.Value), AmountRequested: int64(instantOut.value),
CltvExpiry: instantOut.CltvExpiry, CltvExpiry: instantOut.cltvExpiry,
MaxMinerFee: 0, MaxMinerFee: 0,
MaxSwapFee: 0, MaxSwapFee: 0,
InitiationHeight: instantOut.initiationHeight, InitiationHeight: instantOut.initiationHeight,
@ -120,7 +114,7 @@ func (s *SQLStore) CreateInstantLoopOut(ctx context.Context,
} }
reservationIdByteSlice := reservationIdsToByteSlice( reservationIdByteSlice := reservationIdsToByteSlice(
instantOut.Reservations, instantOut.reservations,
) )
instantOutArgs := sqlc.InsertInstantOutParams{ instantOutArgs := sqlc.InsertInstantOutParams{
SwapHash: instantOut.SwapHash[:], SwapHash: instantOut.SwapHash[:],
@ -138,8 +132,8 @@ func (s *SQLStore) CreateInstantLoopOut(ctx context.Context,
UpdateState: string(instantOut.State), UpdateState: string(instantOut.State),
} }
return s.baseDb.ExecTx(ctx, loopdb.NewSqlWriteOpts(), return s.baseDb.ExecTx(ctx, &loopdb.SqliteTxOptions{},
func(q Querier) error { func(q *sqlc.Queries) error {
err := q.InsertSwap(ctx, swapArgs) err := q.InsertSwap(ctx, swapArgs)
if err != nil { if err != nil {
return err return err
@ -178,9 +172,9 @@ func (s *SQLStore) UpdateInstantLoopOut(ctx context.Context,
} }
var finalSweeplessSweepTx []byte var finalSweeplessSweepTx []byte
if instantOut.FinalizedSweeplessSweepTx != nil { if instantOut.finalizedSweeplessSweepTx != nil {
var buffer bytes.Buffer var buffer bytes.Buffer
err := instantOut.FinalizedSweeplessSweepTx.Serialize( err := instantOut.finalizedSweeplessSweepTx.Serialize(
&buffer, &buffer,
) )
if err != nil { if err != nil {
@ -210,8 +204,8 @@ func (s *SQLStore) UpdateInstantLoopOut(ctx context.Context,
UpdateState: string(instantOut.State), UpdateState: string(instantOut.State),
} }
return s.baseDb.ExecTx(ctx, loopdb.NewSqlWriteOpts(), return s.baseDb.ExecTx(ctx, &loopdb.SqliteTxOptions{},
func(q Querier) error { func(q *sqlc.Queries) error {
err := q.UpdateInstantOut(ctx, updateParams) err := q.UpdateInstantOut(ctx, updateParams)
if err != nil { if err != nil {
return err return err
@ -361,12 +355,12 @@ func (s *SQLStore) sqlInstantOutToInstantOut(ctx context.Context,
instantOut := &InstantOut{ instantOut := &InstantOut{
SwapHash: swapHash, SwapHash: swapHash,
swapPreimage: swapPreImage, swapPreimage: swapPreImage,
CltvExpiry: row.CltvExpiry, cltvExpiry: row.CltvExpiry,
outgoingChanSet: outgoingChanSet, outgoingChanSet: outgoingChanSet,
Reservations: reservations, reservations: reservations,
protocolVersion: ProtocolVersion(row.ProtocolVersion), protocolVersion: ProtocolVersion(row.ProtocolVersion),
initiationHeight: row.InitiationHeight, initiationHeight: row.InitiationHeight,
Value: btcutil.Amount(row.AmountRequested), value: btcutil.Amount(row.AmountRequested),
keyLocator: keychain.KeyLocator{ keyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(row.ClientKeyFamily), Family: keychain.KeyFamily(row.ClientKeyFamily),
Index: uint32(row.ClientKeyIndex), Index: uint32(row.ClientKeyIndex),
@ -378,7 +372,7 @@ func (s *SQLStore) sqlInstantOutToInstantOut(ctx context.Context,
sweepAddress: sweepAddress, sweepAddress: sweepAddress,
finalizedHtlcTx: finalizedHtlcTx, finalizedHtlcTx: finalizedHtlcTx,
SweepTxHash: sweepTxHash, SweepTxHash: sweepTxHash,
FinalizedSweeplessSweepTx: finalizedSweepLessSweepTx, finalizedSweeplessSweepTx: finalizedSweepLessSweepTx,
sweepConfirmationHeight: uint32(deserializeNullInt32( sweepConfirmationHeight: uint32(deserializeNullInt32(
row.SweepConfirmationHeight, row.SweepConfirmationHeight,
)), )),

@ -92,12 +92,6 @@ type OutRequest struct {
// initiated the swap (loop CLI, autolooper, LiT UI and so on) and is // initiated the swap (loop CLI, autolooper, LiT UI and so on) and is
// appended to the user agent string. // appended to the user agent string.
Initiator string Initiator string
// PaymentTimeout specifies the payment timeout for the individual
// off-chain payments. As the swap payment may be retried (depending on
// the configured maximum payment timeout) the total time spent may be
// a multiple of this value.
PaymentTimeout time.Duration
} }
// Out contains the full details of a loop out request. This includes things // Out contains the full details of a loop out request. This includes things

@ -312,26 +312,9 @@ func (c *autoloopTestCtx) autoloop(step *autoloopStep) {
// Assert that we query the server for a quote for each of our // Assert that we query the server for a quote for each of our
// recommended swaps. Note that this differs from our set of expected // recommended swaps. Note that this differs from our set of expected
// swaps because we may get quotes for suggested swaps but then just // swaps because we may get quotes for suggested swaps but then just
// log them. The order in c.quoteRequestIn is not deterministic, // log them.
// it depends on the order of map traversal (map peerChannels in
// method Manager.SuggestSwaps). So receive from the channel an item
// and then find a corresponding expected item, using amount as a key.
amt2expected := make(map[btcutil.Amount]quoteInRequestResp)
for _, expected := range step.quotesIn { for _, expected := range step.quotesIn {
// Make sure all amounts are unique.
require.NotContains(c.t, amt2expected, expected.request.Amount)
amt2expected[expected.request.Amount] = expected
}
for i := 0; i < len(step.quotesIn); i++ {
request := <-c.quoteRequestIn request := <-c.quoteRequestIn
// Get the expected item, using amount as a key.
expected, has := amt2expected[request.Amount]
require.True(c.t, has)
delete(amt2expected, request.Amount)
assert.Equal( assert.Equal(
c.t, expected.request.Amount, request.Amount, c.t, expected.request.Amount, request.Amount,
) )

@ -46,7 +46,6 @@ import (
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/labels" "github.com/lightninglabs/loop/labels"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
clientrpc "github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/swap"
"github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/funding"
@ -56,6 +55,8 @@ import (
"github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/ticker" "github.com/lightningnetwork/lnd/ticker"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
clientrpc "github.com/lightninglabs/loop/looprpc"
) )
const ( const (

@ -77,6 +77,7 @@ func loopInSweepFee(fee chainfee.SatPerKWeight) btcutil.Amount {
maxSize := htlc.MaxTimeoutWitnessSize() maxSize := htlc.MaxTimeoutWitnessSize()
estimator.AddWitnessInput(maxSize) estimator.AddWitnessInput(maxSize)
weight := int64(estimator.Weight())
return fee.FeeForWeight(estimator.Weight()) return fee.FeeForWeight(weight)
} }

@ -8,12 +8,13 @@ import (
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
clientrpc "github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/swap"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/routing/route"
clientrpc "github.com/lightninglabs/loop/looprpc"
) )
var ( var (

@ -177,7 +177,7 @@ func TestCalculateAmount(t *testing.T) {
} }
} }
// TestSuggestSwap tests swap suggestions for the threshold rule. It does not // TestSuggestSwaps tests swap suggestions for the threshold rule. It does not
// many different values because we have separate tests for swap amount // many different values because we have separate tests for swap amount
// calculation. // calculation.
func TestSuggestSwap(t *testing.T) { func TestSuggestSwap(t *testing.T) {

@ -10,7 +10,7 @@ import (
"time" "time"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
"github.com/lightningnetwork/lnd/cert" "github.com/lightningnetwork/lnd/cert"
"github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lncfg"
@ -76,10 +76,6 @@ var (
defaultLndMacaroon, defaultLndMacaroon,
) )
// DefaultLndRPCTimeout is the default timeout to use when communicating
// with lnd.
DefaultLndRPCTimeout = time.Minute
// DefaultTLSCertPath is the default full path of the autogenerated TLS // DefaultTLSCertPath is the default full path of the autogenerated TLS
// certificate. // certificate.
DefaultTLSCertPath = filepath.Join( DefaultTLSCertPath = filepath.Join(
@ -122,9 +118,6 @@ type lndConfig struct {
MacaroonPath string `long:"macaroonpath" description:"The full path to the single macaroon to use, either the admin.macaroon or a custom baked one. Cannot be specified at the same time as macaroondir. A custom macaroon must contain ALL permissions required for all subservers to work, otherwise permission errors will occur."` MacaroonPath string `long:"macaroonpath" description:"The full path to the single macaroon to use, either the admin.macaroon or a custom baked one. Cannot be specified at the same time as macaroondir. A custom macaroon must contain ALL permissions required for all subservers to work, otherwise permission errors will occur."`
TLSPath string `long:"tlspath" description:"Path to lnd tls certificate"` TLSPath string `long:"tlspath" description:"Path to lnd tls certificate"`
// RPCTimeout is the timeout to use when communicating with lnd.
RPCTimeout time.Duration `long:"rpctimeout" description:"The timeout to use when communicating with lnd"`
} }
type loopServerConfig struct { type loopServerConfig struct {
@ -167,10 +160,8 @@ type Config struct {
MaxLogFileSize int `long:"maxlogfilesize" description:"Maximum logfile size in MB."` MaxLogFileSize int `long:"maxlogfilesize" description:"Maximum logfile size in MB."`
DebugLevel string `long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"` DebugLevel string `long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
MaxLSATCost uint32 `long:"maxlsatcost" hidden:"true"` MaxLSATCost uint32 `long:"maxlsatcost" description:"Maximum cost in satoshis that loopd is going to pay for an LSAT token automatically. Does not include routing fees."`
MaxLSATFee uint32 `long:"maxlsatfee" hidden:"true"` MaxLSATFee uint32 `long:"maxlsatfee" description:"Maximum routing fee in satoshis that we are willing to pay while paying for an LSAT token."`
MaxL402Cost uint32 `long:"maxl402cost" description:"Maximum cost in satoshis that loopd is going to pay for an L402 token automatically. Does not include routing fees."`
MaxL402Fee uint32 `long:"maxl402fee" description:"Maximum routing fee in satoshis that we are willing to pay while paying for an L402 token."`
LoopOutMaxParts uint32 `long:"loopoutmaxparts" description:"The maximum number of payment parts that may be used for a loop out swap."` LoopOutMaxParts uint32 `long:"loopoutmaxparts" description:"The maximum number of payment parts that may be used for a loop out swap."`
@ -215,8 +206,8 @@ func DefaultConfig() Config {
TLSKeyPath: DefaultTLSKeyPath, TLSKeyPath: DefaultTLSKeyPath,
TLSValidity: DefaultAutogenValidity, TLSValidity: DefaultAutogenValidity,
MacaroonPath: DefaultMacaroonPath, MacaroonPath: DefaultMacaroonPath,
MaxL402Cost: l402.DefaultMaxCostSats, MaxLSATCost: lsat.DefaultMaxCostSats,
MaxL402Fee: l402.DefaultMaxRoutingFeeSats, MaxLSATFee: lsat.DefaultMaxRoutingFeeSats,
LoopOutMaxParts: defaultLoopOutMaxParts, LoopOutMaxParts: defaultLoopOutMaxParts,
TotalPaymentTimeout: defaultTotalPaymentTimeout, TotalPaymentTimeout: defaultTotalPaymentTimeout,
MaxPaymentRetries: defaultMaxPaymentRetries, MaxPaymentRetries: defaultMaxPaymentRetries,
@ -224,7 +215,6 @@ func DefaultConfig() Config {
Lnd: &lndConfig{ Lnd: &lndConfig{
Host: "localhost:10009", Host: "localhost:10009",
MacaroonPath: DefaultLndMacaroonPath, MacaroonPath: DefaultLndMacaroonPath,
RPCTimeout: DefaultLndRPCTimeout,
}, },
} }
} }

@ -17,12 +17,14 @@ import (
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/instantout" "github.com/lightninglabs/loop/instantout"
"github.com/lightninglabs/loop/instantout/reservation"
"github.com/lightninglabs/loop/loopd/perms" "github.com/lightninglabs/loop/loopd/perms"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightninglabs/loop/instantout/reservation"
loop_looprpc "github.com/lightninglabs/loop/looprpc" loop_looprpc "github.com/lightninglabs/loop/looprpc"
loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc" loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/macaroons" "github.com/lightningnetwork/lnd/macaroons"
@ -51,7 +53,7 @@ type ListenerCfg struct {
// on the passed TLS configuration. // on the passed TLS configuration.
restListener func(*tls.Config) (net.Listener, error) restListener func(*tls.Config) (net.Listener, error)
// getLnd returns a grpc connection to a lnd instance. // getLnd returns a grpc connection to an lnd instance.
getLnd func(lndclient.Network, *lndConfig) (*lndclient.GrpcLndServices, getLnd func(lndclient.Network, *lndConfig) (*lndclient.GrpcLndServices,
error) error)
} }
@ -118,9 +120,9 @@ func New(config *Config, lisCfg *ListenerCfg) *Daemon {
// Start starts loopd in daemon mode. It will listen for grpc connections, // Start starts loopd in daemon mode. It will listen for grpc connections,
// execute commands and pass back swap status information. // execute commands and pass back swap status information.
func (d *Daemon) Start() error { func (d *Daemon) Start() error {
// There should be no reason to start the daemon twice. Therefore, // There should be no reason to start the daemon twice. Therefore return
// return an error if that's tried. This is mostly to guard against // an error if that's tried. This is mostly to guard against Start and
// Start and StartAsSubserver both being called. // StartAsSubserver both being called.
if atomic.AddInt32(&d.started, 1) != 1 { if atomic.AddInt32(&d.started, 1) != 1 {
return errOnlyStartOnce return errOnlyStartOnce
} }
@ -135,7 +137,7 @@ func (d *Daemon) Start() error {
// With lnd connected, initialize everything else, such as the swap // With lnd connected, initialize everything else, such as the swap
// server client, the swap client RPC server instance and our main swap // server client, the swap client RPC server instance and our main swap
// and error handlers. If this fails, then nothing has been started yet, // and error handlers. If this fails, then nothing has been started yet
// and we can just return the error. // and we can just return the error.
err = d.initialize(true) err = d.initialize(true)
if errors.Is(err, bbolt.ErrTimeout) { if errors.Is(err, bbolt.ErrTimeout) {
@ -322,7 +324,7 @@ func (d *Daemon) startWebServers() error {
err := d.restServer.Serve(d.restListener) err := d.restServer.Serve(d.restListener)
// ErrServerClosed is always returned when the proxy is // ErrServerClosed is always returned when the proxy is
// shut down, so don't log it. // shut down, so don't log it.
if err != nil && !errors.Is(err, http.ErrServerClosed) { if err != nil && err != http.ErrServerClosed {
// Notify the main error handler goroutine that // Notify the main error handler goroutine that
// we exited unexpectedly here. We don't have to // we exited unexpectedly here. We don't have to
// worry about blocking as the internal error // worry about blocking as the internal error
@ -341,7 +343,7 @@ func (d *Daemon) startWebServers() error {
log.Infof("RPC server listening on %s", d.grpcListener.Addr()) log.Infof("RPC server listening on %s", d.grpcListener.Addr())
err = d.grpcServer.Serve(d.grpcListener) err = d.grpcServer.Serve(d.grpcListener)
if err != nil && !errors.Is(err, grpc.ErrServerStopped) { if err != nil && err != grpc.ErrServerStopped {
// Notify the main error handler goroutine that // Notify the main error handler goroutine that
// we exited unexpectedly here. We don't have to // we exited unexpectedly here. We don't have to
// worry about blocking as the internal error // worry about blocking as the internal error
@ -409,18 +411,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
return err return err
} }
// Run the costs migration. sweeperDb := sweepbatcher.NewSQLStore(baseDb, chainParams)
err = loop.MigrateLoopOutCosts(d.mainCtx, d.lnd.LndServices, swapDb)
if err != nil {
log.Errorf("Cost migration failed: %v", err)
return err
}
sweeperDb := sweepbatcher.NewSQLStore(
loopdb.NewTypedStore[sweepbatcher.Querier](baseDb),
chainParams,
)
// Create an instance of the loop client library. // Create an instance of the loop client library.
swapClient, clientCleanup, err := getClient( swapClient, clientCleanup, err := getClient(
@ -504,9 +495,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
) )
// Create the reservation and instantout managers. // Create the reservation and instantout managers.
if d.cfg.EnableExperimental { if d.cfg.EnableExperimental {
reservationStore := reservation.NewSQLStore( reservationStore := reservation.NewSQLStore(baseDb)
loopdb.NewTypedStore[reservation.Querier](baseDb),
)
reservationConfig := &reservation.Config{ reservationConfig := &reservation.Config{
Store: reservationStore, Store: reservationStore,
Wallet: d.lnd.WalletKit, Wallet: d.lnd.WalletKit,
@ -521,8 +510,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
// Create the instantout services. // Create the instantout services.
instantOutStore := instantout.NewSQLStore( instantOutStore := instantout.NewSQLStore(
loopdb.NewTypedStore[instantout.Querier](baseDb), baseDb, clock.NewDefaultClock(), reservationStore,
clock.NewDefaultClock(), reservationStore,
d.lnd.ChainParams, d.lnd.ChainParams,
) )
instantOutConfig := &instantout.Config{ instantOutConfig := &instantout.Config{
@ -694,9 +682,9 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
var runtimeErr error var runtimeErr error
// There are only two ways this goroutine can exit. Either there // There are only two ways this goroutine can exit. Either there
// is an internal error or the caller requests a shutdown. // is an internal error or the caller requests shutdown. In both
// In both cases we wait for the stop to complete before we // cases we wait for the stop to complete before we signal the
// signal the caller that we're done. // caller that we're done.
select { select {
case runtimeErr = <-d.internalErrChan: case runtimeErr = <-d.internalErrChan:
log.Errorf("Runtime error in daemon, shutting down: "+ log.Errorf("Runtime error in daemon, shutting down: "+
@ -705,7 +693,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
case <-d.quit: case <-d.quit:
} }
// We need to shut down before sending the error on the channel, // We need to shutdown before sending the error on the channel,
// otherwise a caller might exit the process too early. // otherwise a caller might exit the process too early.
d.stop() d.stop()
cleanupMacaroonStore() cleanupMacaroonStore()
@ -736,7 +724,7 @@ func (d *Daemon) stop() {
d.mainCtxCancel() d.mainCtxCancel()
} }
// As there is no swap activity anymore, we can forcefully shut down the // As there is no swap activity anymore, we can forcefully shutdown the
// gRPC and HTTP servers now. // gRPC and HTTP servers now.
log.Infof("Stopping gRPC server") log.Infof("Stopping gRPC server")
if d.grpcServer != nil { if d.grpcServer != nil {

@ -2,7 +2,7 @@ package loopd
import ( import (
"github.com/btcsuite/btclog" "github.com/btcsuite/btclog"
"github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/fsm" "github.com/lightninglabs/loop/fsm"
@ -37,7 +37,7 @@ func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) {
lnd.AddSubLogger(root, "SWEEP", intercept, sweepbatcher.UseLogger) lnd.AddSubLogger(root, "SWEEP", intercept, sweepbatcher.UseLogger)
lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger) lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger)
lnd.AddSubLogger(root, "STORE", intercept, loopdb.UseLogger) lnd.AddSubLogger(root, "STORE", intercept, loopdb.UseLogger)
lnd.AddSubLogger(root, l402.Subsystem, intercept, l402.UseLogger) lnd.AddSubLogger(root, lsat.Subsystem, intercept, lsat.UseLogger)
lnd.AddSubLogger( lnd.AddSubLogger(
root, liquidity.Subsystem, intercept, liquidity.UseLogger, root, liquidity.Subsystem, intercept, liquidity.UseLogger,
) )

@ -69,10 +69,6 @@ var RequiredPermissions = map[string][]bakery.Op{
Entity: "loop", Entity: "loop",
Action: "in", Action: "in",
}}, }},
"/looprpc.SwapClient/GetL402Tokens": {{
Entity: "auth",
Action: "read",
}},
"/looprpc.SwapClient/GetLsatTokens": {{ "/looprpc.SwapClient/GetLsatTokens": {{
Entity: "auth", Entity: "auth",
Action: "read", Action: "read",
@ -112,8 +108,4 @@ var RequiredPermissions = map[string][]bakery.Op{
Entity: "swap", Entity: "swap",
Action: "read", Action: "read",
}}, }},
"/looprpc.SwapClient/ListInstantOuts": {{
Entity: "swap",
Action: "read",
}},
} }

@ -96,7 +96,6 @@ func NewListenerConfig(config *Config, rpcCfg RPCConfig) *ListenerCfg {
BlockUntilChainSynced: true, BlockUntilChainSynced: true,
CallerCtx: callerCtx, CallerCtx: callerCtx,
BlockUntilUnlocked: true, BlockUntilUnlocked: true,
RPCTimeout: cfg.RPCTimeout,
} }
// If a custom lnd connection is specified we use that // If a custom lnd connection is specified we use that

@ -15,7 +15,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/instantout" "github.com/lightninglabs/loop/instantout"
@ -101,17 +101,6 @@ func (s *swapClientServer) LoopOut(ctx context.Context,
log.Infof("Loop out request received") log.Infof("Loop out request received")
// Note that LoopOutRequest.PaymentTimeout is unsigned and therefore
// cannot be negative.
paymentTimeout := time.Duration(in.PaymentTimeout) * time.Second
// Make sure we don't exceed the total allowed payment timeout.
if paymentTimeout > s.config.TotalPaymentTimeout {
return nil, fmt.Errorf("payment timeout %v exceeds maximum "+
"allowed timeout of %v", paymentTimeout,
s.config.TotalPaymentTimeout)
}
var sweepAddr btcutil.Address var sweepAddr btcutil.Address
var isExternalAddr bool var isExternalAddr bool
var err error var err error
@ -195,7 +184,6 @@ func (s *swapClientServer) LoopOut(ctx context.Context,
SwapPublicationDeadline: publicationDeadline, SwapPublicationDeadline: publicationDeadline,
Label: in.Label, Label: in.Label,
Initiator: in.Initiator, Initiator: in.Initiator,
PaymentTimeout: paymentTimeout,
} }
switch { switch {
@ -932,18 +920,18 @@ func (s *swapClientServer) LoopIn(ctx context.Context,
return response, nil return response, nil
} }
// GetL402Tokens returns all tokens that are contained in the L402 token store. // GetLsatTokens returns all tokens that are contained in the LSAT token store.
func (s *swapClientServer) GetL402Tokens(ctx context.Context, func (s *swapClientServer) GetLsatTokens(ctx context.Context,
_ *clientrpc.TokensRequest) (*clientrpc.TokensResponse, error) { _ *clientrpc.TokensRequest) (*clientrpc.TokensResponse, error) {
log.Infof("Get L402 tokens request received") log.Infof("Get LSAT tokens request received")
tokens, err := s.impl.L402Store.AllTokens() tokens, err := s.impl.LsatStore.AllTokens()
if err != nil { if err != nil {
return nil, err return nil, err
} }
rpcTokens := make([]*clientrpc.L402Token, len(tokens)) rpcTokens := make([]*clientrpc.LsatToken, len(tokens))
idx := 0 idx := 0
for key, token := range tokens { for key, token := range tokens {
macBytes, err := token.BaseMacaroon().MarshalBinary() macBytes, err := token.BaseMacaroon().MarshalBinary()
@ -951,13 +939,13 @@ func (s *swapClientServer) GetL402Tokens(ctx context.Context,
return nil, err return nil, err
} }
id, err := l402.DecodeIdentifier( id, err := lsat.DecodeIdentifier(
bytes.NewReader(token.BaseMacaroon().Id()), bytes.NewReader(token.BaseMacaroon().Id()),
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
rpcTokens[idx] = &clientrpc.L402Token{ rpcTokens[idx] = &clientrpc.LsatToken{
BaseMacaroon: macBytes, BaseMacaroon: macBytes,
PaymentHash: token.PaymentHash[:], PaymentHash: token.PaymentHash[:],
PaymentPreimage: token.Preimage[:], PaymentPreimage: token.Preimage[:],
@ -976,21 +964,6 @@ func (s *swapClientServer) GetL402Tokens(ctx context.Context,
return &clientrpc.TokensResponse{Tokens: rpcTokens}, nil return &clientrpc.TokensResponse{Tokens: rpcTokens}, nil
} }
// GetLsatTokens returns all tokens that are contained in the L402 token store.
// Deprecated: use GetL402Tokens.
// This API is provided to maintain backward compatibility with gRPC clients
// (e.g. `loop listauth`, Terminal Web, RTL).
// Type LsatToken used by GetLsatTokens in the past was renamed to L402Token,
// but this does not affect binary encoding, so we can use type L402Token here.
func (s *swapClientServer) GetLsatTokens(ctx context.Context,
req *clientrpc.TokensRequest) (*clientrpc.TokensResponse, error) {
log.Warnf("Received deprecated call GetLsatTokens. Please update the " +
"client software. Calling GetL402Tokens now.")
return s.GetL402Tokens(ctx, req)
}
// GetInfo returns basic information about the loop daemon and details to swaps // GetInfo returns basic information about the loop daemon and details to swaps
// from the swap store. // from the swap store.
func (s *swapClientServer) GetInfo(ctx context.Context, func (s *swapClientServer) GetInfo(ctx context.Context,
@ -1221,7 +1194,7 @@ func (s *swapClientServer) InstantOut(ctx context.Context,
} }
instantOutFsm, err := s.instantOutManager.NewInstantOut( instantOutFsm, err := s.instantOutManager.NewInstantOut(
ctx, reservationIds, req.DestAddr, ctx, reservationIds,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -1258,47 +1231,6 @@ func (s *swapClientServer) InstantOutQuote(ctx context.Context,
}, nil }, nil
} }
// ListInstantOuts returns a list of all currently known instant out swaps and
// their current status.
func (s *swapClientServer) ListInstantOuts(ctx context.Context,
_ *clientrpc.ListInstantOutsRequest) (
*clientrpc.ListInstantOutsResponse, error) {
instantOuts, err := s.instantOutManager.ListInstantOuts(ctx)
if err != nil {
return nil, err
}
rpcSwaps := make([]*clientrpc.InstantOut, 0, len(instantOuts))
for _, instantOut := range instantOuts {
rpcSwaps = append(rpcSwaps, rpcInstantOut(instantOut))
}
return &clientrpc.ListInstantOutsResponse{
Swaps: rpcSwaps,
}, nil
}
func rpcInstantOut(instantOut *instantout.InstantOut) *clientrpc.InstantOut {
var sweepTxId string
if instantOut.SweepTxHash != nil {
sweepTxId = instantOut.SweepTxHash.String()
}
reservations := make([][]byte, len(instantOut.Reservations))
for i, res := range instantOut.Reservations {
reservations[i] = res.ID[:]
}
return &clientrpc.InstantOut{
SwapHash: instantOut.SwapHash[:],
State: string(instantOut.State),
Amount: uint64(instantOut.Value),
SweepTxId: sweepTxId,
ReservationIds: reservations,
}
}
func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) { func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) {
switch reason { switch reason {
case liquidity.ReasonNone: case liquidity.ReasonNone:

@ -6,7 +6,6 @@ import (
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/lightninglabs/aperture/l402"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop" "github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/liquidity" "github.com/lightninglabs/loop/liquidity"
@ -22,47 +21,19 @@ func getClient(cfg *Config, swapDb loopdb.SwapStore,
sweeperDb sweepbatcher.BatcherStore, lnd *lndclient.LndServices) ( sweeperDb sweepbatcher.BatcherStore, lnd *lndclient.LndServices) (
*loop.Client, func(), error) { *loop.Client, func(), error) {
// Default is not set for MaxLSATCost and MaxLSATFee to distinguish
// it from user explicitly setting the option to default value.
// So if MaxL402Cost and MaxLSATFee are not set in the config file
// and command line, they are set to 0.
const (
defaultCost = l402.DefaultMaxCostSats
defaultFee = l402.DefaultMaxRoutingFeeSats
)
if cfg.MaxL402Cost != defaultCost && cfg.MaxLSATCost != 0 {
return nil, nil, fmt.Errorf("both maxl402cost and maxlsatcost" +
" were specified; they are not allowed together")
}
if cfg.MaxL402Fee != defaultFee && cfg.MaxLSATFee != 0 {
return nil, nil, fmt.Errorf("both maxl402fee and maxlsatfee" +
" were specified; they are not allowed together")
}
clientConfig := &loop.ClientConfig{ clientConfig := &loop.ClientConfig{
ServerAddress: cfg.Server.Host, ServerAddress: cfg.Server.Host,
ProxyAddress: cfg.Server.Proxy, ProxyAddress: cfg.Server.Proxy,
SwapServerNoTLS: cfg.Server.NoTLS, SwapServerNoTLS: cfg.Server.NoTLS,
TLSPathServer: cfg.Server.TLSPath, TLSPathServer: cfg.Server.TLSPath,
Lnd: lnd, Lnd: lnd,
MaxL402Cost: btcutil.Amount(cfg.MaxL402Cost), MaxLsatCost: btcutil.Amount(cfg.MaxLSATCost),
MaxL402Fee: btcutil.Amount(cfg.MaxL402Fee), MaxLsatFee: btcutil.Amount(cfg.MaxLSATFee),
LoopOutMaxParts: cfg.LoopOutMaxParts, LoopOutMaxParts: cfg.LoopOutMaxParts,
TotalPaymentTimeout: cfg.TotalPaymentTimeout, TotalPaymentTimeout: cfg.TotalPaymentTimeout,
MaxPaymentRetries: cfg.MaxPaymentRetries, MaxPaymentRetries: cfg.MaxPaymentRetries,
} }
if cfg.MaxL402Cost == defaultCost && cfg.MaxLSATCost != 0 {
log.Warnf("Option maxlsatcost is deprecated and will be " +
"removed. Switch to maxl402cost.")
clientConfig.MaxL402Cost = btcutil.Amount(cfg.MaxLSATCost)
}
if cfg.MaxL402Fee == defaultFee && cfg.MaxLSATFee != 0 {
log.Warnf("Option maxlsatfee is deprecated and will be " +
"removed. Switch to maxl402fee.")
clientConfig.MaxL402Fee = btcutil.Amount(cfg.MaxLSATFee)
}
swapClient, cleanUp, err := loop.NewClient( swapClient, cleanUp, err := loop.NewClient(
cfg.DataDir, swapDb, sweeperDb, clientConfig, cfg.DataDir, swapDb, sweeperDb, clientConfig,
) )
@ -85,8 +56,9 @@ func openDatabase(cfg *Config, chainParams *chaincfg.Params) (loopdb.SwapStore,
case DatabaseBackendSqlite: case DatabaseBackendSqlite:
log.Infof("Opening sqlite3 database at: %v", log.Infof("Opening sqlite3 database at: %v",
cfg.Sqlite.DatabaseFileName) cfg.Sqlite.DatabaseFileName)
db, err = loopdb.NewSqliteStore(
db, err = loopdb.NewSqliteStore(cfg.Sqlite, chainParams) cfg.Sqlite, chainParams,
)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -95,8 +67,9 @@ func openDatabase(cfg *Config, chainParams *chaincfg.Params) (loopdb.SwapStore,
case DatabaseBackendPostgres: case DatabaseBackendPostgres:
log.Infof("Opening postgres database at: %v", log.Infof("Opening postgres database at: %v",
cfg.Postgres.DSN(true)) cfg.Postgres.DSN(true))
db, err = loopdb.NewPostgresStore(
db, err = loopdb.NewPostgresStore(cfg.Postgres, chainParams) cfg.Postgres, chainParams,
)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -106,6 +79,9 @@ func openDatabase(cfg *Config, chainParams *chaincfg.Params) (loopdb.SwapStore,
return nil, nil, fmt.Errorf("unknown database backend: %s", return nil, nil, fmt.Errorf("unknown database backend: %s",
cfg.DatabaseBackend) cfg.DatabaseBackend)
} }
if err != nil {
return nil, nil, fmt.Errorf("unable to open database: %v", err)
}
return db, &baseDb, nil return db, &baseDb, nil
} }

@ -32,10 +32,7 @@ func view(config *Config, lisCfg *ListenerCfg) error {
return err return err
} }
sweeperDb := sweepbatcher.NewSQLStore( sweeperDb := sweepbatcher.NewSQLStore(baseDb, chainParams)
loopdb.NewTypedStore[sweepbatcher.Querier](baseDb),
chainParams,
)
swapClient, cleanup, err := getClient( swapClient, cleanup, err := getClient(
config, swapDb, sweeperDb, &lnd.LndServices, config, swapDb, sweeperDb, &lnd.LndServices,

@ -65,18 +65,6 @@ type SwapStore interface {
// it's decoding using the proto package's `Unmarshal` method. // it's decoding using the proto package's `Unmarshal` method.
FetchLiquidityParams(ctx context.Context) ([]byte, error) FetchLiquidityParams(ctx context.Context) ([]byte, error)
// BatchUpdateLoopOutSwapCosts updates the swap costs for a batch of
// loop out swaps.
BatchUpdateLoopOutSwapCosts(ctx context.Context,
swaps map[lntypes.Hash]SwapCost) error
// HasMigration returns true if the migration with the given ID has
// been done.
HasMigration(ctx context.Context, migrationID string) (bool, error)
// SetMigration marks the migration with the given ID as done.
SetMigration(ctx context.Context, migrationID string) error
// Close closes the underlying database. // Close closes the underlying database.
Close() error Close() error
} }

@ -61,10 +61,6 @@ type LoopOutContract struct {
// allow the server to delay the publication in exchange for possibly // allow the server to delay the publication in exchange for possibly
// lower fees. // lower fees.
SwapPublicationDeadline time.Time SwapPublicationDeadline time.Time
// PaymentTimeout is the timeout for any individual off-chain payment
// attempt.
PaymentTimeout time.Duration
} }
// ChannelSet stores a set of channels. // ChannelSet stores a set of channels.

@ -32,7 +32,7 @@ const (
ProtocolVersionUserExpiryLoopOut ProtocolVersion = 4 ProtocolVersionUserExpiryLoopOut ProtocolVersion = 4
// ProtocolVersionHtlcV2 indicates that the client will use the new // ProtocolVersionHtlcV2 indicates that the client will use the new
// HTLC v2 scripts for swaps. // HTLC v2 scrips for swaps.
ProtocolVersionHtlcV2 ProtocolVersion = 5 ProtocolVersionHtlcV2 ProtocolVersion = 5
// ProtocolVersionMultiLoopIn indicates that the client creates a probe // ProtocolVersionMultiLoopIn indicates that the client creates a probe

@ -18,13 +18,13 @@ import (
) )
// FetchLoopOutSwaps returns all swaps currently in the store. // FetchLoopOutSwaps returns all swaps currently in the store.
func (db *BaseDB) FetchLoopOutSwaps(ctx context.Context) ([]*LoopOut, func (s *BaseDB) FetchLoopOutSwaps(ctx context.Context) ([]*LoopOut,
error) { error) {
var loopOuts []*LoopOut var loopOuts []*LoopOut
err := db.ExecTx(ctx, NewSqlReadOpts(), func(tx *sqlc.Queries) error { err := s.ExecTx(ctx, NewSqlReadOpts(), func(*sqlc.Queries) error {
swaps, err := tx.GetLoopOutSwaps(ctx) swaps, err := s.Queries.GetLoopOutSwaps(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -32,7 +32,7 @@ func (db *BaseDB) FetchLoopOutSwaps(ctx context.Context) ([]*LoopOut,
loopOuts = make([]*LoopOut, len(swaps)) loopOuts = make([]*LoopOut, len(swaps))
for i, swap := range swaps { for i, swap := range swaps {
updates, err := tx.GetSwapUpdates( updates, err := s.Queries.GetSwapUpdates(
ctx, swap.SwapHash, ctx, swap.SwapHash,
) )
if err != nil { if err != nil {
@ -40,7 +40,7 @@ func (db *BaseDB) FetchLoopOutSwaps(ctx context.Context) ([]*LoopOut,
} }
loopOut, err := ConvertLoopOutRow( loopOut, err := ConvertLoopOutRow(
db.network, sqlc.GetLoopOutSwapRow(swap), s.network, sqlc.GetLoopOutSwapRow(swap),
updates, updates,
) )
if err != nil { if err != nil {
@ -60,24 +60,24 @@ func (db *BaseDB) FetchLoopOutSwaps(ctx context.Context) ([]*LoopOut,
} }
// FetchLoopOutSwap returns the loop out swap with the given hash. // FetchLoopOutSwap returns the loop out swap with the given hash.
func (db *BaseDB) FetchLoopOutSwap(ctx context.Context, func (s *BaseDB) FetchLoopOutSwap(ctx context.Context,
hash lntypes.Hash) (*LoopOut, error) { hash lntypes.Hash) (*LoopOut, error) {
var loopOut *LoopOut var loopOut *LoopOut
err := db.ExecTx(ctx, NewSqlReadOpts(), func(tx *sqlc.Queries) error { err := s.ExecTx(ctx, NewSqlReadOpts(), func(*sqlc.Queries) error {
swap, err := tx.GetLoopOutSwap(ctx, hash[:]) swap, err := s.Queries.GetLoopOutSwap(ctx, hash[:])
if err != nil { if err != nil {
return err return err
} }
updates, err := tx.GetSwapUpdates(ctx, swap.SwapHash) updates, err := s.Queries.GetSwapUpdates(ctx, swap.SwapHash)
if err != nil { if err != nil {
return err return err
} }
loopOut, err = ConvertLoopOutRow( loopOut, err = ConvertLoopOutRow(
db.network, swap, updates, s.network, swap, updates,
) )
if err != nil { if err != nil {
return err return err
@ -93,11 +93,11 @@ func (db *BaseDB) FetchLoopOutSwap(ctx context.Context,
} }
// CreateLoopOut adds an initiated swap to the store. // CreateLoopOut adds an initiated swap to the store.
func (db *BaseDB) CreateLoopOut(ctx context.Context, hash lntypes.Hash, func (s *BaseDB) CreateLoopOut(ctx context.Context, hash lntypes.Hash,
swap *LoopOutContract) error { swap *LoopOutContract) error {
writeOpts := NewSqlWriteOpts() writeOpts := &SqliteTxOptions{}
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error { return s.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
insertArgs := loopToInsertArgs( insertArgs := loopToInsertArgs(
hash, &swap.SwapContract, hash, &swap.SwapContract,
) )
@ -131,11 +131,11 @@ func (db *BaseDB) CreateLoopOut(ctx context.Context, hash lntypes.Hash,
} }
// BatchCreateLoopOut adds multiple initiated swaps to the store. // BatchCreateLoopOut adds multiple initiated swaps to the store.
func (db *BaseDB) BatchCreateLoopOut(ctx context.Context, func (s *BaseDB) BatchCreateLoopOut(ctx context.Context,
swaps map[lntypes.Hash]*LoopOutContract) error { swaps map[lntypes.Hash]*LoopOutContract) error {
writeOpts := NewSqlWriteOpts() writeOpts := &SqliteTxOptions{}
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error { return s.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
for swapHash, swap := range swaps { for swapHash, swap := range swaps {
swap := swap swap := swap
@ -174,20 +174,20 @@ func (db *BaseDB) BatchCreateLoopOut(ctx context.Context,
// UpdateLoopOut stores a new event for a target loop out swap. This // UpdateLoopOut stores a new event for a target loop out swap. This
// appends to the event log for a particular swap as it goes through // appends to the event log for a particular swap as it goes through
// the various stages in its lifetime. // the various stages in its lifetime.
func (db *BaseDB) UpdateLoopOut(ctx context.Context, hash lntypes.Hash, func (s *BaseDB) UpdateLoopOut(ctx context.Context, hash lntypes.Hash,
time time.Time, state SwapStateData) error { time time.Time, state SwapStateData) error {
return db.updateLoop(ctx, hash, time, state) return s.updateLoop(ctx, hash, time, state)
} }
// FetchLoopInSwaps returns all swaps currently in the store. // FetchLoopInSwaps returns all swaps currently in the store.
func (db *BaseDB) FetchLoopInSwaps(ctx context.Context) ( func (s *BaseDB) FetchLoopInSwaps(ctx context.Context) (
[]*LoopIn, error) { []*LoopIn, error) {
var loopIns []*LoopIn var loopIns []*LoopIn
err := db.ExecTx(ctx, NewSqlReadOpts(), func(tx *sqlc.Queries) error { err := s.ExecTx(ctx, NewSqlReadOpts(), func(*sqlc.Queries) error {
swaps, err := tx.GetLoopInSwaps(ctx) swaps, err := s.Queries.GetLoopInSwaps(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -195,12 +195,12 @@ func (db *BaseDB) FetchLoopInSwaps(ctx context.Context) (
loopIns = make([]*LoopIn, len(swaps)) loopIns = make([]*LoopIn, len(swaps))
for i, swap := range swaps { for i, swap := range swaps {
updates, err := tx.GetSwapUpdates(ctx, swap.SwapHash) updates, err := s.Queries.GetSwapUpdates(ctx, swap.SwapHash)
if err != nil { if err != nil {
return err return err
} }
loopIn, err := db.convertLoopInRow( loopIn, err := s.convertLoopInRow(
swap, updates, swap, updates,
) )
if err != nil { if err != nil {
@ -220,11 +220,11 @@ func (db *BaseDB) FetchLoopInSwaps(ctx context.Context) (
} }
// CreateLoopIn adds an initiated swap to the store. // CreateLoopIn adds an initiated swap to the store.
func (db *BaseDB) CreateLoopIn(ctx context.Context, hash lntypes.Hash, func (s *BaseDB) CreateLoopIn(ctx context.Context, hash lntypes.Hash,
swap *LoopInContract) error { swap *LoopInContract) error {
writeOpts := NewSqlWriteOpts() writeOpts := &SqliteTxOptions{}
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error { return s.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
insertArgs := loopToInsertArgs( insertArgs := loopToInsertArgs(
hash, &swap.SwapContract, hash, &swap.SwapContract,
) )
@ -257,11 +257,11 @@ func (db *BaseDB) CreateLoopIn(ctx context.Context, hash lntypes.Hash,
} }
// BatchCreateLoopIn adds multiple initiated swaps to the store. // BatchCreateLoopIn adds multiple initiated swaps to the store.
func (db *BaseDB) BatchCreateLoopIn(ctx context.Context, func (s *BaseDB) BatchCreateLoopIn(ctx context.Context,
swaps map[lntypes.Hash]*LoopInContract) error { swaps map[lntypes.Hash]*LoopInContract) error {
writeOpts := NewSqlWriteOpts() writeOpts := &SqliteTxOptions{}
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error { return s.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
for swapHash, swap := range swaps { for swapHash, swap := range swaps {
swap := swap swap := swap
@ -301,10 +301,10 @@ func (db *BaseDB) BatchCreateLoopIn(ctx context.Context,
// UpdateLoopIn stores a new event for a target loop in swap. This // UpdateLoopIn stores a new event for a target loop in swap. This
// appends to the event log for a particular swap as it goes through // appends to the event log for a particular swap as it goes through
// the various stages in its lifetime. // the various stages in its lifetime.
func (db *BaseDB) UpdateLoopIn(ctx context.Context, hash lntypes.Hash, func (s *BaseDB) UpdateLoopIn(ctx context.Context, hash lntypes.Hash,
time time.Time, state SwapStateData) error { time time.Time, state SwapStateData) error {
return db.updateLoop(ctx, hash, time, state) return s.updateLoop(ctx, hash, time, state)
} }
// PutLiquidityParams writes the serialized `manager.Parameters` bytes // PutLiquidityParams writes the serialized `manager.Parameters` bytes
@ -312,10 +312,10 @@ func (db *BaseDB) UpdateLoopIn(ctx context.Context, hash lntypes.Hash,
// //
// NOTE: it's the caller's responsibility to encode the param. Atm, // NOTE: it's the caller's responsibility to encode the param. Atm,
// it's encoding using the proto package's `Marshal` method. // it's encoding using the proto package's `Marshal` method.
func (db *BaseDB) PutLiquidityParams(ctx context.Context, func (s *BaseDB) PutLiquidityParams(ctx context.Context,
params []byte) error { params []byte) error {
err := db.Queries.UpsertLiquidityParams(ctx, params) err := s.Queries.UpsertLiquidityParams(ctx, params)
if err != nil { if err != nil {
return err return err
} }
@ -328,11 +328,11 @@ func (db *BaseDB) PutLiquidityParams(ctx context.Context,
// //
// NOTE: it's the caller's responsibility to decode the param. Atm, // NOTE: it's the caller's responsibility to decode the param. Atm,
// it's decoding using the proto package's `Unmarshal` method. // it's decoding using the proto package's `Unmarshal` method.
func (db *BaseDB) FetchLiquidityParams(ctx context.Context) ([]byte, func (s *BaseDB) FetchLiquidityParams(ctx context.Context) ([]byte,
error) { error) {
var params []byte var params []byte
params, err := db.Queries.FetchLiquidityParams(ctx) params, err := s.Queries.FetchLiquidityParams(ctx)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return params, nil return params, nil
} else if err != nil { } else if err != nil {
@ -348,11 +348,11 @@ var _ SwapStore = (*BaseDB)(nil)
// updateLoop updates the swap with the given hash by inserting a new update // updateLoop updates the swap with the given hash by inserting a new update
// in the swap_updates table. // in the swap_updates table.
func (db *BaseDB) updateLoop(ctx context.Context, hash lntypes.Hash, func (s *BaseDB) updateLoop(ctx context.Context, hash lntypes.Hash,
time time.Time, state SwapStateData) error { time time.Time, state SwapStateData) error {
writeOpts := NewSqlWriteOpts() writeOpts := &SqliteTxOptions{}
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error { return s.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
updateParams := sqlc.InsertSwapUpdateParams{ updateParams := sqlc.InsertSwapUpdateParams{
SwapHash: hash[:], SwapHash: hash[:],
UpdateTimestamp: time.UTC(), UpdateTimestamp: time.UTC(),
@ -376,11 +376,11 @@ func (db *BaseDB) updateLoop(ctx context.Context, hash lntypes.Hash,
} }
// BatchInsertUpdate inserts multiple swap updates to the store. // BatchInsertUpdate inserts multiple swap updates to the store.
func (db *BaseDB) BatchInsertUpdate(ctx context.Context, func (s *BaseDB) BatchInsertUpdate(ctx context.Context,
updateData map[lntypes.Hash][]BatchInsertUpdateData) error { updateData map[lntypes.Hash][]BatchInsertUpdateData) error {
writeOpts := NewSqlWriteOpts() writeOpts := &SqliteTxOptions{}
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error { return s.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
for swapHash, updates := range updateData { for swapHash, updates := range updateData {
for _, update := range updates { for _, update := range updates {
updateParams := sqlc.InsertSwapUpdateParams{ updateParams := sqlc.InsertSwapUpdateParams{
@ -407,61 +407,6 @@ func (db *BaseDB) BatchInsertUpdate(ctx context.Context,
}) })
} }
// BatchUpdateLoopOutSwapCosts updates the swap costs for a batch of loop out
// swaps.
func (db *BaseDB) BatchUpdateLoopOutSwapCosts(ctx context.Context,
costs map[lntypes.Hash]SwapCost) error {
writeOpts := NewSqlWriteOpts()
return db.ExecTx(ctx, writeOpts, func(tx *sqlc.Queries) error {
for swapHash, cost := range costs {
lastUpdateID, err := tx.GetLastUpdateID(
ctx, swapHash[:],
)
if err != nil {
return err
}
err = tx.OverrideSwapCosts(
ctx, sqlc.OverrideSwapCostsParams{
ID: lastUpdateID,
ServerCost: int64(cost.Server),
OnchainCost: int64(cost.Onchain),
OffchainCost: int64(cost.Offchain),
},
)
if err != nil {
return err
}
}
return nil
})
}
// HasMigration returns true if the migration with the given ID has been done.
func (db *BaseDB) HasMigration(ctx context.Context, migrationID string) (
bool, error) {
migration, err := db.GetMigration(ctx, migrationID)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return false, err
}
return migration.MigrationTs.Valid, nil
}
// SetMigration marks the migration with the given ID as done.
func (db *BaseDB) SetMigration(ctx context.Context, migrationID string) error {
return db.InsertMigration(ctx, sqlc.InsertMigrationParams{
MigrationID: migrationID,
MigrationTs: sql.NullTime{
Time: time.Now().UTC(),
Valid: true,
},
})
}
// loopToInsertArgs converts a SwapContract struct to the arguments needed to // loopToInsertArgs converts a SwapContract struct to the arguments needed to
// insert it into the database. // insert it into the database.
func loopToInsertArgs(hash lntypes.Hash, func loopToInsertArgs(hash lntypes.Hash,
@ -498,7 +443,6 @@ func loopOutToInsertArgs(hash lntypes.Hash,
PrepayInvoice: loopOut.PrepayInvoice, PrepayInvoice: loopOut.PrepayInvoice,
MaxPrepayRoutingFee: int64(loopOut.MaxPrepayRoutingFee), MaxPrepayRoutingFee: int64(loopOut.MaxPrepayRoutingFee),
PublicationDeadline: loopOut.SwapPublicationDeadline.UTC(), PublicationDeadline: loopOut.SwapPublicationDeadline.UTC(),
PaymentTimeout: int32(loopOut.PaymentTimeout.Seconds()),
} }
} }
@ -592,9 +536,6 @@ func ConvertLoopOutRow(network *chaincfg.Params, row sqlc.GetLoopOutSwapRow,
PrepayInvoice: row.PrepayInvoice, PrepayInvoice: row.PrepayInvoice,
MaxPrepayRoutingFee: btcutil.Amount(row.MaxPrepayRoutingFee), MaxPrepayRoutingFee: btcutil.Amount(row.MaxPrepayRoutingFee),
SwapPublicationDeadline: row.PublicationDeadline, SwapPublicationDeadline: row.PublicationDeadline,
PaymentTimeout: time.Duration(
row.PaymentTimeout,
) * time.Second,
}, },
Loop: Loop{ Loop: Loop{
Hash: swapHash, Hash: swapHash,
@ -627,7 +568,7 @@ func ConvertLoopOutRow(network *chaincfg.Params, row sqlc.GetLoopOutSwapRow,
// convertLoopInRow converts a database row containing a loop in swap to a // convertLoopInRow converts a database row containing a loop in swap to a
// LoopIn struct. // LoopIn struct.
func (db *BaseDB) convertLoopInRow(row sqlc.GetLoopInSwapsRow, func (s *BaseDB) convertLoopInRow(row sqlc.GetLoopInSwapsRow,
updates []sqlc.SwapUpdate) (*LoopIn, error) { updates []sqlc.SwapUpdate) (*LoopIn, error) {
htlcKeys, err := fetchHtlcKeys( htlcKeys, err := fetchHtlcKeys(

@ -13,7 +13,6 @@ import (
"github.com/lightninglabs/loop/loopdb/sqlc" "github.com/lightninglabs/loop/loopdb/sqlc"
"github.com/lightninglabs/loop/test" "github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/routing/route"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -61,7 +60,6 @@ func TestSqliteLoopOutStore(t *testing.T) {
SweepConfTarget: 2, SweepConfTarget: 2,
HtlcConfirmations: 2, HtlcConfirmations: 2,
SwapPublicationDeadline: initiationTime, SwapPublicationDeadline: initiationTime,
PaymentTimeout: time.Second * 11,
} }
t.Run("no outgoing set", func(t *testing.T) { t.Run("no outgoing set", func(t *testing.T) {
@ -122,8 +120,6 @@ func testSqliteLoopOutStore(t *testing.T, pendingSwap *LoopOutContract) {
if expectedState == StatePreimageRevealed { if expectedState == StatePreimageRevealed {
require.NotNil(t, swap.State().HtlcTxHash) require.NotNil(t, swap.State().HtlcTxHash)
} }
require.Equal(t, time.Second*11, swap.Contract.PaymentTimeout)
} }
// If we create a new swap, then it should show up as being initialized // If we create a new swap, then it should show up as being initialized
@ -397,140 +393,6 @@ func TestIssue615(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
} }
// TestBatchUpdateCost tests that we can batch update the cost of multiple swaps
// at once.
func TestBatchUpdateCost(t *testing.T) {
// Create a new sqlite store for testing.
store := NewTestDB(t)
destAddr := test.GetDestAddr(t, 0)
initiationTime := time.Date(2018, 11, 1, 0, 0, 0, 0, time.UTC)
testContract := LoopOutContract{
SwapContract: SwapContract{
AmountRequested: 100,
CltvExpiry: 144,
HtlcKeys: HtlcKeys{
SenderScriptKey: senderKey,
ReceiverScriptKey: receiverKey,
SenderInternalPubKey: senderInternalKey,
ReceiverInternalPubKey: receiverInternalKey,
ClientScriptKeyLocator: keychain.KeyLocator{
Family: 1,
Index: 2,
},
},
MaxMinerFee: 10,
MaxSwapFee: 20,
InitiationHeight: 99,
InitiationTime: initiationTime,
ProtocolVersion: ProtocolVersionMuSig2,
},
MaxPrepayRoutingFee: 40,
PrepayInvoice: "prepayinvoice",
DestAddr: destAddr,
SwapInvoice: "swapinvoice",
MaxSwapRoutingFee: 30,
SweepConfTarget: 2,
HtlcConfirmations: 2,
SwapPublicationDeadline: initiationTime,
PaymentTimeout: time.Second * 11,
}
makeSwap := func(preimage lntypes.Preimage) *LoopOutContract {
contract := testContract
contract.Preimage = preimage
return &contract
}
// Next, we'll add two swaps to the database.
preimage1 := testPreimage
preimage2 := lntypes.Preimage{4, 4, 4}
ctxb := context.Background()
swap1 := makeSwap(preimage1)
swap2 := makeSwap(preimage2)
hash1 := swap1.Preimage.Hash()
err := store.CreateLoopOut(ctxb, hash1, swap1)
require.NoError(t, err)
hash2 := swap2.Preimage.Hash()
err = store.CreateLoopOut(ctxb, hash2, swap2)
require.NoError(t, err)
// Add an update to both swaps containing the cost.
err = store.UpdateLoopOut(
ctxb, hash1, testTime,
SwapStateData{
State: StateSuccess,
Cost: SwapCost{
Server: 1,
Onchain: 2,
Offchain: 3,
},
},
)
require.NoError(t, err)
err = store.UpdateLoopOut(
ctxb, hash2, testTime,
SwapStateData{
State: StateSuccess,
Cost: SwapCost{
Server: 4,
Onchain: 5,
Offchain: 6,
},
},
)
require.NoError(t, err)
updateMap := map[lntypes.Hash]SwapCost{
hash1: {
Server: 2,
Onchain: 3,
Offchain: 4,
},
hash2: {
Server: 6,
Onchain: 7,
Offchain: 8,
},
}
require.NoError(t, store.BatchUpdateLoopOutSwapCosts(ctxb, updateMap))
swaps, err := store.FetchLoopOutSwaps(ctxb)
require.NoError(t, err)
require.Len(t, swaps, 2)
swapsMap := make(map[lntypes.Hash]*LoopOut)
swapsMap[swaps[0].Hash] = swaps[0]
swapsMap[swaps[1].Hash] = swaps[1]
require.Equal(t, updateMap[hash1], swapsMap[hash1].State().Cost)
require.Equal(t, updateMap[hash2], swapsMap[hash2].State().Cost)
}
// TestMigrationTracker tests the migration tracker functionality.
func TestMigrationTracker(t *testing.T) {
ctxb := context.Background()
// Create a new sqlite store for testing.
sqlDB := NewTestDB(t)
hasMigration, err := sqlDB.HasMigration(ctxb, "test")
require.NoError(t, err)
require.False(t, hasMigration)
require.NoError(t, sqlDB.SetMigration(ctxb, "test"))
hasMigration, err = sqlDB.HasMigration(ctxb, "test")
require.NoError(t, err)
require.True(t, hasMigration)
}
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
func randomString(length int) string { func randomString(length int) string {

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
// source: batch.sql // source: batch.sql
package sqlc package sqlc
@ -8,6 +8,7 @@ package sqlc
import ( import (
"context" "context"
"database/sql" "database/sql"
"time"
) )
const confirmBatch = `-- name: ConfirmBatch :exec const confirmBatch = `-- name: ConfirmBatch :exec
@ -24,35 +25,74 @@ func (q *Queries) ConfirmBatch(ctx context.Context, id int32) error {
return err return err
} }
const dropBatch = `-- name: DropBatch :exec
DELETE FROM sweep_batches WHERE id = $1
`
func (q *Queries) DropBatch(ctx context.Context, id int32) error {
_, err := q.db.ExecContext(ctx, dropBatch, id)
return err
}
const getBatchSweeps = `-- name: GetBatchSweeps :many const getBatchSweeps = `-- name: GetBatchSweeps :many
SELECT SELECT
id, swap_hash, batch_id, outpoint_txid, outpoint_index, amt, completed sweeps.id, sweeps.swap_hash, sweeps.batch_id, sweeps.outpoint_txid, sweeps.outpoint_index, sweeps.amt, sweeps.completed,
swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label,
loopout_swaps.swap_hash, loopout_swaps.dest_address, loopout_swaps.swap_invoice, loopout_swaps.max_swap_routing_fee, loopout_swaps.sweep_conf_target, loopout_swaps.htlc_confirmations, loopout_swaps.outgoing_chan_set, loopout_swaps.prepay_invoice, loopout_swaps.max_prepay_routing_fee, loopout_swaps.publication_deadline, loopout_swaps.single_sweep,
htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index
FROM FROM
sweeps sweeps
JOIN
swaps ON sweeps.swap_hash = swaps.swap_hash
JOIN
loopout_swaps ON sweeps.swap_hash = loopout_swaps.swap_hash
JOIN
htlc_keys ON sweeps.swap_hash = htlc_keys.swap_hash
WHERE WHERE
batch_id = $1 sweeps.batch_id = $1
ORDER BY ORDER BY
id ASC sweeps.id ASC
` `
func (q *Queries) GetBatchSweeps(ctx context.Context, batchID int32) ([]Sweep, error) { type GetBatchSweepsRow struct {
ID int32
SwapHash []byte
BatchID int32
OutpointTxid []byte
OutpointIndex int32
Amt int64
Completed bool
ID_2 int32
SwapHash_2 []byte
Preimage []byte
InitiationTime time.Time
AmountRequested int64
CltvExpiry int32
MaxMinerFee int64
MaxSwapFee int64
InitiationHeight int32
ProtocolVersion int32
Label string
SwapHash_3 []byte
DestAddress string
SwapInvoice string
MaxSwapRoutingFee int64
SweepConfTarget int32
HtlcConfirmations int32
OutgoingChanSet string
PrepayInvoice string
MaxPrepayRoutingFee int64
PublicationDeadline time.Time
SingleSweep bool
SwapHash_4 []byte
SenderScriptPubkey []byte
ReceiverScriptPubkey []byte
SenderInternalPubkey []byte
ReceiverInternalPubkey []byte
ClientKeyFamily int32
ClientKeyIndex int32
}
func (q *Queries) GetBatchSweeps(ctx context.Context, batchID int32) ([]GetBatchSweepsRow, error) {
rows, err := q.db.QueryContext(ctx, getBatchSweeps, batchID) rows, err := q.db.QueryContext(ctx, getBatchSweeps, batchID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
var items []Sweep var items []GetBatchSweepsRow
for rows.Next() { for rows.Next() {
var i Sweep var i GetBatchSweepsRow
if err := rows.Scan( if err := rows.Scan(
&i.ID, &i.ID,
&i.SwapHash, &i.SwapHash,
@ -61,6 +101,35 @@ func (q *Queries) GetBatchSweeps(ctx context.Context, batchID int32) ([]Sweep, e
&i.OutpointIndex, &i.OutpointIndex,
&i.Amt, &i.Amt,
&i.Completed, &i.Completed,
&i.ID_2,
&i.SwapHash_2,
&i.Preimage,
&i.InitiationTime,
&i.AmountRequested,
&i.CltvExpiry,
&i.MaxMinerFee,
&i.MaxSwapFee,
&i.InitiationHeight,
&i.ProtocolVersion,
&i.Label,
&i.SwapHash_3,
&i.DestAddress,
&i.SwapInvoice,
&i.MaxSwapRoutingFee,
&i.SweepConfTarget,
&i.HtlcConfirmations,
&i.OutgoingChanSet,
&i.PrepayInvoice,
&i.MaxPrepayRoutingFee,
&i.PublicationDeadline,
&i.SingleSweep,
&i.SwapHash_4,
&i.SenderScriptPubkey,
&i.ReceiverScriptPubkey,
&i.SenderInternalPubkey,
&i.ReceiverInternalPubkey,
&i.ClientKeyFamily,
&i.ClientKeyIndex,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -75,54 +144,6 @@ func (q *Queries) GetBatchSweeps(ctx context.Context, batchID int32) ([]Sweep, e
return items, nil return items, nil
} }
const getBatchSweptAmount = `-- name: GetBatchSweptAmount :one
SELECT
SUM(amt) AS total
FROM
sweeps
WHERE
batch_id = $1
AND
completed = TRUE
`
func (q *Queries) GetBatchSweptAmount(ctx context.Context, batchID int32) (int64, error) {
row := q.db.QueryRowContext(ctx, getBatchSweptAmount, batchID)
var total int64
err := row.Scan(&total)
return total, err
}
const getParentBatch = `-- name: GetParentBatch :one
SELECT
sweep_batches.id, sweep_batches.confirmed, sweep_batches.batch_tx_id, sweep_batches.batch_pk_script, sweep_batches.last_rbf_height, sweep_batches.last_rbf_sat_per_kw, sweep_batches.max_timeout_distance
FROM
sweep_batches
JOIN
sweeps ON sweep_batches.id = sweeps.batch_id
WHERE
sweeps.swap_hash = $1
AND
sweeps.completed = TRUE
AND
sweep_batches.confirmed = TRUE
`
func (q *Queries) GetParentBatch(ctx context.Context, swapHash []byte) (SweepBatch, error) {
row := q.db.QueryRowContext(ctx, getParentBatch, swapHash)
var i SweepBatch
err := row.Scan(
&i.ID,
&i.Confirmed,
&i.BatchTxID,
&i.BatchPkScript,
&i.LastRbfHeight,
&i.LastRbfSatPerKw,
&i.MaxTimeoutDistance,
)
return i, err
}
const getSweepStatus = `-- name: GetSweepStatus :one const getSweepStatus = `-- name: GetSweepStatus :one
SELECT SELECT
COALESCE(s.completed, f.false_value) AS completed COALESCE(s.completed, f.false_value) AS completed

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
package sqlc package sqlc

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
// source: instantout.sql // source: instantout.sql
package sqlc package sqlc
@ -133,7 +133,7 @@ func (q *Queries) GetInstantOutSwapUpdates(ctx context.Context, swapHash []byte)
} }
const getInstantOutSwaps = `-- name: GetInstantOutSwaps :many const getInstantOutSwaps = `-- name: GetInstantOutSwaps :many
SELECT SELECT
swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label, swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label,
instantout_swaps.swap_hash, instantout_swaps.preimage, instantout_swaps.sweep_address, instantout_swaps.outgoing_chan_set, instantout_swaps.htlc_fee_rate, instantout_swaps.reservation_ids, instantout_swaps.swap_invoice, instantout_swaps.finalized_htlc_tx, instantout_swaps.sweep_tx_hash, instantout_swaps.finalized_sweepless_sweep_tx, instantout_swaps.sweep_confirmation_height, instantout_swaps.swap_hash, instantout_swaps.preimage, instantout_swaps.sweep_address, instantout_swaps.outgoing_chan_set, instantout_swaps.htlc_fee_rate, instantout_swaps.reservation_ids, instantout_swaps.swap_invoice, instantout_swaps.finalized_htlc_tx, instantout_swaps.sweep_tx_hash, instantout_swaps.finalized_sweepless_sweep_tx, instantout_swaps.sweep_confirmation_height,
htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index
@ -235,7 +235,7 @@ func (q *Queries) GetInstantOutSwaps(ctx context.Context) ([]GetInstantOutSwapsR
const insertInstantOut = `-- name: InsertInstantOut :exec const insertInstantOut = `-- name: InsertInstantOut :exec
INSERT INTO instantout_swaps ( INSERT INTO instantout_swaps (
swap_hash, swap_hash,
preimage, preimage,
sweep_address, sweep_address,
outgoing_chan_set, outgoing_chan_set,
htlc_fee_rate, htlc_fee_rate,

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
// source: liquidity_params.sql // source: liquidity_params.sql
package sqlc package sqlc

@ -1,45 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.25.0
// source: migration_tracker.sql
package sqlc
import (
"context"
"database/sql"
)
const getMigration = `-- name: GetMigration :one
SELECT
migration_id,
migration_ts
FROM
migration_tracker
WHERE
migration_id = $1
`
func (q *Queries) GetMigration(ctx context.Context, migrationID string) (MigrationTracker, error) {
row := q.db.QueryRowContext(ctx, getMigration, migrationID)
var i MigrationTracker
err := row.Scan(&i.MigrationID, &i.MigrationTs)
return i, err
}
const insertMigration = `-- name: InsertMigration :exec
INSERT INTO migration_tracker (
migration_id,
migration_ts
) VALUES ($1, $2)
`
type InsertMigrationParams struct {
MigrationID string
MigrationTs sql.NullTime
}
func (q *Queries) InsertMigration(ctx context.Context, arg InsertMigrationParams) error {
_, err := q.db.ExecContext(ctx, insertMigration, arg.MigrationID, arg.MigrationTs)
return err
}

@ -1,3 +0,0 @@
-- payment_timeout is the timeout in seconds for each individual off-chain
-- payment.
ALTER TABLE loopout_swaps DROP COLUMN payment_timeout;

@ -1,3 +0,0 @@
-- payment_timeout is the timeout in seconds for each individual off-chain
-- payment.
ALTER TABLE loopout_swaps ADD payment_timeout INTEGER NOT NULL DEFAULT 0;

@ -1,9 +0,0 @@
CREATE TABLE migration_tracker (
-- migration_id is the id of the migration.
migration_id TEXT NOT NULL,
-- migration_ts is the timestamp at which the migration was run.
migration_ts TIMESTAMP,
PRIMARY KEY (migration_id)
);

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
package sqlc package sqlc
@ -64,12 +64,6 @@ type LoopoutSwap struct {
MaxPrepayRoutingFee int64 MaxPrepayRoutingFee int64
PublicationDeadline time.Time PublicationDeadline time.Time
SingleSweep bool SingleSweep bool
PaymentTimeout int32
}
type MigrationTracker struct {
MigrationID string
MigrationTs sql.NullTime
} }
type Reservation struct { type Reservation struct {

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
package sqlc package sqlc
@ -11,20 +11,15 @@ import (
type Querier interface { type Querier interface {
ConfirmBatch(ctx context.Context, id int32) error ConfirmBatch(ctx context.Context, id int32) error
CreateReservation(ctx context.Context, arg CreateReservationParams) error CreateReservation(ctx context.Context, arg CreateReservationParams) error
DropBatch(ctx context.Context, id int32) error
FetchLiquidityParams(ctx context.Context) ([]byte, error) FetchLiquidityParams(ctx context.Context) ([]byte, error)
GetBatchSweeps(ctx context.Context, batchID int32) ([]Sweep, error) GetBatchSweeps(ctx context.Context, batchID int32) ([]GetBatchSweepsRow, error)
GetBatchSweptAmount(ctx context.Context, batchID int32) (int64, error)
GetInstantOutSwap(ctx context.Context, swapHash []byte) (GetInstantOutSwapRow, error) GetInstantOutSwap(ctx context.Context, swapHash []byte) (GetInstantOutSwapRow, error)
GetInstantOutSwapUpdates(ctx context.Context, swapHash []byte) ([]InstantoutUpdate, error) GetInstantOutSwapUpdates(ctx context.Context, swapHash []byte) ([]InstantoutUpdate, error)
GetInstantOutSwaps(ctx context.Context) ([]GetInstantOutSwapsRow, error) GetInstantOutSwaps(ctx context.Context) ([]GetInstantOutSwapsRow, error)
GetLastUpdateID(ctx context.Context, swapHash []byte) (int32, error)
GetLoopInSwap(ctx context.Context, swapHash []byte) (GetLoopInSwapRow, error) GetLoopInSwap(ctx context.Context, swapHash []byte) (GetLoopInSwapRow, error)
GetLoopInSwaps(ctx context.Context) ([]GetLoopInSwapsRow, error) GetLoopInSwaps(ctx context.Context) ([]GetLoopInSwapsRow, error)
GetLoopOutSwap(ctx context.Context, swapHash []byte) (GetLoopOutSwapRow, error) GetLoopOutSwap(ctx context.Context, swapHash []byte) (GetLoopOutSwapRow, error)
GetLoopOutSwaps(ctx context.Context) ([]GetLoopOutSwapsRow, error) GetLoopOutSwaps(ctx context.Context) ([]GetLoopOutSwapsRow, error)
GetMigration(ctx context.Context, migrationID string) (MigrationTracker, error)
GetParentBatch(ctx context.Context, swapHash []byte) (SweepBatch, error)
GetReservation(ctx context.Context, reservationID []byte) (Reservation, error) GetReservation(ctx context.Context, reservationID []byte) (Reservation, error)
GetReservationUpdates(ctx context.Context, reservationID []byte) ([]ReservationUpdate, error) GetReservationUpdates(ctx context.Context, reservationID []byte) ([]ReservationUpdate, error)
GetReservations(ctx context.Context) ([]Reservation, error) GetReservations(ctx context.Context) ([]Reservation, error)
@ -37,11 +32,9 @@ type Querier interface {
InsertInstantOutUpdate(ctx context.Context, arg InsertInstantOutUpdateParams) error InsertInstantOutUpdate(ctx context.Context, arg InsertInstantOutUpdateParams) error
InsertLoopIn(ctx context.Context, arg InsertLoopInParams) error InsertLoopIn(ctx context.Context, arg InsertLoopInParams) error
InsertLoopOut(ctx context.Context, arg InsertLoopOutParams) error InsertLoopOut(ctx context.Context, arg InsertLoopOutParams) error
InsertMigration(ctx context.Context, arg InsertMigrationParams) error
InsertReservationUpdate(ctx context.Context, arg InsertReservationUpdateParams) error InsertReservationUpdate(ctx context.Context, arg InsertReservationUpdateParams) error
InsertSwap(ctx context.Context, arg InsertSwapParams) error InsertSwap(ctx context.Context, arg InsertSwapParams) error
InsertSwapUpdate(ctx context.Context, arg InsertSwapUpdateParams) error InsertSwapUpdate(ctx context.Context, arg InsertSwapUpdateParams) error
OverrideSwapCosts(ctx context.Context, arg OverrideSwapCostsParams) error
UpdateBatch(ctx context.Context, arg UpdateBatchParams) error UpdateBatch(ctx context.Context, arg UpdateBatchParams) error
UpdateInstantOut(ctx context.Context, arg UpdateInstantOutParams) error UpdateInstantOut(ctx context.Context, arg UpdateInstantOutParams) error
UpdateReservation(ctx context.Context, arg UpdateReservationParams) error UpdateReservation(ctx context.Context, arg UpdateReservationParams) error

@ -23,9 +23,6 @@ INSERT INTO sweep_batches (
$6 $6
) RETURNING id; ) RETURNING id;
-- name: DropBatch :exec
DELETE FROM sweep_batches WHERE id = $1;
-- name: UpdateBatch :exec -- name: UpdateBatch :exec
UPDATE sweep_batches SET UPDATE sweep_batches SET
confirmed = $2, confirmed = $2,
@ -65,39 +62,25 @@ INSERT INTO sweeps (
amt = $5, amt = $5,
completed = $6; completed = $6;
-- name: GetParentBatch :one
SELECT
sweep_batches.*
FROM
sweep_batches
JOIN
sweeps ON sweep_batches.id = sweeps.batch_id
WHERE
sweeps.swap_hash = $1
AND
sweeps.completed = TRUE
AND
sweep_batches.confirmed = TRUE;
-- name: GetBatchSweptAmount :one
SELECT
SUM(amt) AS total
FROM
sweeps
WHERE
batch_id = $1
AND
completed = TRUE;
-- name: GetBatchSweeps :many -- name: GetBatchSweeps :many
SELECT SELECT
* sweeps.*,
swaps.*,
loopout_swaps.*,
htlc_keys.*
FROM FROM
sweeps sweeps
JOIN
swaps ON sweeps.swap_hash = swaps.swap_hash
JOIN
loopout_swaps ON sweeps.swap_hash = loopout_swaps.swap_hash
JOIN
htlc_keys ON sweeps.swap_hash = htlc_keys.swap_hash
WHERE WHERE
batch_id = $1 sweeps.batch_id = $1
ORDER BY ORDER BY
id ASC; sweeps.id ASC;
-- name: GetSweepStatus :one -- name: GetSweepStatus :one
SELECT SELECT

@ -1,7 +1,7 @@
-- name: InsertInstantOut :exec -- name: InsertInstantOut :exec
INSERT INTO instantout_swaps ( INSERT INTO instantout_swaps (
swap_hash, swap_hash,
preimage, preimage,
sweep_address, sweep_address,
outgoing_chan_set, outgoing_chan_set,
htlc_fee_rate, htlc_fee_rate,
@ -53,7 +53,7 @@ WHERE
swaps.swap_hash = $1; swaps.swap_hash = $1;
-- name: GetInstantOutSwaps :many -- name: GetInstantOutSwaps :many
SELECT SELECT
swaps.*, swaps.*,
instantout_swaps.*, instantout_swaps.*,
htlc_keys.* htlc_keys.*

@ -1,14 +0,0 @@
-- name: InsertMigration :exec
INSERT INTO migration_tracker (
migration_id,
migration_ts
) VALUES ($1, $2);
-- name: GetMigration :one
SELECT
migration_id,
migration_ts
FROM
migration_tracker
WHERE
migration_id = $1;

@ -1,9 +1,9 @@
-- name: GetLoopOutSwaps :many -- name: GetLoopOutSwaps :many
SELECT SELECT
swaps.*, swaps.*,
loopout_swaps.*, loopout_swaps.*,
htlc_keys.* htlc_keys.*
FROM FROM
swaps swaps
JOIN JOIN
loopout_swaps ON swaps.swap_hash = loopout_swaps.swap_hash loopout_swaps ON swaps.swap_hash = loopout_swaps.swap_hash
@ -13,7 +13,7 @@ ORDER BY
swaps.id; swaps.id;
-- name: GetLoopOutSwap :one -- name: GetLoopOutSwap :one
SELECT SELECT
swaps.*, swaps.*,
loopout_swaps.*, loopout_swaps.*,
htlc_keys.* htlc_keys.*
@ -27,7 +27,7 @@ WHERE
swaps.swap_hash = $1; swaps.swap_hash = $1;
-- name: GetLoopInSwaps :many -- name: GetLoopInSwaps :many
SELECT SELECT
swaps.*, swaps.*,
loopin_swaps.*, loopin_swaps.*,
htlc_keys.* htlc_keys.*
@ -41,7 +41,7 @@ ORDER BY
swaps.id; swaps.id;
-- name: GetLoopInSwap :one -- name: GetLoopInSwap :one
SELECT SELECT
swaps.*, swaps.*,
loopin_swaps.*, loopin_swaps.*,
htlc_keys.* htlc_keys.*
@ -55,7 +55,7 @@ WHERE
swaps.swap_hash = $1; swaps.swap_hash = $1;
-- name: GetSwapUpdates :many -- name: GetSwapUpdates :many
SELECT SELECT
* *
FROM FROM
swap_updates swap_updates
@ -105,10 +105,9 @@ INSERT INTO loopout_swaps (
prepay_invoice, prepay_invoice,
max_prepay_routing_fee, max_prepay_routing_fee,
publication_deadline, publication_deadline,
single_sweep, single_sweep
payment_timeout
) VALUES ( ) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11
); );
-- name: InsertLoopIn :exec -- name: InsertLoopIn :exec
@ -132,20 +131,4 @@ INSERT INTO htlc_keys(
client_key_index client_key_index
) VALUES ( ) VALUES (
$1, $2, $3, $4, $5, $6, $7 $1, $2, $3, $4, $5, $6, $7
); );
-- name: GetLastUpdateID :one
SELECT id
FROM swap_updates
WHERE swap_hash = $1
ORDER BY update_timestamp DESC
LIMIT 1;
-- name: OverrideSwapCosts :exec
UPDATE swap_updates
SET
server_cost = $2,
onchain_cost = $3,
offchain_cost = $4
WHERE id = $1;

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
// source: reservations.sql // source: reservations.sql
package sqlc package sqlc

@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT. // Code generated by sqlc. DO NOT EDIT.
// versions: // versions:
// sqlc v1.25.0 // sqlc v1.17.2
// source: swaps.sql // source: swaps.sql
package sqlc package sqlc
@ -10,23 +10,8 @@ import (
"time" "time"
) )
const getLastUpdateID = `-- name: GetLastUpdateID :one
SELECT id
FROM swap_updates
WHERE swap_hash = $1
ORDER BY update_timestamp DESC
LIMIT 1
`
func (q *Queries) GetLastUpdateID(ctx context.Context, swapHash []byte) (int32, error) {
row := q.db.QueryRowContext(ctx, getLastUpdateID, swapHash)
var id int32
err := row.Scan(&id)
return id, err
}
const getLoopInSwap = `-- name: GetLoopInSwap :one const getLoopInSwap = `-- name: GetLoopInSwap :one
SELECT SELECT
swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label, swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label,
loopin_swaps.swap_hash, loopin_swaps.htlc_conf_target, loopin_swaps.last_hop, loopin_swaps.external_htlc, loopin_swaps.swap_hash, loopin_swaps.htlc_conf_target, loopin_swaps.last_hop, loopin_swaps.external_htlc,
htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index
@ -96,7 +81,7 @@ func (q *Queries) GetLoopInSwap(ctx context.Context, swapHash []byte) (GetLoopIn
} }
const getLoopInSwaps = `-- name: GetLoopInSwaps :many const getLoopInSwaps = `-- name: GetLoopInSwaps :many
SELECT SELECT
swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label, swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label,
loopin_swaps.swap_hash, loopin_swaps.htlc_conf_target, loopin_swaps.last_hop, loopin_swaps.external_htlc, loopin_swaps.swap_hash, loopin_swaps.htlc_conf_target, loopin_swaps.last_hop, loopin_swaps.external_htlc,
htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index
@ -182,9 +167,9 @@ func (q *Queries) GetLoopInSwaps(ctx context.Context) ([]GetLoopInSwapsRow, erro
} }
const getLoopOutSwap = `-- name: GetLoopOutSwap :one const getLoopOutSwap = `-- name: GetLoopOutSwap :one
SELECT SELECT
swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label, swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label,
loopout_swaps.swap_hash, loopout_swaps.dest_address, loopout_swaps.swap_invoice, loopout_swaps.max_swap_routing_fee, loopout_swaps.sweep_conf_target, loopout_swaps.htlc_confirmations, loopout_swaps.outgoing_chan_set, loopout_swaps.prepay_invoice, loopout_swaps.max_prepay_routing_fee, loopout_swaps.publication_deadline, loopout_swaps.single_sweep, loopout_swaps.payment_timeout, loopout_swaps.swap_hash, loopout_swaps.dest_address, loopout_swaps.swap_invoice, loopout_swaps.max_swap_routing_fee, loopout_swaps.sweep_conf_target, loopout_swaps.htlc_confirmations, loopout_swaps.outgoing_chan_set, loopout_swaps.prepay_invoice, loopout_swaps.max_prepay_routing_fee, loopout_swaps.publication_deadline, loopout_swaps.single_sweep,
htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index
FROM FROM
swaps swaps
@ -219,7 +204,6 @@ type GetLoopOutSwapRow struct {
MaxPrepayRoutingFee int64 MaxPrepayRoutingFee int64
PublicationDeadline time.Time PublicationDeadline time.Time
SingleSweep bool SingleSweep bool
PaymentTimeout int32
SwapHash_3 []byte SwapHash_3 []byte
SenderScriptPubkey []byte SenderScriptPubkey []byte
ReceiverScriptPubkey []byte ReceiverScriptPubkey []byte
@ -255,7 +239,6 @@ func (q *Queries) GetLoopOutSwap(ctx context.Context, swapHash []byte) (GetLoopO
&i.MaxPrepayRoutingFee, &i.MaxPrepayRoutingFee,
&i.PublicationDeadline, &i.PublicationDeadline,
&i.SingleSweep, &i.SingleSweep,
&i.PaymentTimeout,
&i.SwapHash_3, &i.SwapHash_3,
&i.SenderScriptPubkey, &i.SenderScriptPubkey,
&i.ReceiverScriptPubkey, &i.ReceiverScriptPubkey,
@ -268,11 +251,11 @@ func (q *Queries) GetLoopOutSwap(ctx context.Context, swapHash []byte) (GetLoopO
} }
const getLoopOutSwaps = `-- name: GetLoopOutSwaps :many const getLoopOutSwaps = `-- name: GetLoopOutSwaps :many
SELECT SELECT
swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label, swaps.id, swaps.swap_hash, swaps.preimage, swaps.initiation_time, swaps.amount_requested, swaps.cltv_expiry, swaps.max_miner_fee, swaps.max_swap_fee, swaps.initiation_height, swaps.protocol_version, swaps.label,
loopout_swaps.swap_hash, loopout_swaps.dest_address, loopout_swaps.swap_invoice, loopout_swaps.max_swap_routing_fee, loopout_swaps.sweep_conf_target, loopout_swaps.htlc_confirmations, loopout_swaps.outgoing_chan_set, loopout_swaps.prepay_invoice, loopout_swaps.max_prepay_routing_fee, loopout_swaps.publication_deadline, loopout_swaps.single_sweep, loopout_swaps.payment_timeout, loopout_swaps.swap_hash, loopout_swaps.dest_address, loopout_swaps.swap_invoice, loopout_swaps.max_swap_routing_fee, loopout_swaps.sweep_conf_target, loopout_swaps.htlc_confirmations, loopout_swaps.outgoing_chan_set, loopout_swaps.prepay_invoice, loopout_swaps.max_prepay_routing_fee, loopout_swaps.publication_deadline, loopout_swaps.single_sweep,
htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index htlc_keys.swap_hash, htlc_keys.sender_script_pubkey, htlc_keys.receiver_script_pubkey, htlc_keys.sender_internal_pubkey, htlc_keys.receiver_internal_pubkey, htlc_keys.client_key_family, htlc_keys.client_key_index
FROM FROM
swaps swaps
JOIN JOIN
loopout_swaps ON swaps.swap_hash = loopout_swaps.swap_hash loopout_swaps ON swaps.swap_hash = loopout_swaps.swap_hash
@ -305,7 +288,6 @@ type GetLoopOutSwapsRow struct {
MaxPrepayRoutingFee int64 MaxPrepayRoutingFee int64
PublicationDeadline time.Time PublicationDeadline time.Time
SingleSweep bool SingleSweep bool
PaymentTimeout int32
SwapHash_3 []byte SwapHash_3 []byte
SenderScriptPubkey []byte SenderScriptPubkey []byte
ReceiverScriptPubkey []byte ReceiverScriptPubkey []byte
@ -347,7 +329,6 @@ func (q *Queries) GetLoopOutSwaps(ctx context.Context) ([]GetLoopOutSwapsRow, er
&i.MaxPrepayRoutingFee, &i.MaxPrepayRoutingFee,
&i.PublicationDeadline, &i.PublicationDeadline,
&i.SingleSweep, &i.SingleSweep,
&i.PaymentTimeout,
&i.SwapHash_3, &i.SwapHash_3,
&i.SenderScriptPubkey, &i.SenderScriptPubkey,
&i.ReceiverScriptPubkey, &i.ReceiverScriptPubkey,
@ -370,7 +351,7 @@ func (q *Queries) GetLoopOutSwaps(ctx context.Context) ([]GetLoopOutSwapsRow, er
} }
const getSwapUpdates = `-- name: GetSwapUpdates :many const getSwapUpdates = `-- name: GetSwapUpdates :many
SELECT SELECT
id, swap_hash, update_timestamp, update_state, htlc_txhash, server_cost, onchain_cost, offchain_cost id, swap_hash, update_timestamp, update_state, htlc_txhash, server_cost, onchain_cost, offchain_cost
FROM FROM
swap_updates swap_updates
@ -489,10 +470,9 @@ INSERT INTO loopout_swaps (
prepay_invoice, prepay_invoice,
max_prepay_routing_fee, max_prepay_routing_fee,
publication_deadline, publication_deadline,
single_sweep, single_sweep
payment_timeout
) VALUES ( ) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11
) )
` `
@ -508,7 +488,6 @@ type InsertLoopOutParams struct {
MaxPrepayRoutingFee int64 MaxPrepayRoutingFee int64
PublicationDeadline time.Time PublicationDeadline time.Time
SingleSweep bool SingleSweep bool
PaymentTimeout int32
} }
func (q *Queries) InsertLoopOut(ctx context.Context, arg InsertLoopOutParams) error { func (q *Queries) InsertLoopOut(ctx context.Context, arg InsertLoopOutParams) error {
@ -524,7 +503,6 @@ func (q *Queries) InsertLoopOut(ctx context.Context, arg InsertLoopOutParams) er
arg.MaxPrepayRoutingFee, arg.MaxPrepayRoutingFee,
arg.PublicationDeadline, arg.PublicationDeadline,
arg.SingleSweep, arg.SingleSweep,
arg.PaymentTimeout,
) )
return err return err
} }
@ -611,29 +589,3 @@ func (q *Queries) InsertSwapUpdate(ctx context.Context, arg InsertSwapUpdatePara
) )
return err return err
} }
const overrideSwapCosts = `-- name: OverrideSwapCosts :exec
UPDATE swap_updates
SET
server_cost = $2,
onchain_cost = $3,
offchain_cost = $4
WHERE id = $1
`
type OverrideSwapCostsParams struct {
ID int32
ServerCost int64
OnchainCost int64
OffchainCost int64
}
func (q *Queries) OverrideSwapCosts(ctx context.Context, arg OverrideSwapCostsParams) error {
_, err := q.db.ExecContext(ctx, overrideSwapCosts,
arg.ID,
arg.ServerCost,
arg.OnchainCost,
arg.OffchainCost,
)
return err
}

@ -15,6 +15,7 @@ import (
sqlite_migrate "github.com/golang-migrate/migrate/v4/database/sqlite" sqlite_migrate "github.com/golang-migrate/migrate/v4/database/sqlite"
"github.com/lightninglabs/loop/loopdb/sqlc" "github.com/lightninglabs/loop/loopdb/sqlc"
"github.com/lightningnetwork/lnd/zpay32" "github.com/lightningnetwork/lnd/zpay32"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
_ "modernc.org/sqlite" // Register relevant drivers. _ "modernc.org/sqlite" // Register relevant drivers.
) )
@ -67,21 +68,6 @@ func NewSqliteStore(cfg *SqliteConfig, network *chaincfg.Params) (*SqliteSwapSto
name: "busy_timeout", name: "busy_timeout",
value: "5000", value: "5000",
}, },
{
// With the WAL mode, this ensures that we also do an
// extra WAL sync after each transaction. The normal
// sync mode skips this and gives better performance,
// but risks durability.
name: "synchronous",
value: "full",
},
{
// This is used to ensure proper durability for users
// running on Mac OS. It uses the correct fsync system
// call to ensure items are fully flushed to disk.
name: "fullfsync",
value: "true",
},
} }
sqliteOptions := make(url.Values) sqliteOptions := make(url.Values)
for _, option := range pragmaOptions { for _, option := range pragmaOptions {
@ -194,7 +180,7 @@ func (db *BaseDB) BeginTx(ctx context.Context,
} }
// ExecTx is a wrapper for txBody to abstract the creation and commit of a db // ExecTx is a wrapper for txBody to abstract the creation and commit of a db
// transaction. The db transaction is embedded in a `*sqlc.Queries` that // transaction. The db transaction is embedded in a `*postgres.Queries` that
// txBody needs to use when executing each one of the queries that need to be // txBody needs to use when executing each one of the queries that need to be
// applied atomically. // applied atomically.
func (db *BaseDB) ExecTx(ctx context.Context, txOptions TxOptions, func (db *BaseDB) ExecTx(ctx context.Context, txOptions TxOptions,
@ -224,9 +210,9 @@ func (db *BaseDB) ExecTx(ctx context.Context, txOptions TxOptions,
// FixFaultyTimestamps fixes faulty timestamps in the database, caused // FixFaultyTimestamps fixes faulty timestamps in the database, caused
// by using milliseconds instead of seconds as the publication deadline. // by using milliseconds instead of seconds as the publication deadline.
func (db *BaseDB) FixFaultyTimestamps(ctx context.Context) error { func (b *BaseDB) FixFaultyTimestamps(ctx context.Context) error {
// Manually fetch all the loop out swaps. // Manually fetch all the loop out swaps.
rows, err := db.DB.QueryContext( rows, err := b.DB.QueryContext(
ctx, "SELECT swap_hash, swap_invoice, publication_deadline FROM loopout_swaps", ctx, "SELECT swap_hash, swap_invoice, publication_deadline FROM loopout_swaps",
) )
if err != nil { if err != nil {
@ -262,7 +248,7 @@ func (db *BaseDB) FixFaultyTimestamps(ctx context.Context) error {
return err return err
} }
tx, err := db.BeginTx(ctx, &SqliteTxOptions{}) tx, err := b.BeginTx(ctx, &SqliteTxOptions{})
if err != nil { if err != nil {
return err return err
} }
@ -283,7 +269,7 @@ func (db *BaseDB) FixFaultyTimestamps(ctx context.Context) error {
continue continue
} }
payReq, err := zpay32.Decode(swap.SwapInvoice, db.network) payReq, err := zpay32.Decode(swap.SwapInvoice, b.network)
if err != nil { if err != nil {
return err return err
} }
@ -323,7 +309,7 @@ type SqliteTxOptions struct {
readOnly bool readOnly bool
} }
// NewSqlReadOpts returns a new KeyStoreTxOptions instance that triggers a read // NewSqlReadOpts returns a new KeyStoreTxOptions instance triggers a read
// transaction. // transaction.
func NewSqlReadOpts() *SqliteTxOptions { func NewSqlReadOpts() *SqliteTxOptions {
return &SqliteTxOptions{ return &SqliteTxOptions{
@ -331,14 +317,6 @@ func NewSqlReadOpts() *SqliteTxOptions {
} }
} }
// NewSqlWriteOpts returns a new KeyStoreTxOptions instance that triggers a
// write (regular) transaction.
func NewSqlWriteOpts() *SqliteTxOptions {
return &SqliteTxOptions{
readOnly: false,
}
}
// ReadOnly returns true if the transaction should be read only. // ReadOnly returns true if the transaction should be read only.
// //
// NOTE: This implements the TxOptions interface. // NOTE: This implements the TxOptions interface.

@ -1009,25 +1009,3 @@ func (b *boltSwapStore) BatchInsertUpdate(ctx context.Context,
return errUnimplemented return errUnimplemented
} }
// BatchUpdateLoopOutSwapCosts updates the swap costs for a batch of loop out
// swaps.
func (b *boltSwapStore) BatchUpdateLoopOutSwapCosts(ctx context.Context,
costs map[lntypes.Hash]SwapCost) error {
return errUnimplemented
}
// HasMigration returns true if the migration with the given ID has been done.
func (b *boltSwapStore) HasMigration(ctx context.Context, migrationID string) (
bool, error) {
return false, errUnimplemented
}
// SetMigration marks the migration with the given ID as done.
func (b *boltSwapStore) SetMigration(ctx context.Context,
migrationID string) error {
return errUnimplemented
}

@ -3,7 +3,6 @@ package loopdb
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"testing" "testing"
"time" "time"
@ -24,8 +23,6 @@ type StoreMock struct {
loopInStoreChan chan LoopInContract loopInStoreChan chan LoopInContract
loopInUpdateChan chan SwapStateData loopInUpdateChan chan SwapStateData
migrations map[string]struct{}
t *testing.T t *testing.T
} }
@ -41,7 +38,6 @@ func NewStoreMock(t *testing.T) *StoreMock {
loopInUpdateChan: make(chan SwapStateData, 1), loopInUpdateChan: make(chan SwapStateData, 1),
LoopInSwaps: make(map[lntypes.Hash]*LoopInContract), LoopInSwaps: make(map[lntypes.Hash]*LoopInContract),
LoopInUpdates: make(map[lntypes.Hash][]SwapStateData), LoopInUpdates: make(map[lntypes.Hash][]SwapStateData),
migrations: make(map[string]struct{}),
t: t, t: t,
} }
} }
@ -341,46 +337,3 @@ func (b *StoreMock) BatchInsertUpdate(ctx context.Context,
return errors.New("not implemented") return errors.New("not implemented")
} }
// BatchUpdateLoopOutSwapCosts updates the swap costs for a batch of loop out
// swaps.
func (s *StoreMock) BatchUpdateLoopOutSwapCosts(ctx context.Context,
costs map[lntypes.Hash]SwapCost) error {
for hash, cost := range costs {
if _, ok := s.LoopOutUpdates[hash]; !ok {
return fmt.Errorf("swap has no updates: %v", hash)
}
updates, ok := s.LoopOutUpdates[hash]
if !ok {
return fmt.Errorf("swap has no updates: %v", hash)
}
updates[len(updates)-1].Cost = cost
}
return nil
}
// HasMigration returns true if the migration with the given ID has been done.
func (s *StoreMock) HasMigration(ctx context.Context, migrationID string) (
bool, error) {
_, ok := s.migrations[migrationID]
return ok, nil
}
// SetMigration marks the migration with the given ID as done.
func (s *StoreMock) SetMigration(ctx context.Context,
migrationID string) error {
if _, ok := s.migrations[migrationID]; ok {
return errors.New("migration already done")
}
s.migrations[migrationID] = struct{}{}
return nil
}

@ -1,49 +0,0 @@
package loopdb
import (
"context"
"github.com/lightninglabs/loop/loopdb/sqlc"
)
// BatchedQuerier implements all DB queries and ExecTx on *sqlc.Queries.
// It is implemented by BaseDB, SqliteSwapStore, etc.
type BatchedQuerier interface {
sqlc.Querier
// ExecTx is a wrapper for txBody to abstract the creation and commit of
// a db transaction. The db transaction is embedded in a `*sqlc.Queries`
// that txBody needs to use when executing each one of the queries that
// need to be applied atomically.
ExecTx(ctx context.Context, txOptions TxOptions,
txBody func(*sqlc.Queries) error) error
}
// TypedStore is similar to BaseDB but provides parameterized ExecTx.
// It is used in other packages expecting ExecTx operating on subset of methods.
type TypedStore[Q any] struct {
BatchedQuerier
}
// NewTypedStore wraps a db, replacing generic ExecTx method with the typed one.
func NewTypedStore[Q any](db BatchedQuerier) *TypedStore[Q] {
// Make sure *sqlc.Queries can be casted to Q.
_ = any((*sqlc.Queries)(nil)).(Q)
return &TypedStore[Q]{
BatchedQuerier: db,
}
}
// ExecTx will execute the passed txBody, operating upon generic parameter Q
// (usually a storage interface) in a single transaction. The set of TxOptions
// are passed in to allow the caller to specify if a transaction is read-only.
func (s *TypedStore[Q]) ExecTx(ctx context.Context,
txOptions TxOptions, txBody func(Q) error) error {
return s.BatchedQuerier.ExecTx(ctx, txOptions,
func(q *sqlc.Queries) error {
return txBody(any(q).(Q))
},
)
}

@ -111,8 +111,8 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,
// Because the Private flag is set, we'll generate our own set // Because the Private flag is set, we'll generate our own set
// of hop hints. // of hop hints.
request.RouteHints, err = SelectHopHints( request.RouteHints, err = SelectHopHints(
globalCtx, cfg.lnd.Client, request.Amount, globalCtx, cfg.lnd, request.Amount, DefaultMaxHopHints,
DefaultMaxHopHints, includeNodes, includeNodes,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -837,7 +837,7 @@ func getTxFee(tx *wire.MsgTx, fee chainfee.SatPerKVByte) btcutil.Amount {
btcTx := btcutil.NewTx(tx) btcTx := btcutil.NewTx(tx)
vsize := mempool.GetTxVirtualSize(btcTx) vsize := mempool.GetTxVirtualSize(btcTx)
return fee.FeeForVSize(lntypes.VByte(vsize)) return fee.FeeForVSize(vsize)
} }
// waitForSwapComplete waits until a spending tx of the htlc gets confirmed and // waitForSwapComplete waits until a spending tx of the htlc gets confirmed and
@ -919,7 +919,9 @@ func (s *loopInSwap) waitForSwapComplete(ctx context.Context,
s.log.Infof("Htlc spend by tx: %v", s.log.Infof("Htlc spend by tx: %v",
spendDetails.SpenderTxHash) spendDetails.SpenderTxHash)
err := s.processHtlcSpend(ctx, spendDetails, sweepFee) err := s.processHtlcSpend(
ctx, spendDetails, htlcValue, sweepFee,
)
if err != nil { if err != nil {
return err return err
} }
@ -957,6 +959,8 @@ func (s *loopInSwap) waitForSwapComplete(ctx context.Context,
switch update.State { switch update.State {
// Swap invoice was paid, so update server cost balance. // Swap invoice was paid, so update server cost balance.
case invpkg.ContractSettled: case invpkg.ContractSettled:
s.cost.Server -= update.AmtPaid
// If invoice settlement and htlc spend happen // If invoice settlement and htlc spend happen
// in the expected order, move the swap to an // in the expected order, move the swap to an
// intermediate state that indicates that the // intermediate state that indicates that the
@ -973,8 +977,6 @@ func (s *loopInSwap) waitForSwapComplete(ctx context.Context,
invoiceFinalized = true invoiceFinalized = true
htlcKeyRevealed = s.tryPushHtlcKey(ctx) htlcKeyRevealed = s.tryPushHtlcKey(ctx)
s.cost.Server = s.AmountRequested -
update.AmtPaid
// Canceled invoice has no effect on server cost // Canceled invoice has no effect on server cost
// balance. // balance.
@ -1021,7 +1023,8 @@ func (s *loopInSwap) tryPushHtlcKey(ctx context.Context) bool {
} }
func (s *loopInSwap) processHtlcSpend(ctx context.Context, func (s *loopInSwap) processHtlcSpend(ctx context.Context,
spend *chainntnfs.SpendDetail, sweepFee btcutil.Amount) error { spend *chainntnfs.SpendDetail, htlcValue,
sweepFee btcutil.Amount) error {
// Determine the htlc input of the spending tx and inspect the witness // Determine the htlc input of the spending tx and inspect the witness
// to find out whether a success or a timeout tx spent the htlc. // to find out whether a success or a timeout tx spent the htlc.
@ -1029,6 +1032,10 @@ func (s *loopInSwap) processHtlcSpend(ctx context.Context,
if s.htlc.IsSuccessWitness(htlcInput.Witness) { if s.htlc.IsSuccessWitness(htlcInput.Witness) {
s.setState(loopdb.StateSuccess) s.setState(loopdb.StateSuccess)
// Server swept the htlc. The htlc value can be added to the
// server cost balance.
s.cost.Server += htlcValue
} else { } else {
// We needed another on chain tx to sweep the timeout clause, // We needed another on chain tx to sweep the timeout clause,
// which we now include in our costs. // which we now include in our costs.

@ -77,10 +77,6 @@ type loopOutSwap struct {
swapInvoicePaymentAddr [32]byte swapInvoicePaymentAddr [32]byte
// prepayAmount holds the amount of the prepay invoice. We use this
// to calculate the total cost of the swap.
prepayAmount btcutil.Amount
swapPaymentChan chan paymentResult swapPaymentChan chan paymentResult
prePaymentChan chan paymentResult prePaymentChan chan paymentResult
@ -199,7 +195,6 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig,
ProtocolVersion: loopdb.CurrentProtocolVersion(), ProtocolVersion: loopdb.CurrentProtocolVersion(),
}, },
OutgoingChanSet: chanSet, OutgoingChanSet: chanSet,
PaymentTimeout: request.PaymentTimeout,
} }
swapKit := newSwapKit( swapKit := newSwapKit(
@ -311,11 +306,7 @@ func (s *loopOutSwap) sendUpdate(ctx context.Context) error {
info := s.swapInfo() info := s.swapInfo()
s.log.Infof("Loop out swap state: %v", info.State) s.log.Infof("Loop out swap state: %v", info.State)
if s.htlc.OutputType == swap.HtlcP2WSH { info.HtlcAddressP2WSH = s.htlc.Address
info.HtlcAddressP2WSH = s.htlc.Address
} else {
info.HtlcAddressP2TR = s.htlc.Address
}
// In order to avoid potentially dangerous ownership sharing // In order to avoid potentially dangerous ownership sharing
// we copy the outgoing channel set. // we copy the outgoing channel set.
@ -407,7 +398,7 @@ func (s *loopOutSwap) executeAndFinalize(globalCtx context.Context) error {
case result := <-s.swapPaymentChan: case result := <-s.swapPaymentChan:
s.swapPaymentChan = nil s.swapPaymentChan = nil
err := s.handlePaymentResult(result, true) err := s.handlePaymentResult(result)
if err != nil { if err != nil {
return err return err
} }
@ -423,7 +414,7 @@ func (s *loopOutSwap) executeAndFinalize(globalCtx context.Context) error {
case result := <-s.prePaymentChan: case result := <-s.prePaymentChan:
s.prePaymentChan = nil s.prePaymentChan = nil
err := s.handlePaymentResult(result, false) err := s.handlePaymentResult(result)
if err != nil { if err != nil {
return err return err
} }
@ -453,12 +444,7 @@ func (s *loopOutSwap) executeAndFinalize(globalCtx context.Context) error {
return s.persistState(globalCtx) return s.persistState(globalCtx)
} }
// handlePaymentResult processes the result of a payment attempt. If the func (s *loopOutSwap) handlePaymentResult(result paymentResult) error {
// payment was successful and this is the main swap payment, the cost of the
// swap is updated.
func (s *loopOutSwap) handlePaymentResult(result paymentResult,
swapPayment bool) error {
switch { switch {
// If our result has a non-nil error, our status will be nil. In this // If our result has a non-nil error, our status will be nil. In this
// case the payment failed so we do not need to take any action. // case the payment failed so we do not need to take any action.
@ -466,22 +452,7 @@ func (s *loopOutSwap) handlePaymentResult(result paymentResult,
return nil return nil
case result.status.State == lnrpc.Payment_SUCCEEDED: case result.status.State == lnrpc.Payment_SUCCEEDED:
// Update the cost of the swap if this is the main swap payment. s.cost.Server += result.status.Value.ToSatoshis()
if swapPayment {
// The client pays for the swap with the swap invoice,
// so we can calculate the total cost of the swap by
// subtracting the amount requested from the total
// amount that we actually paid (which is the sum of
// the swap invoice amount and the prepay invoice
// amount).
s.cost.Server += s.prepayAmount +
result.status.Value.ToSatoshis() -
s.AmountRequested
}
// On top of the swap cost we also pay for routing which
// is reflected in the fee. We add the off-chain fee for both
// the swap payment and the prepay.
s.cost.Offchain += result.status.Fee.ToSatoshis() s.cost.Offchain += result.status.Fee.ToSatoshis()
return nil return nil
@ -497,16 +468,6 @@ func (s *loopOutSwap) handlePaymentResult(result paymentResult,
// executeSwap executes the swap, but returns as soon as the swap outcome is // executeSwap executes the swap, but returns as soon as the swap outcome is
// final. At that point, there may still be pending off-chain payment(s). // final. At that point, there may still be pending off-chain payment(s).
func (s *loopOutSwap) executeSwap(globalCtx context.Context) error { func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {
// Decode the prepay invoice so we can ensure that we account for the
// prepay amount when calculating the final costs of the swap.
_, _, _, amt, err := swap.DecodeInvoice(
s.lnd.ChainParams, s.PrepayInvoice,
)
if err != nil {
return err
}
s.prepayAmount = amt
// We always pay both invoices (again). This is currently the only way // We always pay both invoices (again). This is currently the only way
// to sort of resume payments. // to sort of resume payments.
// //
@ -553,7 +514,7 @@ func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {
} }
// Try to spend htlc and continue (rbf) until a spend has confirmed. // Try to spend htlc and continue (rbf) until a spend has confirmed.
spend, err := s.waitForHtlcSpendConfirmedV2( spendTx, err := s.waitForHtlcSpendConfirmedV2(
globalCtx, *htlcOutpoint, htlcValue, globalCtx, *htlcOutpoint, htlcValue,
) )
if err != nil { if err != nil {
@ -562,7 +523,7 @@ func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {
// If spend details are nil, we resolved the swap without waiting for // If spend details are nil, we resolved the swap without waiting for
// its spend, so we can exit. // its spend, so we can exit.
if spend == nil { if spendTx == nil {
return nil return nil
} }
@ -570,7 +531,7 @@ func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {
// don't just try to match with the hash of our sweep tx, because it // don't just try to match with the hash of our sweep tx, because it
// may be swept by a different (fee) sweep tx from a previous run. // may be swept by a different (fee) sweep tx from a previous run.
htlcInput, err := swap.GetTxInputByOutpoint( htlcInput, err := swap.GetTxInputByOutpoint(
spend.Tx, htlcOutpoint, spendTx, htlcOutpoint,
) )
if err != nil { if err != nil {
return err return err
@ -578,7 +539,11 @@ func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {
sweepSuccessful := s.htlc.IsSuccessWitness(htlcInput.Witness) sweepSuccessful := s.htlc.IsSuccessWitness(htlcInput.Witness)
if sweepSuccessful { if sweepSuccessful {
s.cost.Onchain = spend.OnChainFeePortion s.cost.Server -= htlcValue
s.cost.Onchain = htlcValue -
btcutil.Amount(spendTx.TxOut[0].Value)
s.state = loopdb.StateSuccess s.state = loopdb.StateSuccess
} else { } else {
s.state = loopdb.StateFailSweepTimeout s.state = loopdb.StateFailSweepTimeout
@ -629,18 +594,15 @@ func (s *loopOutSwap) payInvoices(ctx context.Context) {
// Use the recommended routing plugin. // Use the recommended routing plugin.
s.swapPaymentChan = s.payInvoice( s.swapPaymentChan = s.payInvoice(
ctx, s.SwapInvoice, s.MaxSwapRoutingFee, ctx, s.SwapInvoice, s.MaxSwapRoutingFee,
s.LoopOutContract.OutgoingChanSet, s.LoopOutContract.OutgoingChanSet, pluginType, true,
s.LoopOutContract.PaymentTimeout, pluginType, true,
) )
// Pay the prepay invoice. Won't use the routing plugin here as the // Pay the prepay invoice. Won't use the routing plugin here as the
// prepay is trivially small and shouldn't normally need any help. We // prepay is trivially small and shouldn't normally need any help.
// are sending it over the same channel as the loop out payment.
s.log.Infof("Sending prepayment %v", s.PrepayInvoice) s.log.Infof("Sending prepayment %v", s.PrepayInvoice)
s.prePaymentChan = s.payInvoice( s.prePaymentChan = s.payInvoice(
ctx, s.PrepayInvoice, s.MaxPrepayRoutingFee, ctx, s.PrepayInvoice, s.MaxPrepayRoutingFee,
s.LoopOutContract.OutgoingChanSet, nil, RoutingPluginNone, false,
s.LoopOutContract.PaymentTimeout, RoutingPluginNone, false,
) )
} }
@ -668,7 +630,7 @@ func (p paymentResult) failure() error {
// payInvoice pays a single invoice. // payInvoice pays a single invoice.
func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string, func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string,
maxFee btcutil.Amount, outgoingChanIds loopdb.ChannelSet, maxFee btcutil.Amount, outgoingChanIds loopdb.ChannelSet,
paymentTimeout time.Duration, pluginType RoutingPluginType, pluginType RoutingPluginType,
reportPluginResult bool) chan paymentResult { reportPluginResult bool) chan paymentResult {
resultChan := make(chan paymentResult) resultChan := make(chan paymentResult)
@ -683,8 +645,8 @@ func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string,
var result paymentResult var result paymentResult
status, err := s.payInvoiceAsync( status, err := s.payInvoiceAsync(
ctx, invoice, maxFee, outgoingChanIds, paymentTimeout, ctx, invoice, maxFee, outgoingChanIds, pluginType,
pluginType, reportPluginResult, reportPluginResult,
) )
if err != nil { if err != nil {
result.err = err result.err = err
@ -712,9 +674,8 @@ func (s *loopOutSwap) payInvoice(ctx context.Context, invoice string,
// payInvoiceAsync is the asynchronously executed part of paying an invoice. // payInvoiceAsync is the asynchronously executed part of paying an invoice.
func (s *loopOutSwap) payInvoiceAsync(ctx context.Context, func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
invoice string, maxFee btcutil.Amount, invoice string, maxFee btcutil.Amount,
outgoingChanIds loopdb.ChannelSet, paymentTimeout time.Duration, outgoingChanIds loopdb.ChannelSet, pluginType RoutingPluginType,
pluginType RoutingPluginType, reportPluginResult bool) ( reportPluginResult bool) (*lndclient.PaymentStatus, error) {
*lndclient.PaymentStatus, error) {
// Extract hash from payment request. Unfortunately the request // Extract hash from payment request. Unfortunately the request
// components aren't available directly. // components aren't available directly.
@ -727,7 +688,7 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
} }
maxRetries := 1 maxRetries := 1
totalPaymentTimeout := s.executeConfig.totalPaymentTimeout paymentTimeout := s.executeConfig.totalPaymentTimeout
// Attempt to acquire and initialize the routing plugin. // Attempt to acquire and initialize the routing plugin.
routingPlugin, err := AcquireRoutingPlugin( routingPlugin, err := AcquireRoutingPlugin(
@ -742,30 +703,8 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
pluginType, hash.String()) pluginType, hash.String())
maxRetries = s.executeConfig.maxPaymentRetries maxRetries = s.executeConfig.maxPaymentRetries
paymentTimeout /= time.Duration(maxRetries)
// If not set, default to the per payment timeout to the total
// payment timeout divied by the configured maximum retries.
if paymentTimeout == 0 {
paymentTimeout = totalPaymentTimeout /
time.Duration(maxRetries)
}
// If the payment timeout is too long, we need to adjust the
// number of retries to ensure we don't exceed the total
// payment timeout.
if paymentTimeout*time.Duration(maxRetries) >
totalPaymentTimeout {
maxRetries = int(totalPaymentTimeout / paymentTimeout)
s.log.Infof("Adjusted max routing plugin retries to "+
"%v to stay within total payment timeout",
maxRetries)
}
defer ReleaseRoutingPlugin(ctx) defer ReleaseRoutingPlugin(ctx)
} else if paymentTimeout == 0 {
// If not set, default the payment timeout to the total payment
// timeout.
paymentTimeout = totalPaymentTimeout
} }
req := lndclient.SendPaymentRequest{ req := lndclient.SendPaymentRequest{
@ -976,7 +915,7 @@ func (s *loopOutSwap) waitForConfirmedHtlc(globalCtx context.Context) (
case result := <-s.swapPaymentChan: case result := <-s.swapPaymentChan:
s.swapPaymentChan = nil s.swapPaymentChan = nil
err := s.handlePaymentResult(result, true) err := s.handlePaymentResult(result)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -998,7 +937,7 @@ func (s *loopOutSwap) waitForConfirmedHtlc(globalCtx context.Context) (
case result := <-s.prePaymentChan: case result := <-s.prePaymentChan:
s.prePaymentChan = nil s.prePaymentChan = nil
err := s.handlePaymentResult(result, false) err := s.handlePaymentResult(result)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1066,9 +1005,9 @@ func (s *loopOutSwap) waitForConfirmedHtlc(globalCtx context.Context) (
// sweep or a server revocation tx. // sweep or a server revocation tx.
func (s *loopOutSwap) waitForHtlcSpendConfirmedV2(globalCtx context.Context, func (s *loopOutSwap) waitForHtlcSpendConfirmedV2(globalCtx context.Context,
htlcOutpoint wire.OutPoint, htlcValue btcutil.Amount) ( htlcOutpoint wire.OutPoint, htlcValue btcutil.Amount) (
*sweepbatcher.SpendDetail, error) { *wire.MsgTx, error) {
spendChan := make(chan *sweepbatcher.SpendDetail) spendChan := make(chan *wire.MsgTx)
spendErrChan := make(chan error, 1) spendErrChan := make(chan error, 1)
quitChan := make(chan bool, 1) quitChan := make(chan bool, 1)
@ -1115,10 +1054,10 @@ func (s *loopOutSwap) waitForHtlcSpendConfirmedV2(globalCtx context.Context,
for { for {
select { select {
// Htlc spend, break loop. // Htlc spend, break loop.
case spend := <-spendChan: case spendTx := <-spendChan:
s.log.Infof("Htlc spend by tx: %v", spend.Tx.TxHash()) s.log.Infof("Htlc spend by tx: %v", spendTx.TxHash())
return spend, nil return spendTx, nil
// Spend notification error. // Spend notification error.
case err := <-spendErrChan: case err := <-spendErrChan:

@ -17,7 +17,6 @@ import (
"github.com/lightninglabs/loop/sweepbatcher" "github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightninglabs/loop/test" "github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/zpay32" "github.com/lightningnetwork/lnd/zpay32"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -299,15 +298,10 @@ func testCustomSweepConfTarget(t *testing.T) {
batcherStore := sweepbatcher.NewStoreMock() batcherStore := sweepbatcher.NewStoreMock()
sweepStore, err := sweepbatcher.NewSweepFetcherFromSwapStore(
cfg.store, lnd.ChainParams,
)
require.NoError(t, err)
batcher := sweepbatcher.NewBatcher( batcher := sweepbatcher.NewBatcher(
lnd.WalletKit, lnd.ChainNotifier, lnd.Signer, lnd.WalletKit, lnd.ChainNotifier, lnd.Signer,
mockMuSig2SignSweep, mockVerifySchnorrSigSuccess, mockMuSig2SignSweep, mockVerifySchnorrSigSuccess,
lnd.ChainParams, batcherStore, sweepStore, lnd.ChainParams, batcherStore, cfg.store,
) )
tctx, cancel := context.WithCancel(context.Background()) tctx, cancel := context.WithCancel(context.Background())
@ -429,7 +423,7 @@ func testCustomSweepConfTarget(t *testing.T) {
) )
require.NoError(t, err, "unable to retrieve fee estimate") require.NoError(t, err, "unable to retrieve fee estimate")
minFee := feeRate.FeeForWeight(lntypes.WeightUnit(weight)) minFee := feeRate.FeeForWeight(weight)
// Just an estimate that works to sanity check fee upper bound. // Just an estimate that works to sanity check fee upper bound.
maxFee := btcutil.Amount(float64(minFee) * 1.5) maxFee := btcutil.Amount(float64(minFee) * 1.5)
@ -537,15 +531,10 @@ func testPreimagePush(t *testing.T) {
batcherStore := sweepbatcher.NewStoreMock() batcherStore := sweepbatcher.NewStoreMock()
sweepStore, err := sweepbatcher.NewSweepFetcherFromSwapStore(
cfg.store, lnd.ChainParams,
)
require.NoError(t, err)
batcher := sweepbatcher.NewBatcher( batcher := sweepbatcher.NewBatcher(
lnd.WalletKit, lnd.ChainNotifier, lnd.Signer, lnd.WalletKit, lnd.ChainNotifier, lnd.Signer,
mockMuSig2SignSweep, mockVerifySchnorrSigSuccess, mockMuSig2SignSweep, mockVerifySchnorrSigSuccess,
lnd.ChainParams, batcherStore, sweepStore, lnd.ChainParams, batcherStore, cfg.store,
) )
tctx, cancel := context.WithCancel(context.Background()) tctx, cancel := context.WithCancel(context.Background())
@ -963,15 +952,10 @@ func TestLoopOutMuSig2Sweep(t *testing.T) {
batcherStore := sweepbatcher.NewStoreMock() batcherStore := sweepbatcher.NewStoreMock()
sweepStore, err := sweepbatcher.NewSweepFetcherFromSwapStore(
cfg.store, lnd.ChainParams,
)
require.NoError(t, err)
batcher := sweepbatcher.NewBatcher( batcher := sweepbatcher.NewBatcher(
lnd.WalletKit, lnd.ChainNotifier, lnd.Signer, lnd.WalletKit, lnd.ChainNotifier, lnd.Signer,
mockMuSig2SignSweep, mockVerifySchnorrSigSuccess, mockMuSig2SignSweep, mockVerifySchnorrSigSuccess,
lnd.ChainParams, batcherStore, sweepStore, lnd.ChainParams, batcherStore, cfg.store,
) )
tctx, cancel := context.WithCancel(context.Background()) tctx, cancel := context.WithCancel(context.Background())

@ -1,9 +1,9 @@
FROM golang:1.21.9-bookworm FROM golang:1.16.3-buster
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
git \ git \
protobuf-compiler='3.21.12*' \ protobuf-compiler='3.6*' \
clang-format='1:14.0*' clang-format='1:7.0*'
# We don't want any default values for these variables to make sure they're # We don't want any default values for these variables to make sure they're
# explicitly provided by parsing the go.mod file. Otherwise we might forget to # explicitly provided by parsing the go.mod file. Otherwise we might forget to
@ -13,19 +13,14 @@ ARG GRPC_GATEWAY_VERSION
ENV PROTOC_GEN_GO_GRPC_VERSION="v1.1.0" ENV PROTOC_GEN_GO_GRPC_VERSION="v1.1.0"
ENV FALAFEL_VERSION="v0.9.1" ENV FALAFEL_VERSION="v0.9.1"
ENV GOCACHE=/tmp/build/.cache
ENV GOMODCACHE=/tmp/build/.modcache
RUN cd /tmp \ RUN cd /tmp \
&& mkdir -p /tmp/build/.cache \ && export GO111MODULE=on \
&& mkdir -p /tmp/build/.modcache \ && go get google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOBUF_VERSION} \
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOBUF_VERSION} \ && go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@${PROTOC_GEN_GO_GRPC_VERSION} \
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${PROTOC_GEN_GO_GRPC_VERSION} \ && go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@${GRPC_GATEWAY_VERSION} \
&& go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@${GRPC_GATEWAY_VERSION} \ && go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@${GRPC_GATEWAY_VERSION} \
&& go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@${GRPC_GATEWAY_VERSION} \ && go get github.com/lightninglabs/falafel@${FALAFEL_VERSION}
&& go install github.com/lightninglabs/falafel@${FALAFEL_VERSION} \
&& go install golang.org/x/tools/cmd/goimports@v0.1.7 \
&& chmod -R 777 /tmp/build/
WORKDIR /build WORKDIR /build

File diff suppressed because it is too large Load Diff

@ -433,38 +433,20 @@ func local_request_SwapClient_Probe_0(ctx context.Context, marshaler runtime.Mar
} }
func request_SwapClient_GetL402Tokens_0(ctx context.Context, marshaler runtime.Marshaler, client SwapClientClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_SwapClient_GetLsatTokens_0(ctx context.Context, marshaler runtime.Marshaler, client SwapClientClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq TokensRequest var protoReq TokensRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
msg, err := client.GetL402Tokens(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.GetLsatTokens(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err return msg, metadata, err
} }
func local_request_SwapClient_GetL402Tokens_0(ctx context.Context, marshaler runtime.Marshaler, server SwapClientServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func local_request_SwapClient_GetLsatTokens_0(ctx context.Context, marshaler runtime.Marshaler, server SwapClientServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq TokensRequest var protoReq TokensRequest
var metadata runtime.ServerMetadata var metadata runtime.ServerMetadata
msg, err := server.GetL402Tokens(ctx, &protoReq) msg, err := server.GetLsatTokens(ctx, &protoReq)
return msg, metadata, err
}
func request_SwapClient_GetL402Tokens_1(ctx context.Context, marshaler runtime.Marshaler, client SwapClientClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq TokensRequest
var metadata runtime.ServerMetadata
msg, err := client.GetL402Tokens(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_SwapClient_GetL402Tokens_1(ctx context.Context, marshaler runtime.Marshaler, server SwapClientServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq TokensRequest
var metadata runtime.ServerMetadata
msg, err := server.GetL402Tokens(ctx, &protoReq)
return msg, metadata, err return msg, metadata, err
} }
@ -788,7 +770,7 @@ func RegisterSwapClientHandlerServer(ctx context.Context, mux *runtime.ServeMux,
}) })
mux.Handle("GET", pattern_SwapClient_GetL402Tokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle("GET", pattern_SwapClient_GetLsatTokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
var stream runtime.ServerTransportStream var stream runtime.ServerTransportStream
@ -796,12 +778,12 @@ func RegisterSwapClientHandlerServer(ctx context.Context, mux *runtime.ServeMux,
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error var err error
var annotatedContext context.Context var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/looprpc.SwapClient/GetL402Tokens", runtime.WithHTTPPathPattern("/v1/l402/tokens")) annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/looprpc.SwapClient/GetLsatTokens", runtime.WithHTTPPathPattern("/v1/lsat/tokens"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
} }
resp, md, err := local_request_SwapClient_GetL402Tokens_0(annotatedContext, inboundMarshaler, server, req, pathParams) resp, md, err := local_request_SwapClient_GetLsatTokens_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil { if err != nil {
@ -809,32 +791,7 @@ func RegisterSwapClientHandlerServer(ctx context.Context, mux *runtime.ServeMux,
return return
} }
forward_SwapClient_GetL402Tokens_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_SwapClient_GetLsatTokens_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_SwapClient_GetL402Tokens_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/looprpc.SwapClient/GetL402Tokens", runtime.WithHTTPPathPattern("/v1/lsat/tokens"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_SwapClient_GetL402Tokens_1(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SwapClient_GetL402Tokens_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
@ -1177,47 +1134,25 @@ func RegisterSwapClientHandlerClient(ctx context.Context, mux *runtime.ServeMux,
}) })
mux.Handle("GET", pattern_SwapClient_GetL402Tokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle("GET", pattern_SwapClient_GetLsatTokens_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error var err error
var annotatedContext context.Context var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/looprpc.SwapClient/GetL402Tokens", runtime.WithHTTPPathPattern("/v1/l402/tokens")) annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/looprpc.SwapClient/GetLsatTokens", runtime.WithHTTPPathPattern("/v1/lsat/tokens"))
if err != nil { if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return return
} }
resp, md, err := request_SwapClient_GetL402Tokens_0(annotatedContext, inboundMarshaler, client, req, pathParams) resp, md, err := request_SwapClient_GetLsatTokens_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil { if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return return
} }
forward_SwapClient_GetL402Tokens_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_SwapClient_GetLsatTokens_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_SwapClient_GetL402Tokens_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/looprpc.SwapClient/GetL402Tokens", runtime.WithHTTPPathPattern("/v1/lsat/tokens"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_SwapClient_GetL402Tokens_1(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_SwapClient_GetL402Tokens_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
@ -1331,9 +1266,7 @@ var (
pattern_SwapClient_Probe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "loop", "in", "probe", "amt"}, "")) pattern_SwapClient_Probe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "loop", "in", "probe", "amt"}, ""))
pattern_SwapClient_GetL402Tokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "l402", "tokens"}, "")) pattern_SwapClient_GetLsatTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "lsat", "tokens"}, ""))
pattern_SwapClient_GetL402Tokens_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "lsat", "tokens"}, ""))
pattern_SwapClient_GetInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "loop", "info"}, "")) pattern_SwapClient_GetInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "loop", "info"}, ""))
@ -1363,9 +1296,7 @@ var (
forward_SwapClient_Probe_0 = runtime.ForwardResponseMessage forward_SwapClient_Probe_0 = runtime.ForwardResponseMessage
forward_SwapClient_GetL402Tokens_0 = runtime.ForwardResponseMessage forward_SwapClient_GetLsatTokens_0 = runtime.ForwardResponseMessage
forward_SwapClient_GetL402Tokens_1 = runtime.ForwardResponseMessage
forward_SwapClient_GetInfo_0 = runtime.ForwardResponseMessage forward_SwapClient_GetInfo_0 = runtime.ForwardResponseMessage

@ -76,16 +76,7 @@ service SwapClient {
rpc Probe (ProbeRequest) returns (ProbeResponse); rpc Probe (ProbeRequest) returns (ProbeResponse);
/* loop: `listauth` /* loop: `listauth`
GetL402Tokens returns all L402 tokens the daemon ever paid for. GetLsatTokens returns all LSAT tokens the daemon ever paid for.
*/
rpc GetL402Tokens (TokensRequest) returns (TokensResponse);
/*
Deprecated: use GetL402Tokens.
This API is provided to maintain backward compatibility with gRPC clients
(e.g. `loop listauth`, Terminal Web, RTL).
Type LsatToken used by GetLsatTokens in the past was renamed to L402Token,
but this does not affect binary encoding, so we can use type L402Token here.
*/ */
rpc GetLsatTokens (TokensRequest) returns (TokensResponse); rpc GetLsatTokens (TokensRequest) returns (TokensResponse);
@ -136,13 +127,6 @@ service SwapClient {
*/ */
rpc InstantOutQuote (InstantOutQuoteRequest) rpc InstantOutQuote (InstantOutQuoteRequest)
returns (InstantOutQuoteResponse); returns (InstantOutQuoteResponse);
/* loop: `listinstantouts`
ListInstantOuts returns a list of all currently known instant out swaps and
their current status.
*/
rpc ListInstantOuts (ListInstantOutsRequest)
returns (ListInstantOutsResponse);
} }
message LoopOutRequest { message LoopOutRequest {
@ -278,13 +262,6 @@ message LoopOutRequest {
be equal to the sum of the amounts of the reservations. be equal to the sum of the amounts of the reservations.
*/ */
repeated bytes reservation_ids = 18; repeated bytes reservation_ids = 18;
/*
The timeout in seconds to use for off-chain payments. Note that the swap
payment is attempted multiple times where each attempt will set this value
as the timeout for the payment.
*/
uint32 payment_timeout = 19;
} }
/* /*
@ -827,10 +804,10 @@ message TokensResponse {
/* /*
List of all tokens the daemon knows of, including old/expired tokens. List of all tokens the daemon knows of, including old/expired tokens.
*/ */
repeated L402Token tokens = 1; repeated LsatToken tokens = 1;
} }
message L402Token { message LsatToken {
/* /*
The base macaroon that was baked by the auth server. The base macaroon that was baked by the auth server.
*/ */
@ -1355,13 +1332,7 @@ message InstantOutRequest {
channel(s) that will be used are selected based on the lowest routing fee channel(s) that will be used are selected based on the lowest routing fee
for the swap payment to the server. for the swap payment to the server.
*/ */
repeated uint64 outgoing_chan_set = 2; repeated uint64 outgoing_chan_set = 11;
/*
An optional address to sweep the onchain funds to. If not set, the funds
will be swept to the wallet's internal address.
*/
string dest_addr = 3;
} }
message InstantOutResponse { message InstantOutResponse {
@ -1402,41 +1373,4 @@ message InstantOutQuoteResponse {
Sweep. Sweep.
*/ */
int64 sweep_fee_sat = 2; int64 sweep_fee_sat = 2;
} }
message ListInstantOutsRequest {
}
message ListInstantOutsResponse {
/*
The list of all currently known instant out swaps and their status.
*/
repeated InstantOut swaps = 1;
}
message InstantOut {
/*
The swap hash that identifies this swap.
*/
bytes swap_hash = 1;
/*
The state the swap is in.
*/
string state = 2;
/*
The amount of the swap.
*/
uint64 amount = 3;
/*
The used reservations for the swap.
*/
repeated bytes reservation_ids = 4;
/*
The sweep transaction id of the swap.
*/
string sweep_tx_id = 5;
}

@ -39,29 +39,6 @@
] ]
} }
}, },
"/v1/l402/tokens": {
"get": {
"summary": "loop: `listauth`\nGetL402Tokens returns all L402 tokens the daemon ever paid for.",
"operationId": "SwapClient_GetL402Tokens",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/looprpcTokensResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"SwapClient"
]
}
},
"/v1/liquidity/params": { "/v1/liquidity/params": {
"get": { "get": {
"summary": "loop: `getparams`\nGetLiquidityParams gets the parameters that the daemon's liquidity manager\nis currently configured with. This may be nil if nothing is configured.\n[EXPERIMENTAL]: endpoint is subject to change.", "summary": "loop: `getparams`\nGetLiquidityParams gets the parameters that the daemon's liquidity manager\nis currently configured with. This may be nil if nothing is configured.\n[EXPERIMENTAL]: endpoint is subject to change.",
@ -541,8 +518,8 @@
}, },
"/v1/lsat/tokens": { "/v1/lsat/tokens": {
"get": { "get": {
"summary": "loop: `listauth`\nGetL402Tokens returns all L402 tokens the daemon ever paid for.", "summary": "loop: `listauth`\nGetLsatTokens returns all LSAT tokens the daemon ever paid for.",
"operationId": "SwapClient_GetL402Tokens2", "operationId": "SwapClient_GetLsatTokens",
"responses": { "responses": {
"200": { "200": {
"description": "A successful response.", "description": "A successful response.",
@ -783,37 +760,6 @@
} }
} }
}, },
"looprpcInstantOut": {
"type": "object",
"properties": {
"swap_hash": {
"type": "string",
"format": "byte",
"description": "The swap hash that identifies this swap."
},
"state": {
"type": "string",
"description": "The state the swap is in."
},
"amount": {
"type": "string",
"format": "uint64",
"description": "The amount of the swap."
},
"reservation_ids": {
"type": "array",
"items": {
"type": "string",
"format": "byte"
},
"description": "The used reservations for the swap."
},
"sweep_tx_id": {
"type": "string",
"description": "The sweep transaction id of the swap."
}
}
},
"looprpcInstantOutQuoteResponse": { "looprpcInstantOutQuoteResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -847,53 +793,6 @@
} }
} }
}, },
"looprpcL402Token": {
"type": "object",
"properties": {
"base_macaroon": {
"type": "string",
"format": "byte",
"description": "The base macaroon that was baked by the auth server."
},
"payment_hash": {
"type": "string",
"format": "byte",
"description": "The payment hash of the payment that was paid to obtain the token."
},
"payment_preimage": {
"type": "string",
"format": "byte",
"description": "The preimage of the payment hash, knowledge of this is proof that the\npayment has been paid. If the preimage is set to all zeros, this means the\npayment is still pending and the token is not yet fully valid."
},
"amount_paid_msat": {
"type": "string",
"format": "int64",
"description": "The amount of millisatoshis that was paid to get the token."
},
"routing_fee_paid_msat": {
"type": "string",
"format": "int64",
"description": "The amount of millisatoshis paid in routing fee to pay for the token."
},
"time_created": {
"type": "string",
"format": "int64",
"description": "The creation time of the token as UNIX timestamp in seconds."
},
"expired": {
"type": "boolean",
"description": "Indicates whether the token is expired or still valid."
},
"storage_name": {
"type": "string",
"description": "Identifying attribute of this token in the store. Currently represents the\nfile name of the token where it's stored on the file system."
},
"id": {
"type": "string",
"description": "The l402 ID of the token."
}
}
},
"looprpcLiquidityParameters": { "looprpcLiquidityParameters": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -1057,18 +956,6 @@
], ],
"default": "UNKNOWN" "default": "UNKNOWN"
}, },
"looprpcListInstantOutsResponse": {
"type": "object",
"properties": {
"swaps": {
"type": "array",
"items": {
"$ref": "#/definitions/looprpcInstantOut"
},
"description": "The list of all currently known instant out swaps and their status."
}
}
},
"looprpcListReservationsResponse": { "looprpcListReservationsResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -1268,11 +1155,6 @@
"format": "byte" "format": "byte"
}, },
"description": "The reservations to use for the swap. If this field is set, loop will try\nto use the instant out flow using the given reservations. If the\nreservations are not sufficient, the swap will fail. The swap amount must\nbe equal to the sum of the amounts of the reservations." "description": "The reservations to use for the swap. If this field is set, loop will try\nto use the instant out flow using the given reservations. If the\nreservations are not sufficient, the swap will fail. The swap amount must\nbe equal to the sum of the amounts of the reservations."
},
"payment_timeout": {
"type": "integer",
"format": "int64",
"description": "The timeout in seconds to use for off-chain payments. Note that the swap\npayment is attempted multiple times where each attempt will set this value\nas the timeout for the payment."
} }
} }
}, },
@ -1306,6 +1188,53 @@
} }
} }
}, },
"looprpcLsatToken": {
"type": "object",
"properties": {
"base_macaroon": {
"type": "string",
"format": "byte",
"description": "The base macaroon that was baked by the auth server."
},
"payment_hash": {
"type": "string",
"format": "byte",
"description": "The payment hash of the payment that was paid to obtain the token."
},
"payment_preimage": {
"type": "string",
"format": "byte",
"description": "The preimage of the payment hash, knowledge of this is proof that the\npayment has been paid. If the preimage is set to all zeros, this means the\npayment is still pending and the token is not yet fully valid."
},
"amount_paid_msat": {
"type": "string",
"format": "int64",
"description": "The amount of millisatoshis that was paid to get the token."
},
"routing_fee_paid_msat": {
"type": "string",
"format": "int64",
"description": "The amount of millisatoshis paid in routing fee to pay for the token."
},
"time_created": {
"type": "string",
"format": "int64",
"description": "The creation time of the token as UNIX timestamp in seconds."
},
"expired": {
"type": "boolean",
"description": "Indicates whether the token is expired or still valid."
},
"storage_name": {
"type": "string",
"description": "Identifying attribute of this token in the store. Currently represents the\nfile name of the token where it's stored on the file system."
},
"id": {
"type": "string",
"description": "The l402 ID of the token."
}
}
},
"looprpcOutQuoteResponse": { "looprpcOutQuoteResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -1562,7 +1491,7 @@
"tokens": { "tokens": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/definitions/looprpcL402Token" "$ref": "#/definitions/looprpcLsatToken"
}, },
"description": "List of all tokens the daemon knows of, including old/expired tokens." "description": "List of all tokens the daemon knows of, including old/expired tokens."
} }

@ -26,10 +26,8 @@ http:
get: "/v1/loop/in/probe/{amt}" get: "/v1/loop/in/probe/{amt}"
- selector: looprpc.SwapClient.GetInfo - selector: looprpc.SwapClient.GetInfo
get: "/v1/loop/info" get: "/v1/loop/info"
- selector: looprpc.SwapClient.GetL402Tokens - selector: looprpc.SwapClient.GetLsatTokens
get: "/v1/l402/tokens" get: "/v1/lsat/tokens"
additional_bindings:
- get: "/v1/lsat/tokens"
- selector: looprpc.SwapClient.GetLiquidityParams - selector: looprpc.SwapClient.GetLiquidityParams
get: "/v1/liquidity/params" get: "/v1/liquidity/params"
- selector: looprpc.SwapClient.SetLiquidityParams - selector: looprpc.SwapClient.SetLiquidityParams

@ -19,89 +19,80 @@ const _ = grpc.SupportPackageIsVersion7
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type SwapClientClient interface { type SwapClientClient interface {
// loop: `out` // loop: `out`
// LoopOut initiates an loop out swap with the given parameters. The call //LoopOut initiates an loop out swap with the given parameters. The call
// returns after the swap has been set up with the swap server. From that //returns after the swap has been set up with the swap server. From that
// point onwards, progress can be tracked via the SwapStatus stream that is //point onwards, progress can be tracked via the SwapStatus stream that is
// returned from Monitor(). //returned from Monitor().
LoopOut(ctx context.Context, in *LoopOutRequest, opts ...grpc.CallOption) (*SwapResponse, error) LoopOut(ctx context.Context, in *LoopOutRequest, opts ...grpc.CallOption) (*SwapResponse, error)
// loop: `in` // loop: `in`
// LoopIn initiates a loop in swap with the given parameters. The call //LoopIn initiates a loop in swap with the given parameters. The call
// returns after the swap has been set up with the swap server. From that //returns after the swap has been set up with the swap server. From that
// point onwards, progress can be tracked via the SwapStatus stream //point onwards, progress can be tracked via the SwapStatus stream
// that is returned from Monitor(). //that is returned from Monitor().
LoopIn(ctx context.Context, in *LoopInRequest, opts ...grpc.CallOption) (*SwapResponse, error) LoopIn(ctx context.Context, in *LoopInRequest, opts ...grpc.CallOption) (*SwapResponse, error)
// loop: `monitor` // loop: `monitor`
// Monitor will return a stream of swap updates for currently active swaps. //Monitor will return a stream of swap updates for currently active swaps.
Monitor(ctx context.Context, in *MonitorRequest, opts ...grpc.CallOption) (SwapClient_MonitorClient, error) Monitor(ctx context.Context, in *MonitorRequest, opts ...grpc.CallOption) (SwapClient_MonitorClient, error)
// loop: `listswaps` // loop: `listswaps`
// ListSwaps returns a list of all currently known swaps and their current //ListSwaps returns a list of all currently known swaps and their current
// status. //status.
ListSwaps(ctx context.Context, in *ListSwapsRequest, opts ...grpc.CallOption) (*ListSwapsResponse, error) ListSwaps(ctx context.Context, in *ListSwapsRequest, opts ...grpc.CallOption) (*ListSwapsResponse, error)
// loop: `swapinfo` // loop: `swapinfo`
// SwapInfo returns all known details about a single swap. //SwapInfo returns all known details about a single swap.
SwapInfo(ctx context.Context, in *SwapInfoRequest, opts ...grpc.CallOption) (*SwapStatus, error) SwapInfo(ctx context.Context, in *SwapInfoRequest, opts ...grpc.CallOption) (*SwapStatus, error)
// loop: `abandonswap` // loop: `abandonswap`
// AbandonSwap allows the client to abandon a swap. //AbandonSwap allows the client to abandon a swap.
AbandonSwap(ctx context.Context, in *AbandonSwapRequest, opts ...grpc.CallOption) (*AbandonSwapResponse, error) AbandonSwap(ctx context.Context, in *AbandonSwapRequest, opts ...grpc.CallOption) (*AbandonSwapResponse, error)
// loop: `terms` // loop: `terms`
// LoopOutTerms returns the terms that the server enforces for a loop out swap. //LoopOutTerms returns the terms that the server enforces for a loop out swap.
LoopOutTerms(ctx context.Context, in *TermsRequest, opts ...grpc.CallOption) (*OutTermsResponse, error) LoopOutTerms(ctx context.Context, in *TermsRequest, opts ...grpc.CallOption) (*OutTermsResponse, error)
// loop: `quote` // loop: `quote`
// LoopOutQuote returns a quote for a loop out swap with the provided //LoopOutQuote returns a quote for a loop out swap with the provided
// parameters. //parameters.
LoopOutQuote(ctx context.Context, in *QuoteRequest, opts ...grpc.CallOption) (*OutQuoteResponse, error) LoopOutQuote(ctx context.Context, in *QuoteRequest, opts ...grpc.CallOption) (*OutQuoteResponse, error)
// loop: `terms` // loop: `terms`
// GetTerms returns the terms that the server enforces for swaps. //GetTerms returns the terms that the server enforces for swaps.
GetLoopInTerms(ctx context.Context, in *TermsRequest, opts ...grpc.CallOption) (*InTermsResponse, error) GetLoopInTerms(ctx context.Context, in *TermsRequest, opts ...grpc.CallOption) (*InTermsResponse, error)
// loop: `quote` // loop: `quote`
// GetQuote returns a quote for a swap with the provided parameters. //GetQuote returns a quote for a swap with the provided parameters.
GetLoopInQuote(ctx context.Context, in *QuoteRequest, opts ...grpc.CallOption) (*InQuoteResponse, error) GetLoopInQuote(ctx context.Context, in *QuoteRequest, opts ...grpc.CallOption) (*InQuoteResponse, error)
// Probe asks he sever to probe the route to us to have a better upfront //
// estimate about routing fees when loopin-in. //Probe asks he sever to probe the route to us to have a better upfront
//estimate about routing fees when loopin-in.
Probe(ctx context.Context, in *ProbeRequest, opts ...grpc.CallOption) (*ProbeResponse, error) Probe(ctx context.Context, in *ProbeRequest, opts ...grpc.CallOption) (*ProbeResponse, error)
// loop: `listauth` // loop: `listauth`
// GetL402Tokens returns all L402 tokens the daemon ever paid for. //GetLsatTokens returns all LSAT tokens the daemon ever paid for.
GetL402Tokens(ctx context.Context, in *TokensRequest, opts ...grpc.CallOption) (*TokensResponse, error)
// Deprecated: use GetL402Tokens.
// This API is provided to maintain backward compatibility with gRPC clients
// (e.g. `loop listauth`, Terminal Web, RTL).
// Type LsatToken used by GetLsatTokens in the past was renamed to L402Token,
// but this does not affect binary encoding, so we can use type L402Token here.
GetLsatTokens(ctx context.Context, in *TokensRequest, opts ...grpc.CallOption) (*TokensResponse, error) GetLsatTokens(ctx context.Context, in *TokensRequest, opts ...grpc.CallOption) (*TokensResponse, error)
// loop: `getinfo` // loop: `getinfo`
// GetInfo gets basic information about the loop daemon. //GetInfo gets basic information about the loop daemon.
GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error)
// loop: `getparams` // loop: `getparams`
// GetLiquidityParams gets the parameters that the daemon's liquidity manager //GetLiquidityParams gets the parameters that the daemon's liquidity manager
// is currently configured with. This may be nil if nothing is configured. //is currently configured with. This may be nil if nothing is configured.
// [EXPERIMENTAL]: endpoint is subject to change. //[EXPERIMENTAL]: endpoint is subject to change.
GetLiquidityParams(ctx context.Context, in *GetLiquidityParamsRequest, opts ...grpc.CallOption) (*LiquidityParameters, error) GetLiquidityParams(ctx context.Context, in *GetLiquidityParamsRequest, opts ...grpc.CallOption) (*LiquidityParameters, error)
// loop: `setparams` // loop: `setparams`
// SetLiquidityParams sets a new set of parameters for the daemon's liquidity //SetLiquidityParams sets a new set of parameters for the daemon's liquidity
// manager. Note that the full set of parameters must be provided, because //manager. Note that the full set of parameters must be provided, because
// this call fully overwrites our existing parameters. //this call fully overwrites our existing parameters.
// [EXPERIMENTAL]: endpoint is subject to change. //[EXPERIMENTAL]: endpoint is subject to change.
SetLiquidityParams(ctx context.Context, in *SetLiquidityParamsRequest, opts ...grpc.CallOption) (*SetLiquidityParamsResponse, error) SetLiquidityParams(ctx context.Context, in *SetLiquidityParamsRequest, opts ...grpc.CallOption) (*SetLiquidityParamsResponse, error)
// loop: `suggestswaps` // loop: `suggestswaps`
// SuggestSwaps returns a list of recommended swaps based on the current //SuggestSwaps returns a list of recommended swaps based on the current
// state of your node's channels and it's liquidity manager parameters. //state of your node's channels and it's liquidity manager parameters.
// Note that only loop out suggestions are currently supported. //Note that only loop out suggestions are currently supported.
// [EXPERIMENTAL]: endpoint is subject to change. //[EXPERIMENTAL]: endpoint is subject to change.
SuggestSwaps(ctx context.Context, in *SuggestSwapsRequest, opts ...grpc.CallOption) (*SuggestSwapsResponse, error) SuggestSwaps(ctx context.Context, in *SuggestSwapsRequest, opts ...grpc.CallOption) (*SuggestSwapsResponse, error)
// loop: `listreservations` // loop: `listreservations`
// ListReservations returns a list of all reservations the server opened to us. //ListReservations returns a list of all reservations the server opened to us.
ListReservations(ctx context.Context, in *ListReservationsRequest, opts ...grpc.CallOption) (*ListReservationsResponse, error) ListReservations(ctx context.Context, in *ListReservationsRequest, opts ...grpc.CallOption) (*ListReservationsResponse, error)
// loop: `instantout` // loop: `instantout`
// InstantOut initiates an instant out swap with the given parameters. //InstantOut initiates an instant out swap with the given parameters.
InstantOut(ctx context.Context, in *InstantOutRequest, opts ...grpc.CallOption) (*InstantOutResponse, error) InstantOut(ctx context.Context, in *InstantOutRequest, opts ...grpc.CallOption) (*InstantOutResponse, error)
// loop: `instantoutquote` // loop: `instantoutquote`
// InstantOutQuote returns a quote for an instant out swap with the provided //InstantOutQuote returns a quote for an instant out swap with the provided
// parameters. //parameters.
InstantOutQuote(ctx context.Context, in *InstantOutQuoteRequest, opts ...grpc.CallOption) (*InstantOutQuoteResponse, error) InstantOutQuote(ctx context.Context, in *InstantOutQuoteRequest, opts ...grpc.CallOption) (*InstantOutQuoteResponse, error)
// loop: `listinstantouts`
// ListInstantOuts returns a list of all currently known instant out swaps and
// their current status.
ListInstantOuts(ctx context.Context, in *ListInstantOutsRequest, opts ...grpc.CallOption) (*ListInstantOutsResponse, error)
} }
type swapClientClient struct { type swapClientClient struct {
@ -234,15 +225,6 @@ func (c *swapClientClient) Probe(ctx context.Context, in *ProbeRequest, opts ...
return out, nil return out, nil
} }
func (c *swapClientClient) GetL402Tokens(ctx context.Context, in *TokensRequest, opts ...grpc.CallOption) (*TokensResponse, error) {
out := new(TokensResponse)
err := c.cc.Invoke(ctx, "/looprpc.SwapClient/GetL402Tokens", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *swapClientClient) GetLsatTokens(ctx context.Context, in *TokensRequest, opts ...grpc.CallOption) (*TokensResponse, error) { func (c *swapClientClient) GetLsatTokens(ctx context.Context, in *TokensRequest, opts ...grpc.CallOption) (*TokensResponse, error) {
out := new(TokensResponse) out := new(TokensResponse)
err := c.cc.Invoke(ctx, "/looprpc.SwapClient/GetLsatTokens", in, out, opts...) err := c.cc.Invoke(ctx, "/looprpc.SwapClient/GetLsatTokens", in, out, opts...)
@ -315,103 +297,85 @@ func (c *swapClientClient) InstantOutQuote(ctx context.Context, in *InstantOutQu
return out, nil return out, nil
} }
func (c *swapClientClient) ListInstantOuts(ctx context.Context, in *ListInstantOutsRequest, opts ...grpc.CallOption) (*ListInstantOutsResponse, error) {
out := new(ListInstantOutsResponse)
err := c.cc.Invoke(ctx, "/looprpc.SwapClient/ListInstantOuts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// SwapClientServer is the server API for SwapClient service. // SwapClientServer is the server API for SwapClient service.
// All implementations must embed UnimplementedSwapClientServer // All implementations must embed UnimplementedSwapClientServer
// for forward compatibility // for forward compatibility
type SwapClientServer interface { type SwapClientServer interface {
// loop: `out` // loop: `out`
// LoopOut initiates an loop out swap with the given parameters. The call //LoopOut initiates an loop out swap with the given parameters. The call
// returns after the swap has been set up with the swap server. From that //returns after the swap has been set up with the swap server. From that
// point onwards, progress can be tracked via the SwapStatus stream that is //point onwards, progress can be tracked via the SwapStatus stream that is
// returned from Monitor(). //returned from Monitor().
LoopOut(context.Context, *LoopOutRequest) (*SwapResponse, error) LoopOut(context.Context, *LoopOutRequest) (*SwapResponse, error)
// loop: `in` // loop: `in`
// LoopIn initiates a loop in swap with the given parameters. The call //LoopIn initiates a loop in swap with the given parameters. The call
// returns after the swap has been set up with the swap server. From that //returns after the swap has been set up with the swap server. From that
// point onwards, progress can be tracked via the SwapStatus stream //point onwards, progress can be tracked via the SwapStatus stream
// that is returned from Monitor(). //that is returned from Monitor().
LoopIn(context.Context, *LoopInRequest) (*SwapResponse, error) LoopIn(context.Context, *LoopInRequest) (*SwapResponse, error)
// loop: `monitor` // loop: `monitor`
// Monitor will return a stream of swap updates for currently active swaps. //Monitor will return a stream of swap updates for currently active swaps.
Monitor(*MonitorRequest, SwapClient_MonitorServer) error Monitor(*MonitorRequest, SwapClient_MonitorServer) error
// loop: `listswaps` // loop: `listswaps`
// ListSwaps returns a list of all currently known swaps and their current //ListSwaps returns a list of all currently known swaps and their current
// status. //status.
ListSwaps(context.Context, *ListSwapsRequest) (*ListSwapsResponse, error) ListSwaps(context.Context, *ListSwapsRequest) (*ListSwapsResponse, error)
// loop: `swapinfo` // loop: `swapinfo`
// SwapInfo returns all known details about a single swap. //SwapInfo returns all known details about a single swap.
SwapInfo(context.Context, *SwapInfoRequest) (*SwapStatus, error) SwapInfo(context.Context, *SwapInfoRequest) (*SwapStatus, error)
// loop: `abandonswap` // loop: `abandonswap`
// AbandonSwap allows the client to abandon a swap. //AbandonSwap allows the client to abandon a swap.
AbandonSwap(context.Context, *AbandonSwapRequest) (*AbandonSwapResponse, error) AbandonSwap(context.Context, *AbandonSwapRequest) (*AbandonSwapResponse, error)
// loop: `terms` // loop: `terms`
// LoopOutTerms returns the terms that the server enforces for a loop out swap. //LoopOutTerms returns the terms that the server enforces for a loop out swap.
LoopOutTerms(context.Context, *TermsRequest) (*OutTermsResponse, error) LoopOutTerms(context.Context, *TermsRequest) (*OutTermsResponse, error)
// loop: `quote` // loop: `quote`
// LoopOutQuote returns a quote for a loop out swap with the provided //LoopOutQuote returns a quote for a loop out swap with the provided
// parameters. //parameters.
LoopOutQuote(context.Context, *QuoteRequest) (*OutQuoteResponse, error) LoopOutQuote(context.Context, *QuoteRequest) (*OutQuoteResponse, error)
// loop: `terms` // loop: `terms`
// GetTerms returns the terms that the server enforces for swaps. //GetTerms returns the terms that the server enforces for swaps.
GetLoopInTerms(context.Context, *TermsRequest) (*InTermsResponse, error) GetLoopInTerms(context.Context, *TermsRequest) (*InTermsResponse, error)
// loop: `quote` // loop: `quote`
// GetQuote returns a quote for a swap with the provided parameters. //GetQuote returns a quote for a swap with the provided parameters.
GetLoopInQuote(context.Context, *QuoteRequest) (*InQuoteResponse, error) GetLoopInQuote(context.Context, *QuoteRequest) (*InQuoteResponse, error)
// Probe asks he sever to probe the route to us to have a better upfront //
// estimate about routing fees when loopin-in. //Probe asks he sever to probe the route to us to have a better upfront
//estimate about routing fees when loopin-in.
Probe(context.Context, *ProbeRequest) (*ProbeResponse, error) Probe(context.Context, *ProbeRequest) (*ProbeResponse, error)
// loop: `listauth` // loop: `listauth`
// GetL402Tokens returns all L402 tokens the daemon ever paid for. //GetLsatTokens returns all LSAT tokens the daemon ever paid for.
GetL402Tokens(context.Context, *TokensRequest) (*TokensResponse, error)
// Deprecated: use GetL402Tokens.
// This API is provided to maintain backward compatibility with gRPC clients
// (e.g. `loop listauth`, Terminal Web, RTL).
// Type LsatToken used by GetLsatTokens in the past was renamed to L402Token,
// but this does not affect binary encoding, so we can use type L402Token here.
GetLsatTokens(context.Context, *TokensRequest) (*TokensResponse, error) GetLsatTokens(context.Context, *TokensRequest) (*TokensResponse, error)
// loop: `getinfo` // loop: `getinfo`
// GetInfo gets basic information about the loop daemon. //GetInfo gets basic information about the loop daemon.
GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error)
// loop: `getparams` // loop: `getparams`
// GetLiquidityParams gets the parameters that the daemon's liquidity manager //GetLiquidityParams gets the parameters that the daemon's liquidity manager
// is currently configured with. This may be nil if nothing is configured. //is currently configured with. This may be nil if nothing is configured.
// [EXPERIMENTAL]: endpoint is subject to change. //[EXPERIMENTAL]: endpoint is subject to change.
GetLiquidityParams(context.Context, *GetLiquidityParamsRequest) (*LiquidityParameters, error) GetLiquidityParams(context.Context, *GetLiquidityParamsRequest) (*LiquidityParameters, error)
// loop: `setparams` // loop: `setparams`
// SetLiquidityParams sets a new set of parameters for the daemon's liquidity //SetLiquidityParams sets a new set of parameters for the daemon's liquidity
// manager. Note that the full set of parameters must be provided, because //manager. Note that the full set of parameters must be provided, because
// this call fully overwrites our existing parameters. //this call fully overwrites our existing parameters.
// [EXPERIMENTAL]: endpoint is subject to change. //[EXPERIMENTAL]: endpoint is subject to change.
SetLiquidityParams(context.Context, *SetLiquidityParamsRequest) (*SetLiquidityParamsResponse, error) SetLiquidityParams(context.Context, *SetLiquidityParamsRequest) (*SetLiquidityParamsResponse, error)
// loop: `suggestswaps` // loop: `suggestswaps`
// SuggestSwaps returns a list of recommended swaps based on the current //SuggestSwaps returns a list of recommended swaps based on the current
// state of your node's channels and it's liquidity manager parameters. //state of your node's channels and it's liquidity manager parameters.
// Note that only loop out suggestions are currently supported. //Note that only loop out suggestions are currently supported.
// [EXPERIMENTAL]: endpoint is subject to change. //[EXPERIMENTAL]: endpoint is subject to change.
SuggestSwaps(context.Context, *SuggestSwapsRequest) (*SuggestSwapsResponse, error) SuggestSwaps(context.Context, *SuggestSwapsRequest) (*SuggestSwapsResponse, error)
// loop: `listreservations` // loop: `listreservations`
// ListReservations returns a list of all reservations the server opened to us. //ListReservations returns a list of all reservations the server opened to us.
ListReservations(context.Context, *ListReservationsRequest) (*ListReservationsResponse, error) ListReservations(context.Context, *ListReservationsRequest) (*ListReservationsResponse, error)
// loop: `instantout` // loop: `instantout`
// InstantOut initiates an instant out swap with the given parameters. //InstantOut initiates an instant out swap with the given parameters.
InstantOut(context.Context, *InstantOutRequest) (*InstantOutResponse, error) InstantOut(context.Context, *InstantOutRequest) (*InstantOutResponse, error)
// loop: `instantoutquote` // loop: `instantoutquote`
// InstantOutQuote returns a quote for an instant out swap with the provided //InstantOutQuote returns a quote for an instant out swap with the provided
// parameters. //parameters.
InstantOutQuote(context.Context, *InstantOutQuoteRequest) (*InstantOutQuoteResponse, error) InstantOutQuote(context.Context, *InstantOutQuoteRequest) (*InstantOutQuoteResponse, error)
// loop: `listinstantouts`
// ListInstantOuts returns a list of all currently known instant out swaps and
// their current status.
ListInstantOuts(context.Context, *ListInstantOutsRequest) (*ListInstantOutsResponse, error)
mustEmbedUnimplementedSwapClientServer() mustEmbedUnimplementedSwapClientServer()
} }
@ -452,9 +416,6 @@ func (UnimplementedSwapClientServer) GetLoopInQuote(context.Context, *QuoteReque
func (UnimplementedSwapClientServer) Probe(context.Context, *ProbeRequest) (*ProbeResponse, error) { func (UnimplementedSwapClientServer) Probe(context.Context, *ProbeRequest) (*ProbeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Probe not implemented") return nil, status.Errorf(codes.Unimplemented, "method Probe not implemented")
} }
func (UnimplementedSwapClientServer) GetL402Tokens(context.Context, *TokensRequest) (*TokensResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetL402Tokens not implemented")
}
func (UnimplementedSwapClientServer) GetLsatTokens(context.Context, *TokensRequest) (*TokensResponse, error) { func (UnimplementedSwapClientServer) GetLsatTokens(context.Context, *TokensRequest) (*TokensResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetLsatTokens not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetLsatTokens not implemented")
} }
@ -479,9 +440,6 @@ func (UnimplementedSwapClientServer) InstantOut(context.Context, *InstantOutRequ
func (UnimplementedSwapClientServer) InstantOutQuote(context.Context, *InstantOutQuoteRequest) (*InstantOutQuoteResponse, error) { func (UnimplementedSwapClientServer) InstantOutQuote(context.Context, *InstantOutQuoteRequest) (*InstantOutQuoteResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method InstantOutQuote not implemented") return nil, status.Errorf(codes.Unimplemented, "method InstantOutQuote not implemented")
} }
func (UnimplementedSwapClientServer) ListInstantOuts(context.Context, *ListInstantOutsRequest) (*ListInstantOutsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListInstantOuts not implemented")
}
func (UnimplementedSwapClientServer) mustEmbedUnimplementedSwapClientServer() {} func (UnimplementedSwapClientServer) mustEmbedUnimplementedSwapClientServer() {}
// UnsafeSwapClientServer may be embedded to opt out of forward compatibility for this service. // UnsafeSwapClientServer may be embedded to opt out of forward compatibility for this service.
@ -696,24 +654,6 @@ func _SwapClient_Probe_Handler(srv interface{}, ctx context.Context, dec func(in
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _SwapClient_GetL402Tokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TokensRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SwapClientServer).GetL402Tokens(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/looprpc.SwapClient/GetL402Tokens",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SwapClientServer).GetL402Tokens(ctx, req.(*TokensRequest))
}
return interceptor(ctx, in, info, handler)
}
func _SwapClient_GetLsatTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _SwapClient_GetLsatTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TokensRequest) in := new(TokensRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@ -858,24 +798,6 @@ func _SwapClient_InstantOutQuote_Handler(srv interface{}, ctx context.Context, d
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _SwapClient_ListInstantOuts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListInstantOutsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SwapClientServer).ListInstantOuts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/looprpc.SwapClient/ListInstantOuts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SwapClientServer).ListInstantOuts(ctx, req.(*ListInstantOutsRequest))
}
return interceptor(ctx, in, info, handler)
}
// SwapClient_ServiceDesc is the grpc.ServiceDesc for SwapClient service. // SwapClient_ServiceDesc is the grpc.ServiceDesc for SwapClient service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@ -923,10 +845,6 @@ var SwapClient_ServiceDesc = grpc.ServiceDesc{
MethodName: "Probe", MethodName: "Probe",
Handler: _SwapClient_Probe_Handler, Handler: _SwapClient_Probe_Handler,
}, },
{
MethodName: "GetL402Tokens",
Handler: _SwapClient_GetL402Tokens_Handler,
},
{ {
MethodName: "GetLsatTokens", MethodName: "GetLsatTokens",
Handler: _SwapClient_GetLsatTokens_Handler, Handler: _SwapClient_GetLsatTokens_Handler,
@ -959,10 +877,6 @@ var SwapClient_ServiceDesc = grpc.ServiceDesc{
MethodName: "InstantOutQuote", MethodName: "InstantOutQuote",
Handler: _SwapClient_InstantOutQuote_Handler, Handler: _SwapClient_InstantOutQuote_Handler,
}, },
{
MethodName: "ListInstantOuts",
Handler: _SwapClient_ListInstantOuts_Handler,
},
}, },
Streams: []grpc.StreamDesc{ Streams: []grpc.StreamDesc{
{ {

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.33.0 // protoc-gen-go v1.31.0
// protoc v3.21.12 // protoc v3.6.1
// source: debug.proto // source: debug.proto
package looprpc package looprpc

@ -18,9 +18,10 @@ const _ = grpc.SupportPackageIsVersion7
// //
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type DebugClient interface { type DebugClient interface {
// ForceAutoLoop is intended for *testing purposes only* and will not work on //
// mainnet. This endpoint ticks our autoloop timer, triggering automated //ForceAutoLoop is intended for *testing purposes only* and will not work on
// dispatch of a swap if one is suggested. //mainnet. This endpoint ticks our autoloop timer, triggering automated
//dispatch of a swap if one is suggested.
ForceAutoLoop(ctx context.Context, in *ForceAutoLoopRequest, opts ...grpc.CallOption) (*ForceAutoLoopResponse, error) ForceAutoLoop(ctx context.Context, in *ForceAutoLoopRequest, opts ...grpc.CallOption) (*ForceAutoLoopResponse, error)
} }
@ -45,9 +46,10 @@ func (c *debugClient) ForceAutoLoop(ctx context.Context, in *ForceAutoLoopReques
// All implementations must embed UnimplementedDebugServer // All implementations must embed UnimplementedDebugServer
// for forward compatibility // for forward compatibility
type DebugServer interface { type DebugServer interface {
// ForceAutoLoop is intended for *testing purposes only* and will not work on //
// mainnet. This endpoint ticks our autoloop timer, triggering automated //ForceAutoLoop is intended for *testing purposes only* and will not work on
// dispatch of a swap if one is suggested. //mainnet. This endpoint ticks our autoloop timer, triggering automated
//dispatch of a swap if one is suggested.
ForceAutoLoop(context.Context, *ForceAutoLoopRequest) (*ForceAutoLoopResponse, error) ForceAutoLoop(context.Context, *ForceAutoLoopRequest) (*ForceAutoLoopResponse, error)
mustEmbedUnimplementedDebugServer() mustEmbedUnimplementedDebugServer()
} }

@ -313,31 +313,6 @@ func RegisterSwapClientJSONCallbacks(registry map[string]func(ctx context.Contex
callback(string(respBytes), nil) callback(string(respBytes), nil)
} }
registry["looprpc.SwapClient.GetL402Tokens"] = func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
req := &TokensRequest{}
err := marshaler.Unmarshal([]byte(reqJSON), req)
if err != nil {
callback("", err)
return
}
client := NewSwapClientClient(conn)
resp, err := client.GetL402Tokens(ctx, req)
if err != nil {
callback("", err)
return
}
respBytes, err := marshaler.Marshal(resp)
if err != nil {
callback("", err)
return
}
callback(string(respBytes), nil)
}
registry["looprpc.SwapClient.GetLsatTokens"] = func(ctx context.Context, registry["looprpc.SwapClient.GetLsatTokens"] = func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
@ -537,29 +512,4 @@ func RegisterSwapClientJSONCallbacks(registry map[string]func(ctx context.Contex
} }
callback(string(respBytes), nil) callback(string(respBytes), nil)
} }
registry["looprpc.SwapClient.ListInstantOuts"] = func(ctx context.Context,
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
req := &ListInstantOutsRequest{}
err := marshaler.Unmarshal([]byte(reqJSON), req)
if err != nil {
callback("", err)
return
}
client := NewSwapClientClient(conn)
resp, err := client.ListInstantOuts(ctx, req)
if err != nil {
callback("", err)
return
}
respBytes, err := marshaler.Marshal(resp)
if err != nil {
callback("", err)
return
}
callback(string(respBytes), nil)
}
} }

@ -130,7 +130,7 @@ services:
- "loopd" - "loopd"
- "--network=regtest" - "--network=regtest"
- "--debuglevel=debug" - "--debuglevel=debug"
- "--server.host=loopserver:11009" - "--server.host=loopclient:11009"
- "--server.notls" - "--server.notls"
- "--lnd.host=lndclient:10009" - "--lnd.host=lndclient:10009"
- "--lnd.macaroonpath=/root/.lnd/data/chain/bitcoin/regtest/admin.macaroon" - "--lnd.macaroonpath=/root/.lnd/data/chain/bitcoin/regtest/admin.macaroon"
@ -142,4 +142,4 @@ networks:
volumes: volumes:
bitcoind: bitcoind:
lndserver: lndserver:
lndclient: lndclient:

@ -513,7 +513,7 @@ func (r *lowToHighRoutingPlugin) BeforePayment(ctx context.Context,
// Calculate the limit until we'll disable edges. The way we calculate // Calculate the limit until we'll disable edges. The way we calculate
// this limit is that we take the minimum and maximum fee peers which // this limit is that we take the minimum and maximum fee peers which
// define our fee range. Within this fee range we'll scale linearly // define our fee range. Within this fee range we'll scale linearly
// where each step equals to the range divided by maxAttempts. // where each step euqals to the range divided by maxAttempts.
minFee := r.nodesByMaxFee[0].fee minFee := r.nodesByMaxFee[0].fee
maxFee := r.nodesByMaxFee[len(r.nodesByMaxFee)-1].fee maxFee := r.nodesByMaxFee[len(r.nodesByMaxFee)-1].fee
limit := minFee + limit := minFee +

@ -86,11 +86,11 @@
; Maximum cost in satoshis that loopd is going to pay for an L402 token ; Maximum cost in satoshis that loopd is going to pay for an L402 token
; automatically. Does not include routing fees. ; automatically. Does not include routing fees.
; maxl402cost=1000 ; maxlsatcost=1000
; Maximum routing fee in satoshis that we are willing to pay while paying for an ; Maximum routing fee in satoshis that we are willing to pay while paying for an
; L402 token. ; L402 token.
; maxl402fee=10 ; maxlsatfee=10
; The maximum number of payment parts that may be used for a loop out swap. ; The maximum number of payment parts that may be used for a loop out swap.
; loopoutmaxparts=5 ; loopoutmaxparts=5

@ -16,5 +16,5 @@ docker run \
-e UID=$UID \ -e UID=$UID \
-v "$DIR/../:/build" \ -v "$DIR/../:/build" \
-w /build \ -w /build \
sqlc/sqlc:1.25.0 generate kjconroy/sqlc:1.17.2 generate

@ -42,7 +42,6 @@ type serverMock struct {
swapInvoice string swapInvoice string
swapHash lntypes.Hash swapHash lntypes.Hash
prepayHash lntypes.Hash
// preimagePush is a channel that preimage pushes are sent into. // preimagePush is a channel that preimage pushes are sent into.
preimagePush chan lntypes.Preimage preimagePush chan lntypes.Preimage
@ -82,17 +81,13 @@ func (s *serverMock) NewLoopOutSwap(_ context.Context, swapHash lntypes.Hash,
return nil, errors.New("unexpected test swap amount") return nil, errors.New("unexpected test swap amount")
} }
s.swapHash = swapHash
swapPayReqString, err := getInvoice(swapHash, s.swapInvoiceAmt, swapPayReqString, err := getInvoice(swapHash, s.swapInvoiceAmt,
swapInvoiceDesc) swapInvoiceDesc)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Set the prepay hash to be different from the swap hash. prePayReqString, err := getInvoice(swapHash, s.prepayInvoiceAmt,
s.prepayHash = swapHash
s.prepayHash[0] ^= 1
prePayReqString, err := getInvoice(s.prepayHash, s.prepayInvoiceAmt,
prepayInvoiceDesc) prepayInvoiceDesc)
if err != nil { if err != nil {
return nil, err return nil, err

@ -1,4 +1,4 @@
package version package staticaddr
import ( import (
looprpc "github.com/lightninglabs/loop/swapserverrpc" looprpc "github.com/lightninglabs/loop/swapserverrpc"

@ -41,7 +41,7 @@ const (
HtlcV3 HtlcV3
) )
// HtlcScript defines an interface for the different HTLC implementations. // htlcScript defines an interface for the different HTLC implementations.
type HtlcScript interface { type HtlcScript interface {
// genSuccessWitness returns the success script to spend this htlc with // genSuccessWitness returns the success script to spend this htlc with
// the preimage. // the preimage.
@ -63,11 +63,11 @@ type HtlcScript interface {
// MaxSuccessWitnessSize returns the maximum witness size for the // MaxSuccessWitnessSize returns the maximum witness size for the
// success case witness. // success case witness.
MaxSuccessWitnessSize() lntypes.WeightUnit MaxSuccessWitnessSize() int
// MaxTimeoutWitnessSize returns the maximum witness size for the // MaxTimeoutWitnessSize returns the maximum witness size for the
// timeout case witness. // timeout case witness.
MaxTimeoutWitnessSize() lntypes.WeightUnit MaxTimeoutWitnessSize() int
// TimeoutScript returns the redeem script required to unlock the htlc // TimeoutScript returns the redeem script required to unlock the htlc
// after timeout. // after timeout.
@ -436,7 +436,7 @@ func (h *HtlcScriptV2) SuccessScript() []byte {
} }
// MaxSuccessWitnessSize returns maximum success witness size. // MaxSuccessWitnessSize returns maximum success witness size.
func (h *HtlcScriptV2) MaxSuccessWitnessSize() lntypes.WeightUnit { func (h *HtlcScriptV2) MaxSuccessWitnessSize() int {
// Calculate maximum success witness size // Calculate maximum success witness size
// //
// - number_of_witness_elements: 1 byte // - number_of_witness_elements: 1 byte
@ -446,11 +446,11 @@ func (h *HtlcScriptV2) MaxSuccessWitnessSize() lntypes.WeightUnit {
// - preimage: 32 bytes // - preimage: 32 bytes
// - witness_script_length: 1 byte // - witness_script_length: 1 byte
// - witness_script: len(script) bytes // - witness_script: len(script) bytes
return lntypes.WeightUnit(1 + 1 + 73 + 1 + 32 + 1 + len(h.script)) return 1 + 1 + 73 + 1 + 32 + 1 + len(h.script)
} }
// MaxTimeoutWitnessSize returns maximum timeout witness size. // MaxTimeoutWitnessSize returns maximum timeout witness size.
func (h *HtlcScriptV2) MaxTimeoutWitnessSize() lntypes.WeightUnit { func (h *HtlcScriptV2) MaxTimeoutWitnessSize() int {
// Calculate maximum timeout witness size // Calculate maximum timeout witness size
// //
// - number_of_witness_elements: 1 byte // - number_of_witness_elements: 1 byte
@ -461,7 +461,7 @@ func (h *HtlcScriptV2) MaxTimeoutWitnessSize() lntypes.WeightUnit {
// - zero: 1 byte // - zero: 1 byte
// - witness_script_length: 1 byte // - witness_script_length: 1 byte
// - witness_script: len(script) bytes // - witness_script: len(script) bytes
return lntypes.WeightUnit(1 + 1 + 73 + 1 + 33 + 1 + 1 + len(h.script)) return 1 + 1 + 73 + 1 + 33 + 1 + 1 + len(h.script)
} }
// SuccessSequence returns the sequence to spend this htlc in the success case. // SuccessSequence returns the sequence to spend this htlc in the success case.
@ -735,7 +735,7 @@ func (h *HtlcScriptV3) SuccessScript() []byte {
// MaxSuccessWitnessSize returns the maximum witness size for the // MaxSuccessWitnessSize returns the maximum witness size for the
// success case witness. // success case witness.
func (h *HtlcScriptV3) MaxSuccessWitnessSize() lntypes.WeightUnit { func (h *HtlcScriptV3) MaxSuccessWitnessSize() int {
// Calculate maximum success witness size // Calculate maximum success witness size
// //
// - number_of_witness_elements: 1 byte // - number_of_witness_elements: 1 byte
@ -755,7 +755,7 @@ func (h *HtlcScriptV3) MaxSuccessWitnessSize() lntypes.WeightUnit {
// MaxTimeoutWitnessSize returns the maximum witness size for the // MaxTimeoutWitnessSize returns the maximum witness size for the
// timeout case witness. // timeout case witness.
func (h *HtlcScriptV3) MaxTimeoutWitnessSize() lntypes.WeightUnit { func (h *HtlcScriptV3) MaxTimeoutWitnessSize() int {
// Calculate maximum timeout witness size // Calculate maximum timeout witness size
// //
// - number_of_witness_elements: 1 byte // - number_of_witness_elements: 1 byte
@ -768,7 +768,7 @@ func (h *HtlcScriptV3) MaxTimeoutWitnessSize() lntypes.WeightUnit {
// - leafVersionAndParity: 1 // - leafVersionAndParity: 1
// - internalPubkey: 32 // - internalPubkey: 32
// - proof: 32 // - proof: 32
return lntypes.WeightUnit(1 + 1 + 64 + 1 + 36 + 1 + 65) return 1 + 1 + 64 + 1 + 36 + 1 + 65
} }
// SuccessSequence returns the sequence to spend this htlc in the // SuccessSequence returns the sequence to spend this htlc in the

@ -15,7 +15,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/aperture/lsat"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
looprpc "github.com/lightninglabs/loop/swapserverrpc" looprpc "github.com/lightninglabs/loop/swapserverrpc"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
@ -161,14 +161,14 @@ func (s *grpcSwapServerClient) stop() {
var _ swapServerClient = (*grpcSwapServerClient)(nil) var _ swapServerClient = (*grpcSwapServerClient)(nil)
func newSwapServerClient(cfg *ClientConfig, l402Store l402.Store) ( func newSwapServerClient(cfg *ClientConfig, lsatStore lsat.Store) (
*grpcSwapServerClient, error) { *grpcSwapServerClient, error) {
// Create the server connection with the interceptor that will handle // Create the server connection with the interceptor that will handle
// the L402 protocol for us. // the LSAT protocol for us.
clientInterceptor := l402.NewInterceptor( clientInterceptor := lsat.NewInterceptor(
cfg.Lnd, l402Store, serverRPCTimeout, cfg.MaxL402Cost, cfg.Lnd, lsatStore, serverRPCTimeout, cfg.MaxLsatCost,
cfg.MaxL402Fee, false, cfg.MaxLsatFee, false,
) )
serverConn, err := getSwapServerConn( serverConn, err := getSwapServerConn(
cfg.ServerAddress, cfg.ProxyAddress, cfg.SwapServerNoTLS, cfg.ServerAddress, cfg.ProxyAddress, cfg.SwapServerNoTLS,
@ -636,7 +636,7 @@ const (
paymentTypeInvoice paymentTypeInvoice
) )
// routeCancelMetadata contains cancellation information for swaps that are // routeCancelMetadata contains cancelation information for swaps that are
// canceled because the client could not route off-chain to the server. // canceled because the client could not route off-chain to the server.
type routeCancelMetadata struct { type routeCancelMetadata struct {
// paymentType is the type of payment that failed. // paymentType is the type of payment that failed.
@ -895,7 +895,7 @@ func rpcRouteCancel(details *outCancelDetails) (
// proxyAddr indicates that a SOCKS proxy found at the address should be used to // proxyAddr indicates that a SOCKS proxy found at the address should be used to
// establish the connection. // establish the connection.
func getSwapServerConn(address, proxyAddress string, insecure bool, func getSwapServerConn(address, proxyAddress string, insecure bool,
tlsPath string, interceptor *l402.ClientInterceptor) (*grpc.ClientConn, tlsPath string, interceptor *lsat.ClientInterceptor) (*grpc.ClientConn,
error) { error) {
// Create a dial options array. // Create a dial options array.

@ -1,9 +1,9 @@
FROM golang:1.21.9-bookworm FROM golang:1.16.3-buster
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
git \ git \
protobuf-compiler='3.21.12*' \ protobuf-compiler='3.6*' \
clang-format='1:14.0*' clang-format='1:7.0*'
# We don't want any default values for these variables to make sure they're # We don't want any default values for these variables to make sure they're
# explicitly provided by parsing the go.mod file. Otherwise we might forget to # explicitly provided by parsing the go.mod file. Otherwise we might forget to
@ -11,15 +11,11 @@ RUN apt-get update && apt-get install -y \
ARG PROTOBUF_VERSION ARG PROTOBUF_VERSION
ENV PROTOC_GEN_GO_GRPC_VERSION="v1.1.0" ENV PROTOC_GEN_GO_GRPC_VERSION="v1.1.0"
ENV GOCACHE=/tmp/build/.cache
ENV GOMODCACHE=/tmp/build/.modcache
RUN cd /tmp \ RUN cd /tmp \
&& mkdir -p /tmp/build/.cache \ && export GO111MODULE=on \
&& mkdir -p /tmp/build/.modcache \ && go get google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOBUF_VERSION} \
&& go install google.golang.org/protobuf/cmd/protoc-gen-go@${PROTOBUF_VERSION} \ && go get google.golang.org/grpc/cmd/protoc-gen-go-grpc@${PROTOC_GEN_GO_GRPC_VERSION}
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@${PROTOC_GEN_GO_GRPC_VERSION} \
&& chmod -R 777 /tmp/build/
WORKDIR /build WORKDIR /build

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.30.0 // protoc-gen-go v1.30.0
// protoc v3.21.12 // protoc v3.6.1
// source: common.proto // source: common.proto
// We can't change this to swapserverrpc, it would be a breaking change because // We can't change this to swapserverrpc, it would be a breaking change because
@ -36,8 +36,9 @@ type HopHint struct {
ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"` ChanId uint64 `protobuf:"varint,2,opt,name=chan_id,json=chanId,proto3" json:"chan_id,omitempty"`
// The base fee of the channel denominated in millisatoshis. // The base fee of the channel denominated in millisatoshis.
FeeBaseMsat uint32 `protobuf:"varint,3,opt,name=fee_base_msat,json=feeBaseMsat,proto3" json:"fee_base_msat,omitempty"` FeeBaseMsat uint32 `protobuf:"varint,3,opt,name=fee_base_msat,json=feeBaseMsat,proto3" json:"fee_base_msat,omitempty"`
// The fee rate of the channel for sending one satoshi across it denominated in //
// millionths of a satoshi. //The fee rate of the channel for sending one satoshi across it denominated in
//millionths of a satoshi.
FeeProportionalMillionths uint32 `protobuf:"varint,4,opt,name=fee_proportional_millionths,json=feeProportionalMillionths,proto3" json:"fee_proportional_millionths,omitempty"` FeeProportionalMillionths uint32 `protobuf:"varint,4,opt,name=fee_proportional_millionths,json=feeProportionalMillionths,proto3" json:"fee_proportional_millionths,omitempty"`
// The time-lock delta of the channel. // The time-lock delta of the channel.
CltvExpiryDelta uint32 `protobuf:"varint,5,opt,name=cltv_expiry_delta,json=cltvExpiryDelta,proto3" json:"cltv_expiry_delta,omitempty"` CltvExpiryDelta uint32 `protobuf:"varint,5,opt,name=cltv_expiry_delta,json=cltvExpiryDelta,proto3" json:"cltv_expiry_delta,omitempty"`
@ -115,8 +116,9 @@ type RouteHint struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// A list of hop hints that when chained together can assist in reaching a //
// specific destination. //A list of hop hints that when chained together can assist in reaching a
//specific destination.
HopHints []*HopHint `protobuf:"bytes,1,rep,name=hop_hints,json=hopHints,proto3" json:"hop_hints,omitempty"` HopHints []*HopHint `protobuf:"bytes,1,rep,name=hop_hints,json=hopHints,proto3" json:"hop_hints,omitempty"`
} }

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.30.0 // protoc-gen-go v1.30.0
// protoc v3.21.12 // protoc v3.6.1
// source: instantout.proto // source: instantout.proto
// We can't change this to swapserverrpc, it would be a breaking change because // We can't change this to swapserverrpc, it would be a breaking change because

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.30.0 // protoc-gen-go v1.30.0
// protoc v3.21.12 // protoc v3.6.1
// source: reservation.proto // source: reservation.proto
// We can't change this to swapserverrpc, it would be a breaking change because // We can't change this to swapserverrpc, it would be a breaking change because

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.30.0 // protoc-gen-go v1.30.0
// protoc v3.21.12 // protoc v3.6.1
// source: server.proto // source: server.proto
// We can't change this to swapserverrpc, it would be a breaking change because // We can't change this to swapserverrpc, it would be a breaking change because
@ -25,26 +25,27 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
// * //*
// This enum defines the protocol versions that clients may adhere to. Note that //This enum defines the protocol versions that clients may adhere to. Note that
// this is not a flagged enum. If a particular protocol version adds a feature, //this is not a flagged enum. If a particular protocol version adds a feature,
// then in general all the preceding features are also supported. Exception to this //then in general all the preceding features are also supported. Exception to this
// is when features get deprecated. //is when features get deprecated.
type ProtocolVersion int32 type ProtocolVersion int32
const ( const (
// / No protocol version reported at all. /// No protocol version reported at all.
ProtocolVersion_LEGACY ProtocolVersion = 0 ProtocolVersion_LEGACY ProtocolVersion = 0
// / Client may attempt to send the loop out payment in multiple parts. /// Client may attempt to send the loop out payment in multiple parts.
ProtocolVersion_MULTI_LOOP_OUT ProtocolVersion = 1 ProtocolVersion_MULTI_LOOP_OUT ProtocolVersion = 1
// * //*
// Loop will use native segwit (P2WSH) htlcs by default, while externally //Loop will use native segwit (P2WSH) htlcs by default, while externally
// published htlcs may use native (P2WSH) or nested (NP2WSH) segwit as well. //published htlcs may use native (P2WSH) or nested (NP2WSH) segwit as well.
ProtocolVersion_NATIVE_SEGWIT_LOOP_IN ProtocolVersion = 2 ProtocolVersion_NATIVE_SEGWIT_LOOP_IN ProtocolVersion = 2
// Once the on chain loop out htlc is confirmed, the client can push the swap //
// preimage to the server to speed up claim of their off chain htlc (acquiring //Once the on chain loop out htlc is confirmed, the client can push the swap
// incoming liquidity more quickly than if the server waited for the on chain //preimage to the server to speed up claim of their off chain htlc (acquiring
// claim tx). //incoming liquidity more quickly than if the server waited for the on chain
//claim tx).
ProtocolVersion_PREIMAGE_PUSH_LOOP_OUT ProtocolVersion = 3 ProtocolVersion_PREIMAGE_PUSH_LOOP_OUT ProtocolVersion = 3
// The client will propose a cltv expiry height for loop out. // The client will propose a cltv expiry height for loop out.
ProtocolVersion_USER_EXPIRY_LOOP_OUT ProtocolVersion = 4 ProtocolVersion_USER_EXPIRY_LOOP_OUT ProtocolVersion = 4
@ -137,20 +138,23 @@ const (
ServerSwapState_SERVER_HTLC_PUBLISHED ServerSwapState = 1 ServerSwapState_SERVER_HTLC_PUBLISHED ServerSwapState = 1
// The swap completed successfully. // The swap completed successfully.
ServerSwapState_SERVER_SUCCESS ServerSwapState = 2 ServerSwapState_SERVER_SUCCESS ServerSwapState = 2
// The swap failed for a reason that is unknown to the server, this is only //
// set for older swaps. //The swap failed for a reason that is unknown to the server, this is only
//set for older swaps.
ServerSwapState_SERVER_FAILED_UNKNOWN ServerSwapState = 3 ServerSwapState_SERVER_FAILED_UNKNOWN ServerSwapState = 3
// No htlc was confirmed in time for the loop in swap to complete. // No htlc was confirmed in time for the loop in swap to complete.
ServerSwapState_SERVER_FAILED_NO_HTLC ServerSwapState = 4 ServerSwapState_SERVER_FAILED_NO_HTLC ServerSwapState = 4
// A loop in htlc confirmed on chain, but it did not have the correct value. // A loop in htlc confirmed on chain, but it did not have the correct value.
ServerSwapState_SERVER_FAILED_INVALID_HTLC_AMOUNT ServerSwapState = 5 ServerSwapState_SERVER_FAILED_INVALID_HTLC_AMOUNT ServerSwapState = 5
// We did not succeed in completing the loop in off chain payment before the //
// timeout. //We did not succeed in completing the loop in off chain payment before the
//timeout.
ServerSwapState_SERVER_FAILED_OFF_CHAIN_TIMEOUT ServerSwapState = 6 ServerSwapState_SERVER_FAILED_OFF_CHAIN_TIMEOUT ServerSwapState = 6
// The on chain timeout was claimed. // The on chain timeout was claimed.
ServerSwapState_SERVER_FAILED_TIMEOUT ServerSwapState = 7 ServerSwapState_SERVER_FAILED_TIMEOUT ServerSwapState = 7
// The server could not publish the loop out on chain htlc before the deadline //
// provided. //The server could not publish the loop out on chain htlc before the deadline
//provided.
ServerSwapState_SERVER_FAILED_SWAP_DEADLINE ServerSwapState = 8 ServerSwapState_SERVER_FAILED_SWAP_DEADLINE ServerSwapState = 8
// The server could not publish the loop out on chain htlc. // The server could not publish the loop out on chain htlc.
ServerSwapState_SERVER_FAILED_HTLC_PUBLICATION ServerSwapState = 9 ServerSwapState_SERVER_FAILED_HTLC_PUBLICATION ServerSwapState = 9
@ -165,10 +169,12 @@ const (
// The client canceled the swap because they could not route the swap // The client canceled the swap because they could not route the swap
// payment. // payment.
ServerSwapState_SERVER_CLIENT_INVOICE_CANCEL ServerSwapState = 14 ServerSwapState_SERVER_CLIENT_INVOICE_CANCEL ServerSwapState = 14
// A loop in swap was rejected because it contained multiple outputs for a //
// single swap. //A loop in swap was rejected because it contained multiple outputs for a
//single swap.
ServerSwapState_SERVER_FAILED_MULTIPLE_SWAP_SCRIPTS ServerSwapState = 15 ServerSwapState_SERVER_FAILED_MULTIPLE_SWAP_SCRIPTS ServerSwapState = 15
// The swap failed during creation. //
//The swap failed during creation.
ServerSwapState_SERVER_FAILED_INITIALIZATION ServerSwapState = 16 ServerSwapState_SERVER_FAILED_INITIALIZATION ServerSwapState = 16
) )
@ -300,19 +306,25 @@ func (RoutePaymentType) EnumDescriptor() ([]byte, []int) {
type PaymentFailureReason int32 type PaymentFailureReason int32
const ( const (
// Payment isn't failed (yet). //
//Payment isn't failed (yet).
PaymentFailureReason_LND_FAILURE_REASON_NONE PaymentFailureReason = 0 PaymentFailureReason_LND_FAILURE_REASON_NONE PaymentFailureReason = 0
// There are more routes to try, but the payment timeout was exceeded. //
//There are more routes to try, but the payment timeout was exceeded.
PaymentFailureReason_LND_FAILURE_REASON_TIMEOUT PaymentFailureReason = 1 PaymentFailureReason_LND_FAILURE_REASON_TIMEOUT PaymentFailureReason = 1
// All possible routes were tried and failed permanently. Or were no //
// routes to the destination at all. //All possible routes were tried and failed permanently. Or were no
//routes to the destination at all.
PaymentFailureReason_LND_FAILURE_REASON_NO_ROUTE PaymentFailureReason = 2 PaymentFailureReason_LND_FAILURE_REASON_NO_ROUTE PaymentFailureReason = 2
// A non-recoverable error has occured. //
//A non-recoverable error has occured.
PaymentFailureReason_LND_FAILURE_REASON_ERROR PaymentFailureReason = 3 PaymentFailureReason_LND_FAILURE_REASON_ERROR PaymentFailureReason = 3
// Payment details incorrect (unknown hash, invalid amt or //
// invalid final cltv delta) //Payment details incorrect (unknown hash, invalid amt or
//invalid final cltv delta)
PaymentFailureReason_LND_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS PaymentFailureReason = 4 PaymentFailureReason_LND_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS PaymentFailureReason = 4
// Insufficient local balance. //
//Insufficient local balance.
PaymentFailureReason_LND_FAILURE_REASON_INSUFFICIENT_BALANCE PaymentFailureReason = 5 PaymentFailureReason_LND_FAILURE_REASON_INSUFFICIENT_BALANCE PaymentFailureReason = 5
) )
@ -465,9 +477,9 @@ type ServerLoopOutRequest struct {
ReceiverKey []byte `protobuf:"bytes,1,opt,name=receiver_key,json=receiverKey,proto3" json:"receiver_key,omitempty"` ReceiverKey []byte `protobuf:"bytes,1,opt,name=receiver_key,json=receiverKey,proto3" json:"receiver_key,omitempty"`
SwapHash []byte `protobuf:"bytes,2,opt,name=swap_hash,json=swapHash,proto3" json:"swap_hash,omitempty"` SwapHash []byte `protobuf:"bytes,2,opt,name=swap_hash,json=swapHash,proto3" json:"swap_hash,omitempty"`
Amt uint64 `protobuf:"varint,3,opt,name=amt,proto3" json:"amt,omitempty"` Amt uint64 `protobuf:"varint,3,opt,name=amt,proto3" json:"amt,omitempty"`
// / The unix time in seconds we want the on-chain swap to be published by. /// The unix time in seconds we want the on-chain swap to be published by.
SwapPublicationDeadline int64 `protobuf:"varint,4,opt,name=swap_publication_deadline,json=swapPublicationDeadline,proto3" json:"swap_publication_deadline,omitempty"` SwapPublicationDeadline int64 `protobuf:"varint,4,opt,name=swap_publication_deadline,json=swapPublicationDeadline,proto3" json:"swap_publication_deadline,omitempty"`
// / The protocol version that the client adheres to. /// The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,5,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,5,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// The requested absolute block height of the on-chain htlc. This is // The requested absolute block height of the on-chain htlc. This is
// subjected to min and max constraints as reported in the LoopOutTerms // subjected to min and max constraints as reported in the LoopOutTerms
@ -476,13 +488,10 @@ type ServerLoopOutRequest struct {
// The user agent string that identifies the software running on the user's // The user agent string that identifies the software running on the user's
// side. This can be changed in the user's client software but it _SHOULD_ // side. This can be changed in the user's client software but it _SHOULD_
// conform to the following pattern: // conform to the following pattern:
// // Agent-Name/semver-version(/additional-info)
// Agent-Name/semver-version(/additional-info)
//
// Examples: // Examples:
// // loopd/v0.10.0-beta/commit=3b635821
// loopd/v0.10.0-beta/commit=3b635821 // litd/v0.2.0-alpha/commit=326d754
// litd/v0.2.0-alpha/commit=326d754
UserAgent string `protobuf:"bytes,7,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` UserAgent string `protobuf:"bytes,7,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
} }
@ -657,11 +666,11 @@ type ServerLoopOutQuoteRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// / The swap amount. If zero, a quote for a maximum amt swap will be given. /// The swap amount. If zero, a quote for a maximum amt swap will be given.
Amt uint64 `protobuf:"varint,1,opt,name=amt,proto3" json:"amt,omitempty"` Amt uint64 `protobuf:"varint,1,opt,name=amt,proto3" json:"amt,omitempty"`
// / The unix time in seconds we want the on-chain swap to be published by. /// The unix time in seconds we want the on-chain swap to be published by.
SwapPublicationDeadline int64 `protobuf:"varint,2,opt,name=swap_publication_deadline,json=swapPublicationDeadline,proto3" json:"swap_publication_deadline,omitempty"` SwapPublicationDeadline int64 `protobuf:"varint,2,opt,name=swap_publication_deadline,json=swapPublicationDeadline,proto3" json:"swap_publication_deadline,omitempty"`
// / The protocol version that the client adheres to. /// The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,3,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// The requested absolute block height of the on-chain htlc. This is // The requested absolute block height of the on-chain htlc. This is
// subjected to min and max constraints as reported in the LoopOutTerms // subjected to min and max constraints as reported in the LoopOutTerms
@ -670,13 +679,10 @@ type ServerLoopOutQuoteRequest struct {
// The user agent string that identifies the software running on the user's // The user agent string that identifies the software running on the user's
// side. This can be changed in the user's client software but it _SHOULD_ // side. This can be changed in the user's client software but it _SHOULD_
// conform to the following pattern: // conform to the following pattern:
// // Agent-Name/semver-version(/additional-info)
// Agent-Name/semver-version(/additional-info)
//
// Examples: // Examples:
// // loopd/v0.10.0-beta/commit=3b635821
// loopd/v0.10.0-beta/commit=3b635821 // litd/v0.2.0-alpha/commit=326d754
// litd/v0.2.0-alpha/commit=326d754
UserAgent string `protobuf:"bytes,5,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` UserAgent string `protobuf:"bytes,5,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
} }
@ -753,9 +759,9 @@ type ServerLoopOutQuote struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
SwapPaymentDest string `protobuf:"bytes,1,opt,name=swap_payment_dest,json=swapPaymentDest,proto3" json:"swap_payment_dest,omitempty"` SwapPaymentDest string `protobuf:"bytes,1,opt,name=swap_payment_dest,json=swapPaymentDest,proto3" json:"swap_payment_dest,omitempty"`
// / The total estimated swap fee given the quote amt. /// The total estimated swap fee given the quote amt.
SwapFee int64 `protobuf:"varint,2,opt,name=swap_fee,json=swapFee,proto3" json:"swap_fee,omitempty"` SwapFee int64 `protobuf:"varint,2,opt,name=swap_fee,json=swapFee,proto3" json:"swap_fee,omitempty"`
// / Deprecated, total swap fee given quote amt is calculated in swap_fee. /// Deprecated, total swap fee given quote amt is calculated in swap_fee.
// //
// Deprecated: Marked as deprecated in server.proto. // Deprecated: Marked as deprecated in server.proto.
SwapFeeRate int64 `protobuf:"varint,3,opt,name=swap_fee_rate,json=swapFeeRate,proto3" json:"swap_fee_rate,omitempty"` SwapFeeRate int64 `protobuf:"varint,3,opt,name=swap_fee_rate,json=swapFeeRate,proto3" json:"swap_fee_rate,omitempty"`
@ -861,18 +867,15 @@ type ServerLoopOutTermsRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// / The protocol version that the client adheres to. /// The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// The user agent string that identifies the software running on the user's // The user agent string that identifies the software running on the user's
// side. This can be changed in the user's client software but it _SHOULD_ // side. This can be changed in the user's client software but it _SHOULD_
// conform to the following pattern: // conform to the following pattern:
// // Agent-Name/semver-version(/additional-info)
// Agent-Name/semver-version(/additional-info)
//
// Examples: // Examples:
// // loopd/v0.10.0-beta/commit=3b635821
// loopd/v0.10.0-beta/commit=3b635821 // litd/v0.2.0-alpha/commit=326d754
// litd/v0.2.0-alpha/commit=326d754
UserAgent string `protobuf:"bytes,2,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` UserAgent string `protobuf:"bytes,2,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
} }
@ -1006,20 +1009,17 @@ type ServerLoopInRequest struct {
Amt uint64 `protobuf:"varint,3,opt,name=amt,proto3" json:"amt,omitempty"` Amt uint64 `protobuf:"varint,3,opt,name=amt,proto3" json:"amt,omitempty"`
SwapInvoice string `protobuf:"bytes,4,opt,name=swap_invoice,json=swapInvoice,proto3" json:"swap_invoice,omitempty"` SwapInvoice string `protobuf:"bytes,4,opt,name=swap_invoice,json=swapInvoice,proto3" json:"swap_invoice,omitempty"`
LastHop []byte `protobuf:"bytes,5,opt,name=last_hop,json=lastHop,proto3" json:"last_hop,omitempty"` LastHop []byte `protobuf:"bytes,5,opt,name=last_hop,json=lastHop,proto3" json:"last_hop,omitempty"`
// / The protocol version that the client adheres to. /// The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,6,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,6,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// An invoice that can be used for the purpose of probing. // An invoice that can be used for the purpose of probing.
ProbeInvoice string `protobuf:"bytes,7,opt,name=probe_invoice,json=probeInvoice,proto3" json:"probe_invoice,omitempty"` ProbeInvoice string `protobuf:"bytes,7,opt,name=probe_invoice,json=probeInvoice,proto3" json:"probe_invoice,omitempty"`
// The user agent string that identifies the software running on the user's // The user agent string that identifies the software running on the user's
// side. This can be changed in the user's client software but it _SHOULD_ // side. This can be changed in the user's client software but it _SHOULD_
// conform to the following pattern: // conform to the following pattern:
// // Agent-Name/semver-version(/additional-info)
// Agent-Name/semver-version(/additional-info)
//
// Examples: // Examples:
// // loopd/v0.10.0-beta/commit=3b635821
// loopd/v0.10.0-beta/commit=3b635821 // litd/v0.2.0-alpha/commit=326d754
// litd/v0.2.0-alpha/commit=326d754
UserAgent string `protobuf:"bytes,8,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` UserAgent string `protobuf:"bytes,8,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
} }
@ -1195,7 +1195,7 @@ type ServerLoopInQuoteRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// / The swap amount. If zero, a quote for a maximum amt swap will be given. /// The swap amount. If zero, a quote for a maximum amt swap will be given.
Amt uint64 `protobuf:"varint,1,opt,name=amt,proto3" json:"amt,omitempty"` Amt uint64 `protobuf:"varint,1,opt,name=amt,proto3" json:"amt,omitempty"`
// The destination pubkey. // The destination pubkey.
Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty"` Pubkey []byte `protobuf:"bytes,3,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
@ -1203,18 +1203,15 @@ type ServerLoopInQuoteRequest struct {
LastHop []byte `protobuf:"bytes,4,opt,name=last_hop,json=lastHop,proto3" json:"last_hop,omitempty"` LastHop []byte `protobuf:"bytes,4,opt,name=last_hop,json=lastHop,proto3" json:"last_hop,omitempty"`
// Optional route hints to reach the destination through private channels. // Optional route hints to reach the destination through private channels.
RouteHints []*RouteHint `protobuf:"bytes,5,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"` RouteHints []*RouteHint `protobuf:"bytes,5,rep,name=route_hints,json=routeHints,proto3" json:"route_hints,omitempty"`
// / The protocol version that the client adheres to. /// The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,2,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,2,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// The user agent string that identifies the software running on the user's // The user agent string that identifies the software running on the user's
// side. This can be changed in the user's client software but it _SHOULD_ // side. This can be changed in the user's client software but it _SHOULD_
// conform to the following pattern: // conform to the following pattern:
// // Agent-Name/semver-version(/additional-info)
// Agent-Name/semver-version(/additional-info)
//
// Examples: // Examples:
// // loopd/v0.10.0-beta/commit=3b635821
// loopd/v0.10.0-beta/commit=3b635821 // litd/v0.2.0-alpha/commit=326d754
// litd/v0.2.0-alpha/commit=326d754
UserAgent string `protobuf:"bytes,6,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` UserAgent string `protobuf:"bytes,6,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
} }
@ -1382,18 +1379,15 @@ type ServerLoopInTermsRequest struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// / The protocol version that the client adheres to. /// The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// The user agent string that identifies the software running on the user's // The user agent string that identifies the software running on the user's
// side. This can be changed in the user's client software but it _SHOULD_ // side. This can be changed in the user's client software but it _SHOULD_
// conform to the following pattern: // conform to the following pattern:
// // Agent-Name/semver-version(/additional-info)
// Agent-Name/semver-version(/additional-info)
//
// Examples: // Examples:
// // loopd/v0.10.0-beta/commit=3b635821
// loopd/v0.10.0-beta/commit=3b635821 // litd/v0.2.0-alpha/commit=326d754
// litd/v0.2.0-alpha/commit=326d754
UserAgent string `protobuf:"bytes,2,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"` UserAgent string `protobuf:"bytes,2,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
} }
@ -1508,8 +1502,9 @@ type ServerLoopOutPushPreimageRequest struct {
// The protocol version that the client adheres to. // The protocol version that the client adheres to.
ProtocolVersion ProtocolVersion `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"` ProtocolVersion ProtocolVersion `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ProtocolVersion" json:"protocol_version,omitempty"`
// Preimage is the preimage of the loop out swap that we wish to push to the //
// server to speed up off-chain claim once the on-chain htlc has confirmed. //Preimage is the preimage of the loop out swap that we wish to push to the
//server to speed up off-chain claim once the on-chain htlc has confirmed.
Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"` Preimage []byte `protobuf:"bytes,2,opt,name=preimage,proto3" json:"preimage,omitempty"`
} }
@ -1898,7 +1893,6 @@ type CancelLoopOutSwapRequest struct {
// Additional information about the swap cancelation. // Additional information about the swap cancelation.
// //
// Types that are assignable to CancelInfo: // Types that are assignable to CancelInfo:
//
// *CancelLoopOutSwapRequest_RouteCancel // *CancelLoopOutSwapRequest_RouteCancel
CancelInfo isCancelLoopOutSwapRequest_CancelInfo `protobuf_oneof:"cancel_info"` CancelInfo isCancelLoopOutSwapRequest_CancelInfo `protobuf_oneof:"cancel_info"`
} }

@ -14,8 +14,6 @@ import (
"github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/swap"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
) )
// Sweeper creates htlc sweep txes. // Sweeper creates htlc sweep txes.
@ -183,26 +181,10 @@ func (s *Sweeper) GetSweepFee(ctx context.Context,
destAddr btcutil.Address, sweepConfTarget int32) ( destAddr btcutil.Address, sweepConfTarget int32) (
btcutil.Amount, error) { btcutil.Amount, error) {
// Use GetSweepFeeDetails to get the fee and other unused data.
fee, _, _, err := s.GetSweepFeeDetails(
ctx, addInputEstimate, destAddr, sweepConfTarget,
)
return fee, err
}
// GetSweepFee calculates the required tx fee to spend to P2WKH. It takes a
// function that is expected to add the weight of the input to the weight
// estimator. It returns also the fee rate and transaction weight.
func (s *Sweeper) GetSweepFeeDetails(ctx context.Context,
addInputEstimate func(*input.TxWeightEstimator) error,
destAddr btcutil.Address, sweepConfTarget int32) (
btcutil.Amount, chainfee.SatPerKWeight, lntypes.WeightUnit, error) {
// Get fee estimate from lnd. // Get fee estimate from lnd.
feeRate, err := s.Lnd.WalletKit.EstimateFeeRate(ctx, sweepConfTarget) feeRate, err := s.Lnd.WalletKit.EstimateFeeRate(ctx, sweepConfTarget)
if err != nil { if err != nil {
return 0, 0, 0, fmt.Errorf("estimate fee: %v", err) return 0, fmt.Errorf("estimate fee: %v", err)
} }
// Calculate weight for this tx. // Calculate weight for this tx.
@ -224,16 +206,16 @@ func (s *Sweeper) GetSweepFeeDetails(ctx context.Context,
weightEstimate.AddP2TROutput() weightEstimate.AddP2TROutput()
default: default:
return 0, 0, 0, fmt.Errorf("estimate fee: unknown address "+ return 0, fmt.Errorf("estimate fee: unknown address type %T",
"type %T", destAddr) destAddr)
} }
err = addInputEstimate(&weightEstimate) err = addInputEstimate(&weightEstimate)
if err != nil { if err != nil {
return 0, 0, 0, err return 0, err
} }
weight := weightEstimate.Weight() weight := weightEstimate.Weight()
return feeRate.FeeForWeight(weight), feeRate, weight, nil return feeRate.FeeForWeight(int64(weight)), nil
} }

@ -17,8 +17,7 @@ func init() {
UseLogger(build.NewSubLogger("SWEEP", nil)) UseLogger(build.NewSubLogger("SWEEP", nil))
} }
// batchPrefixLogger returns a logger that prefixes all log messages with // batchPrefixLogger returns a logger that prefixes all log messages with the ID.
// the ID.
func batchPrefixLogger(batchID string) btclog.Logger { func batchPrefixLogger(batchID string) btclog.Logger {
return build.NewPrefixLog(fmt.Sprintf("[Batch %s]", batchID), log) return build.NewPrefixLog(fmt.Sprintf("[Batch %s]", batchID), log)
} }

@ -3,7 +3,6 @@ package sweepbatcher
import ( import (
"context" "context"
"database/sql" "database/sql"
"fmt"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
@ -15,28 +14,22 @@ import (
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
) )
// Querier is the interface that contains all the queries generated type BaseDB interface {
// by sqlc for sweep batcher.
type Querier interface {
// ConfirmBatch confirms a batch by setting the state to confirmed. // ConfirmBatch confirms a batch by setting the state to confirmed.
ConfirmBatch(ctx context.Context, id int32) error ConfirmBatch(ctx context.Context, id int32) error
// GetBatchSweeps fetches all the sweeps that are part a batch. // GetBatchSweeps fetches all the sweeps that are part a batch.
GetBatchSweeps(ctx context.Context, batchID int32) ( GetBatchSweeps(ctx context.Context, batchID int32) (
[]sqlc.Sweep, error) []sqlc.GetBatchSweepsRow, error)
// GetBatchSweptAmount returns the total amount of sats swept by a
// (confirmed) batch.
GetBatchSweptAmount(ctx context.Context, batchID int32) (int64, error)
// GetSweepStatus returns true if the sweep has been completed. // GetSweepStatus returns true if the sweep has been completed.
GetSweepStatus(ctx context.Context, swapHash []byte) (bool, error) GetSweepStatus(ctx context.Context, swapHash []byte) (bool, error)
// GetParentBatch fetches the parent batch of a completed sweep. // GetSwapUpdates fetches all the updates for a swap.
GetParentBatch(ctx context.Context, swapHash []byte) (sqlc.SweepBatch, GetSwapUpdates(ctx context.Context, swapHash []byte) (
error) []sqlc.SwapUpdate, error)
// GetUnconfirmedBatches fetches all the batches from the // FetchUnconfirmedSweepBatches fetches all the batches from the
// database that are not in a confirmed state. // database that are not in a confirmed state.
GetUnconfirmedBatches(ctx context.Context) ([]sqlc.SweepBatch, error) GetUnconfirmedBatches(ctx context.Context) ([]sqlc.SweepBatch, error)
@ -45,26 +38,17 @@ type Querier interface {
InsertBatch(ctx context.Context, arg sqlc.InsertBatchParams) ( InsertBatch(ctx context.Context, arg sqlc.InsertBatchParams) (
int32, error) int32, error)
// DropBatch drops a batch from the database.
DropBatch(ctx context.Context, id int32) error
// UpdateBatch updates a batch in the database. // UpdateBatch updates a batch in the database.
UpdateBatch(ctx context.Context, arg sqlc.UpdateBatchParams) error UpdateBatch(ctx context.Context, arg sqlc.UpdateBatchParams) error
// UpsertSweep inserts a sweep into the database, or updates an existing // UpsertSweep inserts a sweep into the database, or updates an existing
// sweep if it already exists. // sweep if it already exists.
UpsertSweep(ctx context.Context, arg sqlc.UpsertSweepParams) error UpsertSweep(ctx context.Context, arg sqlc.UpsertSweepParams) error
}
// BaseDB is the interface that contains all the queries generated
// by sqlc for sweep batcher and transaction functionality.
type BaseDB interface {
Querier
// ExecTx allows for executing a function in the context of a database // ExecTx allows for executing a function in the context of a database
// transaction. // transaction.
ExecTx(ctx context.Context, txOptions loopdb.TxOptions, ExecTx(ctx context.Context, txOptions loopdb.TxOptions,
txBody func(Querier) error) error txBody func(*sqlc.Queries) error) error
} }
// SQLStore manages the reservations in the database. // SQLStore manages the reservations in the database.
@ -86,8 +70,8 @@ func NewSQLStore(db BaseDB, network *chaincfg.Params) *SQLStore {
// FetchUnconfirmedSweepBatches fetches all the batches from the database that // FetchUnconfirmedSweepBatches fetches all the batches from the database that
// are not in a confirmed state. // are not in a confirmed state.
func (s *SQLStore) FetchUnconfirmedSweepBatches(ctx context.Context) ( func (s *SQLStore) FetchUnconfirmedSweepBatches(ctx context.Context) ([]*dbBatch,
[]*dbBatch, error) { error) {
var batches []*dbBatch var batches []*dbBatch
@ -116,24 +100,6 @@ func (s *SQLStore) InsertSweepBatch(ctx context.Context, batch *dbBatch) (int32,
return s.baseDb.InsertBatch(ctx, batchToInsertArgs(*batch)) return s.baseDb.InsertBatch(ctx, batchToInsertArgs(*batch))
} }
// DropBatch drops a batch from the database. Note that we only use this call
// for batches that have no sweeps and so we'd not be able to resume.
func (s *SQLStore) DropBatch(ctx context.Context, id int32) error {
readOpts := loopdb.NewSqlWriteOpts()
return s.baseDb.ExecTx(ctx, readOpts, func(tx Querier) error {
dbSweeps, err := tx.GetBatchSweeps(ctx, id)
if err != nil {
return err
}
if len(dbSweeps) != 0 {
return fmt.Errorf("cannot drop a non-empty batch")
}
return tx.DropBatch(ctx, id)
})
}
// UpdateSweepBatch updates a batch in the database. // UpdateSweepBatch updates a batch in the database.
func (s *SQLStore) UpdateSweepBatch(ctx context.Context, batch *dbBatch) error { func (s *SQLStore) UpdateSweepBatch(ctx context.Context, batch *dbBatch) error {
return s.baseDb.UpdateBatch(ctx, batchToUpdateArgs(*batch)) return s.baseDb.UpdateBatch(ctx, batchToUpdateArgs(*batch))
@ -151,14 +117,21 @@ func (s *SQLStore) FetchBatchSweeps(ctx context.Context, id int32) (
readOpts := loopdb.NewSqlReadOpts() readOpts := loopdb.NewSqlReadOpts()
var sweeps []*dbSweep var sweeps []*dbSweep
err := s.baseDb.ExecTx(ctx, readOpts, func(tx Querier) error { err := s.baseDb.ExecTx(ctx, readOpts, func(tx *sqlc.Queries) error {
dbSweeps, err := tx.GetBatchSweeps(ctx, id) dbSweeps, err := tx.GetBatchSweeps(ctx, id)
if err != nil { if err != nil {
return err return err
} }
for _, dbSweep := range dbSweeps { for _, dbSweep := range dbSweeps {
sweep, err := s.convertSweepRow(dbSweep) updates, err := s.baseDb.GetSwapUpdates(
ctx, dbSweep.SwapHash,
)
if err != nil {
return err
}
sweep, err := s.convertSweepRow(dbSweep, updates)
if err != nil { if err != nil {
return err return err
} }
@ -175,34 +148,6 @@ func (s *SQLStore) FetchBatchSweeps(ctx context.Context, id int32) (
return sweeps, nil return sweeps, nil
} }
// TotalSweptAmount returns the total amount swept by a (confirmed) batch.
func (s *SQLStore) TotalSweptAmount(ctx context.Context, id int32) (
btcutil.Amount, error) {
amt, err := s.baseDb.GetBatchSweptAmount(ctx, id)
if err != nil {
return 0, err
}
return btcutil.Amount(amt), nil
}
// GetParentBatch fetches the parent batch of a completed sweep.
func (s *SQLStore) GetParentBatch(ctx context.Context, swapHash lntypes.Hash) (
*dbBatch, error) {
batch, err := s.baseDb.GetParentBatch(ctx, swapHash[:])
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
return convertBatchRow(batch), nil
}
// UpsertSweep inserts a sweep into the database, or updates an existing sweep // UpsertSweep inserts a sweep into the database, or updates an existing sweep
// if it already exists. // if it already exists.
func (s *SQLStore) UpsertSweep(ctx context.Context, sweep *dbSweep) error { func (s *SQLStore) UpsertSweep(ctx context.Context, sweep *dbSweep) error {
@ -257,6 +202,9 @@ type dbSweep struct {
// Completed indicates whether this sweep is completed. // Completed indicates whether this sweep is completed.
Completed bool Completed bool
// LoopOut is the loop out that the sweep belongs to.
LoopOut *loopdb.LoopOut
} }
// convertBatchRow converts a batch row from db to a sweepbatcher.Batch struct. // convertBatchRow converts a batch row from db to a sweepbatcher.Batch struct.
@ -348,7 +296,9 @@ func batchToUpdateArgs(batch dbBatch) sqlc.UpdateBatchParams {
} }
// convertSweepRow converts a sweep row from db to a sweep struct. // convertSweepRow converts a sweep row from db to a sweep struct.
func (s *SQLStore) convertSweepRow(row sqlc.Sweep) (dbSweep, error) { func (s *SQLStore) convertSweepRow(row sqlc.GetBatchSweepsRow,
updates []sqlc.SwapUpdate) (dbSweep, error) {
sweep := dbSweep{ sweep := dbSweep{
ID: row.ID, ID: row.ID,
BatchID: row.BatchID, BatchID: row.BatchID,
@ -372,7 +322,40 @@ func (s *SQLStore) convertSweepRow(row sqlc.Sweep) (dbSweep, error) {
Index: uint32(row.OutpointIndex), Index: uint32(row.OutpointIndex),
} }
return sweep, nil sweep.LoopOut, err = loopdb.ConvertLoopOutRow(
s.network,
sqlc.GetLoopOutSwapRow{
ID: row.ID,
SwapHash: row.SwapHash,
Preimage: row.Preimage,
InitiationTime: row.InitiationTime,
AmountRequested: row.AmountRequested,
CltvExpiry: row.CltvExpiry,
MaxMinerFee: row.MaxMinerFee,
MaxSwapFee: row.MaxSwapFee,
InitiationHeight: row.InitiationHeight,
ProtocolVersion: row.ProtocolVersion,
Label: row.Label,
DestAddress: row.DestAddress,
SwapInvoice: row.SwapInvoice,
MaxSwapRoutingFee: row.MaxSwapRoutingFee,
SweepConfTarget: row.SweepConfTarget,
HtlcConfirmations: row.HtlcConfirmations,
OutgoingChanSet: row.OutgoingChanSet,
PrepayInvoice: row.PrepayInvoice,
MaxPrepayRoutingFee: row.MaxPrepayRoutingFee,
PublicationDeadline: row.PublicationDeadline,
SingleSweep: row.SingleSweep,
SenderScriptPubkey: row.SenderScriptPubkey,
ReceiverScriptPubkey: row.ReceiverScriptPubkey,
SenderInternalPubkey: row.SenderInternalPubkey,
ReceiverInternalPubkey: row.ReceiverInternalPubkey,
ClientKeyFamily: row.ClientKeyFamily,
ClientKeyIndex: row.ClientKeyIndex,
}, updates,
)
return sweep, err
} }
// sweepToUpsertArgs converts a Sweep struct to the arguments needed to insert. // sweepToUpsertArgs converts a Sweep struct to the arguments needed to insert.

@ -5,7 +5,6 @@ import (
"errors" "errors"
"sort" "sort"
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
) )
@ -23,7 +22,7 @@ func NewStoreMock() *StoreMock {
} }
} }
// FetchUnconfirmedSweepBatches fetches all the loop out sweep batches from the // FetchUnconfirmedBatches fetches all the loop out sweep batches from the
// database that are not in a confirmed state. // database that are not in a confirmed state.
func (s *StoreMock) FetchUnconfirmedSweepBatches(ctx context.Context) ( func (s *StoreMock) FetchUnconfirmedSweepBatches(ctx context.Context) (
[]*dbBatch, error) { []*dbBatch, error) {
@ -56,12 +55,6 @@ func (s *StoreMock) InsertSweepBatch(ctx context.Context,
return id, nil return id, nil
} }
// DropBatch drops a batch from the database.
func (s *StoreMock) DropBatch(ctx context.Context, id int32) error {
delete(s.batches, id)
return nil
}
// UpdateSweepBatch updates a batch in the database. // UpdateSweepBatch updates a batch in the database.
func (s *StoreMock) UpdateSweepBatch(ctx context.Context, func (s *StoreMock) UpdateSweepBatch(ctx context.Context,
batch *dbBatch) error { batch *dbBatch) error {
@ -130,44 +123,3 @@ func (s *StoreMock) AssertSweepStored(id lntypes.Hash) bool {
_, ok := s.sweeps[id] _, ok := s.sweeps[id]
return ok return ok
} }
// GetParentBatch returns the parent batch of a swap.
func (s *StoreMock) GetParentBatch(ctx context.Context, swapHash lntypes.Hash) (
*dbBatch, error) {
for _, sweep := range s.sweeps {
if sweep.SwapHash == swapHash {
batch, ok := s.batches[sweep.BatchID]
if !ok {
return nil, errors.New("batch not found")
}
return &batch, nil
}
}
return nil, errors.New("batch not found")
}
// TotalSweptAmount returns the total amount of BTC that has been swept from a
// batch.
func (s *StoreMock) TotalSweptAmount(ctx context.Context, batchID int32) (
btcutil.Amount, error) {
batch, ok := s.batches[batchID]
if !ok {
return 0, errors.New("batch not found")
}
if batch.State != batchConfirmed && batch.State != batchClosed {
return 0, nil
}
var total btcutil.Amount
for _, sweep := range s.sweeps {
if sweep.BatchID == batchID {
total += sweep.Amount
}
}
return 0, nil
}

@ -3,8 +3,6 @@ package sweepbatcher
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/hex"
"errors"
"fmt" "fmt"
"math" "math"
"sync" "sync"
@ -35,6 +33,10 @@ const (
// fee rate is increased when an rbf is attempted. // fee rate is increased when an rbf is attempted.
defaultFeeRateStep = chainfee.SatPerKWeight(100) defaultFeeRateStep = chainfee.SatPerKWeight(100)
// defaultBatchConfTarget is the default confirmation target of the
// batch transaction.
defaultBatchConfTarget = 12
// batchConfHeight is the default confirmation height of the batch // batchConfHeight is the default confirmation height of the batch
// transaction. // transaction.
batchConfHeight = 3 batchConfHeight = 3
@ -45,7 +47,7 @@ const (
) )
var ( var (
ErrBatchShuttingDown = errors.New("batch shutting down") ErrBatchShuttingDown = fmt.Errorf("batch shutting down")
) )
// sweep stores any data related to sweeping a specific outpoint. // sweep stores any data related to sweeping a specific outpoint.
@ -193,15 +195,7 @@ type batch struct {
// main event loop. // main event loop.
callLeave chan struct{} callLeave chan struct{}
// stopping signals that the batch is stopping. // quit signals that the batch must stop.
stopping chan struct{}
// finished signals that the batch has stopped and all child goroutines
// have finished.
finished chan struct{}
// quit is owned by the parent batcher and signals that the batch must
// stop.
quit chan struct{} quit chan struct{}
// wallet is the wallet client used to create and publish the batch // wallet is the wallet client used to create and publish the batch
@ -215,7 +209,7 @@ type batch struct {
// signerClient is the signer client used to sign the batch transaction. // signerClient is the signer client used to sign the batch transaction.
signerClient lndclient.SignerClient signerClient lndclient.SignerClient
// muSig2SignSweep includes all the required functionality to collect // muSig2Kit includes all the required functionality to collect
// and verify signatures by the swap server in order to cooperatively // and verify signatures by the swap server in order to cooperatively
// sweep funds. // sweep funds.
muSig2SignSweep MuSig2SignSweep muSig2SignSweep MuSig2SignSweep
@ -265,7 +259,6 @@ type batchKit struct {
purger Purger purger Purger
store BatcherStore store BatcherStore
log btclog.Logger log btclog.Logger
quit chan struct{}
} }
// scheduleNextCall schedules the next call to the batch handler's main event // scheduleNextCall schedules the next call to the batch handler's main event
@ -275,12 +268,6 @@ func (b *batch) scheduleNextCall() (func(), error) {
case b.callEnter <- struct{}{}: case b.callEnter <- struct{}{}:
case <-b.quit: case <-b.quit:
return func() {}, ErrBatcherShuttingDown
case <-b.stopping:
return func() {}, ErrBatchShuttingDown
case <-b.finished:
return func() {}, ErrBatchShuttingDown return func() {}, ErrBatchShuttingDown
} }
@ -304,9 +291,7 @@ func NewBatch(cfg batchConfig, bk batchKit) *batch {
errChan: make(chan error, 1), errChan: make(chan error, 1),
callEnter: make(chan struct{}), callEnter: make(chan struct{}),
callLeave: make(chan struct{}), callLeave: make(chan struct{}),
stopping: make(chan struct{}), quit: make(chan struct{}),
finished: make(chan struct{}),
quit: bk.quit,
batchTxid: bk.batchTxid, batchTxid: bk.batchTxid,
wallet: bk.wallet, wallet: bk.wallet,
chainNotifier: bk.chainNotifier, chainNotifier: bk.chainNotifier,
@ -320,22 +305,7 @@ func NewBatch(cfg batchConfig, bk batchKit) *batch {
} }
// NewBatchFromDB creates a new batch that already existed in storage. // NewBatchFromDB creates a new batch that already existed in storage.
func NewBatchFromDB(cfg batchConfig, bk batchKit) (*batch, error) { func NewBatchFromDB(cfg batchConfig, bk batchKit) *batch {
// Make sure the batch is not empty.
if len(bk.sweeps) == 0 {
// This should never happen, as this precondition is already
// ensured in spinUpBatchFromDB.
return nil, fmt.Errorf("empty batch is not allowed")
}
// Assign batchConfTarget to primary sweep's confTarget.
for _, sweep := range bk.sweeps {
if sweep.swapHash == bk.primaryID {
cfg.batchConfTarget = sweep.confTarget
break
}
}
return &batch{ return &batch{
id: bk.id, id: bk.id,
state: bk.state, state: bk.state,
@ -348,9 +318,7 @@ func NewBatchFromDB(cfg batchConfig, bk batchKit) (*batch, error) {
errChan: make(chan error, 1), errChan: make(chan error, 1),
callEnter: make(chan struct{}), callEnter: make(chan struct{}),
callLeave: make(chan struct{}), callLeave: make(chan struct{}),
stopping: make(chan struct{}), quit: make(chan struct{}),
finished: make(chan struct{}),
quit: bk.quit,
batchTxid: bk.batchTxid, batchTxid: bk.batchTxid,
batchPkScript: bk.batchPkScript, batchPkScript: bk.batchPkScript,
rbfCache: bk.rbfCache, rbfCache: bk.rbfCache,
@ -363,7 +331,7 @@ func NewBatchFromDB(cfg batchConfig, bk batchKit) (*batch, error) {
store: bk.store, store: bk.store,
log: bk.log, log: bk.log,
cfg: &cfg, cfg: &cfg,
}, nil }
} }
// addSweep tries to add a sweep to the batch. If this is the first sweep being // addSweep tries to add a sweep to the batch. If this is the first sweep being
@ -469,7 +437,7 @@ func (b *batch) sweepExists(hash lntypes.Hash) bool {
// Wait waits for the batch to gracefully stop. // Wait waits for the batch to gracefully stop.
func (b *batch) Wait() { func (b *batch) Wait() {
b.log.Infof("Stopping") b.log.Infof("Stopping")
<-b.finished b.wg.Wait()
} }
// Run is the batch's main event loop. // Run is the batch's main event loop.
@ -477,12 +445,8 @@ func (b *batch) Run(ctx context.Context) error {
runCtx, cancel := context.WithCancel(ctx) runCtx, cancel := context.WithCancel(ctx)
defer func() { defer func() {
cancel() cancel()
close(b.stopping) close(b.quit)
// Make sure not to call b.wg.Wait from any other place to avoid
// race condition between b.wg.Add(1) and b.wg.Wait().
b.wg.Wait() b.wg.Wait()
close(b.finished)
}() }()
if b.muSig2SignSweep == nil { if b.muSig2SignSweep == nil {
@ -574,12 +538,6 @@ func (b *batch) publish(ctx context.Context) error {
coopSuccess bool coopSuccess bool
) )
if len(b.sweeps) == 0 {
b.log.Debugf("skipping publish: no sweeps in the batch")
return nil
}
// Run the RBF rate update. // Run the RBF rate update.
err = b.updateRbfRate(ctx) err = b.updateRbfRate(ctx)
if err != nil { if err != nil {
@ -616,11 +574,9 @@ func (b *batch) publishBatch(ctx context.Context) (btcutil.Amount, error) {
batchTx.LockTime = uint32(b.currentHeight) batchTx.LockTime = uint32(b.currentHeight)
var ( var (
batchAmt btcutil.Amount batchAmt btcutil.Amount
prevOuts = make([]*wire.TxOut, 0, len(b.sweeps)) prevOuts = make([]*wire.TxOut, 0, len(b.sweeps))
signDescs = make( signDescs = make([]*lndclient.SignDescriptor, 0, len(b.sweeps))
[]*lndclient.SignDescriptor, 0, len(b.sweeps),
)
sweeps = make([]sweep, 0, len(b.sweeps)) sweeps = make([]sweep, 0, len(b.sweeps))
fee btcutil.Amount fee btcutil.Amount
inputCounter int inputCounter int
@ -709,7 +665,9 @@ func (b *batch) publishBatch(ctx context.Context) (btcutil.Amount, error) {
weightEstimate.AddP2TROutput() weightEstimate.AddP2TROutput()
fee = b.rbfCache.FeeRate.FeeForWeight(weightEstimate.Weight()) totalWeight := int64(weightEstimate.Weight())
fee = b.rbfCache.FeeRate.FeeForWeight(totalWeight)
// Clamp the calculated fee to the max allowed fee amount for the batch. // Clamp the calculated fee to the max allowed fee amount for the batch.
fee = clampBatchFee(fee, batchAmt) fee = clampBatchFee(fee, batchAmt)
@ -742,11 +700,9 @@ func (b *batch) publishBatch(ctx context.Context) (btcutil.Amount, error) {
batchTx.TxIn[i].Witness = witness batchTx.TxIn[i].Witness = witness
} }
b.log.Infof("attempting to publish non-coop tx=%v with feerate=%v, "+ b.log.Debugf("attempting to publish non-coop tx with feerate=%v, "+
"totalfee=%v, sweeps=%d, destAddr=%s", batchTx.TxHash(), "totalfee=%v, sweeps=%v, destAddr=%s", b.rbfCache.FeeRate, fee,
b.rbfCache.FeeRate, fee, len(batchTx.TxIn), address) len(batchTx.TxIn), address.String())
b.debugLogTx("serialized non-coop sweep", batchTx)
err = b.wallet.PublishTransaction( err = b.wallet.PublishTransaction(
ctx, batchTx, labels.LoopOutBatchSweepSuccess(b.id), ctx, batchTx, labels.LoopOutBatchSweepSuccess(b.id),
@ -839,7 +795,9 @@ func (b *batch) publishBatchCoop(ctx context.Context) (btcutil.Amount,
weightEstimate.AddP2TROutput() weightEstimate.AddP2TROutput()
fee = b.rbfCache.FeeRate.FeeForWeight(weightEstimate.Weight()) totalWeight := int64(weightEstimate.Weight())
fee = b.rbfCache.FeeRate.FeeForWeight(totalWeight)
// Clamp the calculated fee to the max allowed fee amount for the batch. // Clamp the calculated fee to the max allowed fee amount for the batch.
fee = clampBatchFee(fee, batchAmt) fee = clampBatchFee(fee, batchAmt)
@ -888,11 +846,9 @@ func (b *batch) publishBatchCoop(ctx context.Context) (btcutil.Amount,
return fee, err, false return fee, err, false
} }
b.log.Infof("attempting to publish coop tx=%v with feerate=%v, "+ b.log.Debugf("attempting to publish coop tx with feerate=%v, "+
"totalfee=%v, sweeps=%d, destAddr=%s", batchTx.TxHash(), "totalfee=%v, sweeps=%v, destAddr=%s", b.rbfCache.FeeRate, fee,
b.rbfCache.FeeRate, fee, len(batchTx.TxIn), address) len(batchTx.TxIn), address.String())
b.debugLogTx("serialized coop sweep", batchTx)
err = b.wallet.PublishTransaction( err = b.wallet.PublishTransaction(
ctx, batchTx, labels.LoopOutBatchSweepSuccess(b.id), ctx, batchTx, labels.LoopOutBatchSweepSuccess(b.id),
@ -910,17 +866,6 @@ func (b *batch) publishBatchCoop(ctx context.Context) (btcutil.Amount,
return fee, nil, true return fee, nil, true
} }
func (b *batch) debugLogTx(msg string, tx *wire.MsgTx) {
// Serialize the transaction and convert to hex string.
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
if err := tx.Serialize(buf); err != nil {
b.log.Errorf("failed to serialize tx for debug log: %v", err)
return
}
b.log.Debugf("%s: %s", msg, hex.EncodeToString(buf.Bytes()))
}
// coopSignBatchTx collects the necessary signatures from the server in order // coopSignBatchTx collects the necessary signatures from the server in order
// to cooperatively sweep the funds. // to cooperatively sweep the funds.
func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet, func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
@ -1064,10 +1009,6 @@ func (b *batch) updateRbfRate(ctx context.Context) error {
// If the feeRate is unset then we never published before, so we // If the feeRate is unset then we never published before, so we
// retrieve the fee estimate from our wallet. // retrieve the fee estimate from our wallet.
if b.rbfCache.FeeRate == 0 { if b.rbfCache.FeeRate == 0 {
if b.cfg.batchConfTarget == 0 {
b.log.Warnf("updateRbfRate called with zero " +
"batchConfTarget")
}
b.log.Infof("initializing rbf fee rate for conf target=%v", b.log.Infof("initializing rbf fee rate for conf target=%v",
b.cfg.batchConfTarget) b.cfg.batchConfTarget)
rate, err := b.wallet.EstimateFeeRate( rate, err := b.wallet.EstimateFeeRate(
@ -1195,32 +1136,6 @@ func (b *batch) monitorConfirmations(ctx context.Context) error {
return nil return nil
} }
// getFeePortionForSweep calculates the fee portion that each sweep should pay
// for the batch transaction. The fee is split evenly among the sweeps, If the
// fee cannot be split evenly, the remainder is paid by the first sweep.
func getFeePortionForSweep(spendTx *wire.MsgTx, numSweeps int,
totalSweptAmt btcutil.Amount) (btcutil.Amount, btcutil.Amount) {
totalFee := int64(totalSweptAmt) - spendTx.TxOut[0].Value
feePortionPerSweep := totalFee / int64(numSweeps)
roundingDiff := totalFee - (int64(numSweeps) * feePortionPerSweep)
return btcutil.Amount(feePortionPerSweep), btcutil.Amount(roundingDiff)
}
// getFeePortionPaidBySweep returns the fee portion that the sweep should pay
// for the batch transaction. If the sweep is the first sweep in the batch, it
// pays the rounding difference.
func getFeePortionPaidBySweep(spendTx *wire.MsgTx, feePortionPerSweep,
roundingDiff btcutil.Amount, sweep *sweep) btcutil.Amount {
if bytes.Equal(spendTx.TxIn[0].SignatureScript, sweep.htlc.SigScript) {
return feePortionPerSweep + roundingDiff
}
return feePortionPerSweep
}
// handleSpend handles a spend notification. // handleSpend handles a spend notification.
func (b *batch) handleSpend(ctx context.Context, spendTx *wire.MsgTx) error { func (b *batch) handleSpend(ctx context.Context, spendTx *wire.MsgTx) error {
var ( var (
@ -1236,14 +1151,12 @@ func (b *batch) handleSpend(ctx context.Context, spendTx *wire.MsgTx) error {
// sweeps that did not make it to the confirmed transaction and feed // sweeps that did not make it to the confirmed transaction and feed
// them back to the batcher. This will ensure that the sweeps will enter // them back to the batcher. This will ensure that the sweeps will enter
// a new batch instead of remaining dangling. // a new batch instead of remaining dangling.
var totalSweptAmt btcutil.Amount
for _, sweep := range b.sweeps { for _, sweep := range b.sweeps {
found := false found := false
for _, txIn := range spendTx.TxIn { for _, txIn := range spendTx.TxIn {
if txIn.PreviousOutPoint == sweep.outpoint { if txIn.PreviousOutPoint == sweep.outpoint {
found = true found = true
totalSweptAmt += sweep.value
notifyList = append(notifyList, sweep) notifyList = append(notifyList, sweep)
} }
} }
@ -1263,13 +1176,7 @@ func (b *batch) handleSpend(ctx context.Context, spendTx *wire.MsgTx) error {
} }
} }
// Calculate the fee portion that each sweep should pay for the batch.
feePortionPaidPerSweep, roundingDifference := getFeePortionForSweep(
spendTx, len(notifyList), totalSweptAmt,
)
for _, sweep := range notifyList { for _, sweep := range notifyList {
sweep := sweep
// Save the sweep as completed. // Save the sweep as completed.
err := b.persistSweep(ctx, sweep, true) err := b.persistSweep(ctx, sweep, true)
if err != nil { if err != nil {
@ -1285,17 +1192,9 @@ func (b *batch) handleSpend(ctx context.Context, spendTx *wire.MsgTx) error {
continue continue
} }
spendDetail := SpendDetail{
Tx: spendTx,
OnChainFeePortion: getFeePortionPaidBySweep(
spendTx, feePortionPaidPerSweep,
roundingDifference, &sweep,
),
}
// Dispatch the sweep notifier, we don't care about the outcome // Dispatch the sweep notifier, we don't care about the outcome
// of this action so we don't wait for it. // of this action so we don't wait for it.
go sweep.notifySweepSpend(ctx, &spendDetail) go notifySweepSpend(ctx, sweep, spendTx)
} }
// Proceed with purging the sweeps. This will feed the sweeps that // Proceed with purging the sweeps. This will feed the sweeps that
@ -1419,12 +1318,10 @@ func (b *batch) insertAndAcquireID(ctx context.Context) (int32, error) {
} }
// notifySweepSpend writes the spendTx to the sweep's notifier channel. // notifySweepSpend writes the spendTx to the sweep's notifier channel.
func (s *sweep) notifySweepSpend(ctx context.Context, func notifySweepSpend(ctx context.Context, s sweep, spendTx *wire.MsgTx) {
spendDetail *SpendDetail) {
select { select {
// Try to write the update to the notification channel. // Try to write the update to the notification channel.
case s.notifier.SpendChan <- spendDetail: case s.notifier.SpendChan <- spendTx:
// If a quit signal was provided by the swap, continue. // If a quit signal was provided by the swap, continue.
case <-s.notifier.QuitChan: case <-s.notifier.QuitChan:

@ -2,7 +2,6 @@ package sweepbatcher
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"sync" "sync"
"time" "time"
@ -13,9 +12,7 @@ import (
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/lndclient" "github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/utils" "github.com/lightninglabs/loop/utils"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
) )
@ -49,83 +46,32 @@ const (
type BatcherStore interface { type BatcherStore interface {
// FetchUnconfirmedSweepBatches fetches all the batches from the // FetchUnconfirmedSweepBatches fetches all the batches from the
// database that are not in a confirmed state. // database that are not in a confirmed state.
FetchUnconfirmedSweepBatches(ctx context.Context) ([]*dbBatch, error) FetchUnconfirmedSweepBatches(ctx context.Context) ([]*dbBatch,
error)
// InsertSweepBatch inserts a batch into the database, returning the id // InsertSweepBatch inserts a batch into the database, returning the id
// of the inserted batch. // of the inserted batch.
InsertSweepBatch(ctx context.Context, batch *dbBatch) (int32, error) InsertSweepBatch(ctx context.Context,
batch *dbBatch) (int32, error)
// DropBatch drops a batch from the database. This should only be used
// when a batch is empty.
DropBatch(ctx context.Context, id int32) error
// UpdateSweepBatch updates a batch in the database. // UpdateSweepBatch updates a batch in the database.
UpdateSweepBatch(ctx context.Context, batch *dbBatch) error UpdateSweepBatch(ctx context.Context,
batch *dbBatch) error
// ConfirmBatch confirms a batch by setting its state to confirmed. // ConfirmBatch confirms a batch by setting its state to confirmed.
ConfirmBatch(ctx context.Context, id int32) error ConfirmBatch(ctx context.Context, id int32) error
// FetchBatchSweeps fetches all the sweeps that belong to a batch. // FetchBatchSweeps fetches all the sweeps that belong to a batch.
FetchBatchSweeps(ctx context.Context, id int32) ([]*dbSweep, error) FetchBatchSweeps(ctx context.Context,
id int32) ([]*dbSweep, error)
// UpsertSweep inserts a sweep into the database, or updates an existing // UpsertSweep inserts a sweep into the database, or updates an existing
// sweep if it already exists. // sweep if it already exists.
UpsertSweep(ctx context.Context, sweep *dbSweep) error UpsertSweep(ctx context.Context, sweep *dbSweep) error
// GetSweepStatus returns the completed status of the sweep. // GetSweepStatus returns the completed status of the sweep.
GetSweepStatus(ctx context.Context, swapHash lntypes.Hash) (bool, error) GetSweepStatus(ctx context.Context, swapHash lntypes.Hash) (
bool, error)
// GetParentBatch returns the parent batch of a (completed) sweep.
GetParentBatch(ctx context.Context, swapHash lntypes.Hash) (*dbBatch,
error)
// TotalSweptAmount returns the total amount swept by a (confirmed)
// batch.
TotalSweptAmount(ctx context.Context, id int32) (btcutil.Amount, error)
}
// SweepInfo stores any data related to sweeping a specific outpoint.
type SweepInfo struct {
// ConfTarget is the confirmation target of the sweep.
ConfTarget int32
// Timeout is the timeout of the swap that the sweep belongs to.
Timeout int32
// InitiationHeight is the height at which the swap was initiated.
InitiationHeight int32
// HTLC is the HTLC that is being swept.
HTLC swap.Htlc
// Preimage is the preimage of the HTLC that is being swept.
Preimage lntypes.Preimage
// SwapInvoicePaymentAddr is the payment address of the swap invoice.
SwapInvoicePaymentAddr [32]byte
// HTLCKeys is the set of keys used to sign the HTLC.
HTLCKeys loopdb.HtlcKeys
// HTLCSuccessEstimator is a function that estimates the weight of the
// HTLC success script.
HTLCSuccessEstimator func(*input.TxWeightEstimator) error
// ProtocolVersion is the protocol version of the swap that the sweep
// belongs to.
ProtocolVersion loopdb.ProtocolVersion
// IsExternalAddr is true if the sweep spends to a non-wallet address.
IsExternalAddr bool
// DestAddr is the destination address of the sweep.
DestAddr btcutil.Address
}
// SweepFetcher is used to get details of a sweep.
type SweepFetcher interface {
// FetchSweep returns details of the sweep with the given hash.
FetchSweep(ctx context.Context, hash lntypes.Hash) (*SweepInfo, error)
} }
// MuSig2SignSweep is a function that can be used to sign a sweep transaction // MuSig2SignSweep is a function that can be used to sign a sweep transaction
@ -156,22 +102,11 @@ type SweepRequest struct {
Notifier *SpendNotifier Notifier *SpendNotifier
} }
type SpendDetail struct {
// Tx is the transaction that spent the outpoint.
Tx *wire.MsgTx
// OnChainFeePortion is the fee portion that was paid to get this sweep
// confirmed on chain. This is the difference between the value of the
// outpoint and the value of all sweeps that were included in the batch
// divided by the number of sweeps.
OnChainFeePortion btcutil.Amount
}
// SpendNotifier is a notifier that is used to notify the requester of a sweep // SpendNotifier is a notifier that is used to notify the requester of a sweep
// that the sweep was successful. // that the sweep was successful.
type SpendNotifier struct { type SpendNotifier struct {
// SpendChan is a channel where the spend details are received. // SpendChan is a channel where the spend details are received.
SpendChan chan *SpendDetail SpendChan chan *wire.MsgTx
// SpendErrChan is a channel where spend errors are received. // SpendErrChan is a channel where spend errors are received.
SpendErrChan chan error SpendErrChan chan error
@ -181,7 +116,7 @@ type SpendNotifier struct {
} }
var ( var (
ErrBatcherShuttingDown = errors.New("batcher shutting down") ErrBatcherShuttingDown = fmt.Errorf("batcher shutting down")
) )
// Batcher is a system that is responsible for accepting sweep requests and // Batcher is a system that is responsible for accepting sweep requests and
@ -199,10 +134,6 @@ type Batcher struct {
// quit signals that the batch must stop. // quit signals that the batch must stop.
quit chan struct{} quit chan struct{}
// initDone is a channel that is closed when the batcher has been
// initialized.
initDone chan struct{}
// wallet is the wallet kit client that is used by batches. // wallet is the wallet kit client that is used by batches.
wallet lndclient.WalletKitClient wallet lndclient.WalletKitClient
@ -229,8 +160,9 @@ type Batcher struct {
// batcher and the batches. // batcher and the batches.
store BatcherStore store BatcherStore
// sweepStore is used to load sweeps from the database. // swapStore includes all the database interactions that are needed for
sweepStore SweepFetcher // interacting with swaps.
swapStore loopdb.SwapStore
// wg is a waitgroup that is used to wait for all the goroutines to // wg is a waitgroup that is used to wait for all the goroutines to
// exit. // exit.
@ -242,14 +174,13 @@ func NewBatcher(wallet lndclient.WalletKitClient,
chainNotifier lndclient.ChainNotifierClient, chainNotifier lndclient.ChainNotifierClient,
signerClient lndclient.SignerClient, musig2ServerSigner MuSig2SignSweep, signerClient lndclient.SignerClient, musig2ServerSigner MuSig2SignSweep,
verifySchnorrSig VerifySchnorrSig, chainparams *chaincfg.Params, verifySchnorrSig VerifySchnorrSig, chainparams *chaincfg.Params,
store BatcherStore, sweepStore SweepFetcher) *Batcher { store BatcherStore, swapStore loopdb.SwapStore) *Batcher {
return &Batcher{ return &Batcher{
batches: make(map[int32]*batch), batches: make(map[int32]*batch),
sweepReqs: make(chan SweepRequest), sweepReqs: make(chan SweepRequest),
errChan: make(chan error, 1), errChan: make(chan error, 1),
quit: make(chan struct{}), quit: make(chan struct{}),
initDone: make(chan struct{}),
wallet: wallet, wallet: wallet,
chainNotifier: chainNotifier, chainNotifier: chainNotifier,
signerClient: signerClient, signerClient: signerClient,
@ -257,7 +188,7 @@ func NewBatcher(wallet lndclient.WalletKitClient,
VerifySchnorrSig: verifySchnorrSig, VerifySchnorrSig: verifySchnorrSig,
chainParams: chainparams, chainParams: chainparams,
store: store, store: store,
sweepStore: sweepStore, swapStore: swapStore,
} }
} }
@ -266,7 +197,6 @@ func (b *Batcher) Run(ctx context.Context) error {
runCtx, cancel := context.WithCancel(ctx) runCtx, cancel := context.WithCancel(ctx)
defer func() { defer func() {
cancel() cancel()
close(b.quit)
for _, batch := range b.batches { for _, batch := range b.batches {
batch.Wait() batch.Wait()
@ -289,9 +219,6 @@ func (b *Batcher) Run(ctx context.Context) error {
} }
} }
// Signal that the batcher has been initialized.
close(b.initDone)
for { for {
select { select {
case sweepReq := <-b.sweepReqs: case sweepReq := <-b.sweepReqs:
@ -343,7 +270,8 @@ func (b *Batcher) handleSweep(ctx context.Context, sweep *sweep,
// can't attach its notifier to the batch as that is no longer running. // can't attach its notifier to the batch as that is no longer running.
// Instead we directly detect and return the spend here. // Instead we directly detect and return the spend here.
if completed && *notifier != (SpendNotifier{}) { if completed && *notifier != (SpendNotifier{}) {
return b.monitorSpendAndNotify(ctx, sweep, notifier) go b.monitorSpendAndNotify(ctx, sweep, notifier)
return nil
} }
sweep.notifier = notifier sweep.notifier = notifier
@ -360,25 +288,22 @@ func (b *Batcher) handleSweep(ctx context.Context, sweep *sweep,
if batch.sweepExists(sweep.swapHash) { if batch.sweepExists(sweep.swapHash) {
accepted, err := batch.addSweep(ctx, sweep) accepted, err := batch.addSweep(ctx, sweep)
if err != nil && !errors.Is(err, ErrBatchShuttingDown) { if err != nil {
return err return err
} }
if !accepted { if !accepted {
return fmt.Errorf("existing sweep %x was not "+ return fmt.Errorf("existing sweep %x was not "+
"accepted by batch %d", "accepted by batch %d", sweep.swapHash[:6],
sweep.swapHash[:6], batch.id) batch.id)
} }
// The sweep was updated in the batch, our job is done.
return nil
} }
} }
// If one of the batches accepts the sweep, we provide it to that batch. // If one of the batches accepts the sweep, we provide it to that batch.
for _, batch := range b.batches { for _, batch := range b.batches {
accepted, err := batch.addSweep(ctx, sweep) accepted, err := batch.addSweep(ctx, sweep)
if err != nil && !errors.Is(err, ErrBatchShuttingDown) { if err != nil && err != ErrBatchShuttingDown {
return err return err
} }
@ -416,6 +341,7 @@ func (b *Batcher) handleSweep(ctx context.Context, sweep *sweep,
func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) { func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) {
cfg := batchConfig{ cfg := batchConfig{
maxTimeoutDistance: defaultMaxTimeoutDistance, maxTimeoutDistance: defaultMaxTimeoutDistance,
batchConfTarget: defaultBatchConfTarget,
} }
switch b.chainParams { switch b.chainParams {
@ -435,7 +361,6 @@ func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) {
verifySchnorrSig: b.VerifySchnorrSig, verifySchnorrSig: b.VerifySchnorrSig,
purger: b.AddSweep, purger: b.AddSweep,
store: b.store, store: b.store,
quit: b.quit,
} }
batch := NewBatch(cfg, batchKit) batch := NewBatch(cfg, batchKit)
@ -464,23 +389,23 @@ func (b *Batcher) spinUpBatch(ctx context.Context) (*batch, error) {
// spinUpBatchDB spins up a batch that already existed in storage, then // spinUpBatchDB spins up a batch that already existed in storage, then
// returns it. // returns it.
func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error { func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error {
cfg := batchConfig{
maxTimeoutDistance: batch.cfg.maxTimeoutDistance,
batchConfTarget: defaultBatchConfTarget,
}
rbfCache := rbfCache{
LastHeight: batch.rbfCache.LastHeight,
FeeRate: batch.rbfCache.FeeRate,
}
dbSweeps, err := b.store.FetchBatchSweeps(ctx, batch.id) dbSweeps, err := b.store.FetchBatchSweeps(ctx, batch.id)
if err != nil { if err != nil {
return err return err
} }
if len(dbSweeps) == 0 { if len(dbSweeps) == 0 {
log.Infof("skipping restored batch %d as it has no sweeps", return fmt.Errorf("batch %d has no sweeps", batch.id)
batch.id)
// It is safe to drop this empty batch as it has no sweeps.
err := b.store.DropBatch(ctx, batch.id)
if err != nil {
log.Warnf("unable to drop empty batch %d: %v",
batch.id, err)
}
return nil
} }
primarySweep := dbSweeps[0] primarySweep := dbSweeps[0]
@ -488,7 +413,7 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error {
sweeps := make(map[lntypes.Hash]sweep) sweeps := make(map[lntypes.Hash]sweep)
for _, dbSweep := range dbSweeps { for _, dbSweep := range dbSweeps {
sweep, err := b.convertSweep(ctx, dbSweep) sweep, err := b.convertSweep(dbSweep)
if err != nil { if err != nil {
return err return err
} }
@ -496,13 +421,6 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error {
sweeps[sweep.swapHash] = *sweep sweeps[sweep.swapHash] = *sweep
} }
rbfCache := rbfCache{
LastHeight: batch.rbfCache.LastHeight,
FeeRate: batch.rbfCache.FeeRate,
}
logger := batchPrefixLogger(fmt.Sprintf("%d", batch.id))
batchKit := batchKit{ batchKit := batchKit{
id: batch.id, id: batch.id,
batchTxid: batch.batchTxid, batchTxid: batch.batchTxid,
@ -519,18 +437,10 @@ func (b *Batcher) spinUpBatchFromDB(ctx context.Context, batch *batch) error {
verifySchnorrSig: b.VerifySchnorrSig, verifySchnorrSig: b.VerifySchnorrSig,
purger: b.AddSweep, purger: b.AddSweep,
store: b.store, store: b.store,
log: logger, log: batchPrefixLogger(fmt.Sprintf("%d", batch.id)),
quit: b.quit,
} }
cfg := batchConfig{ newBatch := NewBatchFromDB(cfg, batchKit)
maxTimeoutDistance: batch.cfg.maxTimeoutDistance,
}
newBatch, err := NewBatchFromDB(cfg, batchKit)
if err != nil {
return fmt.Errorf("failed in NewBatchFromDB: %w", err)
}
// We add the batch to our map of batches and start it. // We add the batch to our map of batches and start it.
b.batches[batch.id] = newBatch b.batches[batch.id] = newBatch
@ -599,88 +509,57 @@ func (b *Batcher) FetchUnconfirmedBatches(ctx context.Context) ([]*batch,
// monitorSpendAndNotify monitors the spend of a specific outpoint and writes // monitorSpendAndNotify monitors the spend of a specific outpoint and writes
// the response back to the response channel. // the response back to the response channel.
func (b *Batcher) monitorSpendAndNotify(ctx context.Context, sweep *sweep, func (b *Batcher) monitorSpendAndNotify(ctx context.Context, sweep *sweep,
notifier *SpendNotifier) error { notifier *SpendNotifier) {
b.wg.Add(1)
defer b.wg.Done()
spendCtx, cancel := context.WithCancel(ctx) spendCtx, cancel := context.WithCancel(ctx)
defer cancel() defer cancel()
// First get the batch that completed the sweep.
parentBatch, err := b.store.GetParentBatch(ctx, sweep.swapHash)
if err != nil {
return err
}
// Then we get the total amount that was swept by the batch.
totalSwept, err := b.store.TotalSweptAmount(ctx, parentBatch.ID)
if err != nil {
return err
}
spendChan, spendErr, err := b.chainNotifier.RegisterSpendNtfn( spendChan, spendErr, err := b.chainNotifier.RegisterSpendNtfn(
spendCtx, &sweep.outpoint, sweep.htlc.PkScript, spendCtx, &sweep.outpoint, sweep.htlc.PkScript,
sweep.initiationHeight, sweep.initiationHeight,
) )
if err != nil { if err != nil {
return err select {
case notifier.SpendErrChan <- err:
case <-ctx.Done():
}
_ = b.writeToErrChan(ctx, err)
return
} }
b.wg.Add(1) log.Infof("Batcher monitoring spend for swap %x", sweep.swapHash[:6])
go func() {
defer b.wg.Done()
log.Infof("Batcher monitoring spend for swap %x",
sweep.swapHash[:6])
for { for {
select {
case spend := <-spendChan:
select { select {
case spend := <-spendChan: case notifier.SpendChan <- spend.SpendingTx:
spendTx := spend.SpendingTx case <-ctx.Done():
// Calculate the fee portion that each sweep }
// should pay for the batch.
feePortionPerSweep, roundingDifference :=
getFeePortionForSweep(
spendTx, len(spendTx.TxIn),
totalSwept,
)
onChainFeePortion := getFeePortionPaidBySweep(
spendTx, feePortionPerSweep,
roundingDifference, sweep,
)
// Notify the requester of the spend
// with the spend details, including the fee
// portion for this particular sweep.
spendDetail := &SpendDetail{
Tx: spendTx,
OnChainFeePortion: onChainFeePortion,
}
select {
case notifier.SpendChan <- spendDetail:
case <-ctx.Done():
}
return
case err := <-spendErr:
select {
case notifier.SpendErrChan <- err:
case <-ctx.Done():
}
_ = b.writeToErrChan(ctx, err)
return
case <-notifier.QuitChan:
return
return
case err := <-spendErr:
select {
case notifier.SpendErrChan <- err:
case <-ctx.Done(): case <-ctx.Done():
return
} }
}
}()
return nil _ = b.writeToErrChan(ctx, err)
return
case <-notifier.QuitChan:
return
case <-ctx.Done():
return
}
}
} }
func (b *Batcher) writeToErrChan(ctx context.Context, err error) error { func (b *Batcher) writeToErrChan(ctx context.Context, err error) error {
@ -694,128 +573,85 @@ func (b *Batcher) writeToErrChan(ctx context.Context, err error) error {
} }
// convertSweep converts a fetched sweep from the database to a sweep that is // convertSweep converts a fetched sweep from the database to a sweep that is
// ready to be processed by the batcher. It loads swap from loopdb by calling // ready to be processed by the batcher.
// method FetchLoopOutSwap. func (b *Batcher) convertSweep(dbSweep *dbSweep) (*sweep, error) {
func (b *Batcher) convertSweep(ctx context.Context, dbSweep *dbSweep) ( swap := dbSweep.LoopOut
*sweep, error) {
htlc, err := utils.GetHtlc(
dbSweep.SwapHash, &swap.Contract.SwapContract, b.chainParams,
)
if err != nil {
return nil, err
}
s, err := b.sweepStore.FetchSweep(ctx, dbSweep.SwapHash) swapPaymentAddr, err := utils.ObtainSwapPaymentAddr(
swap.Contract.SwapInvoice, b.chainParams,
)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch sweep data for %x: %w", return nil, err
dbSweep.SwapHash[:6], err)
} }
return &sweep{ return &sweep{
swapHash: dbSweep.SwapHash, swapHash: swap.Hash,
outpoint: dbSweep.Outpoint, outpoint: dbSweep.Outpoint,
value: dbSweep.Amount, value: dbSweep.Amount,
confTarget: s.ConfTarget, confTarget: swap.Contract.SweepConfTarget,
timeout: s.Timeout, timeout: swap.Contract.CltvExpiry,
initiationHeight: s.InitiationHeight, initiationHeight: swap.Contract.InitiationHeight,
htlc: s.HTLC, htlc: *htlc,
preimage: s.Preimage, preimage: swap.Contract.Preimage,
swapInvoicePaymentAddr: s.SwapInvoicePaymentAddr, swapInvoicePaymentAddr: *swapPaymentAddr,
htlcKeys: s.HTLCKeys, htlcKeys: swap.Contract.HtlcKeys,
htlcSuccessEstimator: s.HTLCSuccessEstimator, htlcSuccessEstimator: htlc.AddSuccessToEstimator,
protocolVersion: s.ProtocolVersion, protocolVersion: swap.Contract.ProtocolVersion,
isExternalAddr: s.IsExternalAddr, isExternalAddr: swap.Contract.IsExternalAddr,
destAddr: s.DestAddr, destAddr: swap.Contract.DestAddr,
}, nil }, nil
} }
// LoopOutFetcher is used to load LoopOut swaps from the database. // fetchSweep fetches the sweep related information from the database.
// It is implemented by loopdb.SwapStore. func (b *Batcher) fetchSweep(ctx context.Context,
type LoopOutFetcher interface { sweepReq SweepRequest) (*sweep, error) {
// FetchLoopOutSwap returns the loop out swap with the given hash.
FetchLoopOutSwap(ctx context.Context,
hash lntypes.Hash) (*loopdb.LoopOut, error)
}
// SwapStoreWrapper is LoopOutFetcher wrapper providing SweepFetcher interface.
type SwapStoreWrapper struct {
// swapStore is used to load LoopOut swaps from the database.
swapStore LoopOutFetcher
// chainParams are the chain parameters of the chain that is used by
// batches.
chainParams *chaincfg.Params
}
// FetchSweep returns details of the sweep with the given hash. swapHash, err := lntypes.MakeHash(sweepReq.SwapHash[:])
// Implements SweepFetcher interface. if err != nil {
func (f *SwapStoreWrapper) FetchSweep(ctx context.Context, return nil, fmt.Errorf("failed to parse swapHash: %v", err)
swapHash lntypes.Hash) (*SweepInfo, error) { }
swap, err := f.swapStore.FetchLoopOutSwap(ctx, swapHash) swap, err := b.swapStore.FetchLoopOutSwap(ctx, swapHash)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch loop out for %x: %w", return nil, fmt.Errorf("failed to fetch loop out for %x: %v",
swapHash[:6], err) swapHash[:6], err)
} }
htlc, err := utils.GetHtlc( htlc, err := utils.GetHtlc(
swapHash, &swap.Contract.SwapContract, f.chainParams, swapHash, &swap.Contract.SwapContract, b.chainParams,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get htlc: %w", err) return nil, fmt.Errorf("failed to get htlc: %v", err)
} }
swapPaymentAddr, err := utils.ObtainSwapPaymentAddr( swapPaymentAddr, err := utils.ObtainSwapPaymentAddr(
swap.Contract.SwapInvoice, f.chainParams, swap.Contract.SwapInvoice, b.chainParams,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get payment addr: %w", err) return nil, fmt.Errorf("failed to get payment addr: %v", err)
}
return &SweepInfo{
ConfTarget: swap.Contract.SweepConfTarget,
Timeout: swap.Contract.CltvExpiry,
InitiationHeight: swap.Contract.InitiationHeight,
HTLC: *htlc,
Preimage: swap.Contract.Preimage,
SwapInvoicePaymentAddr: *swapPaymentAddr,
HTLCKeys: swap.Contract.HtlcKeys,
HTLCSuccessEstimator: htlc.AddSuccessToEstimator,
ProtocolVersion: swap.Contract.ProtocolVersion,
IsExternalAddr: swap.Contract.IsExternalAddr,
DestAddr: swap.Contract.DestAddr,
}, nil
}
// NewSweepFetcherFromSwapStore accepts swapStore (e.g. loopdb) and returns
// a wrapper implementing SweepFetcher interface (suitable for NewBatcher).
func NewSweepFetcherFromSwapStore(swapStore LoopOutFetcher,
chainParams *chaincfg.Params) (*SwapStoreWrapper, error) {
return &SwapStoreWrapper{
swapStore: swapStore,
chainParams: chainParams,
}, nil
}
// fetchSweep fetches the sweep related information from the database.
func (b *Batcher) fetchSweep(ctx context.Context,
sweepReq SweepRequest) (*sweep, error) {
s, err := b.sweepStore.FetchSweep(ctx, sweepReq.SwapHash)
if err != nil {
return nil, fmt.Errorf("failed to fetch sweep data for %x: %w",
sweepReq.SwapHash[:6], err)
} }
return &sweep{ return &sweep{
swapHash: sweepReq.SwapHash, swapHash: swap.Hash,
outpoint: sweepReq.Outpoint, outpoint: sweepReq.Outpoint,
value: sweepReq.Value, value: sweepReq.Value,
confTarget: s.ConfTarget, confTarget: swap.Contract.SweepConfTarget,
timeout: s.Timeout, timeout: swap.Contract.CltvExpiry,
initiationHeight: s.InitiationHeight, initiationHeight: swap.Contract.InitiationHeight,
htlc: s.HTLC, htlc: *htlc,
preimage: s.Preimage, preimage: swap.Contract.Preimage,
swapInvoicePaymentAddr: s.SwapInvoicePaymentAddr, swapInvoicePaymentAddr: *swapPaymentAddr,
htlcKeys: s.HTLCKeys, htlcKeys: swap.Contract.HtlcKeys,
htlcSuccessEstimator: s.HTLCSuccessEstimator, htlcSuccessEstimator: htlc.AddSuccessToEstimator,
protocolVersion: s.ProtocolVersion, protocolVersion: swap.Contract.ProtocolVersion,
isExternalAddr: s.IsExternalAddr, isExternalAddr: swap.Contract.IsExternalAddr,
destAddr: s.DestAddr, destAddr: swap.Contract.DestAddr,
}, nil }, nil
} }

File diff suppressed because it is too large Load Diff

@ -278,24 +278,11 @@ func (h *mockLightningClient) ListInvoices(_ context.Context,
// ListPayments makes a paginated call to our list payments endpoint. // ListPayments makes a paginated call to our list payments endpoint.
func (h *mockLightningClient) ListPayments(_ context.Context, func (h *mockLightningClient) ListPayments(_ context.Context,
req lndclient.ListPaymentsRequest) (*lndclient.ListPaymentsResponse, _ lndclient.ListPaymentsRequest) (*lndclient.ListPaymentsResponse,
error) { error) {
if req.Offset >= uint64(len(h.lnd.Payments)) {
return &lndclient.ListPaymentsResponse{}, nil
}
lastIndexOffset := req.Offset + req.MaxPayments
if lastIndexOffset > uint64(len(h.lnd.Payments)) {
lastIndexOffset = uint64(len(h.lnd.Payments))
}
result := h.lnd.Payments[req.Offset:lastIndexOffset]
return &lndclient.ListPaymentsResponse{ return &lndclient.ListPaymentsResponse{
Payments: result, Payments: h.lnd.Payments,
FirstIndexOffset: req.Offset,
LastIndexOffset: lastIndexOffset - 1,
}, nil }, nil
} }

@ -70,7 +70,7 @@ func mockMuSig2SignSweep(ctx context.Context,
return nil, nil, nil return nil, nil, nil
} }
func newSwapClient(t *testing.T, config *clientConfig) *Client { func newSwapClient(config *clientConfig) *Client {
sweeper := &sweep.Sweeper{ sweeper := &sweep.Sweeper{
Lnd: config.LndServices, Lnd: config.LndServices,
} }
@ -79,16 +79,11 @@ func newSwapClient(t *testing.T, config *clientConfig) *Client {
batcherStore := sweepbatcher.NewStoreMock() batcherStore := sweepbatcher.NewStoreMock()
sweepStore, err := sweepbatcher.NewSweepFetcherFromSwapStore(
config.Store, config.LndServices.ChainParams,
)
require.NoError(t, err)
batcher := sweepbatcher.NewBatcher( batcher := sweepbatcher.NewBatcher(
config.LndServices.WalletKit, config.LndServices.ChainNotifier, config.LndServices.WalletKit, config.LndServices.ChainNotifier,
config.LndServices.Signer, mockMuSig2SignSweep, config.LndServices.Signer, mockMuSig2SignSweep,
mockVerifySchnorrSigSuccess, config.LndServices.ChainParams, mockVerifySchnorrSigSuccess, config.LndServices.ChainParams,
batcherStore, sweepStore, batcherStore, config.Store,
) )
executor := newExecutor(&executorConfig{ executor := newExecutor(&executorConfig{
@ -133,7 +128,7 @@ func createClientTestContext(t *testing.T,
return expiryChan return expiryChan
} }
swapClient := newSwapClient(t, &clientConfig{ swapClient := newSwapClient(&clientConfig{
LndServices: &clientLnd.LndServices, LndServices: &clientLnd.LndServices,
Server: serverMock, Server: serverMock,
Store: store, Store: store,

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save