@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
@ -23,6 +24,7 @@ type recoverLoopInCommand struct {
Vout uint32
SwapHash string
SweepAddr string
OutputAmt uint64
FeeRate uint32
StartKeyIndex int
NumTries int
@ -92,6 +94,9 @@ func newRecoverLoopInCommand() *cobra.Command {
& cc . Publish , "publish" , false , "publish sweep TX to the chain " +
"API instead of just printing the TX" ,
)
cc . cmd . Flags ( ) . Uint64Var (
& cc . OutputAmt , "output_amt" , 0 , "amount of the output to sweep" ,
)
cc . rootKey = newRootKey ( cc . cmd , "deriving starting key" )
@ -153,8 +158,20 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
return fmt . Errorf ( "swap not found" )
}
// If the swap is an external htlc, we require the output amount to be
// set, as a lot of failure cases steam from the output amount being
// wrong.
if loopIn . Contract . ExternalHtlc && c . OutputAmt == 0 {
return fmt . Errorf ( "output_amt is required for external htlc" )
}
fmt . Println ( "Loop expires at block height" , loopIn . Contract . CltvExpiry )
outputValue := loopIn . Contract . AmountRequested
if c . OutputAmt != 0 {
outputValue = btcutil . Amount ( c . OutputAmt )
}
// Get the swaps htlc.
htlc , err := loop . GetHtlc (
loopIn . Hash , & loopIn . Contract . SwapContract , chainParams ,
@ -208,7 +225,7 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
// Add output for the destination address.
sweepTx . AddTxOut ( & wire . TxOut {
PkScript : sweepScript ,
Value : int64 ( loopIn. Contract . AmountRequested ) - int64 ( fee ) ,
Value : int64 ( outputValue ) - int64 ( fee ) ,
} )
// 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 {
fmt . Println ( "Brute forcing key index..." )
for i := c . StartKeyIndex ; i < c . StartKeyIndex + c . NumTries ; i ++ {
rawTx , err = getSignedTx (
signer , loopIn, sweepTx, htlc ,
signer , sweepTx, htlc ,
keychain . KeyFamily ( swap . KeyFamily ) , uint32 ( i ) ,
outputValue ,
)
if err == nil {
break
@ -232,9 +250,10 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
}
} else {
rawTx , err = getSignedTx (
signer , loopIn, sweepTx, htlc ,
signer , sweepTx, htlc ,
loopIn . Contract . HtlcKeys . ClientScriptKeyLocator . Family ,
loopIn . Contract . HtlcKeys . ClientScriptKeyLocator . Index ,
outputValue ,
)
if err != nil {
return err
@ -260,14 +279,14 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
return nil
}
func getSignedTx ( signer * lnd . Signer , loopIn * loopdb . LoopIn , sweepTx * wire . MsgTx ,
htlc * swap . Htlc , keyFamily keychain . KeyFamily ,
keyIndex uint32 ) ( [ ] byte , error ) {
func getSignedTx ( signer * lnd . Signer , sweepTx * wire . MsgTx , htlc * swap . Htlc ,
keyFamily keychain . KeyFamily , keyIndex uint32 ,
outputValue btcutil . Amount ) ( [ ] byte , error ) {
// Create the sign descriptor.
prevTxOut := & wire . TxOut {
PkScript : htlc . PkScript ,
Value : int64 ( loopIn. Contract . AmountRequested ) ,
Value : int64 ( outputValue ) ,
}
prevOutputFetcher := txscript . NewCannedPrevOutputFetcher (
prevTxOut . PkScript , prevTxOut . Value ,