<p>As I commented, with the <code>psbt</code> package from <code>btcsuite/btcutil</code> it is possible.</p>

<p>I have created an example of how to use it. I don't know if this is the best/most efficient way of doing it. But I hope this gives you a template and example to work with. But it is relatively low-level and without some deeper technical understanding of Bitcoin it may be difficult to follow.</p>

<p>It spends the second (0-indexed) output from <a href="https://blockstream.info/testnet/tx/5f716ed311546173bb11f3c13c1b3b42ac4405126005467d6db1659b568fcc7e?expand" rel="nofollow noreferrer">this</a> transaction on Testnet.</p>



<pre><code>package main

import (
    "bytes"
    "encoding/hex"
    "fmt"

    "github.com/btcsuite/btcd/chaincfg"
    "github.com/btcsuite/btcd/chaincfg/chainhash"
    "github.com/btcsuite/btcd/txscript"
    "github.com/btcsuite/btcd/wire"
    "github.com/btcsuite/btcutil"
    "github.com/btcsuite/btcutil/hdkeychain"
    "github.com/btcsuite/btcutil/psbt"
)

const (
    // Provided PSBT with one P2PKH input. Created in part 1 below.
    psbtBase64 = "cHNidP8BAFIBAAAAAX7Mj1abZbFtfUYFYBIFRKxCOxs8wfMRu3NhVBHTbnFfAQAAAAAAAAAAAayEAQAAAAAAFgAU8yFPpRndMpAJ7aO+RtRN4Nh3mbYAAAAAAAEBH6CGAQAAAAAAFgAUJw/E3xSMUU+8VVGHXk7Dc4vGNjkiBgOoVLKI2rj2DMlswSDkSf0KR7jQHULLPOWS/x3q8b3MqQyj8e/WAAAAAAMAAAAAAA=="

    // Extended Private Key.
    extPrivateKeyStr = "vprv9GpFMh8VMAXKgdZVFGXFvsexjr25MHKvtCY7vKHbRr8A6xCm4bQYbQrJmLz6h3F9MGf5edwxQuZR7DCLFVvjMxgfJ9so9mcN2SHGR3QFr3S"
)

// Part 1: Creating the PSBT (will be returned as base64)
func part1() string {
    // The extended private key was generated with Electrum and we derive the
    // specific key used.
    // `keyC` contains the private key that _contains_ the coins to be spend.
    keyC, _ := hdkeychain.NewKeyFromString(extPrivateKeyStr)
    fingerprint := keyC.ParentFingerprint()
    keyC, _ = keyC.Child(0)
    keyC, _ = keyC.Child(3) // Electrum derivation of the 4th address.
    pubKeyC, _ := keyC.ECPubKey()

    // Create a brand new PSBT spending the following outpoint.
    txhash, _ := chainhash.NewHashFromStr("5f716ed311546173bb11f3c13c1b3b42ac4405126005467d6db1659b568fcc7e")
    outpoint := wire.NewOutPoint(txhash, 1)
    inputs := []*wire.OutPoint{outpoint}
    pubkeyScript, _ := hex.DecodeString("0014270fc4df148c514fbc5551875e4ec3738bc63639")
    spendTxOut := wire.NewTxOut(100000, pubkeyScript)

    // The address and amount to send funds to.
    outAddress, err := btcutil.DecodeAddress("tb1q7vs5lfgem5efqz0d5wlyd4zdurv80xdkfkf3cn", &amp;chaincfg.TestNet3Params)
    // The witnessScript consists of a `0x00`, followed by the size of the
    // pubkey-hash `0x20` and the pubkey-hash itself.
    witnessScript := append([]byte{0, 20}, outAddress.ScriptAddress()...)
    outputs := []*wire.TxOut{wire.NewTxOut(99500, witnessScript)}

    // Create the psbt instance.
    pC, err := psbt.New(inputs, outputs, wire.TxVersion, 0, []uint32{0}) // Note: typically the sequence is `0xffffffff`!
    if err != nil {
        panic(err)
    }

    // Use the Updater to add information to the input.
    u, err := psbt.NewUpdater(pC)
    if err != nil {
        panic(err)
    }

    u.AddInBip32Derivation(fingerprint, []uint32{0, 3}, pubKeyC.SerializeCompressed(), 0)
    u.AddInWitnessUtxo(spendTxOut, 0)
    u.AddInSighashType(0, 0)

    // Show the base64 encoding of the unsigned PSBT.
    b64, _ := pC.B64Encode()
    return b64

}

// Part 2: Sign the PSBT in base64 encoding and return it.
func part2(psbtBase64 string) string {
    // Reader for the PSBT.
    psbtBytes := []byte(psbtBase64)
    r := bytes.NewReader(psbtBytes)

    // Create instance of a PSBT.
    p, err := psbt.NewFromRawBytes(r, true)
    if err != nil {
        panic(err)
    }

    // Load the extended private key.
    bip32Key, err := hdkeychain.NewKeyFromString(extPrivateKeyStr)
    if err != nil {
        panic(err)
    }

    // Derivation path should be read from PSBT.
    // Note: We ignore checking the fingerprint, etc.
    path := p.Inputs[0].Bip32Derivation[0]
    for _, d := range path.Bip32Path {
        bip32Key, _ = bip32Key.Child(d)
    }

    pubKey, err := bip32Key.ECPubKey()
    if err != nil {
        panic(err)
    }

    privKey, err := bip32Key.ECPrivKey()
    if err != nil {
        panic(err)
    }

    // Manually creating the signature.
    sigHashes := txscript.NewTxSigHashes(p.UnsignedTx)
    sig, err := txscript.RawTxInWitnessSignature(p.UnsignedTx, sigHashes, 0,
        p.Inputs[0].WitnessUtxo.Value, p.Inputs[0].WitnessUtxo.PkScript,
        txscript.SigHashAll, privKey)

    // Use the Updater to add the signature to the input.
    u, err := psbt.NewUpdater(p)
    if err != nil {
        panic(err)
    }
    sucess, err := u.Sign(0, sig, pubKey.SerializeCompressed(), nil, nil)
    if err != nil {
        panic(err)
    }
    if sucess != psbt.SignSuccesful {
        panic("could not sucessfully sign for some reason")
    }

    // Finalize PSBT.
    err = psbt.Finalize(p, 0)
    tx, err := psbt.Extract(p)

    var buf bytes.Buffer
    tx.Serialize(&amp;buf)
    return hex.EncodeToString(buf.Bytes())
}

func main() {
    fmt.Println("Base64 PSBT: ", part1())

    fmt.Println("Signed tx: ", part2(psbtBase64))
}
</code></pre>

CC BY-SA 4.0
2020-07-10T22:54:01.763Z
I understood you code, but I found out it seems to be working only for transactions with only one input. What about multiple input transactions?
Rockietto
CC BY-SA 4.0
2020-07-12T07:55:49.383Z
The `Inputs` field of the `psbt` structure is a slice of inputs that can be indexed, as is done with the example code by simply using index `0`.
Bjarne Magnussen
CC BY-SA 4.0
2020-06-04T19:25:53.673Z
2020-06-04T19:25:53.673Z
Bjarne Magnussen
<p>I have a PSBT (in Base64 format) which I need to sign using GoLang, but I can't figure out which steps I need to do that. I found <a href="https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#Simple_Signer_Algorithm" rel="nofollow noreferrer">this</a> but I'm not really confident with Bitcoin and Python, so I didn't fully understood the Signer Algorithm. What should I do?</p>

CC BY-SA 4.0
2020-06-03T10:23:01.697Z
I haven't used this particular feature, but `btcsuite/btcutil` (written in Go) has a `psbt` package that should allow you to do that: https://godoc.org/github.com/btcsuite/btcutil/psbt
Bjarne Magnussen
CC BY-SA 4.0
2020-06-03T13:43:53.753Z
I saw it, but no example and I'm not enough confident with BTC to fully understand what I have to do
Rockietto
<signature><bip174-psbt>
How to sign a PSBT transaction?
Rockietto
# How to sign a PSBT transaction?

(Asked by: username_0 on 2020-06-02)

I have a PSBT (in Base64 format) which I need to sign using GoLang, but I can't figure out which steps I need to do that. I found [this](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#Simple_Signer_Algorithm) but I'm not really confident with Bitcoin and Python, so I didn't fully understood the Signer Algorithm. What should I do?

**Tags:** signature, bip174-psbt

> **Comments:**
> **username_1**: I haven't used this particular feature, but `btcsuite/btcutil` (written in Go) has a `psbt` package that should allow you to do that: https://godoc.org/github.com/btcsuite/btcutil/psbt  
> **username_0**: I saw it, but no example and I'm not enough confident with BTC to fully understand what I have to do  

---

## 1 answers

### Answer by username_1 on 2020-06-04. Score: 2 | Accepted answer

As I commented, with the `psbt` package from `btcsuite/btcutil` it is possible.

I have created an example of how to use it. I don't know if this is the best/most efficient way of doing it. But I hope this gives you a template and example to work with. But it is relatively low-level and without some deeper technical understanding of Bitcoin it may be difficult to follow.

It spends the second (0-indexed) output from [this](https://blockstream.info/testnet/tx/5f716ed311546173bb11f3c13c1b3b42ac4405126005467d6db1659b568fcc7e?expand) transaction on Testnet.

```
package main

import (
    "bytes"
    "encoding/hex"
    "fmt"

    "github.com/btcsuite/btcd/chaincfg"
    "github.com/btcsuite/btcd/chaincfg/chainhash"
    "github.com/btcsuite/btcd/txscript"
    "github.com/btcsuite/btcd/wire"
    "github.com/btcsuite/btcutil"
    "github.com/btcsuite/btcutil/hdkeychain"
    "github.com/btcsuite/btcutil/psbt"
)

const (
    // Provided PSBT with one P2PKH input. Created in part 1 below.
    psbtBase64 = "cHNidP8BAFIBAAAAAX7Mj1abZbFtfUYFYBIFRKxCOxs8wfMRu3NhVBHTbnFfAQAAAAAAAAAAAayEAQAAAAAAFgAU8yFPpRndMpAJ7aO+RtRN4Nh3mbYAAAAAAAEBH6CGAQAAAAAAFgAUJw/E3xSMUU+8VVGHXk7Dc4vGNjkiBgOoVLKI2rj2DMlswSDkSf0KR7jQHULLPOWS/x3q8b3MqQyj8e/WAAAAAAMAAAAAAA=="

    // Extended Private Key.
    extPrivateKeyStr = "vprv9GpFMh8VMAXKgdZVFGXFvsexjr25MHKvtCY7vKHbRr8A6xCm4bQYbQrJmLz6h3F9MGf5edwxQuZR7DCLFVvjMxgfJ9so9mcN2SHGR3QFr3S"
)

// Part 1: Creating the PSBT (will be returned as base64)
func part1() string {
    // The extended private key was generated with Electrum and we derive the
    // specific key used.
    // `keyC` contains the private key that _contains_ the coins to be spend.
    keyC, _ := hdkeychain.NewKeyFromString(extPrivateKeyStr)
    fingerprint := keyC.ParentFingerprint()
    keyC, _ = keyC.Child(0)
    keyC, _ = keyC.Child(3) // Electrum derivation of the 4th address.
    pubKeyC, _ := keyC.ECPubKey()

    // Create a brand new PSBT spending the following outpoint.
    txhash, _ := chainhash.NewHashFromStr("5f716ed311546173bb11f3c13c1b3b42ac4405126005467d6db1659b568fcc7e")
    outpoint := wire.NewOutPoint(txhash, 1)
    inputs := []*wire.OutPoint{outpoint}
    pubkeyScript, _ := hex.DecodeString("0014270fc4df148c514fbc5551875e4ec3738bc63639")
    spendTxOut := wire.NewTxOut(100000, pubkeyScript)

    // The address and amount to send funds to.
    outAddress, err := btcutil.DecodeAddress("tb1q7vs5lfgem5efqz0d5wlyd4zdurv80xdkfkf3cn", &chaincfg.TestNet3Params)
    // The witnessScript consists of a `0x00`, followed by the size of the
    // pubkey-hash `0x20` and the pubkey-hash itself.
    witnessScript := append([]byte{0, 20}, outAddress.ScriptAddress()...)
    outputs := []*wire.TxOut{wire.NewTxOut(99500, witnessScript)}

    // Create the psbt instance.
    pC, err := psbt.New(inputs, outputs, wire.TxVersion, 0, []uint32{0}) // Note: typically the sequence is `0xffffffff`!
    if err != nil {
        panic(err)
    }

    // Use the Updater to add information to the input.
    u, err := psbt.NewUpdater(pC)
    if err != nil {
        panic(err)
    }

    u.AddInBip32Derivation(fingerprint, []uint32{0, 3}, pubKeyC.SerializeCompressed(), 0)
    u.AddInWitnessUtxo(spendTxOut, 0)
    u.AddInSighashType(0, 0)

    // Show the base64 encoding of the unsigned PSBT.
    b64, _ := pC.B64Encode()
    return b64

}

// Part 2: Sign the PSBT in base64 encoding and return it.
func part2(psbtBase64 string) string {
    // Reader for the PSBT.
    psbtBytes := []byte(psbtBase64)
    r := bytes.NewReader(psbtBytes)

    // Create instance of a PSBT.
    p, err := psbt.NewFromRawBytes(r, true)
    if err != nil {
        panic(err)
    }

    // Load the extended private key.
    bip32Key, err := hdkeychain.NewKeyFromString(extPrivateKeyStr)
    if err != nil {
        panic(err)
    }

    // Derivation path should be read from PSBT.
    // Note: We ignore checking the fingerprint, etc.
    path := p.Inputs[0].Bip32Derivation[0]
    for _, d := range path.Bip32Path {
        bip32Key, _ = bip32Key.Child(d)
    }

    pubKey, err := bip32Key.ECPubKey()
    if err != nil {
        panic(err)
    }

    privKey, err := bip32Key.ECPrivKey()
    if err != nil {
        panic(err)
    }

    // Manually creating the signature.
    sigHashes := txscript.NewTxSigHashes(p.UnsignedTx)
    sig, err := txscript.RawTxInWitnessSignature(p.UnsignedTx, sigHashes, 0,
        p.Inputs[0].WitnessUtxo.Value, p.Inputs[0].WitnessUtxo.PkScript,
        txscript.SigHashAll, privKey)

    // Use the Updater to add the signature to the input.
    u, err := psbt.NewUpdater(p)
    if err != nil {
        panic(err)
    }
    sucess, err := u.Sign(0, sig, pubKey.SerializeCompressed(), nil, nil)
    if err != nil {
        panic(err)
    }
    if sucess != psbt.SignSuccesful {
        panic("could not sucessfully sign for some reason")
    }

    // Finalize PSBT.
    err = psbt.Finalize(p, 0)
    tx, err := psbt.Extract(p)

    var buf bytes.Buffer
    tx.Serialize(&buf)
    return hex.EncodeToString(buf.Bytes())
}

func main() {
    fmt.Println("Base64 PSBT: ", part1())

    fmt.Println("Signed tx: ", part2(psbtBase64))
}

```

> **Comments:**
> **username_0**: I understood you code, but I found out it seems to be working only for transactions with only one input. What about multiple input transactions?  
> **username_1**: The `Inputs` field of the `psbt` structure is a slice of inputs that can be indexed, as is done with the example code by simply using index `0`.  

---

