Merge pull request #2198 from Roasbeef/sendall-rpc
multi: add ability to sweep all coins in the the wallet to an addr to sendcoins
This commit is contained in:
22 files changed
+1761
-712
No files matched your search
@@ -180,9 +180,10 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
||||
// TODO(roasbeef): generate sighash midstate if not present?
|
||||
|
||||
amt := signDesc.Output.Value
|
||||
sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes,
|
||||
signDesc.InputIndex, amt, witnessScript, signDesc.HashType,
|
||||
privKey)
|
||||
sig, err := txscript.RawTxInWitnessSignature(
|
||||
tx, signDesc.SigHashes, signDesc.InputIndex, amt,
|
||||
witnessScript, signDesc.HashType, privKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -227,8 +228,9 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
||||
// spend the p2sh output. The sigScript will contain only a
|
||||
// single push of the p2wkh witness program corresponding to
|
||||
// the matching public key of this address.
|
||||
p2wkhAddr, err := btcutil.NewAddressWitnessPubKeyHash(pubKeyHash,
|
||||
b.netParams)
|
||||
p2wkhAddr, err := btcutil.NewAddressWitnessPubKeyHash(
|
||||
pubKeyHash, b.netParams,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -244,7 +246,7 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inputScript.ScriptSig = sigScript
|
||||
inputScript.SigScript = sigScript
|
||||
|
||||
// Otherwise, this is a regular p2wkh output, so we include the
|
||||
// witness program itself as the subscript to generate the proper
|
||||
@@ -267,7 +269,8 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
||||
// TODO(roasbeef): adhere to passed HashType
|
||||
witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes,
|
||||
signDesc.InputIndex, signDesc.Output.Value, witnessProgram,
|
||||
signDesc.HashType, privKey, true)
|
||||
signDesc.HashType, privKey, true,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ type TransactionSubscription interface {
|
||||
type WalletController interface {
|
||||
// FetchInputInfo queries for the WalletController's knowledge of the
|
||||
// passed outpoint. If the base wallet determines this output is under
|
||||
// its control, then the original txout should be returned. Otherwise,
|
||||
// its control, then the original txout should be returned. Otherwise,
|
||||
// a non-nil error value of ErrNotMine should be returned instead.
|
||||
FetchInputInfo(prevOut *wire.OutPoint) (*wire.TxOut, error)
|
||||
|
||||
|
||||
@@ -50,11 +50,15 @@ func (c *ChannelContribution) toChanConfig() channeldb.ChannelConfig {
|
||||
}
|
||||
|
||||
// InputScript represents any script inputs required to redeem a previous
|
||||
// output. This struct is used rather than just a witness, or scripSig in
|
||||
// order to accommodate nested p2sh which utilizes both types of input scripts.
|
||||
// output. This struct is used rather than just a witness, or scripSig in order
|
||||
// to accommodate nested p2sh which utilizes both types of input scripts.
|
||||
type InputScript struct {
|
||||
Witness [][]byte
|
||||
ScriptSig []byte
|
||||
// Witness is the full witness stack required to unlock this output.
|
||||
Witness wire.TxWitness
|
||||
|
||||
// SigScript will only be populated if this is an input script sweeping
|
||||
// a nested p2sh output.
|
||||
SigScript []byte
|
||||
}
|
||||
|
||||
// ChannelReservation represents an intent to open a lightning payment channel
|
||||
|
||||
@@ -438,13 +438,15 @@ func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor
|
||||
"address %v", addresses[0])
|
||||
}
|
||||
|
||||
scriptSig, err := txscript.SignatureScript(tx, signDesc.InputIndex,
|
||||
signDesc.Output.PkScript, txscript.SigHashAll, privKey, true)
|
||||
sigScript, err := txscript.SignatureScript(
|
||||
tx, signDesc.InputIndex, signDesc.Output.PkScript,
|
||||
txscript.SigHashAll, privKey, true,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{ScriptSig: scriptSig}, nil
|
||||
return &InputScript{SigScript: sigScript}, nil
|
||||
|
||||
case txscript.WitnessV0PubKeyHashTy:
|
||||
privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
|
||||
|
||||
+16
-5
@@ -747,14 +747,15 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
|
||||
signDesc.Output = info
|
||||
signDesc.InputIndex = i
|
||||
|
||||
inputScript, err := l.Cfg.Signer.ComputeInputScript(fundingTx,
|
||||
&signDesc)
|
||||
inputScript, err := l.Cfg.Signer.ComputeInputScript(
|
||||
fundingTx, &signDesc,
|
||||
)
|
||||
if err != nil {
|
||||
req.err <- err
|
||||
return
|
||||
}
|
||||
|
||||
txIn.SignatureScript = inputScript.ScriptSig
|
||||
txIn.SignatureScript = inputScript.SigScript
|
||||
txIn.Witness = inputScript.Witness
|
||||
pendingReservation.ourFundingInputScripts = append(
|
||||
pendingReservation.ourFundingInputScripts,
|
||||
@@ -958,7 +959,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
|
||||
if len(inputScripts) != 0 && len(txin.Witness) == 0 {
|
||||
// Attach the input scripts so we can verify it below.
|
||||
txin.Witness = inputScripts[sigIndex].Witness
|
||||
txin.SignatureScript = inputScripts[sigIndex].ScriptSig
|
||||
txin.SignatureScript = inputScripts[sigIndex].SigScript
|
||||
|
||||
// Fetch the alleged previous output along with the
|
||||
// pkscript referenced by this input.
|
||||
@@ -1251,12 +1252,22 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
|
||||
l.limboMtx.Unlock()
|
||||
}
|
||||
|
||||
// WithCoinSelectLock will execute the passed function closure in a
|
||||
// synchronized manner preventing any coin selection operations from proceeding
|
||||
// while the closure if executing. This can be seen as the ability to execute a
|
||||
// function closure under an exclusive coin selection lock.
|
||||
func (l *LightningWallet) WithCoinSelectLock(f func() error) error {
|
||||
l.coinSelectMtx.Lock()
|
||||
defer l.coinSelectMtx.Unlock()
|
||||
|
||||
return f()
|
||||
}
|
||||
|
||||
// selectCoinsAndChange performs coin selection in order to obtain witness
|
||||
// outputs which sum to at least 'numCoins' amount of satoshis. If coin
|
||||
// selection is successful/possible, then the selected coins are available
|
||||
// within the passed contribution's inputs. If necessary, a change address will
|
||||
// also be generated.
|
||||
// TODO(roasbeef): remove hardcoded fees.
|
||||
func (l *LightningWallet) selectCoinsAndChange(feeRate SatPerKWeight,
|
||||
amt btcutil.Amount, minConfs int32,
|
||||
contribution *ChannelContribution) error {
|
||||
|
||||
+97
-15
@@ -69,6 +69,16 @@ const (
|
||||
// broadcast a revoked commitment, but then also immediately attempt to
|
||||
// go to the second level to claim the HTLC.
|
||||
HtlcSecondLevelRevoke WitnessType = 9
|
||||
|
||||
// WitnessKeyHash is a witness type that allows us to spend a regular
|
||||
// p2wkh output that's sent to an output which is under complete
|
||||
// control of the backing wallet.
|
||||
WitnessKeyHash WitnessType = 10
|
||||
|
||||
// NestedWitnessKeyHash is a witness type that allows us to sweep an
|
||||
// output that sends to a nested P2SH script that pays to a key solely
|
||||
// under our control. The witness generated needs to include the
|
||||
NestedWitnessKeyHash WitnessType = 11
|
||||
)
|
||||
|
||||
// Stirng returns a human readable version of the target WitnessType.
|
||||
@@ -110,18 +120,22 @@ func (wt WitnessType) String() string {
|
||||
}
|
||||
|
||||
// WitnessGenerator represents a function which is able to generate the final
|
||||
// witness for a particular public key script. This function acts as an
|
||||
// abstraction layer, hiding the details of the underlying script.
|
||||
// witness for a particular public key script. Additionally, if required, this
|
||||
// function will also return the sigScript for spending nested P2SH witness
|
||||
// outputs. This function acts as an abstraction layer, hiding the details of
|
||||
// the underlying script.
|
||||
type WitnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
||||
inputIndex int) ([][]byte, error)
|
||||
inputIndex int) (*InputScript, error)
|
||||
|
||||
// GenWitnessFunc will return a WitnessGenerator function that an output
|
||||
// uses to generate the witness for a sweep transaction.
|
||||
// GenWitnessFunc will return a WitnessGenerator function that an output uses
|
||||
// to generate the witness and optionally the sigScript for a sweep
|
||||
// transaction. The sigScript will be generated if the witness type warrants
|
||||
// one for spending, such as the NestedWitnessKeyHash witness type.
|
||||
func (wt WitnessType) GenWitnessFunc(signer Signer,
|
||||
descriptor *SignDescriptor) WitnessGenerator {
|
||||
|
||||
return func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
||||
inputIndex int) ([][]byte, error) {
|
||||
inputIndex int) (*InputScript, error) {
|
||||
|
||||
desc := descriptor
|
||||
desc.SigHashes = hc
|
||||
@@ -129,34 +143,102 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
||||
|
||||
switch wt {
|
||||
case CommitmentTimeLock:
|
||||
return CommitSpendTimeout(signer, desc, tx)
|
||||
witness, err := CommitSpendTimeout(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case CommitmentNoDelay:
|
||||
return CommitSpendNoDelay(signer, desc, tx)
|
||||
witness, err := CommitSpendNoDelay(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case CommitmentRevoke:
|
||||
return CommitSpendRevoke(signer, desc, tx)
|
||||
witness, err := CommitSpendRevoke(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case HtlcOfferedRevoke:
|
||||
return ReceiverHtlcSpendRevoke(signer, desc, tx)
|
||||
witness, err := ReceiverHtlcSpendRevoke(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case HtlcAcceptedRevoke:
|
||||
return SenderHtlcSpendRevoke(signer, desc, tx)
|
||||
witness, err := SenderHtlcSpendRevoke(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case HtlcOfferedTimeoutSecondLevel:
|
||||
return HtlcSecondLevelSpend(signer, desc, tx)
|
||||
witness, err := HtlcSecondLevelSpend(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case HtlcAcceptedSuccessSecondLevel:
|
||||
return HtlcSecondLevelSpend(signer, desc, tx)
|
||||
witness, err := HtlcSecondLevelSpend(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case HtlcOfferedRemoteTimeout:
|
||||
// We pass in a value of -1 for the timeout, as we
|
||||
// expect the caller to have already set the lock time
|
||||
// value.
|
||||
return receiverHtlcSpendTimeout(signer, desc, tx, -1)
|
||||
witness, err := receiverHtlcSpendTimeout(signer, desc, tx, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case HtlcSecondLevelRevoke:
|
||||
return htlcSpendRevoke(signer, desc, tx)
|
||||
witness, err := htlcSpendRevoke(signer, desc, tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &InputScript{
|
||||
Witness: witness,
|
||||
}, nil
|
||||
|
||||
case WitnessKeyHash:
|
||||
fallthrough
|
||||
case NestedWitnessKeyHash:
|
||||
return signer.ComputeInputScript(tx, desc)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown witness type: %v", wt)
|
||||
|
||||
Reference in new issue
Block a user