Skip to content

Commit c986150

Browse files
committed
cmd/loop: add command "loop out sweephtlc"
The command is hidden, it is not for everyday use.
1 parent 7123fb4 commit c986150

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

cmd/loop/loopout.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ var loopOutCommand = &cli.Command{
121121
verboseFlag,
122122
channelFlag,
123123
},
124+
Commands: []*cli.Command{
125+
sweepHtlcCommand,
126+
},
124127
Action: loopOut,
125128
}
126129

cmd/loop/sweephtlc.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/hex"
7+
"fmt"
8+
9+
"github.com/btcsuite/btcd/wire"
10+
"github.com/lightninglabs/loop/looprpc"
11+
"github.com/urfave/cli/v3"
12+
)
13+
14+
// sweepHtlcCommand exposes HTLC success-path sweeping over loop CLI.
15+
var sweepHtlcCommand = &cli.Command{
16+
Name: "sweephtlc",
17+
Usage: "sweep an HTLC output using the preimage success path",
18+
Flags: []cli.Flag{
19+
&cli.StringFlag{
20+
Name: "outpoint",
21+
Usage: "htlc outpoint to sweep (format: txid:vout)",
22+
Required: true,
23+
},
24+
&cli.StringFlag{
25+
Name: "htlcaddr",
26+
Usage: "htlc address corresponding to the outpoint",
27+
Required: true,
28+
},
29+
&cli.UintFlag{
30+
Name: "feerate",
31+
Usage: "fee rate to use in sat/vbyte",
32+
Required: true,
33+
},
34+
&cli.StringFlag{
35+
Name: "destaddr",
36+
Usage: "optional destination address; defaults to a " +
37+
"new wallet address",
38+
},
39+
&cli.StringFlag{
40+
Name: "preimage",
41+
Usage: "optional preimage hex to override stored " +
42+
"swap preimage",
43+
},
44+
&cli.BoolFlag{
45+
Name: "publish",
46+
Usage: "publish the sweep transaction immediately",
47+
Value: false,
48+
},
49+
},
50+
Hidden: true,
51+
Action: sweepHtlc,
52+
}
53+
54+
// sweepHtlc executes the SweepHtlc RPC and prints the sweep transaction hex.
55+
func sweepHtlc(ctx context.Context, cmd *cli.Command) error {
56+
// Loopd connecting client.
57+
client, cleanup, err := getClient(cmd)
58+
if err != nil {
59+
return err
60+
}
61+
defer cleanup()
62+
63+
// Find the preimage if the user passed it.
64+
var preimage []byte
65+
if cmd.IsSet("preimage") {
66+
preimage, err = hex.DecodeString(cmd.String("preimage"))
67+
if err != nil {
68+
return fmt.Errorf("invalid preimage: %w", err)
69+
}
70+
}
71+
72+
// Call SweepHtlc on loopd trying to sweep the HTLC.
73+
resp, err := client.SweepHtlc(ctx, &looprpc.SweepHtlcRequest{
74+
Outpoint: cmd.String("outpoint"),
75+
DestAddress: cmd.String("destaddr"),
76+
HtlcAddress: cmd.String("htlcaddr"),
77+
SatPerVbyte: uint32(cmd.Uint("feerate")),
78+
Preimage: preimage,
79+
Publish: cmd.Bool("publish"),
80+
})
81+
if err != nil {
82+
return err
83+
}
84+
85+
// Always display the raw sweep transaction.
86+
fmt.Printf("sweep_tx_hex: %x\n", resp.SweepTx)
87+
88+
// Report publish status in a user-friendly way based on response.
89+
switch {
90+
case resp.GetNotRequested() != nil:
91+
fmt.Println("publish: not requested (pass --publish to " +
92+
"broadcast)")
93+
94+
case resp.GetPublished() != nil:
95+
fmt.Println("publish: success")
96+
97+
case resp.GetFailed() != nil:
98+
errMsg := resp.GetFailed().GetError()
99+
fmt.Printf("publish: failed: %s\n", errMsg)
100+
101+
return fmt.Errorf("publish failed: %s", errMsg)
102+
103+
default:
104+
fmt.Println("publish: unknown status")
105+
}
106+
107+
// Print txid if the transaction is valid.
108+
var tx wire.MsgTx
109+
if err := tx.Deserialize(bytes.NewReader(resp.SweepTx)); err == nil {
110+
fmt.Printf("sweep_txid: %s\n", tx.TxHash().String())
111+
} else {
112+
fmt.Printf("sweep_txid: could not decode tx: %v\n", err)
113+
}
114+
115+
// Print the fee-rate.
116+
fmt.Printf("fee_sats: %d\n", resp.FeeSats)
117+
118+
return nil
119+
}

docs/loop.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ The following flags are supported:
5353
| `--channel="…"` | the comma-separated list of short channel IDs of the channels to loop out | string |
5454
| `--help` (`-h`) | show help | bool | `false` |
5555

56+
### `out sweephtlc` subcommand
57+
58+
sweep an HTLC output using the preimage success path.
59+
60+
Usage:
61+
62+
```bash
63+
$ loop [GLOBAL FLAGS] out sweephtlc [COMMAND FLAGS] [ARGUMENTS...]
64+
```
65+
66+
The following flags are supported:
67+
68+
| Name | Description | Type | Default value |
69+
|------------------|----------------------------------------------------------------|--------|:-------------:|
70+
| `--outpoint="…"` | htlc outpoint to sweep (format: txid:vout) | string |
71+
| `--htlcaddr="…"` | htlc address corresponding to the outpoint | string |
72+
| `--feerate="…"` | fee rate to use in sat/vbyte | uint | `0` |
73+
| `--destaddr="…"` | optional destination address; defaults to a new wallet address | string |
74+
| `--preimage="…"` | optional preimage hex to override stored swap preimage | string |
75+
| `--publish` | publish the sweep transaction immediately | bool | `false` |
76+
| `--help` (`-h`) | show help | bool | `false` |
77+
5678
### `in` command
5779

5880
perform an on-chain to off-chain swap (loop in).

0 commit comments

Comments
 (0)