Skip to content

Commit 2ff22f2

Browse files
committed
assets: add store implementation
1 parent 8c58a0c commit 2ff22f2

File tree

2 files changed

+401
-0
lines changed

2 files changed

+401
-0
lines changed

assets/store.go

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
package assets
2+
3+
import (
4+
"context"
5+
6+
"github.com/btcsuite/btcd/btcec/v2"
7+
"github.com/btcsuite/btcd/chaincfg/chainhash"
8+
"github.com/btcsuite/btcd/wire"
9+
"github.com/lightninglabs/loop/assets/htlc"
10+
"github.com/lightninglabs/loop/fsm"
11+
"github.com/lightninglabs/loop/loopdb"
12+
"github.com/lightninglabs/loop/loopdb/sqlc"
13+
"github.com/lightningnetwork/lnd/clock"
14+
"github.com/lightningnetwork/lnd/keychain"
15+
"github.com/lightningnetwork/lnd/lntypes"
16+
)
17+
18+
// BaseDB is the interface that contains all the queries generated
19+
// by sqlc for the instantout table.
20+
type BaseDB interface {
21+
// ExecTx allows for executing a function in the context of a database
22+
// transaction.
23+
ExecTx(ctx context.Context, txOptions loopdb.TxOptions,
24+
txBody func(*sqlc.Queries) error) error
25+
26+
CreateAssetSwap(ctx context.Context, arg sqlc.CreateAssetSwapParams) error
27+
CreateAssetOutSwap(ctx context.Context, swapHash []byte) error
28+
GetAllAssetOutSwaps(ctx context.Context) ([]sqlc.GetAllAssetOutSwapsRow, error)
29+
GetAssetOutSwap(ctx context.Context, swapHash []byte) (sqlc.GetAssetOutSwapRow, error)
30+
InsertAssetSwapUpdate(ctx context.Context, arg sqlc.InsertAssetSwapUpdateParams) error
31+
UpdateAssetSwapHtlcTx(ctx context.Context, arg sqlc.UpdateAssetSwapHtlcTxParams) error
32+
UpdateAssetSwapOutPreimage(ctx context.Context, arg sqlc.UpdateAssetSwapOutPreimageParams) error
33+
UpdateAssetSwapOutProof(ctx context.Context, arg sqlc.UpdateAssetSwapOutProofParams) error
34+
UpdateAssetSwapSweepTx(ctx context.Context, arg sqlc.UpdateAssetSwapSweepTxParams) error
35+
}
36+
37+
// PostgresStore is the backing store for the instant out manager.
38+
type PostgresStore struct {
39+
queries BaseDB
40+
clock clock.Clock
41+
}
42+
43+
// NewPostgresStore creates a new PostgresStore.
44+
func NewPostgresStore(queries BaseDB) *PostgresStore {
45+
return &PostgresStore{
46+
queries: queries,
47+
clock: clock.NewDefaultClock(),
48+
}
49+
}
50+
51+
// CreateAssetSwapOut creates a new asset swap out in the database.
52+
func (p *PostgresStore) CreateAssetSwapOut(ctx context.Context,
53+
swap *SwapOut) error {
54+
55+
params := sqlc.CreateAssetSwapParams{
56+
SwapHash: swap.SwapHash[:],
57+
AssetID: swap.AssetID,
58+
Amt: int64(swap.Amount),
59+
SenderPubkey: swap.SenderPubKey.SerializeCompressed(),
60+
ReceiverPubkey: swap.ReceiverPubKey.SerializeCompressed(),
61+
CsvExpiry: int32(swap.CsvExpiry),
62+
InitiationHeight: int32(swap.InitiationHeight),
63+
CreatedTime: p.clock.Now(),
64+
ServerKeyFamily: int64(swap.ClientKeyLocator.Family),
65+
ServerKeyIndex: int64(swap.ClientKeyLocator.Index),
66+
}
67+
68+
return p.queries.ExecTx(
69+
ctx, &loopdb.SqliteTxOptions{}, func(q *sqlc.Queries) error {
70+
err := q.CreateAssetSwap(ctx, params)
71+
if err != nil {
72+
return err
73+
}
74+
75+
return q.CreateAssetOutSwap(ctx, swap.SwapHash[:])
76+
},
77+
)
78+
}
79+
80+
// UpdateAssetSwapHtlcOutpoint updates the htlc outpoint of the swap out in the
81+
// database.
82+
func (p *PostgresStore) UpdateAssetSwapHtlcOutpoint(ctx context.Context,
83+
swapHash lntypes.Hash, outpoint *wire.OutPoint, confirmationHeight int32) error {
84+
85+
return p.queries.ExecTx(
86+
ctx, &loopdb.SqliteTxOptions{}, func(q *sqlc.Queries) error {
87+
return q.UpdateAssetSwapHtlcTx(
88+
ctx, sqlc.UpdateAssetSwapHtlcTxParams{
89+
SwapHash: swapHash[:],
90+
HtlcTxid: outpoint.Hash[:],
91+
HtlcVout: int32(outpoint.Index),
92+
HtlcConfirmationHeight: confirmationHeight,
93+
})
94+
},
95+
)
96+
}
97+
98+
// UpdateAssetSwapOutProof updates the raw proof of the swap out in the
99+
// database.
100+
func (p *PostgresStore) UpdateAssetSwapOutProof(ctx context.Context,
101+
swapHash lntypes.Hash, rawProof []byte) error {
102+
103+
return p.queries.ExecTx(
104+
ctx, &loopdb.SqliteTxOptions{}, func(q *sqlc.Queries) error {
105+
return q.UpdateAssetSwapOutProof(
106+
ctx, sqlc.UpdateAssetSwapOutProofParams{
107+
SwapHash: swapHash[:],
108+
RawProofFile: rawProof,
109+
})
110+
},
111+
)
112+
}
113+
114+
// UpdateAssetSwapOutPreimage updates the preimage of the swap out in the
115+
// database.
116+
func (p *PostgresStore) UpdateAssetSwapOutPreimage(ctx context.Context,
117+
swapHash lntypes.Hash, preimage lntypes.Preimage) error {
118+
119+
return p.queries.ExecTx(
120+
ctx, &loopdb.SqliteTxOptions{}, func(q *sqlc.Queries) error {
121+
return q.UpdateAssetSwapOutPreimage(
122+
ctx, sqlc.UpdateAssetSwapOutPreimageParams{
123+
SwapHash: swapHash[:],
124+
SwapPreimage: preimage[:],
125+
})
126+
},
127+
)
128+
}
129+
130+
// UpdateAssetSwapOutSweepTx updates the sweep tx of the swap out in the
131+
// database.
132+
func (p *PostgresStore) UpdateAssetSwapOutSweepTx(ctx context.Context,
133+
swapHash lntypes.Hash, sweepTxid chainhash.Hash, confHeight int32,
134+
sweepPkscript []byte) error {
135+
136+
return p.queries.ExecTx(
137+
ctx, &loopdb.SqliteTxOptions{}, func(q *sqlc.Queries) error {
138+
return q.UpdateAssetSwapSweepTx(
139+
ctx, sqlc.UpdateAssetSwapSweepTxParams{
140+
SwapHash: swapHash[:],
141+
SweepTxid: sweepTxid[:],
142+
SweepConfirmationHeight: confHeight,
143+
SweepPkscript: sweepPkscript,
144+
})
145+
},
146+
)
147+
}
148+
149+
// InsertAssetSwapUpdate inserts a new swap update in the database.
150+
func (p *PostgresStore) InsertAssetSwapUpdate(ctx context.Context,
151+
swapHash lntypes.Hash, state fsm.StateType) error {
152+
153+
return p.queries.ExecTx(
154+
ctx, &loopdb.SqliteTxOptions{}, func(q *sqlc.Queries) error {
155+
return q.InsertAssetSwapUpdate(
156+
ctx, sqlc.InsertAssetSwapUpdateParams{
157+
SwapHash: swapHash[:],
158+
UpdateState: string(state),
159+
UpdateTimestamp: p.clock.Now(),
160+
})
161+
},
162+
)
163+
}
164+
165+
// GetAllAssetOuts returns all the asset outs from the database.
166+
func (p *PostgresStore) GetAllAssetOuts(ctx context.Context) ([]*SwapOut, error) {
167+
dbAssetOuts, err := p.queries.GetAllAssetOutSwaps(ctx)
168+
if err != nil {
169+
return nil, err
170+
}
171+
172+
assetOuts := make([]*SwapOut, 0, len(dbAssetOuts))
173+
for _, dbAssetOut := range dbAssetOuts {
174+
assetOut, err := newSwapOutFromDB(
175+
dbAssetOut.AssetSwap, dbAssetOut.AssetOutSwap,
176+
dbAssetOut.UpdateState,
177+
)
178+
if err != nil {
179+
return nil, err
180+
}
181+
assetOuts = append(assetOuts, assetOut)
182+
}
183+
return assetOuts, nil
184+
}
185+
186+
// GetActiveAssetOuts returns all the active asset outs from the database.
187+
func (p *PostgresStore) GetActiveAssetOuts(ctx context.Context) ([]*SwapOut,
188+
error) {
189+
190+
dbAssetOuts, err := p.queries.GetAllAssetOutSwaps(ctx)
191+
if err != nil {
192+
return nil, err
193+
}
194+
195+
assetOuts := make([]*SwapOut, 0)
196+
for _, dbAssetOut := range dbAssetOuts {
197+
if IsFinishedState(fsm.StateType(dbAssetOut.UpdateState)) {
198+
continue
199+
}
200+
201+
assetOut, err := newSwapOutFromDB(
202+
dbAssetOut.AssetSwap, dbAssetOut.AssetOutSwap,
203+
dbAssetOut.UpdateState,
204+
)
205+
if err != nil {
206+
return nil, err
207+
}
208+
assetOuts = append(assetOuts, assetOut)
209+
}
210+
211+
return assetOuts, nil
212+
}
213+
214+
// newSwapOutFromDB creates a new SwapOut from the databse rows.
215+
func newSwapOutFromDB(assetSwap sqlc.AssetSwap,
216+
assetOutSwap sqlc.AssetOutSwap, state string) (
217+
*SwapOut, error) {
218+
219+
swapHash, err := lntypes.MakeHash(assetSwap.SwapHash)
220+
if err != nil {
221+
return nil, err
222+
}
223+
224+
var swapPreimage lntypes.Preimage
225+
if assetSwap.SwapPreimage != nil {
226+
swapPreimage, err = lntypes.MakePreimage(assetSwap.SwapPreimage)
227+
if err != nil {
228+
return nil, err
229+
}
230+
}
231+
232+
senderPubkey, err := btcec.ParsePubKey(assetSwap.SenderPubkey)
233+
if err != nil {
234+
return nil, err
235+
}
236+
237+
receiverPubkey, err := btcec.ParsePubKey(assetSwap.ReceiverPubkey)
238+
if err != nil {
239+
return nil, err
240+
}
241+
242+
var htlcOutpoint *wire.OutPoint
243+
if assetSwap.HtlcTxid != nil {
244+
htlcHash, err := chainhash.NewHash(assetSwap.HtlcTxid)
245+
if err != nil {
246+
return nil, err
247+
}
248+
htlcOutpoint = wire.NewOutPoint(
249+
htlcHash, uint32(assetSwap.HtlcVout),
250+
)
251+
}
252+
253+
var sweepOutpoint *wire.OutPoint
254+
if assetSwap.SweepTxid != nil {
255+
sweepHash, err := chainhash.NewHash(assetSwap.SweepTxid)
256+
if err != nil {
257+
return nil, err
258+
}
259+
sweepOutpoint = wire.NewOutPoint(
260+
sweepHash, 0,
261+
)
262+
}
263+
264+
return &SwapOut{
265+
SwapKit: htlc.SwapKit{
266+
SwapHash: swapHash,
267+
Amount: uint64(assetSwap.Amt),
268+
SenderPubKey: senderPubkey,
269+
ReceiverPubKey: receiverPubkey,
270+
CsvExpiry: uint32(assetSwap.CsvExpiry),
271+
AssetID: assetSwap.AssetID,
272+
},
273+
SwapPreimage: swapPreimage,
274+
State: fsm.StateType(state),
275+
InitiationHeight: uint32(assetSwap.InitiationHeight),
276+
ClientKeyLocator: keychain.KeyLocator{
277+
Family: keychain.KeyFamily(
278+
assetSwap.ServerKeyFamily,
279+
),
280+
Index: uint32(assetSwap.ServerKeyIndex),
281+
},
282+
HtlcOutPoint: htlcOutpoint,
283+
HtlcConfirmationHeight: uint32(assetSwap.HtlcConfirmationHeight),
284+
SweepOutpoint: sweepOutpoint,
285+
SweepConfirmationHeight: uint32(assetSwap.SweepConfirmationHeight),
286+
SweepPkscript: assetSwap.SweepPkscript,
287+
RawHtlcProof: assetOutSwap.RawProofFile,
288+
}, nil
289+
}

0 commit comments

Comments
 (0)