@@ -2,25 +2,35 @@ package staticaddr
22
33import (
44 "context"
5+ "database/sql"
56 "errors"
67
78 "github.com/btcsuite/btcd/btcec/v2"
9+ "github.com/btcsuite/btcd/btcutil"
10+ "github.com/btcsuite/btcd/chaincfg/chainhash"
11+ "github.com/btcsuite/btcd/wire"
812 "github.com/jackc/pgx/v4"
13+ "github.com/lightninglabs/loop/fsm"
914 "github.com/lightninglabs/loop/loopdb"
1015 "github.com/lightninglabs/loop/loopdb/sqlc"
16+ "github.com/lightningnetwork/lnd/clock"
1117 "github.com/lightningnetwork/lnd/keychain"
1218)
1319
1420// SqlStore is the backing store for static addresses.
1521type SqlStore struct {
1622 baseDB * loopdb.BaseDB
23+
24+ clock clock.Clock
1725}
1826
1927// NewSqlStore constructs a new SQLStore from a BaseDB. The BaseDB is agnostic
2028// to the underlying driver which can be postgres or sqlite.
2129func NewSqlStore (db * loopdb.BaseDB ) * SqlStore {
2230 return & SqlStore {
2331 baseDB : db ,
32+
33+ clock : clock .NewDefaultClock (),
2434 }
2535}
2636
@@ -112,6 +122,179 @@ func (s *SqlStore) GetAllStaticAddresses(ctx context.Context) (
112122 return result , nil
113123}
114124
125+ // CreateDeposit creates a static address record in the database.
126+ func (s * SqlStore ) CreateDeposit (ctx context.Context , deposit * Deposit ) error {
127+ createArgs := sqlc.CreateDepositParams {
128+ DepositID : deposit .ID [:],
129+ TxHash : deposit .Hash [:],
130+ OutIndex : int32 (deposit .Index ),
131+ Amount : int64 (deposit .Value ),
132+ ConfirmationHeight : deposit .ConfirmationHeight ,
133+ TimeOutSweepPkScript : deposit .TimeOutSweepPkScript ,
134+ }
135+
136+ updateArgs := sqlc.InsertDepositUpdateParams {
137+ DepositID : deposit .ID [:],
138+ UpdateTimestamp : s .clock .Now ().UTC (),
139+ UpdateState : string (deposit .State ),
140+ }
141+
142+ return s .baseDB .ExecTx (ctx , & loopdb.SqliteTxOptions {},
143+ func (q * sqlc.Queries ) error {
144+ err := q .CreateDeposit (ctx , createArgs )
145+ if err != nil {
146+ return err
147+ }
148+
149+ return q .InsertDepositUpdate (ctx , updateArgs )
150+ })
151+ }
152+
153+ // UpdateDeposit updates the deposit in the database.
154+ func (s * SqlStore ) UpdateDeposit (ctx context.Context , deposit * Deposit ) error {
155+ insertUpdateArgs := sqlc.InsertDepositUpdateParams {
156+ DepositID : deposit .ID [:],
157+ UpdateTimestamp : s .clock .Now ().UTC (),
158+ UpdateState : string (deposit .State ),
159+ }
160+
161+ var (
162+ txHash = deposit .Hash [:]
163+ outIndex = sql.NullInt32 {
164+ Int32 : int32 (deposit .Index ),
165+ Valid : true ,
166+ }
167+ )
168+
169+ updateArgs := sqlc.UpdateDepositParams {
170+ DepositID : deposit .ID [:],
171+ TxHash : txHash ,
172+ OutIndex : outIndex .Int32 ,
173+ ConfirmationHeight : marshalSqlNullInt64 (
174+ deposit .ConfirmationHeight ,
175+ ).Int64 ,
176+ }
177+
178+ return s .baseDB .ExecTx (ctx , & loopdb.SqliteTxOptions {},
179+ func (q * sqlc.Queries ) error {
180+ err := q .UpdateDeposit (ctx , updateArgs )
181+ if err != nil {
182+ return err
183+ }
184+
185+ return q .InsertDepositUpdate (ctx , insertUpdateArgs )
186+ })
187+ }
188+
189+ // GetDeposit retrieves the deposit from the database.
190+ func (s * SqlStore ) GetDeposit (ctx context.Context , id ID ) (* Deposit , error ) {
191+ var deposit * Deposit
192+ err := s .baseDB .ExecTx (ctx , loopdb .NewSqlReadOpts (),
193+ func (q * sqlc.Queries ) error {
194+ var err error
195+ row , err := q .GetDeposit (ctx , id [:])
196+ if err != nil {
197+ return err
198+ }
199+
200+ updates , err := q .GetDepositUpdates (ctx , id [:])
201+ if err != nil {
202+ return err
203+ }
204+
205+ if len (updates ) == 0 {
206+ return errors .New ("no deposit updates" )
207+ }
208+
209+ deposit , err = s .toDeposit (row , updates [len (updates )- 1 ])
210+ if err != nil {
211+ return err
212+ }
213+
214+ return nil
215+ })
216+ if err != nil {
217+ return nil , err
218+ }
219+
220+ return deposit , nil
221+ }
222+
223+ // AllDeposits retrieves all known deposits to our static address.
224+ func (s * SqlStore ) AllDeposits (ctx context.Context ) ([]* Deposit , error ) {
225+ var allDeposits []* Deposit
226+
227+ err := s .baseDB .ExecTx (ctx , loopdb .NewSqlReadOpts (),
228+ func (q * sqlc.Queries ) error {
229+ var err error
230+
231+ deposits , err := q .AllDeposits (ctx )
232+ if err != nil {
233+ return err
234+ }
235+
236+ for _ , deposit := range deposits {
237+ updates , err := q .GetDepositUpdates (
238+ ctx , deposit .DepositID ,
239+ )
240+ if err != nil {
241+ return err
242+ }
243+
244+ if len (updates ) == 0 {
245+ return errors .New ("no deposit updates" )
246+ }
247+
248+ lastUpdate := updates [len (updates )- 1 ]
249+
250+ d , err := s .toDeposit (deposit , lastUpdate )
251+ if err != nil {
252+ return err
253+ }
254+
255+ allDeposits = append (allDeposits , d )
256+ }
257+
258+ return nil
259+ })
260+ if err != nil {
261+ return nil , err
262+ }
263+
264+ return allDeposits , nil
265+ }
266+
267+ // toDeposit converts an sql deposit to a deposit.
268+ func (s * SqlStore ) toDeposit (row sqlc.Deposit ,
269+ lastUpdate sqlc.DepositUpdate ) (* Deposit , error ) {
270+
271+ id := ID {}
272+ err := id .FromByteSlice (row .DepositID )
273+ if err != nil {
274+ return nil , err
275+ }
276+
277+ var txHash * chainhash.Hash
278+ if row .TxHash != nil {
279+ txHash , err = chainhash .NewHash (row .TxHash )
280+ if err != nil {
281+ return nil , err
282+ }
283+ }
284+
285+ return & Deposit {
286+ ID : id ,
287+ State : fsm .StateType (lastUpdate .UpdateState ),
288+ OutPoint : wire.OutPoint {
289+ Hash : * txHash ,
290+ Index : uint32 (row .OutIndex ),
291+ },
292+ Value : btcutil .Amount (row .Amount ),
293+ ConfirmationHeight : row .ConfirmationHeight ,
294+ TimeOutSweepPkScript : row .TimeOutSweepPkScript ,
295+ }, nil
296+ }
297+
115298// Close closes the database connection.
116299func (s * SqlStore ) Close () {
117300 s .baseDB .DB .Close ()
@@ -144,3 +327,11 @@ func (s *SqlStore) toAddressParameters(row sqlc.StaticAddress) (
144327 ProtocolVersion : AddressProtocolVersion (row .ProtocolVersion ),
145328 }, nil
146329}
330+
331+ // marshalSqlNullInt64 converts an int64 to a sql.NullInt64.
332+ func marshalSqlNullInt64 (i int64 ) sql.NullInt64 {
333+ return sql.NullInt64 {
334+ Int64 : i ,
335+ Valid : i != 0 ,
336+ }
337+ }
0 commit comments