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