From 2643fb1a757328552d85ce891a3793dfe5f34b98 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 15 Jan 2020 17:36:48 -0800 Subject: [PATCH] psbt: move output into new file --- psbt/partial_output.go | 139 +++++++++++++++++++++++++++++++++++++++++ psbt/psbt.go | 109 -------------------------------- 2 files changed, 139 insertions(+), 109 deletions(-) create mode 100644 psbt/partial_output.go diff --git a/psbt/partial_output.go b/psbt/partial_output.go new file mode 100644 index 0000000..64d1bd4 --- /dev/null +++ b/psbt/partial_output.go @@ -0,0 +1,139 @@ +package psbt + +import ( + "bytes" + "io" + "sort" + + "github.com/btcsuite/btcd/wire" +) + +// POutput is a struct encapsulating all the data that can be attached +// to any specific output of the PSBT. +type POutput struct { + RedeemScript []byte + WitnessScript []byte + Bip32Derivation []*Bip32Derivation +} + +// NewPsbtOutput creates an instance of PsbtOutput; the three parameters +// redeemScript, witnessScript and Bip32Derivation are all allowed to be +// `nil`. +func NewPsbtOutput(redeemScript []byte, witnessScript []byte, + bip32Derivation []*Bip32Derivation) *POutput { + return &POutput{ + RedeemScript: redeemScript, + WitnessScript: witnessScript, + Bip32Derivation: bip32Derivation, + } +} + +// 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) + if err != nil { + return err + } + if keyint == -1 { + // Reached separator byte + break + } + + value, err := wire.ReadVarBytes( + r, 0, MaxPsbtValueLength, "PSBT value", + ) + if err != nil { + return err + } + + switch OutputType(keyint) { + + case RedeemScriptOutputType: + if po.RedeemScript != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + po.RedeemScript = value + + case WitnessScriptOutputType: + if po.WitnessScript != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + po.WitnessScript = value + + case Bip32DerivationOutputType: + if !validatePubkey(keydata) { + return ErrInvalidKeydata + } + master, derivationPath, err := readBip32Derivation(value) + if err != nil { + return err + } + + // Duplicate keys are not allowed + for _, x := range po.Bip32Derivation { + if bytes.Equal(x.PubKey, keydata) { + return ErrDuplicateKey + } + } + + po.Bip32Derivation = append(po.Bip32Derivation, + &Bip32Derivation{ + PubKey: keydata, + MasterKeyFingerprint: master, + Bip32Path: derivationPath, + }, + ) + + default: + // Unknown type is allowed for inputs but not outputs. + return ErrInvalidPsbtFormat + } + } + + return nil +} + +// serialize attempts to write out the target POutput into the passed +// io.Writer. +func (po *POutput) serialize(w io.Writer) error { + if po.RedeemScript != nil { + err := serializeKVPairWithType( + w, uint8(RedeemScriptOutputType), nil, po.RedeemScript, + ) + if err != nil { + return err + } + } + if po.WitnessScript != nil { + err := serializeKVPairWithType( + w, uint8(WitnessScriptOutputType), nil, po.WitnessScript, + ) + if err != nil { + return err + } + } + + sort.Sort(Bip32Sorter(po.Bip32Derivation)) + for _, kd := range po.Bip32Derivation { + err := serializeKVPairWithType(w, + uint8(Bip32DerivationOutputType), + kd.PubKey, + SerializeBIP32Derivation( + kd.MasterKeyFingerprint, + kd.Bip32Path, + ), + ) + if err != nil { + return err + } + } + + return nil +} diff --git a/psbt/psbt.go b/psbt/psbt.go index aaebbd5..89325a7 100644 --- a/psbt/psbt.go +++ b/psbt/psbt.go @@ -113,117 +113,8 @@ type Unknown struct { } -// POutput is a struct encapsulating all the data that can be attached -// to any specific output of the PSBT. -type POutput struct { - RedeemScript []byte - WitnessScript []byte - Bip32Derivation []*Bip32Derivation -} -// NewPsbtOutput creates an instance of PsbtOutput; the three parameters -// redeemScript, witnessScript and Bip32Derivation are all allowed to be -// `nil`. -func NewPsbtOutput(redeemScript []byte, witnessScript []byte, - bip32Derivation []*Bip32Derivation) *POutput { - return &POutput{ - RedeemScript: redeemScript, - WitnessScript: witnessScript, - Bip32Derivation: bip32Derivation, - } -} -func (po *POutput) deserialize(r io.Reader) error { - for { - keyint, keydata, err := getKey(r) - if err != nil { - return err - } - if keyint == -1 { - // Reached separator byte - break - } - value, err := wire.ReadVarBytes(r, 0, MaxPsbtValueLength, - "PSBT value") - if err != nil { - return err - } - - switch uint8(keyint) { - - case PsbtOutRedeemScript: - if po.RedeemScript != nil { - return ErrDuplicateKey - } - if keydata != nil { - return ErrInvalidKeydata - } - po.RedeemScript = value - - case PsbtOutWitnessScript: - if po.WitnessScript != nil { - return ErrDuplicateKey - } - if keydata != nil { - return ErrInvalidKeydata - } - po.WitnessScript = value - - case PsbtOutBip32Derivation: - if !validatePubkey(keydata) { - return ErrInvalidKeydata - } - master, derivationPath, err := readBip32Derivation(value) - if err != nil { - return err - } - // Duplicate keys are not allowed - for _, x := range po.Bip32Derivation { - if bytes.Equal(x.PubKey, keydata) { - return ErrDuplicateKey - } - } - po.Bip32Derivation = append(po.Bip32Derivation, - &Bip32Derivation{ - PubKey: keydata, - MasterKeyFingerprint: master, - Bip32Path: derivationPath, - }) - - default: - // unknown type is allowed for inputs but not outputs - return ErrInvalidPsbtFormat - } - } - return nil -} - -func (po *POutput) serialize(w io.Writer) error { - if po.RedeemScript != nil { - err := serializeKVPairWithType(w, PsbtOutRedeemScript, nil, - po.RedeemScript) - if err != nil { - return err - } - } - if po.WitnessScript != nil { - err := serializeKVPairWithType(w, PsbtOutWitnessScript, nil, - po.WitnessScript) - if err != nil { - return err - } - } - sort.Sort(Bip32Sorter(po.Bip32Derivation)) - for _, kd := range po.Bip32Derivation { - err := serializeKVPairWithType(w, PsbtOutBip32Derivation, - kd.PubKey, - SerializeBIP32Derivation(kd.MasterKeyFingerprint, - kd.Bip32Path)) - if err != nil { - return err - } - } - return nil } // Psbt is a set of 1 + N + M key-value pair lists, 1 global,