From 650640c854672c86db114423c7c676d28ac7d7de Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Fri, 13 Mar 2026 11:18:31 +0100 Subject: [PATCH] Revert "staticaddr: support dynamic deposit confirmation requirements" This reverts commit 66a17f47e69c2913f4fac55f9deba0adc20bd3ec. --- staticaddr/deposit/manager.go | 2 +- staticaddr/loopin/actions.go | 32 ------------------ staticaddr/loopin/manager.go | 41 ++++++++--------------- staticaddr/loopin/manager_test.go | 55 +++++-------------------------- 4 files changed, 24 insertions(+), 106 deletions(-) diff --git a/staticaddr/deposit/manager.go b/staticaddr/deposit/manager.go index 2f023901..af882030 100644 --- a/staticaddr/deposit/manager.go +++ b/staticaddr/deposit/manager.go @@ -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 = 3 + MinConfs = 6 // MaxConfs is unset since we don't require a max number of // confirmations for deposits. diff --git a/staticaddr/loopin/actions.go b/staticaddr/loopin/actions.go index eadf7ba5..70a27811 100644 --- a/staticaddr/loopin/actions.go +++ b/staticaddr/loopin/actions.go @@ -30,7 +30,6 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" - "google.golang.org/grpc/status" ) const ( @@ -147,10 +146,6 @@ 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) @@ -919,30 +914,3 @@ 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) - } - } -} diff --git a/staticaddr/loopin/manager.go b/staticaddr/loopin/manager.go index 97f6e41d..444ab585 100644 --- a/staticaddr/loopin/manager.go +++ b/staticaddr/loopin/manager.go @@ -850,13 +850,11 @@ func (m *Manager) GetAllSwaps(ctx context.Context) ([]*StaticAddressLoopIn, return swaps, nil } -// SelectDeposits sorts the deposits to optimize for successful swaps with -// dynamic confirmation requirements: 1) more confirmations first (higher chance -// of server acceptance), 2) larger amounts first (to minimize number of deposits -// used), 3) expiring sooner first (to use time-sensitive deposits). It then -// selects the deposits that are needed to cover the amount requested without -// leaving a dust change. It returns an error if the sum of deposits minus dust -// is less than the requested amount. +// SelectDeposits sorts the deposits by amount in descending order, then by +// blocks-until-expiry in ascending order. It then selects the deposits that +// are needed to cover the amount requested without leaving a dust change. It +// returns an error if the sum of deposits minus dust is less than the requested +// amount. func SelectDeposits(targetAmount btcutil.Amount, unfilteredDeposits []*deposit.Deposit, csvExpiry uint32, blockHeight uint32) ([]*deposit.Deposit, error) { @@ -877,28 +875,17 @@ func SelectDeposits(targetAmount btcutil.Amount, deposits = append(deposits, d) } - // Sort deposits to optimize for successful swaps with dynamic - // confirmation requirements: - // 1. More confirmations first (higher chance of server acceptance) - // 2. Larger amounts first (to minimize number of deposits used) + // Sort the deposits by amount in descending order, then by + // blocks-until-expiry in ascending order. sort.Slice(deposits, func(i, j int) bool { - // Primary: more confirmations first. Guard against the - // theoretical case where ConfirmationHeight > blockHeight - // (e.g. during a transient reorg inconsistency). - var iConfs, jConfs uint32 - if blockHeight > uint32(deposits[i].ConfirmationHeight) { - iConfs = blockHeight - - uint32(deposits[i].ConfirmationHeight) - } - if blockHeight > uint32(deposits[j].ConfirmationHeight) { - jConfs = blockHeight - - uint32(deposits[j].ConfirmationHeight) - } - if iConfs != jConfs { - return iConfs > jConfs - } + if deposits[i].Value == deposits[j].Value { + iExp := uint32(deposits[i].ConfirmationHeight) + + csvExpiry - blockHeight + jExp := uint32(deposits[j].ConfirmationHeight) + + csvExpiry - blockHeight - // Secondary: larger amounts first. + return iExp < jExp + } return deposits[i].Value > deposits[j].Value }) diff --git a/staticaddr/loopin/manager_test.go b/staticaddr/loopin/manager_test.go index d367a3dc..d908a9e1 100644 --- a/staticaddr/loopin/manager_test.go +++ b/staticaddr/loopin/manager_test.go @@ -26,14 +26,10 @@ type testCase struct { // TestSelectDeposits tests the selectDeposits function, which selects // deposits that can cover a target value while respecting the dust limit. -// Sorting priority: 1) more confirmations first, 2) larger amounts first, -// 3) expiring sooner first. func TestSelectDeposits(t *testing.T) { - // Note: confirmations = blockHeight - ConfirmationHeight - // Lower ConfirmationHeight means more confirmations at a given block. d1, d2, d3, d4 := &deposit.Deposit{ Value: 1_000_000, - ConfirmationHeight: 5_000, // most confs at height 5100 + ConfirmationHeight: 5_000, }, &deposit.Deposit{ Value: 2_000_000, ConfirmationHeight: 5_001, @@ -42,7 +38,7 @@ func TestSelectDeposits(t *testing.T) { ConfirmationHeight: 5_002, }, &deposit.Deposit{ Value: 3_000_000, - ConfirmationHeight: 5_003, // fewest confs at height 5100 + ConfirmationHeight: 5_003, } d1.Hash = chainhash.Hash{1} d1.Index = 0 @@ -53,51 +49,32 @@ func TestSelectDeposits(t *testing.T) { d4.Hash = chainhash.Hash{4} d4.Index = 0 - // Use a realistic block height and csv expiry for all standard - // test cases. csvExpiry must be large enough that deposits remain - // swappable at this block height. - const ( - testBlockHeight uint32 = 5_100 - testCsvExpiry uint32 = 2_500 - ) - testCases := []testCase{ { name: "single deposit exact target", deposits: []*deposit.Deposit{d1}, targetValue: 1_000_000, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{d1}, expectedErr: "", }, { - // d1 has more confirmations, so it's preferred even - // though d2 is larger. - name: "prefer more confirmed deposit over larger", + name: "prefer larger deposit when both cover", deposits: []*deposit.Deposit{d1, d2}, targetValue: 1_000_000, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, - expected: []*deposit.Deposit{d1}, + expected: []*deposit.Deposit{d2}, expectedErr: "", }, { - // d1 has the most confirmations among d1, d2, d3. - name: "prefer most confirmed among three", + name: "prefer largest among three when one is enough", deposits: []*deposit.Deposit{d1, d2, d3}, targetValue: 1_000_000, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, - expected: []*deposit.Deposit{d1}, + expected: []*deposit.Deposit{d3}, expectedErr: "", }, { name: "single deposit insufficient by 1", deposits: []*deposit.Deposit{d1}, targetValue: 1_000_001, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{}, expectedErr: "not enough deposits to cover", }, @@ -105,8 +82,6 @@ func TestSelectDeposits(t *testing.T) { name: "target leaves exact dust limit change", deposits: []*deposit.Deposit{d1}, targetValue: 1_000_000 - dustLimit, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{d1}, expectedErr: "", }, @@ -114,8 +89,6 @@ func TestSelectDeposits(t *testing.T) { name: "target leaves dust change (just over)", deposits: []*deposit.Deposit{d1}, targetValue: 1_000_000 - dustLimit + 1, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{}, expectedErr: "not enough deposits to cover", }, @@ -123,8 +96,6 @@ func TestSelectDeposits(t *testing.T) { name: "all deposits exactly match target", deposits: []*deposit.Deposit{d1, d2, d3}, targetValue: d1.Value + d2.Value + d3.Value, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{d1, d2, d3}, expectedErr: "", }, @@ -132,8 +103,6 @@ func TestSelectDeposits(t *testing.T) { name: "sum minus dust limit is allowed (change == dust)", deposits: []*deposit.Deposit{d1, d2, d3}, targetValue: d1.Value + d2.Value + d3.Value - dustLimit, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{d1, d2, d3}, expectedErr: "", }, @@ -141,20 +110,14 @@ func TestSelectDeposits(t *testing.T) { name: "sum minus dust limit plus 1 is not allowed (dust change)", deposits: []*deposit.Deposit{d1, d2, d3}, targetValue: d1.Value + d2.Value + d3.Value - dustLimit + 1, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, expected: []*deposit.Deposit{}, expectedErr: "not enough deposits to cover", }, { - // d3 and d4 have the same value but d3 has more - // confirmations (lower ConfirmationHeight), so it - // wins at the primary sort level. - name: "same value, prefer more confirmed", + name: "tie by value, prefer earlier expiry", deposits: []*deposit.Deposit{d3, d4}, - targetValue: d4.Value - dustLimit, - csvExpiry: testCsvExpiry, - blockHeight: testBlockHeight, + targetValue: d4.Value - dustLimit, // d3/d4 have the + // same value but different expiration. expected: []*deposit.Deposit{d3}, expectedErr: "", },