|
|
|
@ -105,8 +105,8 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
privKeys := make([]*secp256k1.PrivateKey, 0, len(c.InputOutpoints))
|
|
|
|
|
|
|
|
|
|
// Get the addresses for the inputs.
|
|
|
|
|
for _, input := range c.InputOutpoints {
|
|
|
|
|
addrString, err := api.Address(input)
|
|
|
|
|
for _, inputOutpoint := range c.InputOutpoints {
|
|
|
|
|
addrString, err := api.Address(inputOutpoint)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
@ -118,12 +118,12 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
|
|
|
|
|
addresses = append(addresses, addr)
|
|
|
|
|
|
|
|
|
|
txHash, err := chainhash.NewHashFromStr(input[:64])
|
|
|
|
|
txHash, err := chainhash.NewHashFromStr(inputOutpoint[:64])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vout, err := strconv.Atoi(input[65:])
|
|
|
|
|
vout, err := strconv.Atoi(inputOutpoint[65:])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
@ -144,7 +144,13 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start with the txweight estimator.
|
|
|
|
|
estimator := input.TxWeightEstimator{}
|
|
|
|
|
var estimator input.TxWeightEstimator
|
|
|
|
|
sweepScript, err := lnd.PrepareWalletAddress(
|
|
|
|
|
c.SweepAddr, chainParams, &estimator, extendedKey, "sweep",
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find the key for the given addresses and add their
|
|
|
|
|
// output weight to the tx estimator.
|
|
|
|
@ -169,7 +175,9 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
estimator.AddTaprootKeySpendInput(txscript.SigHashDefault)
|
|
|
|
|
estimator.AddTaprootKeySpendInput(
|
|
|
|
|
txscript.SigHashDefault,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("address type %T not supported", addr)
|
|
|
|
@ -189,47 +197,32 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
|
|
|
|
|
// Next get the full value of the inputs.
|
|
|
|
|
var totalInput btcutil.Amount
|
|
|
|
|
for _, input := range outpoints {
|
|
|
|
|
for _, outpoint := range outpoints {
|
|
|
|
|
// Get the transaction.
|
|
|
|
|
tx, err := api.Transaction(input.Hash.String())
|
|
|
|
|
tx, err := api.Transaction(outpoint.Hash.String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value := tx.Vout[input.Index].Value
|
|
|
|
|
value := tx.Vout[outpoint.Index].Value
|
|
|
|
|
|
|
|
|
|
// Get the output index.
|
|
|
|
|
totalInput += btcutil.Amount(value)
|
|
|
|
|
|
|
|
|
|
scriptPubkey, err := hex.DecodeString(tx.Vout[input.Index].ScriptPubkey)
|
|
|
|
|
scriptPubkey, err := hex.DecodeString(
|
|
|
|
|
tx.Vout[outpoint.Index].ScriptPubkey,
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the output to the map.
|
|
|
|
|
prevOuts[*input] = &wire.TxOut{
|
|
|
|
|
prevOuts[*outpoint] = &wire.TxOut{
|
|
|
|
|
Value: int64(value),
|
|
|
|
|
PkScript: scriptPubkey,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculate the fee.
|
|
|
|
|
sweepAddr, err := btcutil.DecodeAddress(c.SweepAddr, chainParams)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch sweepAddr.(type) {
|
|
|
|
|
case *btcutil.AddressWitnessPubKeyHash:
|
|
|
|
|
estimator.AddP2WKHOutput()
|
|
|
|
|
|
|
|
|
|
case *btcutil.AddressTaproot:
|
|
|
|
|
estimator.AddP2TROutput()
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("address type %T not supported", sweepAddr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculate the fee.
|
|
|
|
|
feeRateKWeight := chainfee.SatPerKVByte(1000 * c.FeeRate).FeePerKWeight()
|
|
|
|
|
totalFee := feeRateKWeight.FeeForWeight(int64(estimator.Weight()))
|
|
|
|
@ -238,14 +231,8 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
tx := wire.NewMsgTx(2)
|
|
|
|
|
|
|
|
|
|
// Add the inputs.
|
|
|
|
|
for _, input := range outpoints {
|
|
|
|
|
tx.AddTxIn(wire.NewTxIn(input, nil, nil))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add the output.
|
|
|
|
|
sweepScript, err := txscript.PayToAddrScript(sweepAddr)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
for _, outpoint := range outpoints {
|
|
|
|
|
tx.AddTxIn(wire.NewTxIn(outpoint, nil, nil))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tx.AddTxOut(wire.NewTxOut(int64(totalInput-totalFee), sweepScript))
|
|
|
|
@ -285,7 +272,8 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return fmt.Errorf("address type %T not supported", addresses[i])
|
|
|
|
|
return fmt.Errorf("address type %T not supported",
|
|
|
|
|
addresses[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -296,7 +284,7 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Print the transaction.
|
|
|
|
|
fmt.Printf("Sweeping transaction:\n%s\n", hex.EncodeToString(txBuf.Bytes()))
|
|
|
|
|
fmt.Printf("Sweeping transaction:\n%x\n", txBuf.Bytes())
|
|
|
|
|
|
|
|
|
|
// Publish the transaction.
|
|
|
|
|
if c.Publish {
|
|
|
|
|