Skip to content

Commit 1ce09ef

Browse files
committed
loopd: simplify ListUnspentDeposits to use deposit state
Remove the MinConfs-based bifurcation from ListUnspentDeposits. All wallet UTXOs are now checked against the deposit store: known deposits in the Deposited state are available, unknown outpoints are new deposits and also available, and all other known states are filtered out. The mock deposit store now returns ErrDepositNotFound for missing outpoints to match the real store behavior, and tests are updated to verify availability by deposit state rather than confirmation depth.
1 parent 3fed19f commit 1ce09ef

2 files changed

Lines changed: 44 additions & 52 deletions

File tree

loopd/swapclient_server.go

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,54 +1671,43 @@ func (s *swapClientServer) ListUnspentDeposits(ctx context.Context,
16711671
// not spendable because they already have been used but not yet spent
16721672
// by the server. We filter out such deposits here.
16731673
var (
1674-
outpoints []string
1675-
isUnspent = make(map[wire.OutPoint]struct{})
1674+
outpoints []string
1675+
isUnspent = make(map[wire.OutPoint]struct{})
1676+
knownUtxos = make(map[wire.OutPoint]struct{})
16761677
)
16771678

1678-
// Keep track of confirmed outpoints that we need to check against our
1679-
// database.
1680-
confirmedToCheck := make(map[wire.OutPoint]struct{})
1681-
16821679
for _, utxo := range utxos {
1683-
if utxo.Confirmations < deposit.MinConfs {
1684-
// Unconfirmed deposits are always available.
1685-
isUnspent[utxo.OutPoint] = struct{}{}
1686-
} else {
1687-
// Confirmed deposits need to be checked.
1688-
outpoints = append(outpoints, utxo.OutPoint.String())
1689-
confirmedToCheck[utxo.OutPoint] = struct{}{}
1690-
}
1680+
outpoints = append(outpoints, utxo.OutPoint.String())
1681+
knownUtxos[utxo.OutPoint] = struct{}{}
16911682
}
16921683

16931684
// Check the spent status of the deposits by looking at their states.
1694-
ignoreUnknownOutpoints := false
1685+
ignoreUnknownOutpoints := true
16951686
deposits, err := s.depositManager.DepositsForOutpoints(
16961687
ctx, outpoints, ignoreUnknownOutpoints,
16971688
)
16981689
if err != nil {
16991690
return nil, err
17001691
}
1692+
1693+
knownDeposits := make(map[wire.OutPoint]struct{}, len(deposits))
17011694
for _, d := range deposits {
1702-
// A nil deposit means we don't have a record for it. We'll
1703-
// handle this case after the loop.
17041695
if d == nil {
17051696
continue
17061697
}
17071698

1708-
// If the deposit is in the "Deposited" state, it's available.
1699+
knownDeposits[d.OutPoint] = struct{}{}
17091700
if d.IsInState(deposit.Deposited) {
17101701
isUnspent[d.OutPoint] = struct{}{}
17111702
}
1712-
1713-
// We have a record for this deposit, so we no longer need to
1714-
// check it.
1715-
delete(confirmedToCheck, d.OutPoint)
17161703
}
17171704

1718-
// Any remaining outpoints in confirmedToCheck are ones that lnd knows
1719-
// about but we don't. These are new, unspent deposits.
1720-
for op := range confirmedToCheck {
1721-
isUnspent[op] = struct{}{}
1705+
// Any wallet outpoints that are unknown to the deposit store are new
1706+
// deposits and therefore still available.
1707+
for op := range knownUtxos {
1708+
if _, ok := knownDeposits[op]; !ok {
1709+
isUnspent[op] = struct{}{}
1710+
}
17221711
}
17231712

17241713
// Prepare the list of unspent deposits for the rpc response.

loopd/swapclient_server_test.go

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ func (s *mockDepositStore) DepositForOutpoint(_ context.Context,
10021002
if d, ok := s.byOutpoint[outpoint]; ok {
10031003
return d, nil
10041004
}
1005-
return nil, nil
1005+
return nil, deposit.ErrDepositNotFound
10061006
}
10071007
func (s *mockDepositStore) AllDeposits(_ context.Context) ([]*deposit.Deposit,
10081008
error) {
@@ -1051,11 +1051,11 @@ func TestListUnspentDeposits(t *testing.T) {
10511051
}
10521052
}
10531053

1054-
minConfs := int64(deposit.MinConfs)
1055-
utxoBelow := makeUtxo(0, minConfs-1) // always included
1056-
utxoAt := makeUtxo(1, minConfs) // included only if Deposited
1057-
utxoAbove1 := makeUtxo(2, minConfs+1)
1058-
utxoAbove2 := makeUtxo(3, minConfs+2)
1054+
utxoUnknown := makeUtxo(0, 0)
1055+
utxoDeposited := makeUtxo(1, 1)
1056+
utxoWithdrawn := makeUtxo(2, 2)
1057+
utxoLoopingIn := makeUtxo(3, 5)
1058+
utxoConfirmedUnknown := makeUtxo(4, 3)
10591059

10601060
// Helper to build the deposit manager with specific states.
10611061
buildDepositMgr := func(
@@ -1073,17 +1073,19 @@ func TestListUnspentDeposits(t *testing.T) {
10731073
return deposit.NewManager(&deposit.ManagerConfig{Store: store})
10741074
}
10751075

1076-
// Include below-min-conf and >=min with Deposited; exclude others.
1077-
t.Run("below min conf always, Deposited included, others excluded",
1076+
// Unknown deposits are available, Deposited is available and known
1077+
// non-Deposited states are excluded.
1078+
t.Run("unknown and Deposited included, locked states excluded",
10781079
func(t *testing.T) {
10791080
mock.SetListUnspent([]*lnwallet.Utxo{
1080-
utxoBelow, utxoAt, utxoAbove1, utxoAbove2,
1081+
utxoUnknown, utxoDeposited, utxoWithdrawn,
1082+
utxoLoopingIn,
10811083
})
10821084

10831085
depMgr := buildDepositMgr(map[wire.OutPoint]fsm.StateType{
1084-
utxoAt.OutPoint: deposit.Deposited,
1085-
utxoAbove1.OutPoint: deposit.Withdrawn,
1086-
utxoAbove2.OutPoint: deposit.LoopingIn,
1086+
utxoDeposited.OutPoint: deposit.Deposited,
1087+
utxoWithdrawn.OutPoint: deposit.Withdrawn,
1088+
utxoLoopingIn.OutPoint: deposit.LoopingIn,
10871089
})
10881090

10891091
server := &swapClientServer{
@@ -1096,7 +1098,7 @@ func TestListUnspentDeposits(t *testing.T) {
10961098
)
10971099
require.NoError(t, err)
10981100

1099-
// Expect utxoBelow and utxoAt only.
1101+
// Expect the unknown utxo and the Deposited utxo only.
11001102
require.Len(t, resp.Utxos, 2)
11011103
got := map[string]struct{}{}
11021104
for _, u := range resp.Utxos {
@@ -1105,25 +1107,25 @@ func TestListUnspentDeposits(t *testing.T) {
11051107
// same across utxos.
11061108
require.NotEmpty(t, u.StaticAddress)
11071109
}
1108-
_, ok1 := got[utxoBelow.OutPoint.String()]
1109-
_, ok2 := got[utxoAt.OutPoint.String()]
1110+
_, ok1 := got[utxoUnknown.OutPoint.String()]
1111+
_, ok2 := got[utxoDeposited.OutPoint.String()]
11101112
require.True(t, ok1)
11111113
require.True(t, ok2)
11121114
})
11131115

1114-
// Swap states, now include utxoBelow and utxoAbove1.
1115-
t.Run("Deposited on >=min included; non-Deposited excluded",
1116+
// Confirmation depth no longer changes availability; state does.
1117+
t.Run("availability ignores conf depth once deposit state is known",
11161118
func(t *testing.T) {
11171119
mock.SetListUnspent(
11181120
[]*lnwallet.Utxo{
1119-
utxoBelow, utxoAt, utxoAbove1,
1120-
utxoAbove2,
1121+
utxoUnknown, utxoDeposited,
1122+
utxoWithdrawn, utxoLoopingIn,
11211123
})
11221124

11231125
depMgr := buildDepositMgr(map[wire.OutPoint]fsm.StateType{
1124-
utxoAt.OutPoint: deposit.Withdrawn,
1125-
utxoAbove1.OutPoint: deposit.Deposited,
1126-
utxoAbove2.OutPoint: deposit.Withdrawn,
1126+
utxoDeposited.OutPoint: deposit.Deposited,
1127+
utxoWithdrawn.OutPoint: deposit.Withdrawn,
1128+
utxoLoopingIn.OutPoint: deposit.LoopingIn,
11271129
})
11281130

11291131
server := &swapClientServer{
@@ -1141,8 +1143,8 @@ func TestListUnspentDeposits(t *testing.T) {
11411143
for _, u := range resp.Utxos {
11421144
got[u.Outpoint] = struct{}{}
11431145
}
1144-
_, ok1 := got[utxoBelow.OutPoint.String()]
1145-
_, ok2 := got[utxoAbove1.OutPoint.String()]
1146+
_, ok1 := got[utxoUnknown.OutPoint.String()]
1147+
_, ok2 := got[utxoDeposited.OutPoint.String()]
11461148
require.True(t, ok1)
11471149
require.True(t, ok2)
11481150
})
@@ -1151,7 +1153,7 @@ func TestListUnspentDeposits(t *testing.T) {
11511153
t.Run("confirmed utxo not in store is included", func(t *testing.T) {
11521154
// Only return a confirmed UTXO from lnd and make sure the
11531155
// deposit manager/store doesn't know about it.
1154-
mock.SetListUnspent([]*lnwallet.Utxo{utxoAbove2})
1156+
mock.SetListUnspent([]*lnwallet.Utxo{utxoConfirmedUnknown})
11551157

11561158
// Empty store (no states for any outpoint).
11571159
depMgr := buildDepositMgr(map[wire.OutPoint]fsm.StateType{})
@@ -1170,7 +1172,8 @@ func TestListUnspentDeposits(t *testing.T) {
11701172
// doesn't exist in the store yet.
11711173
require.Len(t, resp.Utxos, 1)
11721174
require.Equal(
1173-
t, utxoAbove2.OutPoint.String(), resp.Utxos[0].Outpoint,
1175+
t, utxoConfirmedUnknown.OutPoint.String(),
1176+
resp.Utxos[0].Outpoint,
11741177
)
11751178
require.NotEmpty(t, resp.Utxos[0].StaticAddress)
11761179
})

0 commit comments

Comments
 (0)