mirror of
https://github.com/guggero/chantools.git
synced 2026-08-13 12:33:34 +02:00
signpsbt: implement Taproot keyspend signing
This commit is contained in:
parent
f478242346
commit
172c5da72e
2 changed files with 63 additions and 7 deletions
|
|
@ -172,12 +172,30 @@ func signPsbt(rootKey *hdkeychain.ExtendedKey,
|
|||
}
|
||||
utxo := pIn.WitnessUtxo
|
||||
|
||||
localPrivateKey, err := localKey.ECPrivKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting private key: %w", err)
|
||||
}
|
||||
|
||||
// The signing is a bit different for P2WPKH, we need to specify
|
||||
// the pk script as the witness script.
|
||||
var witnessScript []byte
|
||||
if txscript.IsPayToWitnessPubKeyHash(utxo.PkScript) {
|
||||
switch {
|
||||
case txscript.IsPayToWitnessPubKeyHash(utxo.PkScript):
|
||||
witnessScript = utxo.PkScript
|
||||
} else {
|
||||
|
||||
case txscript.IsPayToTaproot(utxo.PkScript):
|
||||
err := signer.AddTaprootSignature(
|
||||
packet, inputIndex, utxo, localPrivateKey,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding taproot "+
|
||||
"signature: %w", err)
|
||||
}
|
||||
|
||||
continue
|
||||
|
||||
default:
|
||||
if len(pIn.WitnessScript) == 0 {
|
||||
return fmt.Errorf("invalid PSBT, input %d is "+
|
||||
"missing witness script", inputIndex)
|
||||
|
|
@ -185,11 +203,6 @@ func signPsbt(rootKey *hdkeychain.ExtendedKey,
|
|||
witnessScript = pIn.WitnessScript
|
||||
}
|
||||
|
||||
localPrivateKey, err := localKey.ECPrivKey()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting private key: %w", err)
|
||||
}
|
||||
|
||||
// Do we already have a partial signature for our key?
|
||||
localPubKey := localPrivateKey.PubKey().SerializeCompressed()
|
||||
haveSig := false
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package lnd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -234,6 +235,48 @@ func (s *Signer) AddPartialSignatureForPrivateKey(packet *psbt.Packet,
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Signer) AddTaprootSignature(packet *psbt.Packet, inputIndex int,
|
||||
utxo *wire.TxOut, privateKey *btcec.PrivateKey) error {
|
||||
|
||||
pIn := &packet.Inputs[inputIndex]
|
||||
|
||||
// Now we add our partial signature.
|
||||
prevOutFetcher := wallet.PsbtPrevOutputFetcher(packet)
|
||||
signDesc := &input.SignDescriptor{
|
||||
Output: utxo,
|
||||
InputIndex: inputIndex,
|
||||
HashType: txscript.SigHashDefault,
|
||||
PrevOutputFetcher: prevOutFetcher,
|
||||
SigHashes: txscript.NewTxSigHashes(
|
||||
packet.UnsignedTx, prevOutFetcher,
|
||||
),
|
||||
SignMethod: input.TaprootKeySpendBIP0086SignMethod,
|
||||
}
|
||||
|
||||
if len(pIn.TaprootMerkleRoot) > 0 {
|
||||
signDesc.SignMethod = input.TaprootKeySpendSignMethod
|
||||
signDesc.TapTweak = pIn.TaprootMerkleRoot
|
||||
}
|
||||
|
||||
ourSigRaw, err := s.SignOutputRawWithPrivateKey(
|
||||
packet.UnsignedTx, signDesc, privateKey,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error signing with our key: %w", err)
|
||||
}
|
||||
|
||||
witness := wire.TxWitness{ourSigRaw.Serialize()}
|
||||
var witnessBuf bytes.Buffer
|
||||
err = psbt.WriteTxWitness(&witnessBuf, witness)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error serializing witness: %w", err)
|
||||
}
|
||||
|
||||
pIn.FinalScriptWitness = witnessBuf.Bytes()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// maybeTweakPrivKey examines the single tweak parameters on the passed sign
|
||||
// descriptor and may perform a mapping on the passed private key in order to
|
||||
// utilize the tweaks, if populated.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue