Skip to content

Commit a05962e

Browse files
committed
multi: standardize sweep/change addr support
1 parent 7e3ea44 commit a05962e

File tree

9 files changed

+184
-135
lines changed

9 files changed

+184
-135
lines changed

cmd/chantools/closepoolaccount.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,21 @@ func closePoolAccount(extendedKey *hdkeychain.ExtendedKey, apiURL string,
166166
sweepAddr string, publish bool, feeRate uint32, minExpiry,
167167
maxNumBlocks, maxNumAccounts, maxNumBatchKeys uint32) error {
168168

169-
signer := &lnd.Signer{
170-
ExtendedKey: extendedKey,
171-
ChainParams: chainParams,
169+
var (
170+
estimator input.TxWeightEstimator
171+
signer = &lnd.Signer{
172+
ExtendedKey: extendedKey,
173+
ChainParams: chainParams,
174+
}
175+
api = newExplorerAPI(apiURL)
176+
)
177+
178+
sweepScript, err := lnd.PrepareWalletAddress(
179+
sweepAddr, chainParams, &estimator, extendedKey, "sweep",
180+
)
181+
if err != nil {
182+
return err
172183
}
173-
api := newExplorerAPI(apiURL)
174184

175185
tx, err := api.Transaction(outpoint.Hash.String())
176186
if err != nil {
@@ -246,7 +256,6 @@ func closePoolAccount(extendedKey *hdkeychain.ExtendedKey, apiURL string,
246256
// Calculate the fee based on the given fee rate and our weight
247257
// estimation.
248258
var (
249-
estimator input.TxWeightEstimator
250259
prevOutFetcher = txscript.NewCannedPrevOutputFetcher(
251260
pkScript, sweepValue,
252261
)
@@ -282,15 +291,10 @@ func closePoolAccount(extendedKey *hdkeychain.ExtendedKey, apiURL string,
282291
signDesc.HashType = txscript.SigHashDefault
283292
signDesc.SignMethod = input.TaprootScriptSpendSignMethod
284293
}
285-
estimator.AddP2WKHOutput()
286294
feeRateKWeight := chainfee.SatPerKVByte(1000 * feeRate).FeePerKWeight()
287295
totalFee := feeRateKWeight.FeeForWeight(int64(estimator.Weight()))
288296

289297
// Add our sweep destination output.
290-
sweepScript, err := lnd.GetP2WPKHScript(sweepAddr, chainParams)
291-
if err != nil {
292-
return err
293-
}
294298
sweepTx.TxOut = []*wire.TxOut{{
295299
Value: sweepValue - int64(totalFee),
296300
PkScript: sweepScript,

cmd/chantools/doublespendinputs.go

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
105105
privKeys := make([]*secp256k1.PrivateKey, 0, len(c.InputOutpoints))
106106

107107
// Get the addresses for the inputs.
108-
for _, input := range c.InputOutpoints {
109-
addrString, err := api.Address(input)
108+
for _, inputOutpoint := range c.InputOutpoints {
109+
addrString, err := api.Address(inputOutpoint)
110110
if err != nil {
111111
return err
112112
}
@@ -118,12 +118,12 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
118118

119119
addresses = append(addresses, addr)
120120

121-
txHash, err := chainhash.NewHashFromStr(input[:64])
121+
txHash, err := chainhash.NewHashFromStr(inputOutpoint[:64])
122122
if err != nil {
123123
return err
124124
}
125125

126-
vout, err := strconv.Atoi(input[65:])
126+
vout, err := strconv.Atoi(inputOutpoint[65:])
127127
if err != nil {
128128
return err
129129
}
@@ -144,7 +144,13 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
144144
}
145145

146146
// Start with the txweight estimator.
147-
estimator := input.TxWeightEstimator{}
147+
var estimator input.TxWeightEstimator
148+
sweepScript, err := lnd.PrepareWalletAddress(
149+
c.SweepAddr, chainParams, &estimator, extendedKey, "sweep",
150+
)
151+
if err != nil {
152+
return err
153+
}
148154

149155
// Find the key for the given addresses and add their
150156
// output weight to the tx estimator.
@@ -169,7 +175,9 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
169175
return err
170176
}
171177

172-
estimator.AddTaprootKeySpendInput(txscript.SigHashDefault)
178+
estimator.AddTaprootKeySpendInput(
179+
txscript.SigHashDefault,
180+
)
173181

174182
default:
175183
return fmt.Errorf("address type %T not supported", addr)
@@ -189,47 +197,32 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
189197

190198
// Next get the full value of the inputs.
191199
var totalInput btcutil.Amount
192-
for _, input := range outpoints {
200+
for _, outpoint := range outpoints {
193201
// Get the transaction.
194-
tx, err := api.Transaction(input.Hash.String())
202+
tx, err := api.Transaction(outpoint.Hash.String())
195203
if err != nil {
196204
return err
197205
}
198206

199-
value := tx.Vout[input.Index].Value
207+
value := tx.Vout[outpoint.Index].Value
200208

201209
// Get the output index.
202210
totalInput += btcutil.Amount(value)
203211

204-
scriptPubkey, err := hex.DecodeString(tx.Vout[input.Index].ScriptPubkey)
212+
scriptPubkey, err := hex.DecodeString(
213+
tx.Vout[outpoint.Index].ScriptPubkey,
214+
)
205215
if err != nil {
206216
return err
207217
}
208218

209219
// Add the output to the map.
210-
prevOuts[*input] = &wire.TxOut{
220+
prevOuts[*outpoint] = &wire.TxOut{
211221
Value: int64(value),
212222
PkScript: scriptPubkey,
213223
}
214224
}
215225

216-
// Calculate the fee.
217-
sweepAddr, err := btcutil.DecodeAddress(c.SweepAddr, chainParams)
218-
if err != nil {
219-
return err
220-
}
221-
222-
switch sweepAddr.(type) {
223-
case *btcutil.AddressWitnessPubKeyHash:
224-
estimator.AddP2WKHOutput()
225-
226-
case *btcutil.AddressTaproot:
227-
estimator.AddP2TROutput()
228-
229-
default:
230-
return fmt.Errorf("address type %T not supported", sweepAddr)
231-
}
232-
233226
// Calculate the fee.
234227
feeRateKWeight := chainfee.SatPerKVByte(1000 * c.FeeRate).FeePerKWeight()
235228
totalFee := feeRateKWeight.FeeForWeight(int64(estimator.Weight()))
@@ -238,14 +231,8 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
238231
tx := wire.NewMsgTx(2)
239232

240233
// Add the inputs.
241-
for _, input := range outpoints {
242-
tx.AddTxIn(wire.NewTxIn(input, nil, nil))
243-
}
244-
245-
// Add the output.
246-
sweepScript, err := txscript.PayToAddrScript(sweepAddr)
247-
if err != nil {
248-
return err
234+
for _, outpoint := range outpoints {
235+
tx.AddTxIn(wire.NewTxIn(outpoint, nil, nil))
249236
}
250237

251238
tx.AddTxOut(wire.NewTxOut(int64(totalInput-totalFee), sweepScript))
@@ -285,7 +272,8 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
285272
}
286273

287274
default:
288-
return fmt.Errorf("address type %T not supported", addresses[i])
275+
return fmt.Errorf("address type %T not supported",
276+
addresses[i])
289277
}
290278
}
291279

@@ -296,7 +284,7 @@ func (c *doubleSpendInputs) Execute(_ *cobra.Command, _ []string) error {
296284
}
297285

298286
// Print the transaction.
299-
fmt.Printf("Sweeping transaction:\n%s\n", hex.EncodeToString(txBuf.Bytes()))
287+
fmt.Printf("Sweeping transaction:\n%x\n", txBuf.Bytes())
300288

301289
// Publish the transaction.
302290
if c.Publish {

cmd/chantools/pullanchor.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,12 @@ func (c *pullAnchorCommand) Execute(_ *cobra.Command, _ []string) error {
115115
err)
116116
}
117117

118-
changeScript, err := lnd.GetP2WPKHScript(c.ChangeAddr, chainParams)
119-
if err != nil {
120-
return fmt.Errorf("error parsing change addr: %w", err)
121-
}
122-
123118
// Set default values.
124119
if c.FeeRate == 0 {
125120
c.FeeRate = defaultFeeSatPerVByte
126121
}
127122
return createPullTransactionTemplate(
128-
extendedKey, c.APIURL, outpoint, c.AnchorAddrs, changeScript,
123+
extendedKey, c.APIURL, outpoint, c.AnchorAddrs, c.ChangeAddr,
129124
c.FeeRate,
130125
)
131126
}
@@ -141,14 +136,23 @@ type targetAnchor struct {
141136

142137
func createPullTransactionTemplate(rootKey *hdkeychain.ExtendedKey,
143138
apiURL string, sponsorOutpoint *wire.OutPoint, anchorAddrs []string,
144-
changeScript []byte, feeRate uint32) error {
139+
changeAddr string, feeRate uint32) error {
145140

146-
signer := &lnd.Signer{
147-
ExtendedKey: rootKey,
148-
ChainParams: chainParams,
141+
var (
142+
signer = &lnd.Signer{
143+
ExtendedKey: rootKey,
144+
ChainParams: chainParams,
145+
}
146+
api = newExplorerAPI(apiURL)
147+
estimator input.TxWeightEstimator
148+
)
149+
150+
changeScript, err := lnd.PrepareWalletAddress(
151+
changeAddr, chainParams, &estimator, rootKey, "change",
152+
)
153+
if err != nil {
154+
return err
149155
}
150-
api := newExplorerAPI(apiURL)
151-
estimator := input.TxWeightEstimator{}
152156

153157
// Make sure the sponsor input is a P2WPKH or P2TR input and is known
154158
// to the block explorer, so we can fetch the witness utxo.
@@ -209,7 +213,6 @@ func createPullTransactionTemplate(rootKey *hdkeychain.ExtendedKey,
209213
}
210214

211215
// Now we can calculate the fee and add the change output.
212-
estimator.AddP2WKHOutput()
213216
anchorAmt := uint64(len(anchorAddrs)) * 330
214217
totalOutputValue := btcutil.Amount(sponsorTxOut.Value + anchorAmt)
215218
feeRateKWeight := chainfee.SatPerKVByte(1000 * feeRate).FeePerKWeight()

cmd/chantools/recoverloopin.go

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/hex"
66
"fmt"
77

8-
"github.com/btcsuite/btcd/btcutil"
98
"github.com/btcsuite/btcd/chaincfg/chainhash"
109
"github.com/btcsuite/btcd/txscript"
1110
"github.com/btcsuite/btcd/wire"
@@ -165,29 +164,20 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
165164
}
166165

167166
// Get the destination address.
168-
sweepAddr, err := btcutil.DecodeAddress(c.SweepAddr, chainParams)
167+
var estimator input.TxWeightEstimator
168+
sweepScript, err := lnd.PrepareWalletAddress(
169+
c.SweepAddr, chainParams, &estimator, extendedKey, "sweep",
170+
)
169171
if err != nil {
170172
return err
171173
}
172174

173175
// Calculate the sweep fee.
174-
estimator := &input.TxWeightEstimator{}
175-
err = htlc.AddTimeoutToEstimator(estimator)
176+
err = htlc.AddTimeoutToEstimator(&estimator)
176177
if err != nil {
177178
return err
178179
}
179180

180-
switch sweepAddr.(type) {
181-
case *btcutil.AddressWitnessPubKeyHash:
182-
estimator.AddP2WKHOutput()
183-
184-
case *btcutil.AddressTaproot:
185-
estimator.AddP2TROutput()
186-
187-
default:
188-
return fmt.Errorf("unsupported address type")
189-
}
190-
191181
feeRateKWeight := chainfee.SatPerKVByte(
192182
1000 * c.FeeRate,
193183
).FeePerKWeight()
@@ -216,13 +206,8 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error {
216206
})
217207

218208
// Add output for the destination address.
219-
sweepPkScript, err := txscript.PayToAddrScript(sweepAddr)
220-
if err != nil {
221-
return err
222-
}
223-
224209
sweepTx.AddTxOut(&wire.TxOut{
225-
PkScript: sweepPkScript,
210+
PkScript: sweepScript,
226211
Value: int64(loopIn.Contract.AmountRequested) - int64(fee),
227212
})
228213

cmd/chantools/rescuefunding.go

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -236,35 +236,38 @@ func (c *rescueFundingCommand) Execute(_ *cobra.Command, _ []string) error {
236236
return err
237237
}
238238

239-
// Make sure the sweep addr is a P2WKH address so we can do accurate
240-
// fee estimation.
241-
sweepScript, err := lnd.GetP2WPKHScript(c.SweepAddr, chainParams)
242-
if err != nil {
243-
return fmt.Errorf("error parsing sweep addr: %w", err)
244-
}
245-
246239
return rescueFunding(
247-
localKeyDesc, remotePubKey, signer, chainOp,
248-
sweepScript, btcutil.Amount(c.FeeRate), c.APIURL,
240+
localKeyDesc, remotePubKey, signer, chainOp, c.SweepAddr,
241+
btcutil.Amount(c.FeeRate), c.APIURL,
249242
)
250243
}
251244

252245
func rescueFunding(localKeyDesc *keychain.KeyDescriptor,
253246
remoteKey *btcec.PublicKey, signer *lnd.Signer,
254-
chainPoint *wire.OutPoint, sweepPKScript []byte, feeRate btcutil.Amount,
247+
chainPoint *wire.OutPoint, sweepAddr string, feeRate btcutil.Amount,
255248
apiURL string) error {
256249

250+
var (
251+
estimator input.TxWeightEstimator
252+
api = newExplorerAPI(apiURL)
253+
)
254+
sweepScript, err := lnd.PrepareWalletAddress(
255+
sweepAddr, chainParams, &estimator, signer.ExtendedKey, "sweep",
256+
)
257+
if err != nil {
258+
return err
259+
}
260+
257261
// Prepare the wire part of the PSBT.
258262
txIn := &wire.TxIn{
259263
PreviousOutPoint: *chainPoint,
260264
Sequence: 0,
261265
}
262266
txOut := &wire.TxOut{
263-
PkScript: sweepPKScript,
267+
PkScript: sweepScript,
264268
}
265269

266270
// Locate the output in the funding TX.
267-
api := newExplorerAPI(apiURL)
268271
tx, err := api.Transaction(chainPoint.Hash.String())
269272
if err != nil {
270273
return fmt.Errorf("error fetching UTXO info for outpoint %s: "+
@@ -303,17 +306,15 @@ func rescueFunding(localKeyDesc *keychain.KeyDescriptor,
303306
WitnessScript: witnessScript,
304307
Unknowns: []*psbt.Unknown{{
305308
// We add the public key the other party needs to sign
306-
// with as a proprietary field so we can easily read it
309+
// with as a proprietary field, so we can easily read it
307310
// out with the signrescuefunding command.
308311
Key: PsbtKeyTypeOutputMissingSigPubkey,
309312
Value: remoteKey.SerializeCompressed(),
310313
}},
311314
}
312315

313-
// Estimate the transaction weight so we can do the fee estimation.
314-
var estimator input.TxWeightEstimator
316+
// Estimate the transaction weight, so we can do the fee estimation.
315317
estimator.AddWitnessInput(MultiSigWitnessSize)
316-
estimator.AddP2WKHOutput()
317318
feeRateKWeight := chainfee.SatPerKVByte(1000 * feeRate).FeePerKWeight()
318319
totalFee := feeRateKWeight.FeeForWeight(int64(estimator.Weight()))
319320
txOut.Value = utxo.Value - int64(totalFee)

0 commit comments

Comments
 (0)