Skip to content

Commit 5d75e99

Browse files
authored
Merge pull request #708 from sputn1ck/listinstantouts
Add `listinstantouts` command
2 parents 65b8cb6 + 034bc24 commit 5d75e99

13 files changed

+711
-239
lines changed

cmd/loop/instantout.go

+28
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,31 @@ func instantOut(ctx *cli.Context) error {
202202

203203
return nil
204204
}
205+
206+
var listInstantOutsCommand = cli.Command{
207+
Name: "listinstantouts",
208+
Usage: "list all instant out swaps",
209+
Description: `
210+
List all instant out swaps.
211+
`,
212+
Action: listInstantOuts,
213+
}
214+
215+
func listInstantOuts(ctx *cli.Context) error {
216+
// First set up the swap client itself.
217+
client, cleanup, err := getClient(ctx)
218+
if err != nil {
219+
return err
220+
}
221+
defer cleanup()
222+
223+
resp, err := client.ListInstantOuts(
224+
context.Background(), &looprpc.ListInstantOutsRequest{},
225+
)
226+
if err != nil {
227+
return err
228+
}
229+
230+
printRespJSON(resp)
231+
return nil
232+
}

cmd/loop/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func main() {
148148
listSwapsCommand, swapInfoCommand, getLiquidityParamsCommand,
149149
setLiquidityRuleCommand, suggestSwapCommand, setParamsCommand,
150150
getInfoCommand, abandonSwapCommand, reservationsCommands,
151-
instantOutCommand,
151+
instantOutCommand, listInstantOutsCommand,
152152
}
153153

154154
err := app.Run(os.Args)

instantout/actions.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@ func (f *FSM) InitInstantOutAction(eventCtx fsm.EventContext) fsm.EventType {
185185
protocolVersion: ProtocolVersionFullReservation,
186186
initiationHeight: initCtx.initationHeight,
187187
outgoingChanSet: initCtx.outgoingChanSet,
188-
cltvExpiry: initCtx.cltvExpiry,
188+
CltvExpiry: initCtx.cltvExpiry,
189189
clientPubkey: keyRes.PubKey,
190190
serverPubkey: serverPubkey,
191-
value: btcutil.Amount(reservationAmt),
191+
Value: btcutil.Amount(reservationAmt),
192192
htlcFeeRate: feeRate,
193193
swapInvoice: instantOutResponse.SwapInvoice,
194-
reservations: reservations,
194+
Reservations: reservations,
195195
keyLocator: keyRes.KeyLocator,
196196
sweepAddress: sweepAddress,
197197
}
@@ -211,7 +211,7 @@ func (f *FSM) InitInstantOutAction(eventCtx fsm.EventContext) fsm.EventType {
211211
func (f *FSM) PollPaymentAcceptedAction(_ fsm.EventContext) fsm.EventType {
212212
// Now that we're doing the swap, we first lock the reservations
213213
// so that they can't be used for other swaps.
214-
for _, reservation := range f.InstantOut.reservations {
214+
for _, reservation := range f.InstantOut.Reservations {
215215
err := f.cfg.ReservationManager.LockReservation(
216216
f.ctx, reservation.ID,
217217
)
@@ -227,7 +227,7 @@ func (f *FSM) PollPaymentAcceptedAction(_ fsm.EventContext) fsm.EventType {
227227
Invoice: f.InstantOut.swapInvoice,
228228
Timeout: defaultSendpaymentTimeout,
229229
MaxParts: defaultMaxParts,
230-
MaxFee: getMaxRoutingFee(f.InstantOut.value),
230+
MaxFee: getMaxRoutingFee(f.InstantOut.Value),
231231
},
232232
)
233233
if err != nil {
@@ -301,7 +301,7 @@ func (f *FSM) BuildHTLCAction(eventCtx fsm.EventContext) fsm.EventType {
301301
return f.handleErrorAndUnlockReservations(err)
302302
}
303303

304-
if len(htlcInitRes.HtlcServerNonces) != len(f.InstantOut.reservations) {
304+
if len(htlcInitRes.HtlcServerNonces) != len(f.InstantOut.Reservations) {
305305
return f.handleErrorAndUnlockReservations(
306306
errors.New("invalid number of server nonces"),
307307
)
@@ -435,8 +435,8 @@ func (f *FSM) PushPreimageAction(eventCtx fsm.EventContext) fsm.EventType {
435435
return OnErrorPublishHtlc
436436
}
437437

438-
f.InstantOut.finalizedSweeplessSweepTx = sweepTx
439-
txHash := f.InstantOut.finalizedSweeplessSweepTx.TxHash()
438+
f.InstantOut.FinalizedSweeplessSweepTx = sweepTx
439+
txHash := f.InstantOut.FinalizedSweeplessSweepTx.TxHash()
440440

441441
f.InstantOut.SweepTxHash = &txHash
442442

@@ -598,7 +598,7 @@ func (f *FSM) handleErrorAndUnlockReservations(err error) fsm.EventType {
598598
defer cancel()
599599

600600
// Unlock the reservations.
601-
for _, reservation := range f.InstantOut.reservations {
601+
for _, reservation := range f.InstantOut.Reservations {
602602
err := f.cfg.ReservationManager.UnlockReservation(
603603
ctx, reservation.ID,
604604
)

instantout/instantout.go

+19-19
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ type InstantOut struct {
3535
// State is the current state of the swap.
3636
State fsm.StateType
3737

38-
// cltvExpiry is the expiry of the swap.
39-
cltvExpiry int32
38+
// CltvExpiry is the expiry of the swap.
39+
CltvExpiry int32
4040

4141
// outgoingChanSet optionally specifies the short channel ids of the
4242
// channels that may be used to loop out.
4343
outgoingChanSet loopdb.ChannelSet
4444

45-
// reservations are the reservations that are used in as inputs for the
45+
// Reservations are the Reservations that are used in as inputs for the
4646
// instant out swap.
47-
reservations []*reservation.Reservation
47+
Reservations []*reservation.Reservation
4848

4949
// protocolVersion is the version of the protocol that is used for the
5050
// swap.
@@ -53,8 +53,8 @@ type InstantOut struct {
5353
// initiationHeight is the height at which the swap was initiated.
5454
initiationHeight int32
5555

56-
// value is the amount that is swapped.
57-
value btcutil.Amount
56+
// Value is the amount that is swapped.
57+
Value btcutil.Amount
5858

5959
// keyLocator is the key locator that is used for the swap.
6060
keyLocator keychain.KeyLocator
@@ -81,9 +81,9 @@ type InstantOut struct {
8181
// SweepTxHash is the hash of the sweep transaction.
8282
SweepTxHash *chainhash.Hash
8383

84-
// finalizedSweeplessSweepTx is the transaction that is used to sweep
84+
// FinalizedSweeplessSweepTx is the transaction that is used to sweep
8585
// the funds in the cooperative path.
86-
finalizedSweeplessSweepTx *wire.MsgTx
86+
FinalizedSweeplessSweepTx *wire.MsgTx
8787

8888
// sweepConfirmationHeight is the height at which the sweep
8989
// transaction was confirmed.
@@ -93,7 +93,7 @@ type InstantOut struct {
9393
// getHtlc returns the swap.htlc for the instant out.
9494
func (i *InstantOut) getHtlc(chainParams *chaincfg.Params) (*swap.Htlc, error) {
9595
return swap.NewHtlcV2(
96-
i.cltvExpiry, pubkeyTo33ByteSlice(i.serverPubkey),
96+
i.CltvExpiry, pubkeyTo33ByteSlice(i.serverPubkey),
9797
pubkeyTo33ByteSlice(i.clientPubkey), i.SwapHash, chainParams,
9898
)
9999
}
@@ -104,11 +104,11 @@ func (i *InstantOut) createMusig2Session(ctx context.Context,
104104
[][]byte, error) {
105105

106106
// Create the htlc musig2 context.
107-
musig2Sessions := make([]*input.MuSig2SessionInfo, len(i.reservations))
108-
clientNonces := make([][]byte, len(i.reservations))
107+
musig2Sessions := make([]*input.MuSig2SessionInfo, len(i.Reservations))
108+
clientNonces := make([][]byte, len(i.Reservations))
109109

110110
// Create the sessions and nonces from the reservations.
111-
for idx, reservation := range i.reservations {
111+
for idx, reservation := range i.Reservations {
112112
session, err := reservation.Musig2CreateSession(ctx, signer)
113113
if err != nil {
114114
return nil, nil, err
@@ -123,12 +123,12 @@ func (i *InstantOut) createMusig2Session(ctx context.Context,
123123

124124
// getInputReservation returns the input reservation for the instant out.
125125
func (i *InstantOut) getInputReservations() (InputReservations, error) {
126-
if len(i.reservations) == 0 {
126+
if len(i.Reservations) == 0 {
127127
return nil, errors.New("no reservations")
128128
}
129129

130-
inputs := make(InputReservations, len(i.reservations))
131-
for idx, reservation := range i.reservations {
130+
inputs := make(InputReservations, len(i.Reservations))
131+
for idx, reservation := range i.Reservations {
132132
pkScript, err := reservation.GetPkScript()
133133
if err != nil {
134134
return nil, err
@@ -170,7 +170,7 @@ func (i *InstantOut) createHtlcTransaction(network *chaincfg.Params) (
170170
// Estimate the fee
171171
weight := htlcWeight(len(inputReservations))
172172
fee := i.htlcFeeRate.FeeForWeight(weight)
173-
if fee > i.value/5 {
173+
if fee > i.Value/5 {
174174
return nil, errors.New("fee is higher than 20% of " +
175175
"sweep value")
176176
}
@@ -182,7 +182,7 @@ func (i *InstantOut) createHtlcTransaction(network *chaincfg.Params) (
182182

183183
// Create the sweep output
184184
sweepOutput := &wire.TxOut{
185-
Value: int64(i.value) - int64(fee),
185+
Value: int64(i.Value) - int64(fee),
186186
PkScript: htlc.PkScript,
187187
}
188188

@@ -214,7 +214,7 @@ func (i *InstantOut) createSweeplessSweepTx(feerate chainfee.SatPerKWeight) (
214214
// Estimate the fee
215215
weight := sweeplessSweepWeight(len(inputReservations))
216216
fee := feerate.FeeForWeight(weight)
217-
if fee > i.value/5 {
217+
if fee > i.Value/5 {
218218
return nil, errors.New("fee is higher than 20% of " +
219219
"sweep value")
220220
}
@@ -226,7 +226,7 @@ func (i *InstantOut) createSweeplessSweepTx(feerate chainfee.SatPerKWeight) (
226226

227227
// Create the sweep output
228228
sweepOutput := &wire.TxOut{
229-
Value: int64(i.value) - int64(fee),
229+
Value: int64(i.Value) - int64(fee),
230230
PkScript: pkscript,
231231
}
232232

instantout/manager.go

+5
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,8 @@ func (m *Manager) GetInstantOutQuote(ctx context.Context,
258258
OnChainFee: chainFee,
259259
}, nil
260260
}
261+
262+
// ListInstantOuts returns all instant outs from the database.
263+
func (m *Manager) ListInstantOuts(ctx context.Context) ([]*InstantOut, error) {
264+
return m.cfg.Store.ListInstantLoopOuts(ctx)
265+
}

instantout/store.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ func (s *SQLStore) CreateInstantLoopOut(ctx context.Context,
9494
SwapHash: instantOut.SwapHash[:],
9595
Preimage: instantOut.swapPreimage[:],
9696
InitiationTime: s.clock.Now(),
97-
AmountRequested: int64(instantOut.value),
98-
CltvExpiry: instantOut.cltvExpiry,
97+
AmountRequested: int64(instantOut.Value),
98+
CltvExpiry: instantOut.CltvExpiry,
9999
MaxMinerFee: 0,
100100
MaxSwapFee: 0,
101101
InitiationHeight: instantOut.initiationHeight,
@@ -114,7 +114,7 @@ func (s *SQLStore) CreateInstantLoopOut(ctx context.Context,
114114
}
115115

116116
reservationIdByteSlice := reservationIdsToByteSlice(
117-
instantOut.reservations,
117+
instantOut.Reservations,
118118
)
119119
instantOutArgs := sqlc.InsertInstantOutParams{
120120
SwapHash: instantOut.SwapHash[:],
@@ -172,9 +172,9 @@ func (s *SQLStore) UpdateInstantLoopOut(ctx context.Context,
172172
}
173173

174174
var finalSweeplessSweepTx []byte
175-
if instantOut.finalizedSweeplessSweepTx != nil {
175+
if instantOut.FinalizedSweeplessSweepTx != nil {
176176
var buffer bytes.Buffer
177-
err := instantOut.finalizedSweeplessSweepTx.Serialize(
177+
err := instantOut.FinalizedSweeplessSweepTx.Serialize(
178178
&buffer,
179179
)
180180
if err != nil {
@@ -355,12 +355,12 @@ func (s *SQLStore) sqlInstantOutToInstantOut(ctx context.Context,
355355
instantOut := &InstantOut{
356356
SwapHash: swapHash,
357357
swapPreimage: swapPreImage,
358-
cltvExpiry: row.CltvExpiry,
358+
CltvExpiry: row.CltvExpiry,
359359
outgoingChanSet: outgoingChanSet,
360-
reservations: reservations,
360+
Reservations: reservations,
361361
protocolVersion: ProtocolVersion(row.ProtocolVersion),
362362
initiationHeight: row.InitiationHeight,
363-
value: btcutil.Amount(row.AmountRequested),
363+
Value: btcutil.Amount(row.AmountRequested),
364364
keyLocator: keychain.KeyLocator{
365365
Family: keychain.KeyFamily(row.ClientKeyFamily),
366366
Index: uint32(row.ClientKeyIndex),
@@ -372,7 +372,7 @@ func (s *SQLStore) sqlInstantOutToInstantOut(ctx context.Context,
372372
sweepAddress: sweepAddress,
373373
finalizedHtlcTx: finalizedHtlcTx,
374374
SweepTxHash: sweepTxHash,
375-
finalizedSweeplessSweepTx: finalizedSweepLessSweepTx,
375+
FinalizedSweeplessSweepTx: finalizedSweepLessSweepTx,
376376
sweepConfirmationHeight: uint32(deserializeNullInt32(
377377
row.SweepConfirmationHeight,
378378
)),

loopd/perms/perms.go

+4
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,8 @@ var RequiredPermissions = map[string][]bakery.Op{
108108
Entity: "swap",
109109
Action: "read",
110110
}},
111+
"/looprpc.SwapClient/ListInstantOuts": {{
112+
Entity: "swap",
113+
Action: "read",
114+
}},
111115
}

loopd/swapclient_server.go

+41
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,47 @@ func (s *swapClientServer) InstantOutQuote(ctx context.Context,
12311231
}, nil
12321232
}
12331233

1234+
// ListInstantOuts returns a list of all currently known instant out swaps and
1235+
// their current status.
1236+
func (s *swapClientServer) ListInstantOuts(ctx context.Context,
1237+
_ *clientrpc.ListInstantOutsRequest) (
1238+
*clientrpc.ListInstantOutsResponse, error) {
1239+
1240+
instantOuts, err := s.instantOutManager.ListInstantOuts(ctx)
1241+
if err != nil {
1242+
return nil, err
1243+
}
1244+
1245+
rpcSwaps := make([]*clientrpc.InstantOut, 0, len(instantOuts))
1246+
for _, instantOut := range instantOuts {
1247+
rpcSwaps = append(rpcSwaps, rpcInstantOut(instantOut))
1248+
}
1249+
1250+
return &clientrpc.ListInstantOutsResponse{
1251+
Swaps: rpcSwaps,
1252+
}, nil
1253+
}
1254+
1255+
func rpcInstantOut(instantOut *instantout.InstantOut) *clientrpc.InstantOut {
1256+
var sweepTxId string
1257+
if instantOut.SweepTxHash != nil {
1258+
sweepTxId = instantOut.SweepTxHash.String()
1259+
}
1260+
1261+
reservations := make([][]byte, len(instantOut.Reservations))
1262+
for i, res := range instantOut.Reservations {
1263+
reservations[i] = res.ID[:]
1264+
}
1265+
1266+
return &clientrpc.InstantOut{
1267+
SwapHash: instantOut.SwapHash[:],
1268+
State: string(instantOut.State),
1269+
Amount: uint64(instantOut.Value),
1270+
SweepTxId: sweepTxId,
1271+
ReservationIds: reservations,
1272+
}
1273+
}
1274+
12341275
func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) {
12351276
switch reason {
12361277
case liquidity.ReasonNone:

0 commit comments

Comments
 (0)