mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 18:00:11 +01:00
Merge pull request #1942 from guggero/psbt-export
btcutil/psbt: export helper functions, fix/add encoding of unknown fields
This commit is contained in:
commit
ecf98ce34f
@ -36,10 +36,10 @@ func (s Bip32Sorter) Less(i, j int) bool {
|
||||
return bytes.Compare(s[i].PubKey, s[j].PubKey) < 0
|
||||
}
|
||||
|
||||
// readBip32Derivation deserializes a byte slice containing chunks of 4 byte
|
||||
// ReadBip32Derivation deserializes a byte slice containing chunks of 4 byte
|
||||
// little endian encodings of uint32 values, the first of which is the
|
||||
// masterkeyfingerprint and the remainder of which are the derivation path.
|
||||
func readBip32Derivation(path []byte) (uint32, []uint32, error) {
|
||||
func ReadBip32Derivation(path []byte) (uint32, []uint32, error) {
|
||||
// BIP-0174 defines the derivation path being encoded as
|
||||
// "<32-bit uint> <32-bit uint>*"
|
||||
// with the asterisk meaning 0 to n times. Which in turn means that an
|
||||
|
@ -61,13 +61,14 @@ func Extract(p *Packet) (*wire.MsgTx, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now that we know how may inputs we'll need, we'll
|
||||
// Now that we know how many inputs we'll need, we'll
|
||||
// construct a packing slice, then read out each input
|
||||
// (with a varint prefix) from the witnessReader.
|
||||
tin.Witness = make(wire.TxWitness, witCount)
|
||||
for j := uint64(0); j < witCount; j++ {
|
||||
wit, err := wire.ReadVarBytes(
|
||||
witnessReader, 0, txscript.MaxScriptSize, "witness",
|
||||
witnessReader, 0,
|
||||
txscript.MaxScriptSize, "witness",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -14,6 +14,7 @@ package psbt
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
@ -462,7 +463,9 @@ func finalizeWitnessInput(p *Packet, inIndex int) error {
|
||||
return ErrNotFinalizable
|
||||
}
|
||||
|
||||
serializedWitness, err = writePKHWitness(sigs[0], pubKeys[0])
|
||||
serializedWitness, err = writePKHWitness(
|
||||
sigs[0], pubKeys[0],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -37,9 +37,7 @@ type PInput struct {
|
||||
// NOTE: Only one of the two arguments should be specified, with the other
|
||||
// being `nil`; otherwise the created PsbtInput object will fail IsSane()
|
||||
// checks and will not be usable.
|
||||
func NewPsbtInput(nonWitnessUtxo *wire.MsgTx,
|
||||
witnessUtxo *wire.TxOut) *PInput {
|
||||
|
||||
func NewPsbtInput(nonWitnessUtxo *wire.MsgTx, witnessUtxo *wire.TxOut) *PInput {
|
||||
return &PInput{
|
||||
NonWitnessUtxo: nonWitnessUtxo,
|
||||
WitnessUtxo: witnessUtxo,
|
||||
@ -57,7 +55,6 @@ func NewPsbtInput(nonWitnessUtxo *wire.MsgTx,
|
||||
// IsSane returns true only if there are no conflicting values in the Psbt
|
||||
// PInput. For segwit v0 no checks are currently implemented.
|
||||
func (pi *PInput) IsSane() bool {
|
||||
|
||||
// TODO(guggero): Implement sanity checks for segwit v1. For segwit v0
|
||||
// it is unsafe to only rely on the witness UTXO so we don't check that
|
||||
// only one is set anymore.
|
||||
@ -69,12 +66,12 @@ func (pi *PInput) IsSane() bool {
|
||||
// deserialize attempts to deserialize a new PInput from the passed io.Reader.
|
||||
func (pi *PInput) deserialize(r io.Reader) error {
|
||||
for {
|
||||
keyint, keydata, err := getKey(r)
|
||||
keyCode, keyData, err := getKey(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if keyint == -1 {
|
||||
// Reached separator byte
|
||||
if keyCode == -1 {
|
||||
// Reached separator byte, this section is done.
|
||||
break
|
||||
}
|
||||
value, err := wire.ReadVarBytes(
|
||||
@ -84,14 +81,14 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
|
||||
switch InputType(keyint) {
|
||||
switch InputType(keyCode) {
|
||||
|
||||
case NonWitnessUtxoType:
|
||||
if pi.NonWitnessUtxo != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
tx := wire.NewMsgTx(2)
|
||||
|
||||
@ -105,8 +102,8 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.WitnessUtxo != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
txout, err := readTxOut(value)
|
||||
if err != nil {
|
||||
@ -116,7 +113,7 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
|
||||
case PartialSigType:
|
||||
newPartialSig := PartialSig{
|
||||
PubKey: keydata,
|
||||
PubKey: keyData,
|
||||
Signature: value,
|
||||
}
|
||||
|
||||
@ -124,7 +121,7 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
return ErrInvalidPsbtFormat
|
||||
}
|
||||
|
||||
// Duplicate keys are not allowed
|
||||
// Duplicate keys are not allowed.
|
||||
for _, x := range pi.PartialSigs {
|
||||
if bytes.Equal(x.PubKey, newPartialSig.PubKey) {
|
||||
return ErrDuplicateKey
|
||||
@ -137,27 +134,27 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.SighashType != 0 {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
// Bounds check on value here since the sighash type must be a
|
||||
// 32-bit unsigned integer.
|
||||
// Bounds check on value here since the sighash type
|
||||
// must be a 32-bit unsigned integer.
|
||||
if len(value) != 4 {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
shtype := txscript.SigHashType(
|
||||
sighashType := txscript.SigHashType(
|
||||
binary.LittleEndian.Uint32(value),
|
||||
)
|
||||
pi.SighashType = shtype
|
||||
pi.SighashType = sighashType
|
||||
|
||||
case RedeemScriptInputType:
|
||||
if pi.RedeemScript != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
pi.RedeemScript = value
|
||||
|
||||
@ -165,23 +162,25 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.WitnessScript != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
pi.WitnessScript = value
|
||||
|
||||
case Bip32DerivationInputType:
|
||||
if !validatePubkey(keydata) {
|
||||
if !validatePubkey(keyData) {
|
||||
return ErrInvalidPsbtFormat
|
||||
}
|
||||
master, derivationPath, err := readBip32Derivation(value)
|
||||
master, derivationPath, err := ReadBip32Derivation(
|
||||
value,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Duplicate keys are not allowed
|
||||
for _, x := range pi.Bip32Derivation {
|
||||
if bytes.Equal(x.PubKey, keydata) {
|
||||
if bytes.Equal(x.PubKey, keyData) {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
}
|
||||
@ -189,7 +188,7 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
pi.Bip32Derivation = append(
|
||||
pi.Bip32Derivation,
|
||||
&Bip32Derivation{
|
||||
PubKey: keydata,
|
||||
PubKey: keyData,
|
||||
MasterKeyFingerprint: master,
|
||||
Bip32Path: derivationPath,
|
||||
},
|
||||
@ -199,8 +198,8 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.FinalScriptSig != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
pi.FinalScriptSig = value
|
||||
@ -209,8 +208,8 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.FinalScriptWitness != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
pi.FinalScriptWitness = value
|
||||
@ -219,26 +218,26 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.TaprootKeySpendSig != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
// The signature can either be 64 or 65 bytes.
|
||||
switch {
|
||||
case len(value) == schnorrSigMinLength:
|
||||
if !validateSchnorrSignature(value) {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
case len(value) == schnorrSigMaxLength:
|
||||
if !validateSchnorrSignature(
|
||||
value[0:schnorrSigMinLength],
|
||||
) {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
default:
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
pi.TaprootKeySpendSig = value
|
||||
@ -246,13 +245,13 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
case TaprootScriptSpendSignatureType:
|
||||
// The key data for the script spend signature is:
|
||||
// <xonlypubkey> <leafhash>
|
||||
if len(keydata) != 32*2 {
|
||||
return ErrInvalidKeydata
|
||||
if len(keyData) != 32*2 {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
newPartialSig := TaprootScriptSpendSig{
|
||||
XOnlyPubKey: keydata[:32],
|
||||
LeafHash: keydata[32:],
|
||||
XOnlyPubKey: keyData[:32],
|
||||
LeafHash: keyData[32:],
|
||||
}
|
||||
|
||||
// The signature can either be 64 or 65 bytes.
|
||||
@ -268,11 +267,11 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
)
|
||||
|
||||
default:
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
if !newPartialSig.checkValid() {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
// Duplicate keys are not allowed.
|
||||
@ -288,11 +287,11 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
|
||||
case TaprootLeafScriptType:
|
||||
if len(value) < 1 {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
newLeafScript := TaprootTapLeafScript{
|
||||
ControlBlock: keydata,
|
||||
ControlBlock: keyData,
|
||||
Script: value[:len(value)-1],
|
||||
LeafVersion: txscript.TapscriptLeafVersion(
|
||||
value[len(value)-1],
|
||||
@ -300,7 +299,7 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
}
|
||||
|
||||
if !newLeafScript.checkValid() {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
// Duplicate keys are not allowed.
|
||||
@ -318,12 +317,12 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
)
|
||||
|
||||
case TaprootBip32DerivationInputType:
|
||||
if !validateXOnlyPubkey(keydata) {
|
||||
return ErrInvalidKeydata
|
||||
if !validateXOnlyPubkey(keyData) {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
taprootDerivation, err := readTaprootBip32Derivation(
|
||||
keydata, value,
|
||||
taprootDerivation, err := ReadTaprootBip32Derivation(
|
||||
keyData, value,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -331,7 +330,7 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
|
||||
// Duplicate keys are not allowed.
|
||||
for _, x := range pi.TaprootBip32Derivation {
|
||||
if bytes.Equal(x.XOnlyPubKey, keydata) {
|
||||
if bytes.Equal(x.XOnlyPubKey, keyData) {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
}
|
||||
@ -344,12 +343,12 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.TaprootInternalKey != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
if !validateXOnlyPubkey(value) {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
pi.TaprootInternalKey = value
|
||||
@ -358,25 +357,27 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
if pi.TaprootMerkleRoot != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
pi.TaprootMerkleRoot = value
|
||||
|
||||
default:
|
||||
// A fall through case for any proprietary types.
|
||||
keyintanddata := []byte{byte(keyint)}
|
||||
keyintanddata = append(keyintanddata, keydata...)
|
||||
keyCodeAndData := append(
|
||||
[]byte{byte(keyCode)}, keyData...,
|
||||
)
|
||||
newUnknown := &Unknown{
|
||||
Key: keyintanddata,
|
||||
Key: keyCodeAndData,
|
||||
Value: value,
|
||||
}
|
||||
|
||||
// Duplicate key+keydata are not allowed
|
||||
// Duplicate key+keyData are not allowed.
|
||||
for _, x := range pi.Unknowns {
|
||||
if bytes.Equal(x.Key, newUnknown.Key) &&
|
||||
bytes.Equal(x.Value, newUnknown.Value) {
|
||||
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
}
|
||||
@ -390,7 +391,6 @@ func (pi *PInput) deserialize(r io.Reader) error {
|
||||
|
||||
// serialize attempts to serialize the target PInput into the passed io.Writer.
|
||||
func (pi *PInput) serialize(w io.Writer) error {
|
||||
|
||||
if !pi.IsSane() {
|
||||
return ErrInvalidPsbtFormat
|
||||
}
|
||||
@ -538,7 +538,7 @@ func (pi *PInput) serialize(w io.Writer) error {
|
||||
)
|
||||
})
|
||||
for _, derivation := range pi.TaprootBip32Derivation {
|
||||
value, err := serializeTaprootBip32Derivation(
|
||||
value, err := SerializeTaprootBip32Derivation(
|
||||
derivation,
|
||||
)
|
||||
if err != nil {
|
||||
@ -593,7 +593,7 @@ func (pi *PInput) serialize(w io.Writer) error {
|
||||
}
|
||||
|
||||
// Unknown is a special case; we don't have a key type, only a key and
|
||||
// a value field
|
||||
// a value field.
|
||||
for _, kv := range pi.Unknowns {
|
||||
err := serializeKVpair(w, kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
|
@ -17,6 +17,7 @@ type POutput struct {
|
||||
TaprootInternalKey []byte
|
||||
TaprootTapTree []byte
|
||||
TaprootBip32Derivation []*TaprootBip32Derivation
|
||||
Unknowns []*Unknown
|
||||
}
|
||||
|
||||
// NewPsbtOutput creates an instance of PsbtOutput; the three parameters
|
||||
@ -34,12 +35,12 @@ func NewPsbtOutput(redeemScript []byte, witnessScript []byte,
|
||||
// deserialize attempts to recode a new POutput from the passed io.Reader.
|
||||
func (po *POutput) deserialize(r io.Reader) error {
|
||||
for {
|
||||
keyint, keydata, err := getKey(r)
|
||||
keyCode, keyData, err := getKey(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if keyint == -1 {
|
||||
// Reached separator byte
|
||||
if keyCode == -1 {
|
||||
// Reached separator byte, this section is done.
|
||||
break
|
||||
}
|
||||
|
||||
@ -50,14 +51,14 @@ func (po *POutput) deserialize(r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
|
||||
switch OutputType(keyint) {
|
||||
switch OutputType(keyCode) {
|
||||
|
||||
case RedeemScriptOutputType:
|
||||
if po.RedeemScript != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
po.RedeemScript = value
|
||||
|
||||
@ -65,30 +66,32 @@ func (po *POutput) deserialize(r io.Reader) error {
|
||||
if po.WitnessScript != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
po.WitnessScript = value
|
||||
|
||||
case Bip32DerivationOutputType:
|
||||
if !validatePubkey(keydata) {
|
||||
return ErrInvalidKeydata
|
||||
if !validatePubkey(keyData) {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
master, derivationPath, err := readBip32Derivation(value)
|
||||
master, derivationPath, err := ReadBip32Derivation(
|
||||
value,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Duplicate keys are not allowed
|
||||
// Duplicate keys are not allowed.
|
||||
for _, x := range po.Bip32Derivation {
|
||||
if bytes.Equal(x.PubKey, keydata) {
|
||||
if bytes.Equal(x.PubKey, keyData) {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
}
|
||||
|
||||
po.Bip32Derivation = append(po.Bip32Derivation,
|
||||
&Bip32Derivation{
|
||||
PubKey: keydata,
|
||||
PubKey: keyData,
|
||||
MasterKeyFingerprint: master,
|
||||
Bip32Path: derivationPath,
|
||||
},
|
||||
@ -98,12 +101,12 @@ func (po *POutput) deserialize(r io.Reader) error {
|
||||
if po.TaprootInternalKey != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
if !validateXOnlyPubkey(value) {
|
||||
return ErrInvalidKeydata
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
po.TaprootInternalKey = value
|
||||
@ -112,19 +115,19 @@ func (po *POutput) deserialize(r io.Reader) error {
|
||||
if po.TaprootTapTree != nil {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
if keydata != nil {
|
||||
return ErrInvalidKeydata
|
||||
if keyData != nil {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
po.TaprootTapTree = value
|
||||
|
||||
case TaprootBip32DerivationOutputType:
|
||||
if !validateXOnlyPubkey(keydata) {
|
||||
return ErrInvalidKeydata
|
||||
if !validateXOnlyPubkey(keyData) {
|
||||
return ErrInvalidKeyData
|
||||
}
|
||||
|
||||
taprootDerivation, err := readTaprootBip32Derivation(
|
||||
keydata, value,
|
||||
taprootDerivation, err := ReadTaprootBip32Derivation(
|
||||
keyData, value,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -132,7 +135,7 @@ func (po *POutput) deserialize(r io.Reader) error {
|
||||
|
||||
// Duplicate keys are not allowed.
|
||||
for _, x := range po.TaprootBip32Derivation {
|
||||
if bytes.Equal(x.XOnlyPubKey, keydata) {
|
||||
if bytes.Equal(x.XOnlyPubKey, keyData) {
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
}
|
||||
@ -142,8 +145,25 @@ func (po *POutput) deserialize(r io.Reader) error {
|
||||
)
|
||||
|
||||
default:
|
||||
// Unknown type is allowed for inputs but not outputs.
|
||||
return ErrInvalidPsbtFormat
|
||||
// A fall through case for any proprietary types.
|
||||
keyCodeAndData := append(
|
||||
[]byte{byte(keyCode)}, keyData...,
|
||||
)
|
||||
newUnknown := &Unknown{
|
||||
Key: keyCodeAndData,
|
||||
Value: value,
|
||||
}
|
||||
|
||||
// Duplicate key+keyData are not allowed.
|
||||
for _, x := range po.Unknowns {
|
||||
if bytes.Equal(x.Key, newUnknown.Key) &&
|
||||
bytes.Equal(x.Value, newUnknown.Value) {
|
||||
|
||||
return ErrDuplicateKey
|
||||
}
|
||||
}
|
||||
|
||||
po.Unknowns = append(po.Unknowns, newUnknown)
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +231,7 @@ func (po *POutput) serialize(w io.Writer) error {
|
||||
)
|
||||
})
|
||||
for _, derivation := range po.TaprootBip32Derivation {
|
||||
value, err := serializeTaprootBip32Derivation(
|
||||
value, err := SerializeTaprootBip32Derivation(
|
||||
derivation,
|
||||
)
|
||||
if err != nil {
|
||||
@ -226,5 +246,14 @@ func (po *POutput) serialize(w io.Writer) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown is a special case; we don't have a key type, only a key and
|
||||
// a value field
|
||||
for _, kv := range po.Unknowns {
|
||||
err := serializeKVpair(w, kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
const psbtMagicLength = 5
|
||||
|
||||
var (
|
||||
// psbtMagic is the separator
|
||||
// psbtMagic is the separator.
|
||||
psbtMagic = [psbtMagicLength]byte{0x70,
|
||||
0x73, 0x62, 0x74, 0xff, // = "psbt" + 0xff sep
|
||||
}
|
||||
@ -34,7 +34,7 @@ var (
|
||||
const MaxPsbtValueLength = 4000000
|
||||
|
||||
// MaxPsbtKeyLength is the length of the largest key that we'll successfully
|
||||
// deserialize from the wire. Anything more will return ErrInvalidKeydata.
|
||||
// deserialize from the wire. Anything more will return ErrInvalidKeyData.
|
||||
const MaxPsbtKeyLength = 10000
|
||||
|
||||
var (
|
||||
@ -47,40 +47,41 @@ var (
|
||||
// due to having the same key repeated in the same key-value pair.
|
||||
ErrDuplicateKey = errors.New("Invalid Psbt due to duplicate key")
|
||||
|
||||
// ErrInvalidKeydata indicates that a key-value pair in the PSBT
|
||||
// ErrInvalidKeyData indicates that a key-value pair in the PSBT
|
||||
// serialization contains data in the key which is not valid.
|
||||
ErrInvalidKeydata = errors.New("Invalid key data")
|
||||
ErrInvalidKeyData = errors.New("Invalid key data")
|
||||
|
||||
// ErrInvalidMagicBytes indicates that a passed Psbt serialization is invalid
|
||||
// due to having incorrect magic bytes.
|
||||
ErrInvalidMagicBytes = errors.New("Invalid Psbt due to incorrect magic bytes")
|
||||
// ErrInvalidMagicBytes indicates that a passed Psbt serialization is
|
||||
// invalid due to having incorrect magic bytes.
|
||||
ErrInvalidMagicBytes = errors.New("Invalid Psbt due to incorrect " +
|
||||
"magic bytes")
|
||||
|
||||
// ErrInvalidRawTxSigned indicates that the raw serialized transaction in the
|
||||
// global section of the passed Psbt serialization is invalid because it
|
||||
// contains scriptSigs/witnesses (i.e. is fully or partially signed), which
|
||||
// is not allowed by BIP174.
|
||||
ErrInvalidRawTxSigned = errors.New("Invalid Psbt, raw transaction must " +
|
||||
"be unsigned.")
|
||||
// ErrInvalidRawTxSigned indicates that the raw serialized transaction
|
||||
// in the global section of the passed Psbt serialization is invalid
|
||||
// because it contains scriptSigs/witnesses (i.e. is fully or partially
|
||||
// signed), which is not allowed by BIP174.
|
||||
ErrInvalidRawTxSigned = errors.New("Invalid Psbt, raw transaction " +
|
||||
"must be unsigned.")
|
||||
|
||||
// ErrInvalidPrevOutNonWitnessTransaction indicates that the transaction
|
||||
// hash (i.e. SHA256^2) of the fully serialized previous transaction
|
||||
// provided in the NonWitnessUtxo key-value field doesn't match the prevout
|
||||
// hash in the UnsignedTx field in the PSBT itself.
|
||||
ErrInvalidPrevOutNonWitnessTransaction = errors.New("Prevout hash does " +
|
||||
"not match the provided non-witness utxo serialization")
|
||||
// provided in the NonWitnessUtxo key-value field doesn't match the
|
||||
// prevout hash in the UnsignedTx field in the PSBT itself.
|
||||
ErrInvalidPrevOutNonWitnessTransaction = errors.New("Prevout hash " +
|
||||
"does not match the provided non-witness utxo serialization")
|
||||
|
||||
// ErrInvalidSignatureForInput indicates that the signature the user is
|
||||
// trying to append to the PSBT is invalid, either because it does
|
||||
// not correspond to the previous transaction hash, or redeem script,
|
||||
// or witness script.
|
||||
// NOTE this does not include ECDSA signature checking.
|
||||
ErrInvalidSignatureForInput = errors.New("Signature does not correspond " +
|
||||
"to this input")
|
||||
ErrInvalidSignatureForInput = errors.New("Signature does not " +
|
||||
"correspond to this input")
|
||||
|
||||
// ErrInputAlreadyFinalized indicates that the PSBT passed to a Finalizer
|
||||
// already contains the finalized scriptSig or witness.
|
||||
ErrInputAlreadyFinalized = errors.New("Cannot finalize PSBT, finalized " +
|
||||
"scriptSig or scriptWitnes already exists")
|
||||
// ErrInputAlreadyFinalized indicates that the PSBT passed to a
|
||||
// Finalizer already contains the finalized scriptSig or witness.
|
||||
ErrInputAlreadyFinalized = errors.New("Cannot finalize PSBT, " +
|
||||
"finalized scriptSig or scriptWitnes already exists")
|
||||
|
||||
// ErrIncompletePSBT indicates that the Extractor object
|
||||
// was unable to successfully extract the passed Psbt struct because
|
||||
@ -99,8 +100,8 @@ var (
|
||||
ErrInvalidSigHashFlags = errors.New("Invalid Sighash Flags")
|
||||
|
||||
// ErrUnsupportedScriptType indicates that the redeem script or
|
||||
// scriptwitness given is not supported by this codebase, or is otherwise
|
||||
// not valid.
|
||||
// script witness given is not supported by this codebase, or is
|
||||
// otherwise not valid.
|
||||
ErrUnsupportedScriptType = errors.New("Unsupported script type")
|
||||
)
|
||||
|
||||
@ -112,7 +113,7 @@ type Unknown struct {
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// Packet is the actual psbt repreesntation. It is a is a set of 1 + N + M
|
||||
// Packet is the actual psbt representation. It is a set of 1 + N + M
|
||||
// key-value pair lists, 1 global, defining the unsigned transaction structure
|
||||
// with N inputs and M outputs. These key-value pairs can contain scripts,
|
||||
// signatures, key derivations and other transaction-defining data.
|
||||
@ -129,7 +130,7 @@ type Packet struct {
|
||||
Outputs []POutput
|
||||
|
||||
// Unknowns are the set of custom types (global only) within this PSBT.
|
||||
Unknowns []Unknown
|
||||
Unknowns []*Unknown
|
||||
}
|
||||
|
||||
// validateUnsignedTx returns true if the transaction is unsigned. Note that
|
||||
@ -148,23 +149,20 @@ func validateUnsignedTX(tx *wire.MsgTx) bool {
|
||||
// NewFromUnsignedTx creates a new Psbt struct, without any signatures (i.e.
|
||||
// only the global section is non-empty) using the passed unsigned transaction.
|
||||
func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) {
|
||||
|
||||
if !validateUnsignedTX(tx) {
|
||||
return nil, ErrInvalidRawTxSigned
|
||||
}
|
||||
|
||||
inSlice := make([]PInput, len(tx.TxIn))
|
||||
outSlice := make([]POutput, len(tx.TxOut))
|
||||
unknownSlice := make([]Unknown, 0)
|
||||
unknownSlice := make([]*Unknown, 0)
|
||||
|
||||
retPsbt := Packet{
|
||||
return &Packet{
|
||||
UnsignedTx: tx,
|
||||
Inputs: inSlice,
|
||||
Outputs: outSlice,
|
||||
Unknowns: unknownSlice,
|
||||
}
|
||||
|
||||
return &retPsbt, nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewFromRawBytes returns a new instance of a Packet struct created by reading
|
||||
@ -175,7 +173,6 @@ func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) {
|
||||
// NOTE: To create a Packet from one's own data, rather than reading in a
|
||||
// serialization from a counterparty, one should use a psbt.New.
|
||||
func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
|
||||
|
||||
// If the PSBT is encoded in bas64, then we'll create a new wrapper
|
||||
// reader that'll allow us to incrementally decode the contents of the
|
||||
// io.Reader.
|
||||
@ -197,11 +194,11 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
|
||||
// Next we parse the GLOBAL section. There is currently only 1 known
|
||||
// key type, UnsignedTx. We insist this exists first; unknowns are
|
||||
// allowed, but only after.
|
||||
keyint, keydata, err := getKey(r)
|
||||
keyCode, keyData, err := getKey(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if GlobalType(keyint) != UnsignedTxType || keydata != nil {
|
||||
if GlobalType(keyCode) != UnsignedTxType || keyData != nil {
|
||||
return nil, ErrInvalidPsbtFormat
|
||||
}
|
||||
|
||||
@ -227,7 +224,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
|
||||
|
||||
// Next we parse any unknowns that may be present, making sure that we
|
||||
// break at the separator.
|
||||
var unknownSlice []Unknown
|
||||
var unknownSlice []*Unknown
|
||||
for {
|
||||
keyint, keydata, err := getKey(r)
|
||||
if err != nil {
|
||||
@ -247,7 +244,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
|
||||
keyintanddata := []byte{byte(keyint)}
|
||||
keyintanddata = append(keyintanddata, keydata...)
|
||||
|
||||
newUnknown := Unknown{
|
||||
newUnknown := &Unknown{
|
||||
Key: keyintanddata,
|
||||
Value: value,
|
||||
}
|
||||
@ -278,7 +275,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
|
||||
outSlice[i] = output
|
||||
}
|
||||
|
||||
// Populate the new Packet object
|
||||
// Populate the new Packet object.
|
||||
newPsbt := Packet{
|
||||
UnsignedTx: msgTx,
|
||||
Inputs: inSlice,
|
||||
@ -298,7 +295,6 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) {
|
||||
// Serialize creates a binary serialization of the referenced Packet struct
|
||||
// with lexicographical ordering (by key) of the subsections.
|
||||
func (p *Packet) Serialize(w io.Writer) error {
|
||||
|
||||
// First we write out the precise set of magic bytes that identify a
|
||||
// valid PSBT transaction.
|
||||
if _, err := w.Write(psbtMagic[:]); err != nil {
|
||||
@ -323,6 +319,15 @@ func (p *Packet) Serialize(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Unknown is a special case; we don't have a key type, only a key and
|
||||
// a value field
|
||||
for _, kv := range p.Unknowns {
|
||||
err := serializeKVpair(w, kv.Key, kv.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// With that our global section is done, so we'll write out the
|
||||
// separator.
|
||||
separator := []byte{0x00}
|
||||
@ -382,7 +387,6 @@ func (p *Packet) IsComplete() bool {
|
||||
// SanityCheck checks conditions on a PSBT to ensure that it obeys the
|
||||
// rules of BIP174, and returns true if so, false if not.
|
||||
func (p *Packet) SanityCheck() error {
|
||||
|
||||
if !validateUnsignedTX(p.UnsignedTx) {
|
||||
return ErrInvalidRawTxSigned
|
||||
}
|
||||
|
@ -1502,3 +1502,28 @@ func TestWitnessForNonWitnessUtxo(t *testing.T) {
|
||||
t.Fatalf("unable to extract funding TX: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnknowns tests that we can parse and serialize unknown fields on all
|
||||
// three levels (global, input, output).
|
||||
func TestUnknowns(t *testing.T) {
|
||||
packetWithUnknowns := "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"
|
||||
|
||||
packet, err := NewFromRawBytes(
|
||||
strings.NewReader(packetWithUnknowns), true,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, packet.Unknowns, 2)
|
||||
|
||||
require.Len(t, packet.Inputs, 1)
|
||||
require.Len(t, packet.Inputs[0].Unknowns, 10)
|
||||
|
||||
require.Len(t, packet.Outputs, 2)
|
||||
require.Len(t, packet.Outputs[0].Unknowns, 7)
|
||||
|
||||
// Convert it to base64 again to make sure the fields are also
|
||||
// serialized.
|
||||
encoded, err := packet.B64Encode()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, packetWithUnknowns, encoded)
|
||||
}
|
||||
|
@ -22,12 +22,12 @@ const (
|
||||
// attached.
|
||||
SignSuccesful = 0
|
||||
|
||||
// SignFinalized indicates that this input is already finalized, so the provided
|
||||
// signature was *not* attached
|
||||
// SignFinalized indicates that this input is already finalized, so the
|
||||
// provided signature was *not* attached
|
||||
SignFinalized = 1
|
||||
|
||||
// SignInvalid indicates that the provided signature data was not valid. In this case
|
||||
// an error will also be returned.
|
||||
// SignInvalid indicates that the provided signature data was not valid.
|
||||
// In this case an error will also be returned.
|
||||
SignInvalid = -1
|
||||
)
|
||||
|
||||
@ -73,9 +73,10 @@ func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte,
|
||||
//
|
||||
// Case 1: if witnessScript is present, it must be of type witness;
|
||||
// if not, signature insertion will of course fail.
|
||||
pInput := u.Upsbt.Inputs[inIndex]
|
||||
switch {
|
||||
case u.Upsbt.Inputs[inIndex].WitnessScript != nil:
|
||||
if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil {
|
||||
case pInput.WitnessScript != nil:
|
||||
if pInput.WitnessUtxo == nil {
|
||||
err := nonWitnessToWitness(u.Upsbt, inIndex)
|
||||
if err != nil {
|
||||
return SignInvalid, err
|
||||
@ -89,12 +90,12 @@ func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte,
|
||||
|
||||
// Case 2: no witness script, only redeem script; can be legacy p2sh or
|
||||
// p2sh-wrapped p2wkh.
|
||||
case u.Upsbt.Inputs[inIndex].RedeemScript != nil:
|
||||
case pInput.RedeemScript != nil:
|
||||
// We only need to decide if the input is witness, and we don't
|
||||
// rely on the witnessutxo/nonwitnessutxo in the PSBT, instead
|
||||
// we check the redeemScript content.
|
||||
if txscript.IsWitnessProgram(redeemScript) {
|
||||
if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil {
|
||||
if pInput.WitnessUtxo == nil {
|
||||
err := nonWitnessToWitness(u.Upsbt, inIndex)
|
||||
if err != nil {
|
||||
return SignInvalid, err
|
||||
@ -113,9 +114,10 @@ func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte,
|
||||
// non-p2sh. To check if it's segwit, check the scriptPubKey of the
|
||||
// output.
|
||||
default:
|
||||
if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil {
|
||||
outIndex := u.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index
|
||||
script := u.Upsbt.Inputs[inIndex].NonWitnessUtxo.TxOut[outIndex].PkScript
|
||||
if pInput.WitnessUtxo == nil {
|
||||
txIn := u.Upsbt.UnsignedTx.TxIn[inIndex]
|
||||
outIndex := txIn.PreviousOutPoint.Index
|
||||
script := pInput.NonWitnessUtxo.TxOut[outIndex].PkScript
|
||||
|
||||
if txscript.IsWitnessProgram(script) {
|
||||
err := nonWitnessToWitness(u.Upsbt, inIndex)
|
||||
|
@ -2,6 +2,7 @@ package psbt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -92,10 +93,10 @@ func (s *TaprootBip32Derivation) SortBefore(other *TaprootBip32Derivation) bool
|
||||
return bytes.Compare(s.XOnlyPubKey, other.XOnlyPubKey) < 0
|
||||
}
|
||||
|
||||
// readTaprootBip32Derivation deserializes a byte slice containing the Taproot
|
||||
// ReadTaprootBip32Derivation deserializes a byte slice containing the Taproot
|
||||
// BIP32 derivation info that consists of a list of leaf hashes as well as the
|
||||
// normal BIP32 derivation info.
|
||||
func readTaprootBip32Derivation(xOnlyPubKey,
|
||||
func ReadTaprootBip32Derivation(xOnlyPubKey,
|
||||
value []byte) (*TaprootBip32Derivation, error) {
|
||||
|
||||
// The taproot key BIP 32 derivation path is defined as:
|
||||
@ -141,7 +142,7 @@ func readTaprootBip32Derivation(xOnlyPubKey,
|
||||
}
|
||||
|
||||
// Read the BIP32 derivation info.
|
||||
fingerprint, path, err := readBip32Derivation(leftoverBuf.Bytes())
|
||||
fingerprint, path, err := ReadBip32Derivation(leftoverBuf.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -152,9 +153,9 @@ func readTaprootBip32Derivation(xOnlyPubKey,
|
||||
return &derivation, nil
|
||||
}
|
||||
|
||||
// serializeTaprootBip32Derivation serializes a TaprootBip32Derivation to its
|
||||
// SerializeTaprootBip32Derivation serializes a TaprootBip32Derivation to its
|
||||
// raw byte representation.
|
||||
func serializeTaprootBip32Derivation(d *TaprootBip32Derivation) ([]byte,
|
||||
func SerializeTaprootBip32Derivation(d *TaprootBip32Derivation) ([]byte,
|
||||
error) {
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
@ -245,7 +245,7 @@ func getKey(r io.Reader) (int, []byte, error) {
|
||||
|
||||
// Check that we don't attempt to decode a dangerously large key.
|
||||
if count > MaxPsbtKeyLength {
|
||||
return -1, nil, ErrInvalidKeydata
|
||||
return -1, nil, ErrInvalidKeyData
|
||||
}
|
||||
|
||||
// Next, we ready out the designated number of bytes, which may include
|
||||
|
Loading…
Reference in New Issue
Block a user