Skip to content

Commit 060266c

Browse files
committed
assets+loopd: add scaffolding for the asset deposit manager
This commit extends the deposit package with the `Deposit` type and a bare-bones `Manager`, along with the structural definition of the `SQLStore` which together implement the basic structure, run loop and storage for the deposit manager. It is not yet functional and serves as a foundation for future commits that will gradually extend its functionality.
1 parent acf5730 commit 060266c

File tree

7 files changed

+664
-5
lines changed

7 files changed

+664
-5
lines changed

assets/deposit/deposit.go

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
package deposit
2+
3+
import (
4+
"context"
5+
"encoding/hex"
6+
"fmt"
7+
"time"
8+
9+
"github.com/btcsuite/btcd/btcec/v2"
10+
"github.com/btcsuite/btcd/wire"
11+
"github.com/btcsuite/btcwallet/wtxmgr"
12+
"github.com/lightninglabs/loop/assets"
13+
"github.com/lightninglabs/taproot-assets/proof"
14+
)
15+
16+
// State is the enum used for deposit states.
17+
type State uint8
18+
19+
const (
20+
// StateInitiated indicates that the deposit has been initiated by the
21+
// client.
22+
StateInitiated State = 0
23+
24+
// StatePending indicates that the deposit is pending confirmation on
25+
// the blockchain.
26+
StatePending State = 1
27+
28+
// StateConfirmed indicates that the deposit has been confirmed on the
29+
// blockchain.
30+
StateConfirmed State = 2
31+
32+
// StateExpired indicates that the deposit has expired.
33+
StateExpired State = 3
34+
35+
// StateTimeoutSweepPublished indicates that the timeout sweep has been
36+
// published.
37+
StateTimeoutSweepPublished State = 4
38+
39+
// StateWithdrawn indicates that the deposit has been withdrawn.
40+
StateWithdrawn State = 5
41+
42+
// StateCooperativeSweepPublished indicates that the cooperative sweep
43+
// withdrawing the deposit has been published.
44+
StateCooperativeSweepPublished State = 6
45+
46+
// StateKeyRevealed indicates that the client has revealed a valid key
47+
// for the deposit which is now ready to be swept.
48+
StateKeyRevealed State = 7
49+
50+
// StateSpent indicates that the deposit has been spent.
51+
StateSpent State = 8
52+
53+
// StateSwept indicates that the deposit has been swept, either by a
54+
// timeout sweep or a cooperative (ie withdrawal) sweep.
55+
StateSwept State = 9
56+
)
57+
58+
// String coverts a deposit state to human readable string.
59+
func (s State) String() string {
60+
switch s {
61+
case StateInitiated:
62+
return "Initiated"
63+
64+
case StatePending:
65+
return "Pending"
66+
67+
case StateConfirmed:
68+
return "Confirmed"
69+
70+
case StateExpired:
71+
return "Expired"
72+
73+
case StateTimeoutSweepPublished:
74+
return "TimeoutSweepPublished"
75+
76+
case StateWithdrawn:
77+
return "Withdrawn"
78+
79+
case StateCooperativeSweepPublished:
80+
return "CooperativeSweepPublished"
81+
82+
case StateKeyRevealed:
83+
return "KeyRevealed"
84+
85+
case StateSpent:
86+
return "Spent"
87+
88+
case StateSwept:
89+
return "Swept"
90+
91+
default:
92+
return "Unknown"
93+
}
94+
}
95+
96+
// IsFinal returns true if the deposit state is final, meaning that no further
97+
// actions can be taken on the deposit.
98+
func (s State) IsFinal() bool {
99+
return s == StateSpent || s == StateSwept
100+
}
101+
102+
// DepositInfo holds publicly available information about an asset deposit.
103+
// It is used to communicate deposit details to clients of the deposit Manager.
104+
type DepositInfo struct {
105+
// ID is the unique identifier for this deposit which will also be used
106+
// to store the deposit in both the server and client databases.
107+
ID string
108+
109+
// Version is the protocol version of the deposit.
110+
Version AssetDepositProtocolVersion
111+
112+
// CreatedAt is the time when the deposit was created (on the client).
113+
CreatedAt time.Time
114+
115+
// Amount is the amount of asset to be deposited.
116+
Amount uint64
117+
118+
// Addr is the TAP deposit address where the asset will be sent.
119+
Addr string
120+
121+
// State is the deposit state.
122+
State State
123+
124+
// ConfirmationHeight is the block height at which the deposit was
125+
// confirmed.
126+
ConfirmationHeight uint32
127+
128+
// Outpoint is the anchor outpoint of the deposit. It is only set if the
129+
// deposit has been confirmed.
130+
Outpoint *wire.OutPoint
131+
132+
// Expiry is the block height at which the deposit will expire. It is
133+
// only set if the deposit has been confirmed.
134+
Expiry uint32
135+
136+
// SweepScriptKey is the script key of the swept asset.
137+
SweepScriptKey *btcec.PublicKey
138+
139+
// SweepInternalKey is the internal key of output of the swept asset.
140+
SweepInternalKey *btcec.PublicKey
141+
}
142+
143+
// Copy creates a copy of the DepositInfo struct.
144+
func (d *DepositInfo) Copy() *DepositInfo {
145+
info := &DepositInfo{
146+
ID: d.ID,
147+
Version: d.Version,
148+
CreatedAt: d.CreatedAt,
149+
Amount: d.Amount,
150+
Addr: d.Addr,
151+
State: d.State,
152+
ConfirmationHeight: d.ConfirmationHeight,
153+
Expiry: d.Expiry,
154+
}
155+
156+
if d.Outpoint != nil {
157+
info.Outpoint = &wire.OutPoint{
158+
Hash: d.Outpoint.Hash,
159+
Index: d.Outpoint.Index,
160+
}
161+
}
162+
163+
if d.SweepScriptKey != nil {
164+
pubKey := *d.SweepScriptKey
165+
info.SweepScriptKey = &pubKey
166+
}
167+
168+
if d.SweepInternalKey != nil {
169+
pubKey := *d.SweepInternalKey
170+
info.SweepInternalKey = &pubKey
171+
}
172+
173+
return info
174+
}
175+
176+
// Deposit is the struct that holds all the information about an asset deposit.
177+
type Deposit struct {
178+
*Kit
179+
180+
*DepositInfo
181+
182+
// PkScript is the pkscript of the deposit anchor output.
183+
PkScript []byte
184+
185+
// Proof is the proof of the deposit transfer.
186+
Proof *proof.Proof
187+
188+
// AnchorRootHash is the root hash of the deposit anchor output.
189+
AnchorRootHash []byte
190+
}
191+
192+
// fundingLabel returns a string label that we can use for marking a transfer
193+
// funding the deposit. This is useful if we need to filter deposits.
194+
func (d *Deposit) fundingLabel() string {
195+
return fmt.Sprintf("deposit funding %v", d.ID)
196+
}
197+
198+
// timeoutSweepLabel is a string label that we can use for marking a timeout
199+
// sweep transfer. This is useful if we need to filter deposits.
200+
func (d *Deposit) timeoutSweepLabel() string {
201+
return fmt.Sprintf("deposit timeout sweep %v", d.ID)
202+
}
203+
204+
// withdrawLabel is a string label that we can use for marking a withdrawal
205+
// sweep transfer. This is useful if we need to filter deposits.
206+
func (d *Deposit) withdrawLabel() string {
207+
return fmt.Sprintf("deposit withdraw sweep %v", d.ID)
208+
}
209+
210+
// lockID converts a deposit ID to a lock ID. The lock ID is used to lock inputs
211+
// used for the deposit sweep transaction. Note that we assume that the deposit
212+
// ID is a hex-encoded string of the same length as the lock ID.
213+
func (d *Deposit) lockID() (wtxmgr.LockID, error) {
214+
var lockID wtxmgr.LockID
215+
depositIDBytes, err := hex.DecodeString(d.ID)
216+
if err != nil {
217+
return wtxmgr.LockID{}, err
218+
}
219+
220+
if len(depositIDBytes) != len(lockID) {
221+
return wtxmgr.LockID{}, fmt.Errorf("invalid deposit ID "+
222+
"length: %d", len(depositIDBytes))
223+
}
224+
225+
copy(lockID[:], depositIDBytes)
226+
227+
return lockID, nil
228+
}
229+
230+
// GenerateSweepKeys generates the sweep script key and internal key for the
231+
// deposit sweep.
232+
func (d *Deposit) GenerateSweepKeys(ctx context.Context,
233+
client *assets.TapdClient) error {
234+
235+
if d.SweepScriptKey != nil {
236+
return nil
237+
}
238+
239+
scriptKey, internalKeyDesc, err := client.DeriveNewKeys(ctx)
240+
if err != nil {
241+
return err
242+
}
243+
244+
d.SweepScriptKey = scriptKey.PubKey
245+
d.SweepInternalKey = internalKeyDesc.PubKey
246+
247+
return nil
248+
}

0 commit comments

Comments
 (0)