Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightninglabs/loop/utils"
"github.com/lightninglabs/taproot-assets/rpcutils"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route"
"google.golang.org/grpc"
Expand Down Expand Up @@ -485,7 +486,10 @@ func (s *Client) Run(ctx context.Context, statusChan chan<- SwapInfo) error {
func (s *Client) resumeSwaps(ctx context.Context,
loopOutSwaps []*loopdb.LoopOut, loopInSwaps []*loopdb.LoopIn) {

swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server, s.AssetClient)
swapCfg := newSwapConfig(
s.lndServices, s.Store, s.Server, s.AssetClient,
clock.NewDefaultClock(),
)

for _, pend := range loopOutSwaps {
if pend.State().State.Type() != loopdb.StateTypePending {
Expand Down Expand Up @@ -578,6 +582,7 @@ func (s *Client) LoopOut(globalCtx context.Context,
// Create a new swap object for this swap.
swapCfg := newSwapConfig(
s.lndServices, s.Store, s.Server, s.AssetClient,
clock.NewDefaultClock(),
)

initResult, err := newLoopOutSwap(
Expand Down Expand Up @@ -759,7 +764,10 @@ func (s *Client) LoopIn(globalCtx context.Context,

// Create a new swap object for this swap.
initiationHeight := s.executor.height()
swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server, s.AssetClient)
swapCfg := newSwapConfig(
s.lndServices, s.Store, s.Server, s.AssetClient,
clock.NewDefaultClock(),
)
initResult, err := newLoopInSwap(
globalCtx, swapCfg, initiationHeight, request,
)
Expand Down
3 changes: 3 additions & 0 deletions cost_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/lightninglabs/lndclient"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
Expand All @@ -25,6 +26,7 @@ func TestCalculateLoopOutCost(t *testing.T) {
lnd: &lnd.LndServices,
store: store,
server: server,
clock: clock.NewTestClock(time.Unix(123, 0)),
}

height := int32(600)
Expand Down Expand Up @@ -118,6 +120,7 @@ func TestCostMigration(t *testing.T) {
lnd: &lnd.LndServices,
store: store,
server: server,
clock: clock.NewTestClock(time.Unix(123, 0)),
}

height := int32(600)
Expand Down
3 changes: 2 additions & 1 deletion loopd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,8 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
}

loop.Resume(
d.mainCtx, notificationManager, swapClient.Store, d.impl.Conn, d.lnd,
d.mainCtx, notificationManager, swapClient.Store,
d.impl.Conn, d.lnd, clock.NewDefaultClock(),
)

// Last, start our internal error handler. This will return exactly one
Expand Down
7 changes: 3 additions & 4 deletions loopin.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"sync"
"time"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
Expand Down Expand Up @@ -264,7 +263,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig,

// Instantiate a struct that contains all required data to start the
// swap.
initiationTime := time.Now()
initiationTime := cfg.clock.Now()

contract := loopdb.LoopInContract{
HtlcConfTarget: request.HtlcConfTarget,
Expand Down Expand Up @@ -837,7 +836,7 @@ func (s *loopInSwap) publishOnChainHtlc(ctx context.Context) (bool, error) {
// the fee for publishing the htlc.
s.cost.Onchain = fee

s.lastUpdateTime = time.Now()
s.lastUpdateTime = s.clock.Now()
if err := s.persistState(ctx); err != nil {
return false, fmt.Errorf("persist htlc tx: %v", err)
}
Expand Down Expand Up @@ -1210,7 +1209,7 @@ func (s *loopInSwap) persistState(ctx context.Context) error {

// setState updates the swap state and last update timestamp.
func (s *loopInSwap) setState(state loopdb.SwapState) {
s.lastUpdateTime = time.Now()
s.lastUpdateTime = s.clock.Now()
s.state = state
}

Expand Down
23 changes: 19 additions & 4 deletions loopin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/lightninglabs/loop/test"
"github.com/lightninglabs/loop/utils"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/clock"
invpkg "github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route"
Expand Down Expand Up @@ -129,8 +130,12 @@ func testLoopInSuccess(t *testing.T) {
ctx := newLoopInTestContext(t)

height := int32(600)
startTime := time.Unix(123, 0)

cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil)
cfg := newSwapConfig(
&ctx.lnd.LndServices, ctx.store, ctx.server, nil,
clock.NewTestClock(startTime),
)

expectedLastHop := &route.Vertex{0x02}

Expand All @@ -144,6 +149,7 @@ func testLoopInSuccess(t *testing.T) {
require.NoError(t, err)

inSwap := initResult.swap
require.Equal(t, startTime, inSwap.InitiationTime)

ctx.store.AssertLoopInStored()

Expand Down Expand Up @@ -279,7 +285,10 @@ func testLoopInTimeout(t *testing.T, externalValue int64) {

height := int32(600)

cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil)
cfg := newSwapConfig(
&ctx.lnd.LndServices, ctx.store, ctx.server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

req := testLoopInRequest
if externalValue != 0 {
Expand Down Expand Up @@ -490,7 +499,10 @@ func testLoopInResume(t *testing.T, state loopdb.SwapState, expired bool,
ctxb := context.Background()

ctx := newLoopInTestContext(t)
cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil)
cfg := newSwapConfig(
&ctx.lnd.LndServices, ctx.store, ctx.server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

// Create sender and receiver keys.
_, senderPubKey := test.CreateKey(1)
Expand Down Expand Up @@ -845,7 +857,10 @@ func advanceToPublishedHtlc(t *testing.T, ctx *loopInTestContext) SwapInfo {
func startNewLoopIn(t *testing.T, ctx *loopInTestContext, height int32) (
*swapConfig, *loopInSwap, error) {

cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil)
cfg := newSwapConfig(
&ctx.lnd.LndServices, ctx.store, ctx.server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

req := &testLoopInRequest

Expand Down
15 changes: 9 additions & 6 deletions loopout.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/lightninglabs/taproot-assets/fn"
"github.com/lightninglabs/taproot-assets/rfqmsg"
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
Expand Down Expand Up @@ -192,7 +193,7 @@ func newLoopOutSwap(globalCtx context.Context, cfg *swapConfig,

// Instantiate a struct that contains all required data to start the
// swap.
initiationTime := time.Now()
initiationTime := cfg.clock.Now()

contract := loopdb.LoopOutContract{
SwapInvoice: swapResp.swapInvoice,
Expand Down Expand Up @@ -633,7 +634,7 @@ func (s *loopOutSwap) executeSwap(globalCtx context.Context) error {

// persistState updates the swap state and sends out an update notification.
func (s *loopOutSwap) persistState(ctx context.Context) error {
updateTime := time.Now()
updateTime := s.clock.Now()

s.lastUpdateTime = updateTime

Expand Down Expand Up @@ -864,12 +865,12 @@ func (s *loopOutSwap) payInvoiceAsync(ctx context.Context,
payCtx, cancel := context.WithCancel(ctx)
defer cancel()

start := time.Now()
start := s.clock.Now()
paymentStatus, attempts, err := s.sendPaymentWithRetry(
payCtx, hash, &req, maxRetries, routingPlugin, pluginType,
)

dt := time.Since(start)
dt := s.clock.Now().Sub(start)
paymentSuccess := err == nil &&
paymentStatus.State == lnrpc.Payment_SUCCEEDED

Expand Down Expand Up @@ -1543,6 +1544,7 @@ type resumeManager struct {
swapStore loopdb.SwapStore
swapClient swapserverrpc.SwapServerClient
lnd *lndclient.GrpcLndServices
clock clock.Clock

reqChan chan *swapserverrpc.ServerUnfinishedSwapNotification
}
Expand All @@ -1552,13 +1554,14 @@ type resumeManager struct {
func Resume(ctx context.Context, ntfnManager NotificationManager,
swapStore loopdb.SwapStore,
swapClientConn *grpc.ClientConn,
lnd *lndclient.GrpcLndServices) {
lnd *lndclient.GrpcLndServices, clock clock.Clock) {

resumeManager := &resumeManager{
ntfnManager: ntfnManager,
swapStore: swapStore,
swapClient: swapserverrpc.NewSwapServerClient(swapClientConn),
lnd: lnd,
clock: clock,
reqChan: make(chan *swapserverrpc.ServerUnfinishedSwapNotification, 1),
}
go resumeManager.start(ctx)
Expand Down Expand Up @@ -1717,7 +1720,7 @@ func (m *resumeManager) resumeLoopOutPayment(ctx context.Context,
cost.Server = payResp.Value.ToSatoshis() - amtRequested
cost.Offchain = payResp.Fee.ToSatoshis()
// Payment succeeded.
updateTime := time.Now()
updateTime := m.clock.Now()

// Update state in store.
err = m.swapStore.UpdateLoopOut(
Expand Down
13 changes: 12 additions & 1 deletion loopout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/lightninglabs/loop/sweep"
"github.com/lightninglabs/loop/sweepbatcher"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/clock"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
Expand Down Expand Up @@ -57,11 +58,13 @@ func testLoopOutPaymentParameters(t *testing.T) {
}

height := int32(600)
startTime := time.Unix(123, 0)

cfg := &swapConfig{
lnd: &lnd.LndServices,
store: store,
server: server,
clock: clock.NewTestClock(startTime),
}

sweeper := &sweep.Sweeper{Lnd: &lnd.LndServices}
Expand All @@ -82,6 +85,7 @@ func testLoopOutPaymentParameters(t *testing.T) {
)
require.NoError(t, err)
swap := initResult.swap
require.Equal(t, startTime, swap.InitiationTime)

// Execute the swap in its own goroutine.
errChan := make(chan error)
Expand Down Expand Up @@ -193,7 +197,10 @@ func testLateHtlcPublish(t *testing.T) {

height := int32(600)

cfg := newSwapConfig(&lnd.LndServices, store, server, nil)
cfg := newSwapConfig(
&lnd.LndServices, store, server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

testRequest.Expiry = height + testLoopOutMinOnChainCltvDelta

Expand Down Expand Up @@ -296,6 +303,7 @@ func testCustomSweepConfTarget(t *testing.T) {

cfg := newSwapConfig(
&lnd.LndServices, loopdb.NewStoreMock(t), server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

initResult, err := newLoopOutSwap(
Expand Down Expand Up @@ -539,6 +547,7 @@ func testPreimagePush(t *testing.T) {

cfg := newSwapConfig(
&lnd.LndServices, loopdb.NewStoreMock(t), server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

initResult, err := newLoopOutSwap(
Expand Down Expand Up @@ -797,6 +806,7 @@ func testFailedOffChainCancelation(t *testing.T) {

cfg := newSwapConfig(
&lnd.LndServices, loopdb.NewStoreMock(t), server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

initResult, err := newLoopOutSwap(
Expand Down Expand Up @@ -951,6 +961,7 @@ func TestLoopOutMuSig2Sweep(t *testing.T) {

cfg := newSwapConfig(
&lnd.LndServices, loopdb.NewStoreMock(t), server, nil,
clock.NewTestClock(time.Unix(123, 0)),
)

initResult, err := newLoopOutSwap(
Expand Down
2 changes: 1 addition & 1 deletion staticaddr/deposit/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const (
// MinConfs is the minimum number of confirmations we require for a
// deposit to be considered available for loop-ins, coop-spends and
// timeouts.
MinConfs = 6
MinConfs = 3

// MaxConfs is unset since we don't require a max number of
// confirmations for deposits.
Expand Down
32 changes: 32 additions & 0 deletions staticaddr/loopin/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire"
"google.golang.org/grpc/status"
)

const (
Expand Down Expand Up @@ -146,6 +147,10 @@ func (f *FSM) InitHtlcAction(ctx context.Context,
ctx, loopInReq,
)
if err != nil {
// Check if this is an insufficient confirmations error and log
// the details to help the user understand what's needed.
logInsufficientConfirmationsDetails(err)

err = fmt.Errorf("unable to initiate the loop-in with the "+
"server: %w", err)

Expand Down Expand Up @@ -914,3 +919,30 @@ func byteSliceTo66ByteSlice(b []byte) ([musig2.PubNonceSize]byte, error) {

return res, nil
}

// logInsufficientConfirmationsDetails extracts and logs the per-deposit
// confirmation details from a gRPC error if present.
func logInsufficientConfirmationsDetails(err error) {
st, ok := status.FromError(err)
if !ok {
return
}

for _, detail := range st.Details() {
confDetails, ok :=
detail.(*swapserverrpc.InsufficientConfirmationsDetails)

if !ok {
continue
}

log.Warnf("Insufficient deposit confirmations, max wait: %d blocks",
confDetails.MaxBlocksToWait)

for _, dep := range confDetails.Deposits {
log.Warnf(" Deposit %s: %d/%d confirmations (need %d more blocks)",
dep.Outpoint, dep.CurrentConfirmations,
dep.RequiredConfirmations, dep.BlocksToWait)
}
}
}
Loading
Loading