Browse Source

sweeptimelock: refactor as preparation for next feature

pull/32/head
Oliver Gugger 4 months ago
parent
commit
46d79f5b80
No known key found for this signature in database GPG Key ID: 8E4256593F177720
2 changed files with 93 additions and 36 deletions
  1. +76
    -34
      cmd/chantools/sweeptimelock.go
  2. +17
    -2
      dataformat/summary.go

+ 76
- 34
cmd/chantools/sweeptimelock.go View File

@ -14,6 +14,7 @@ import (
"github.com/guggero/chantools/dataformat"
"github.com/guggero/chantools/lnd"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/spf13/cobra"
)
@ -104,28 +105,28 @@ func (c *sweepTimeLockCommand) Execute(_ *cobra.Command, _ []string) error {
if c.FeeRate == 0 {
c.FeeRate = defaultFeeSatPerVByte
}
return sweepTimeLock(
return sweepTimeLockFromSummary(
extendedKey, c.APIURL, entries, c.SweepAddr, c.MaxCsvLimit,
c.Publish, c.FeeRate,
)
}
func sweepTimeLock(extendedKey *hdkeychain.ExtendedKey, apiURL string,
type sweepTarget struct {
channelPoint string
txid chainhash.Hash
index uint32
lockScript []byte
value int64
commitPoint *btcec.PublicKey
revocationBasePoint *btcec.PublicKey
delayBasePointDesc *keychain.KeyDescriptor
}
func sweepTimeLockFromSummary(extendedKey *hdkeychain.ExtendedKey, apiURL string,
entries []*dataformat.SummaryEntry, sweepAddr string,
maxCsvTimeout uint16, publish bool, feeRate uint16) error {
// Create signer and transaction template.
signer := &lnd.Signer{
ExtendedKey: extendedKey,
ChainParams: chainParams,
}
api := &btc.ExplorerAPI{BaseURL: apiURL}
sweepTx := wire.NewMsgTx(2)
totalOutputValue := int64(0)
signDescs := make([]*input.SignDescriptor, 0)
var estimator input.TxWeightEstimator
targets := make([]*sweepTarget, 0, len(entries))
for _, entry := range entries {
// Skip entries that can't be swept.
if entry.ForceClose == nil ||
@ -169,14 +170,14 @@ func sweepTimeLock(extendedKey *hdkeychain.ExtendedKey, apiURL string,
}
revBase, err := pubKeyFromHex(fc.RevocationBasePoint.PubKey)
if err != nil {
return fmt.Errorf("error parsing commit point: %v", err)
return fmt.Errorf("error parsing revocation base "+
"point: %v", err)
}
delayDesc := fc.DelayBasePoint.Desc()
delayPrivKey, err := signer.FetchPrivKey(delayDesc)
delayDesc, err := fc.DelayBasePoint.Desc()
if err != nil {
return fmt.Errorf("error getting private key: %v", err)
return fmt.Errorf("error parsing delay base point: %v",
err)
}
delayBase := delayPrivKey.PubKey()
lockScript, err := hex.DecodeString(fc.Outs[txindex].Script)
if err != nil {
@ -184,29 +185,69 @@ func sweepTimeLock(extendedKey *hdkeychain.ExtendedKey, apiURL string,
err)
}
// Create the transaction input.
txHash, err := chainhash.NewHashFromStr(fc.TXID)
if err != nil {
return fmt.Errorf("error parsing tx hash: %v", err)
}
targets = append(targets, &sweepTarget{
channelPoint: entry.ChannelPoint,
txid: *txHash,
index: uint32(txindex),
lockScript: lockScript,
value: int64(fc.Outs[txindex].Value),
commitPoint: commitPoint,
revocationBasePoint: revBase,
delayBasePointDesc: delayDesc,
})
}
return sweepTimeLock(
extendedKey, apiURL, targets, sweepAddr, maxCsvTimeout, publish,
feeRate,
)
}
func sweepTimeLock(extendedKey *hdkeychain.ExtendedKey, apiURL string,
targets []*sweepTarget, sweepAddr string, maxCsvTimeout uint16,
publish bool, feeRate uint16) error {
// Create signer and transaction template.
signer := &lnd.Signer{
ExtendedKey: extendedKey,
ChainParams: chainParams,
}
api := &btc.ExplorerAPI{BaseURL: apiURL}
sweepTx := wire.NewMsgTx(2)
totalOutputValue := int64(0)
signDescs := make([]*input.SignDescriptor, 0)
var estimator input.TxWeightEstimator
for _, target := range targets {
// We can't rely on the CSV delay of the channel DB to be
// correct. But it doesn't cost us a lot to just brute force it.
csvTimeout, script, scriptHash, err := bruteForceDelay(
input.TweakPubKey(delayBase, commitPoint),
input.DeriveRevocationPubkey(revBase, commitPoint),
lockScript, maxCsvTimeout,
input.TweakPubKey(
target.delayBasePointDesc.PubKey,
target.commitPoint,
), input.DeriveRevocationPubkey(
target.revocationBasePoint,
target.commitPoint,
), target.lockScript, maxCsvTimeout,
)
if err != nil {
log.Errorf("Could not create matching script for %s "+
"or csv too high: %v", entry.ChannelPoint,
err)
"or csv too high: %v", target.channelPoint, err)
continue
}
// Create the transaction input.
txHash, err := chainhash.NewHashFromStr(fc.TXID)
if err != nil {
return fmt.Errorf("error parsing tx hash: %v", err)
}
sweepTx.TxIn = append(sweepTx.TxIn, &wire.TxIn{
PreviousOutPoint: wire.OutPoint{
Hash: *txHash,
Index: uint32(txindex),
Hash: target.txid,
Index: target.index,
},
Sequence: input.LockTimeToSequence(
false, uint32(csvTimeout),
@ -215,18 +256,19 @@ func sweepTimeLock(extendedKey *hdkeychain.ExtendedKey, apiURL string,
// Create the sign descriptor for the input.
signDesc := &input.SignDescriptor{
KeyDesc: *delayDesc,
KeyDesc: *target.delayBasePointDesc,
SingleTweak: input.SingleTweakBytes(
commitPoint, delayBase,
target.commitPoint,
target.delayBasePointDesc.PubKey,
),
WitnessScript: script,
Output: &wire.TxOut{
PkScript: scriptHash,
Value: int64(fc.Outs[txindex].Value),
Value: target.value,
},
HashType: txscript.SigHashAll,
}
totalOutputValue += int64(fc.Outs[txindex].Value)
totalOutputValue += target.value
signDescs = append(signDescs, signDesc)
// Account for the input weight.

+ 17
- 2
dataformat/summary.go View File

@ -1,6 +1,9 @@
package dataformat
import (
"encoding/hex"
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/lightningnetwork/lnd/keychain"
)
@ -20,13 +23,25 @@ type BasePoint struct {
PubKey string `json:"pubkey"`
}
func (b *BasePoint) Desc() *keychain.KeyDescriptor {
func (b *BasePoint) Desc() (*keychain.KeyDescriptor, error) {
pubKeyHex, err := hex.DecodeString(b.PubKey)
if err != nil {
return nil, fmt.Errorf("error decoding base point pubkey: %v",
err)
}
pubKey, err := btcec.ParsePubKey(pubKeyHex, btcec.S256())
if err != nil {
return nil, fmt.Errorf("error parsing base point pubkey: %v",
err)
}
return &keychain.KeyDescriptor{
KeyLocator: keychain.KeyLocator{
Family: keychain.KeyFamily(b.Family),
Index: b.Index,
},
}
PubKey: pubKey,
}, nil
}
type Out struct {

Loading…
Cancel
Save