Skip to content

Commit f0ed1b6

Browse files
committed
assets+loopdb: recover active deposits on startup
This commit adds deposit recovery to the deposit manager's startup process. All deposits that have not yet been spent by the server or swept by the client are recovered from the store.
1 parent 183d542 commit f0ed1b6

File tree

7 files changed

+193
-0
lines changed

7 files changed

+193
-0
lines changed

assets/deposit/manager.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
156156

157157
m.currentHeight = bestBlock
158158

159+
err := m.recoverDeposits(ctx)
160+
if err != nil {
161+
log.Errorf("Unable to recover deposits: %v", err)
162+
163+
return err
164+
}
165+
159166
blockChan, blockErrChan, err := m.chainNotifier.RegisterBlockEpochNtfn(
160167
ctxc,
161168
)
@@ -228,6 +235,56 @@ func (m *Manager) criticalError(err error) {
228235
}
229236
}
230237

238+
// recoverDeposits recovers all active deppsits when the deposit manager starts.
239+
func (m *Manager) recoverDeposits(ctx context.Context) error {
240+
// Fetch all active deposits from the store to kick-off the manager.
241+
activeDeposits, err := m.store.GetActiveDeposits(ctx)
242+
if err != nil {
243+
log.Errorf("Unable to fetch deposits from store: %v", err)
244+
245+
return err
246+
}
247+
248+
for i := range activeDeposits {
249+
d := &activeDeposits[i]
250+
log.Infof("Recovering deposit %v (state=%s)", d.ID, d.State)
251+
252+
m.deposits[d.ID] = d
253+
_, _, _, err = m.isDepositFunded(ctx, d)
254+
if err != nil {
255+
return err
256+
}
257+
258+
if d.State == StateInitiated {
259+
// If the deposit has just been initiated, then we need
260+
// to ensure that it is funded.
261+
err = m.fundDepositIfNeeded(ctx, d)
262+
if err != nil {
263+
log.Errorf("Unable to fund deposit %v: %v",
264+
d.ID, err)
265+
266+
return err
267+
}
268+
} else {
269+
// Cache proof info of the deposit in-memory.
270+
err = m.cacheProofInfo(ctx, d)
271+
if err != nil {
272+
return err
273+
}
274+
275+
// Register the deposit as known so that we can claim
276+
// the funds committed to the OP_TRUE script. If the
277+
// deposit is already registered, this will be a no-op.
278+
err = m.registerDepositAsKnown(ctx, d)
279+
if err != nil {
280+
return err
281+
}
282+
}
283+
}
284+
285+
return nil
286+
}
287+
231288
// handleBlockEpoch is called when a new block is added to the chain.
232289
func (m *Manager) handleBlockEpoch(ctx context.Context, height uint32) error {
233290
for _, d := range m.deposits {

assets/deposit/manager_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ func (s *mockStore) GetAllDeposits(context.Context) ([]Deposit, error) {
4040
return []Deposit{}, nil
4141
}
4242

43+
// GetActiveDeposits is a mock implementation of the GetActiveDeposits method.
44+
func (s *mockStore) GetActiveDeposits(context.Context) ([]Deposit, error) {
45+
return []Deposit{}, nil
46+
}
47+
4348
// testAddDeposit is a helper function that (intrusively) adds a deposit to the
4449
// manager.
4550
func testAddDeposit(t *testing.T, m *Manager, d *Deposit) {

assets/deposit/sql_store.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ type Querier interface {
3232

3333
SetAssetDepositSweepKeys(ctx context.Context,
3434
arg sqlc.SetAssetDepositSweepKeysParams) error
35+
36+
GetActiveAssetDeposits(ctx context.Context) (
37+
[]sqlc.GetActiveAssetDepositsRow, error)
3538
}
3639

3740
// DepositBaseDB is the interface that contains all the queries generated
@@ -284,3 +287,27 @@ func sqlcDepositToDeposit(sqlDeposit sqlc.GetAssetDepositsRow,
284287
Info: depositInfo,
285288
}, nil
286289
}
290+
291+
// GetActiveDeposits returns all active deposits from the database. Active
292+
// deposits are those that have not yet been spent or swept.
293+
func (s *SQLStore) GetActiveDeposits(ctx context.Context) ([]Deposit, error) {
294+
sqlDeposits, err := s.db.GetActiveAssetDeposits(ctx)
295+
if err != nil {
296+
return nil, err
297+
}
298+
299+
deposits := make([]Deposit, 0, len(sqlDeposits))
300+
for _, sqlDeposit := range sqlDeposits {
301+
deposit, err := sqlcDepositToDeposit(
302+
sqlc.GetAssetDepositsRow(sqlDeposit),
303+
&s.addressParams,
304+
)
305+
if err != nil {
306+
return nil, err
307+
}
308+
309+
deposits = append(deposits, deposit)
310+
}
311+
312+
return deposits, nil
313+
}

assets/deposit/store.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ type Store interface {
1313

1414
// GetAllDeposits returns all deposits known to the store.
1515
GetAllDeposits(ctx context.Context) ([]Deposit, error)
16+
17+
// GetActiveDeposits returns all active deposits from the database.
18+
// Active deposits are those that have not yet been spent or swept.
19+
GetActiveDeposits(ctx context.Context) ([]Deposit, error)
1620
}

loopdb/sqlc/asset_deposits.sql.go

Lines changed: 84 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/queries/asset_deposits.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,18 @@ ORDER BY d.created_at ASC;
4444
UPDATE asset_deposits
4545
SET sweep_script_pubkey = $2, sweep_internal_pubkey = $3
4646
WHERE deposit_id = $1;
47+
48+
-- name: GetActiveAssetDeposits :many
49+
SELECT d.*, u.update_state, u.update_timestamp
50+
FROM asset_deposits d
51+
JOIN asset_deposit_updates u
52+
ON u.deposit_id = d.deposit_id
53+
WHERE u.id = (
54+
SELECT id
55+
FROM asset_deposit_updates
56+
WHERE deposit_id = d.deposit_id
57+
ORDER BY update_timestamp DESC
58+
LIMIT 1
59+
)
60+
AND u.update_state IN (0, 1, 2, 3, 4, 5, 6);
61+

0 commit comments

Comments
 (0)