55 "encoding/hex"
66 "fmt"
77
8+ "github.com/btcsuite/btcd/btcutil"
89 "github.com/btcsuite/btcd/chaincfg/chainhash"
910 "github.com/btcsuite/btcd/txscript"
1011 "github.com/btcsuite/btcd/wire"
@@ -23,6 +24,7 @@ type recoverLoopInCommand struct {
2324 Vout uint32
2425 SwapHash string
2526 SweepAddr string
27+ OutputAmt uint64
2628 FeeRate uint32
2729 StartKeyIndex int
2830 NumTries int
@@ -92,6 +94,9 @@ func newRecoverLoopInCommand() *cobra.Command {
9294 & cc .Publish , "publish" , false , "publish sweep TX to the chain " +
9395 "API instead of just printing the TX" ,
9496 )
97+ cc .cmd .Flags ().Uint64Var (
98+ & cc .OutputAmt , "output_amt" , 0 , "amount of the output to sweep" ,
99+ )
95100
96101 cc .rootKey = newRootKey (cc .cmd , "deriving starting key" )
97102
@@ -153,8 +158,20 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
153158 return fmt .Errorf ("swap not found" )
154159 }
155160
161+ // If the swap is an external htlc, we require the output amount to be
162+ // set, as a lot of failure cases steam from the output amount being
163+ // wrong.
164+ if loopIn .Contract .ExternalHtlc && c .OutputAmt == 0 {
165+ return fmt .Errorf ("output_amt is required for external htlc" )
166+ }
167+
156168 fmt .Println ("Loop expires at block height" , loopIn .Contract .CltvExpiry )
157169
170+ outputValue := loopIn .Contract .AmountRequested
171+ if c .OutputAmt != 0 {
172+ outputValue = btcutil .Amount (c .OutputAmt )
173+ }
174+
158175 // Get the swaps htlc.
159176 htlc , err := loop .GetHtlc (
160177 loopIn .Hash , & loopIn .Contract .SwapContract , chainParams ,
@@ -208,7 +225,7 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
208225 // Add output for the destination address.
209226 sweepTx .AddTxOut (& wire.TxOut {
210227 PkScript : sweepScript ,
211- Value : int64 (loopIn . Contract . AmountRequested ) - int64 (fee ),
228+ Value : int64 (outputValue ) - int64 (fee ),
212229 })
213230
214231 // If the htlc is version 2, we need to brute force the key locator, as
@@ -218,8 +235,9 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
218235 fmt .Println ("Brute forcing key index..." )
219236 for i := c .StartKeyIndex ; i < c .StartKeyIndex + c .NumTries ; i ++ {
220237 rawTx , err = getSignedTx (
221- signer , loopIn , sweepTx , htlc ,
238+ signer , sweepTx , htlc ,
222239 keychain .KeyFamily (swap .KeyFamily ), uint32 (i ),
240+ outputValue ,
223241 )
224242 if err == nil {
225243 break
@@ -232,9 +250,10 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
232250 }
233251 } else {
234252 rawTx , err = getSignedTx (
235- signer , loopIn , sweepTx , htlc ,
253+ signer , sweepTx , htlc ,
236254 loopIn .Contract .HtlcKeys .ClientScriptKeyLocator .Family ,
237255 loopIn .Contract .HtlcKeys .ClientScriptKeyLocator .Index ,
256+ outputValue ,
238257 )
239258 if err != nil {
240259 return err
@@ -260,14 +279,14 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
260279 return nil
261280}
262281
263- func getSignedTx (signer * lnd.Signer , loopIn * loopdb. LoopIn , sweepTx * wire. MsgTx ,
264- htlc * swap. Htlc , keyFamily keychain.KeyFamily ,
265- keyIndex uint32 ) ([]byte , error ) {
282+ func getSignedTx (signer * lnd.Signer , sweepTx * wire. MsgTx , htlc * swap. Htlc ,
283+ keyFamily keychain.KeyFamily , keyIndex uint32 ,
284+ outputValue btcutil. Amount ) ([]byte , error ) {
266285
267286 // Create the sign descriptor.
268287 prevTxOut := & wire.TxOut {
269288 PkScript : htlc .PkScript ,
270- Value : int64 (loopIn . Contract . AmountRequested ),
289+ Value : int64 (outputValue ),
271290 }
272291 prevOutputFetcher := txscript .NewCannedPrevOutputFetcher (
273292 prevTxOut .PkScript , prevTxOut .Value ,
0 commit comments