ea41fc5177
In this commit, we modify the Extract method to return the transaction directly as in many cases a user will likely want to write the transaction to disk, or perform additional validation rather than obtain the raw bytes directly.
81 lines
2.6 KiB
Go
81 lines
2.6 KiB
Go
// Copyright (c) 2018 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package psbt
|
|
|
|
// The Extractor requires provision of a single PSBT
|
|
// in which all necessary signatures are encoded, and
|
|
// uses it to construct a fully valid network serialized
|
|
// transaction.
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/btcsuite/btcd/txscript"
|
|
"github.com/btcsuite/btcd/wire"
|
|
)
|
|
|
|
// Extract takes a finalized psbt.Packet and outputs a finalized transaction
|
|
// instance. Note that if the PSBT is in-complete, then an error
|
|
// ErrIncompletePSBT will be returned. As the extracted transaction has been
|
|
// fully finalized, it will be ready for network broadcast once returned.
|
|
func Extract(p *Packet) (*wire.MsgTx, error) {
|
|
// If the packet isn't complete, then we'll return an error as it
|
|
// doesn't have all the required witness data.
|
|
if !p.IsComplete() {
|
|
return nil, ErrIncompletePSBT
|
|
}
|
|
|
|
// First, we'll make a copy of the underlying unsigned transaction (the
|
|
// initial template) so we don't mutate it during our activates below.
|
|
finalTx := p.UnsignedTx.Copy()
|
|
|
|
// For each input, we'll now populate any relevant witness and
|
|
// sigScript data.
|
|
for i, tin := range finalTx.TxIn {
|
|
// We'll grab the corresponding internal packet input which
|
|
// matches this materialized transaction input and emplace that
|
|
// final sigScript (if present).
|
|
pInput := p.Inputs[i]
|
|
if pInput.FinalScriptSig != nil {
|
|
tin.SignatureScript = pInput.FinalScriptSig
|
|
}
|
|
|
|
// Similarly, if there's a final witness, then we'll also need
|
|
// to extract that as well, parsing the lower-level transaction
|
|
// encoding.
|
|
if pInput.FinalScriptWitness != nil {
|
|
// In order to set the witness, need to re-deserialize
|
|
// the field as encoded within the PSBT packet. For
|
|
// each input, the witness is encoded as a stack with
|
|
// one or more items.
|
|
witnessReader := bytes.NewReader(
|
|
pInput.FinalScriptWitness,
|
|
)
|
|
|
|
// First we extract the number of witness elements
|
|
// encoded in the above witnessReader.
|
|
witCount, err := wire.ReadVarInt(witnessReader, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Now that we know how may 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",
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tin.Witness[j] = wit
|
|
}
|
|
}
|
|
}
|
|
|
|
return finalTx, nil
|
|
}
|