Create And Sign Bitcoin Transactions With Golang

About a month ago I had written about creating and importing private keys as well as generating public addresses for Bitcoin and several other cryptocurrencies using the Go programming language. This previous tutorial had more of an emphasis on creating cryptocurrency wallets with Golang than anything.

The next step in making Bitcoin and other cryptocurrencies useful is to be able to transfer or send them to other people. Sending Bitcoin is part of a process known as creating and broadcasting a transaction.

While we won’t be actually broadcasting a transaction in this tutorial, we’re going to figure out how to create an unsigned transaction, then sign it, using the Go programming language and some popular Bitcoin packages.

Going forward, it must be made clear that I am not a cryptocurrency or cryptography expert. If you’ve found bugs in what I’ve shared, please let me know in the comments. If you’re just planning to copy and paste the code I’ve provided, please do so understanding that it is at your own risk.

Understanding the Moving Pieces of Bitcoin Transactions

Before we get into the coding, we need to understand how transactions work. It is an unnecessarily difficult concept that too me quite a while to figure out using Golang. It is much easier with other technologies like Node.js because the libraries take the guess work out of it.

When working towards creating a transaction, we have the following parts:

Sender’s private key

Sender’s unspent transaction output (UTXO)

Recipient’s public address

Satoshi amount to be sent

Using the above, further data must be derived and be a part of the transaction, but before we get there, let’s figure out what the above parts will represent to us. If you want an explanation of concepts, far deeper than mine, check out Bitcoins the Hard Way: Using the Raw Bitcoin Protocol, which is where I got the fundamentals necessary to accomplish the task in Go.

The private key is used for two things. When we have an unsigned transaction, the private key will be used to sign the transaction proving that the funds can be spent. The sender’s public key and public address can also be derived from the private key. We’ll get to that in a moment.

When someone is sent Bitcoin, a transaction is made, which is what we’re trying to do. On the receiving end, when everything is said and done, we’re left with what is called unspent transaction output (UTXO). When we wish to turn around and send, we’re creating a transaction from the UTXO. The UTXO has information such as the transaction hash id, the public key script, and the amount of satoshi in the transaction. We can figure out the public key script through a public address. We’ll be creating an unspent transaction output, hence we’ll need to come up with a transaction id and make a public key script with the sender’s information.

The recipient’s public address is where the funds will be sent. A public key script will be created and added to a redeeming transaction rather than the source UTXO transaction.

Finally, the amount in satoshis must be determined. This amount must exist in the UTXO.

Building and Signing a Transaction with Go

There will be quite a bit happening in our Go application to make transactions possible. For simplicity, we’re only going to be using a single input and a single output. We’ll explore multiple inputs and multiple outputs in a future tutorial. We’re also going to be fabricating our own UTXO rather than using a real UTXO, meaning a broadcast will fail. We can’t spend Bitcoin that we don’t own.

Create a project within your $GOPATH. I’ll be adding all my code to a main.go file, but feel free to design your project however you want. Before we add code, we need to get our package dependencies.

From the command line, execute the following:

go get github.com/btcsuite/btcd
go get github.com/btcsuite/btcutil

Both btcd and btcutil are part of a very popular Bitcoin package for Go.

When we create our transaction, we’ll store the data in a Transaction object. If you’re planning to store transaction data locally, this object has the information that you’d probably want, none of which is sensitive. However, the signed transaction data can be broadcasted just once.

In the CreateTransaction function a few things are going to happen.

We’re going to take a WIF string and load it as a private key

We’re going to get the public key script information for both the sender and the recipient

We’re going to create an origin transaction which is the UTXO transaction data for the sender

We’re going to create a new redeem transaction with the origin transaction data plus the new transaction that will happen involving the destination address

We’re going to sign the redeem transaction

We’re going to validate the redeem transaction to see if it is appropriate for broadcasting

With the private key loaded and hopefully correctly formatted, we can start obtaining the public key script and creating our origin transaction which includes previous transaction hash and spend outputs that will eventually be inputs for the redeeming transaction.

The sigScript variable contains the signature as well as the public key of the sender. An invalid signature script will result in a poorly signed transaction that the recipient won’t be able to read. To prevent trying to broadcast a bad transaction, we can actually validate it:

To validate that it is not nonsense data, you can use an online validation tool like TXID.IO. I used it aggressively when testing because I couldn’t grasp how transactions should be formatted. I don’t recommend using real keys in case your computer becomes compromised. Use testnet values when testing.

The Full Project Source Code

In case the bits and pieces that I threw together isn’t enough and you needed the full picture, I’m providing the source code to the above application, even though it is the same thing:

Remember to do your own research on transactions and test before trying to create transactions with production keys.

Conclusion

You just saw how to create and sign Bitcoin transactions, offline, with the Go programming language. Like I said earlier, I am not a cryptocurrency expert, nor am I a cryptography expert. If you’ve found a bug, please explain it in the comments of this article.

Many of the concepts of this tutorial were taken from the Bitcoins the Hard Way: Using the Raw Bitcoin Protocol article which is incredibly helpful. The btcd and btcutil packages have minimal documentation dispersed across everywhere. A lot of the code in this tutorial is Frankenstein code from various locations in the GoDocs.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.