psbt: move output into new file
This commit is contained in:
parent
9411189e0e
commit
33335d05df
2 changed files with 139 additions and 109 deletions
139
psbt/partial_output.go
Normal file
139
psbt/partial_output.go
Normal file
|
@ -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
|
||||||
|
}
|
109
psbt/psbt.go
109
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,
|
// Psbt is a set of 1 + N + M key-value pair lists, 1 global,
|
||||||
|
|
Loading…
Reference in a new issue