mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 01:36:24 +01:00
btcwallet: support taproot script signing in PSBT
This commit is contained in:
parent
0f32a4456d
commit
35dd2d25ea
1 changed files with 64 additions and 0 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/btcutil/psbt"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
|
@ -194,6 +195,17 @@ func (b *BtcWallet) SignPsbt(packet *psbt.Packet) error {
|
|||
in, tx, sigHashes, idx, privKey, rootHash,
|
||||
)
|
||||
|
||||
// For p2tr script spend path.
|
||||
case input.TaprootScriptSpendSignMethod:
|
||||
leafScript := in.TaprootLeafScript[0]
|
||||
leaf := txscript.TapLeaf{
|
||||
LeafVersion: leafScript.LeafVersion,
|
||||
Script: leafScript.Script,
|
||||
}
|
||||
err = signSegWitV1ScriptSpend(
|
||||
in, tx, sigHashes, idx, privKey, leaf,
|
||||
)
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("unsupported signing method for "+
|
||||
"PSBT signing: %v", signMethod)
|
||||
|
@ -268,6 +280,28 @@ func validateSigningMethod(in *psbt.PInput) (input.SignMethod, error) {
|
|||
// the same time? What are the performance and security
|
||||
// implications?
|
||||
case len(derivation.LeafHashes) == 1:
|
||||
// If we're supposed to be signing for a leaf hash, we
|
||||
// also expect the leaf script that hashes to that hash
|
||||
// in the appropriate field.
|
||||
if len(in.TaprootLeafScript) != 1 {
|
||||
return 0, fmt.Errorf("specified leaf hash in " +
|
||||
"taproot BIP0032 derivation but " +
|
||||
"missing taproot leaf script")
|
||||
}
|
||||
|
||||
leafScript := in.TaprootLeafScript[0]
|
||||
leaf := txscript.TapLeaf{
|
||||
LeafVersion: leafScript.LeafVersion,
|
||||
Script: leafScript.Script,
|
||||
}
|
||||
leafHash := leaf.TapHash()
|
||||
if !bytes.Equal(leafHash[:], derivation.LeafHashes[0]) {
|
||||
return 0, fmt.Errorf("specified leaf hash in" +
|
||||
"taproot BIP0032 derivation but " +
|
||||
"corresponding taproot leaf script " +
|
||||
"was not found")
|
||||
}
|
||||
|
||||
return input.TaprootScriptSpendSignMethod, nil
|
||||
|
||||
default:
|
||||
|
@ -343,6 +377,36 @@ func signSegWitV1KeySpend(in *psbt.PInput, tx *wire.MsgTx,
|
|||
return nil
|
||||
}
|
||||
|
||||
// signSegWitV1ScriptSpend attempts to generate a signature for a SegWit version
|
||||
// 1 (p2tr) input and stores it in the TaprootScriptSpendSig field.
|
||||
func signSegWitV1ScriptSpend(in *psbt.PInput, tx *wire.MsgTx,
|
||||
sigHashes *txscript.TxSigHashes, idx int, privKey *btcec.PrivateKey,
|
||||
leaf txscript.TapLeaf) error {
|
||||
|
||||
rawSig, err := txscript.RawTxInTapscriptSignature(
|
||||
tx, sigHashes, idx, in.WitnessUtxo.Value,
|
||||
in.WitnessUtxo.PkScript, leaf, in.SighashType, privKey,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error signing taproot script input %d: %v",
|
||||
idx, err)
|
||||
}
|
||||
|
||||
leafHash := leaf.TapHash()
|
||||
in.TaprootScriptSpendSig = append(
|
||||
in.TaprootScriptSpendSig, &psbt.TaprootScriptSpendSig{
|
||||
XOnlyPubKey: in.TaprootBip32Derivation[0].XOnlyPubKey,
|
||||
LeafHash: leafHash[:],
|
||||
// We snip off the sighash flag from the end (if it was
|
||||
// specified in the first place.)
|
||||
Signature: rawSig[:schnorr.SignatureSize],
|
||||
SigHash: in.SighashType,
|
||||
},
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// prepareScriptsV0 returns the appropriate witness v0 and/or legacy scripts,
|
||||
// depending on the type of input that should be signed.
|
||||
func prepareScriptsV0(in *psbt.PInput) ([]byte, []byte, error) {
|
||||
|
|
Loading…
Add table
Reference in a new issue