loopd: filter static deposit views through active set

Use the deposit manager's visible-deposit view for normal list and
summary RPCs so historical Deposited rows whose outpoints vanished from
lnd's wallet view are not exposed as available funds.
This commit is contained in:
Slyghtning 2026-07-08 13:55:32 +02:00
parent dc7da41b28
commit 1d935c657f
No known key found for this signature in database
GPG key ID: F82D456EA023C9BF
2 changed files with 80 additions and 5 deletions

View file

@ -1022,9 +1022,11 @@ func (s *swapClientServer) GetLoopInQuote(ctx context.Context,
// server can probe the selected value and calculate the per // server can probe the selected value and calculate the per
// input fee. // input fee.
for _, deposit := range depositList.FilteredDeposits { for _, deposit := range depositList.FilteredDeposits {
// For a manual quote we require the current state to be // ListStaticAddressDeposits only returns deposits that are visible
// Deposited so a stale client-side outpoint selection // in the manager's live view. For a manual quote we additionally
// fails early instead of making it to swap initiation. // require the current state to be Deposited so stale client-side
// outpoint selection fails early instead of making it to swap
// initiation.
if deposit.State != looprpc.DepositState_DEPOSITED { if deposit.State != looprpc.DepositState_DEPOSITED {
return nil, fmt.Errorf("deposit %s is not "+ return nil, fmt.Errorf("deposit %s is not "+
"currently available", deposit.Outpoint) "currently available", deposit.Outpoint)
@ -1882,7 +1884,7 @@ func (s *swapClientServer) ListStaticAddressDeposits(ctx context.Context,
"outpoints") "outpoints")
} }
allDeposits, err := s.depositManager.GetAllDeposits(ctx) allDeposits, err := s.depositManager.GetVisibleDeposits(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2119,7 +2121,7 @@ func (s *swapClientServer) GetStaticAddressSummary(ctx context.Context,
_ *looprpc.StaticAddressSummaryRequest) ( _ *looprpc.StaticAddressSummaryRequest) (
*looprpc.StaticAddressSummaryResponse, error) { *looprpc.StaticAddressSummaryResponse, error) {
allDeposits, err := s.depositManager.GetAllDeposits(ctx) allDeposits, err := s.depositManager.GetVisibleDeposits(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -136,6 +136,79 @@ func newTestStaticAddressContext(t *testing.T) (*address.Manager,
return addrMgr, mock return addrMgr, mock
} }
// TestListStaticAddressDepositsReturnsVisibleDeposits verifies normal deposit
// listings include visible deposit records.
func TestListStaticAddressDepositsReturnsVisibleDeposits(t *testing.T) {
t.Parallel()
available := &deposit.Deposit{
OutPoint: wire.OutPoint{
Hash: chainhash.Hash{2},
Index: 2,
},
}
available.SetState(deposit.Deposited)
addrMgr, lnd := newTestStaticAddressContext(t)
server := &swapClientServer{
depositManager: newTestDepositManager(available),
staticAddressManager: addrMgr,
lnd: &lnd.LndServices,
}
resp, err := server.ListStaticAddressDeposits(
context.Background(), &looprpc.ListStaticAddressDepositsRequest{},
)
require.NoError(t, err)
require.Len(t, resp.FilteredDeposits, 1)
require.Equal(
t, available.OutPoint.String(),
resp.FilteredDeposits[0].Outpoint,
)
}
// TestGetStaticAddressSummaryTotalsDeposits verifies visible deposits are
// included in static address summary totals.
func TestGetStaticAddressSummaryTotalsDeposits(t *testing.T) {
t.Parallel()
unconfirmed := &deposit.Deposit{
OutPoint: wire.OutPoint{
Hash: chainhash.Hash{4},
Index: 4,
},
Value: btcutil.Amount(2_000),
ConfirmationHeight: 0,
}
unconfirmed.SetState(deposit.Deposited)
confirmed := &deposit.Deposit{
OutPoint: wire.OutPoint{
Hash: chainhash.Hash{5},
Index: 5,
},
Value: btcutil.Amount(3_000),
ConfirmationHeight: 123,
}
confirmed.SetState(deposit.Deposited)
addrMgr, _ := newTestStaticAddressContext(t)
server := &swapClientServer{
depositManager: newTestDepositManager(
unconfirmed, confirmed,
),
staticAddressManager: addrMgr,
}
resp, err := server.GetStaticAddressSummary(
context.Background(), &looprpc.StaticAddressSummaryRequest{},
)
require.NoError(t, err)
require.EqualValues(t, 2, resp.TotalNumDeposits)
require.EqualValues(t, 2_000, resp.ValueUnconfirmedSatoshis)
require.EqualValues(t, 3_000, resp.ValueDepositedSatoshis)
}
// TestGetLoopInQuoteRejectsUnavailableSelectedDeposit verifies manual quote // TestGetLoopInQuoteRejectsUnavailableSelectedDeposit verifies manual quote
// requests fail for selected deposits that are no longer available. // requests fail for selected deposits that are no longer available.
func TestGetLoopInQuoteRejectsUnavailableSelectedDeposit(t *testing.T) { func TestGetLoopInQuoteRejectsUnavailableSelectedDeposit(t *testing.T) {