Bitcoin transactions (tx) are the double-entry exchanges that get recorded into the blockchain ledger. They are the instruments where we exchange bitcoin units from public address to public address. They contain the amounts exchanged, the source and destination of the funds, a proof for authenticating the owners of the funds and a locking mechanism to make sure that only the destination of the funds will be able to make use of them. Transactions are generated at a pace that currently oscillates between 150.000 per day and 500.000 per day.
So, what does a bitcoin transaction look like?
For every one of these transactions [i] , if we go to the lowest reasonable level, it is an electrical signal that is coded into a string of bits. Since we humans have a tough time reading bits – ones and zeros – we typically encode this bit stream into hexadecimal values, where we group bits in packs of four and we assign every possible combination a sign
We use numbers from 0 to 9 (10 numbers) and letter from A to F (six letters) as the signs that can represent the 16 possible different values that 4 bits can take. In fact, we will find indistinctively our letter written in upper case (A to F) or lower case (a to f) so for our purpose whether we write “A” or “a” it will represent the following four bits “1010”
So, if we take one transaction, whose transaction id is
and read all the bits that it contains and encode it in hexadecimal, we will find something like this
This transaction (tx for short) was taken from here [ii] . How did we get the transaction content? From a full index node with the following command
Well, this is slightly more clear than a succession of “0”s and “1”s but not really much. If we use a transaction-decoding program, we would get the following response
Well, now we are talking a little bit clearer, as we can distinctively see
- Information fields of the transaction such as “version”, “size” and “locktime”
- Two main sections, one for the transaction “inputs” and another for the “outputs”
We can go even further and insert the tx id into an online transaction decoder and get a nice formatting of it. Check it for yourself at https://blockexplorer.com/tx/0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2
However, how did the decoding tool make the transition between hexadecimal values (“hex” for short) and the different fields? Are there any other fields that the tool has decided not to show? After all, even using the decoding tool we still see hex values. Are all fields present in the transaction or are some of them calculated by the decoder tool? Answering all these questions is the purpose of this article.
Types of Bitcoin transactions
We can start our research saying that there is no single anatomy description of a transaction because there is no single type of bitcoin transaction. “Coinbase” transaction for example have no inputs, and have a different format from “Standard” transactions that spend existing bitcoins and assign them to new bitcoin addresses. Even in Standard transactions, we can find format differences if we are seeing a SegWit [iii] transaction where some fields are optional.
We will discuss mainly standard transactions on this article, with some final words for Coinbase transactions and SegWit transactions.
Importance of Bitcoin transactions
We can say that bitcoin transactions are digital records of exchange of bitcoins between a source and a destination. Bitcoin transactions record the origin of the funds – by giving cryptographic proof of the ownership – and the destination of the funds – by locking them to a destination public key -.
- Every transaction includes one or several destination of funds. We will call each of these destinations a “txout”.
- Every transaction includes one or several origin of funds. We will call each of these origins a “txin”, and they correspond to previous “txout”
Here is the first, and very important, concept. Bitcoins reside on the blockchain, and they are publicly available for scrutiny. They are recorded in the txout, assigned to a public key. Hence, our wallets do not contain bitcoins per se; they contain the private keys associated to the public keys to which the bitcoins in the blockchain were assigned. Hence the importance of understanding what do transactions look like, because they contain our bitcoins.
Another important concept is that unspent transactions are not necessarily spent completely each time, but unspent transaction outputs are. In our previous example, transaction B is not completely spent, but the second transaction output inside tx B is. In other words, you can partially spend the contents of a transaction, but you need to spend completely transaction outputs. Bitcoin nodes keep track of unspent transaction outputs (otherwise called UTXOs) in a database for quick retrieval of available bitcoins to spend, and total amount of BTCs available for specific Public Keys.
And you can see that every transaction has got a fee – that is not written into any transaction field but is calculated as the difference between the input values and the output values – . These differences are not “lost” into the Blockchain but they appear as claimed in the Coinbase transaction by the miner that includes the transaction into his mined block.
If we take a closer look at how transactions are chained, we will see that in addition to having a “block of chains” we also have a chain of transactions. More specifically, each new transaction links its txins to previous transactions
In this simplified schema, we have “painted” four blocks, each containing a set of transactions. The blocks are chained sequentially, but transactions (txouts -> txins) are chained not necessarily sequentially. There can be gaps either by leaving unexpended txouts in older blocks, or by txouts that are linked to txins several blocks later.
So we see that transactions are chained but in a different way as blocks. Block chaining is linear and sequential, and block N is followed always by block N+1. Transactions on the other hand can include multiple inputs that refer to multiple outputs existing in multiple previous transactions. It is, to some extent, meshed.
Transaction general structure
Let us get a closer look at the structure of a transaction. They are, from a general point of view, built as a concatenation of
Wait, were is our transaction id (txid) that references and identifies our transaction?
Transaction Id (or txid) uniquely identifies our transaction. The txid is the double sha256 hash (we will call that sha256d) calculated on the transaction itself. The txid is not part of the transaction itself, it is calculated and saved – if necessary – on a database of transactions, separated from the blockchain. So if for our transaction
We calculate the sha256d we should get its txid
One specific aspect of the sah256d calculation and encoding of the results is that when we get displayed the result it gets byte inverted, or otherwise said; the result is RPC-byte-ordered. To give you an idea of what “RPC-byte-ordered” is, let us look at a double sha256 on a simple 0x00 value
If we invert byte by byte, we get the following value
Therefore, in order to byte invert the result we take every two hex values, pair by pair, and we swap positions the first (14) with the last (9a), the second pair (06) with the pair before the last (53), and so on.
If we apply this to our transaction, we should see that the sha256d RPC-byte-ordered of our transaction should give us our transaction id
, right? Here is what we get.
If we invert the order of every pair of bytes, bingo, we’d get to our txid, or
Here is a snippet of python code, taken from here [iv], that allows you to check what the “internal byte order” and the “RPC byte order” look like
Transaction Detailed Structure
Drawing transactions with a little bit more detail, we obtain the following schema
If we want to be a really specific, we can identify (all values in columns “In Our Example” are hexadecimal, unless otherwise stated)
Let us walk through some of these fields
We get the transaction version first, which determines the transaction format (all values in columns “In Our Example” are hexadecimal, unless otherwise stated)
The Version field are 4 bytes, encoded in little-endian. In our example we are getting a version “1”, as the least significant byte show first and is “01”, and the rest of the bytes are set to 0
After the version field, we get a number of “txin”. Let us see in our example how they are encoded (all values in columns “In Our Example” are hexadecimal, unless otherwise stated)
TxOutHash and TxOutIndex
TxOutHash is the transaction ID that contains the txout that we are linking to this txin. The TxOutIndex is specific txout inside that txid that we are referencing. TxOutHash (or txid) is calculated as the double sha256 hash (we will call that sha256d) on the transaction we are referencing (a.k.a. the previous transaction whose funds we are transferring), and then byte inverted, or otherwise said, the result has been RPC-byte-ordered.
How did we find the correct format of the UnlockingScript? Well, the Lock Script contained in the txout we are referencing forced this. We are free to put any Unlocking Script here, but if we want it to be valid, then it has to match what was asked at TxOutIndex (0) of the RPC byte ordered content on TxOutHash (that content being)
so we should look for txid
I went to check the referenced transaction and the LockScript on txout #0 was
So yes, we needed to push a correct Elliptic Curve Signature and the correct public key whose bitcoin address is 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK. This is what our txin did.
As a curiosity, we can see that the second txout in our transaction is locked to the same bitcoin address as the only txout in the previous transaction. In other words, of the 0.1 BTC that were locked to 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK in the previous transaction, 0.085 are returning in the txout of our transaction.
The Signature Itself. Signature Hash Type. Transaction Malleability.
R and S contain a valid Elliptic Curve signature. We are not going to enter into the mathematics of it, but what content do we exactly sign? The signature Hash Type (or SIGHASH flag) has the answer
This brings some important points
- A signature belongs to a txin, but it can sign several txins and txouts. In our case, it signs all txins and all txouts.
- Since in our example we sign all txins, it means we sign our own txin. Since the signature cannot be part of the signed message, we realize that in order to sign our txin we have to remove the signature field form the message to sign.
- If a txin does not sign its own Signature Script, then consider the following Signature Scripts in, say a txin inside a transaction
- Signature + Public Key
- OP_DROP + Signature + Public Key
These are two valid signature scripts, as OP_DROP just clears the stack. However the txins would be different (the second case has an additional Operand) and they would produce a different transaction id (as the contents of the transaction would be different, as in case A one of the txin is different from case B). Two different transactions (and their txids) that can be both validly spending one or more txout is a case of what we call “transaction malleability”. A malicious node receiving transaction A could replace the Signature Script in one txin with the example in B, and produce an equally valid transaction, spending the same txouts but with different txid.
Why would you want to do that? Well, someone is sending you BTCs through transaction A, and somehow a node replaces it with transaction B before transaction A is mined, and succeeds to mine tx B, that makes tx A invalid from that moment on (as it would be trying to spend an txout that has already been spent by transaction B). You would still be receiving your BTCs, but you could tell that someone that his transaction A failed and that he/she should create a new transaction C and try again sending you some BTCs again. Unless that someone checks that his tx A was not just failed but replaced by a successful tx B, you might be able to fool him/her to send you some BTC again. It is twisted but it is possible.
Coming back to the signature, there is a whole set of steps to take to perform the signature. If you want the details, you can find them here [vii] and here [viii] but in a few words, for each txin that needs to include a signature, and its associated previous txout
- Make a copy the previous txout LockScript
- Make a copy of your transaction, and depending on your SigHashType, include the txins and txouts as appropriate
- On the copy of your transaction, remove all Signature Scripts on the txins (as these contains signatures that cannot be part of the message signed) and set the Signature Scripts length to zero
- Insert the copy of the previous txout LockScript in the field where your Signature Script was originally in your txin. Set the Signature Script length to its current value
- Append the SigHashType to your modified copy of your transaction
- Make a double sha256 of your modified copy of your transaction. Sign it.
- Include the signature in your original txin.
To finish with this topic, let us see what all 6 SigHash Types mean
- 0x01 ALL. Signature applies to all txins and txouts. The txin including this sighash type signs all txins and txout in the transaction. Any change on the tx – apart from changes in the signatures themselves, as we have seen – would invalidate this txin, and hence the whole transaction, as transactions are accepted or rejected as a whole. Bitcoin nodes do not mine parts of the transaction.
- 0x02 NONE: Signature applies to all txins but no txouts. The txin including this sighash type signs all txins and no txout in the transaction. The transaction could have its txouts changed – the destination of the BTCs – and still be valid. This is like signing a bearer check.
- 0x03 SINGLE: Signature applies to all txins, but only to the txout with same index number as the txin where this signature is present. Other txins and txouts could change. This would be used in cases where the signer wants to make sure that one specific txout receives BTC, leaving open for the rest of the BTCs be assigned in a “bearer check” style
- 0x81 ALL|ANYONE CAN PAY: Signature applies to the txin where this signature is present and all txouts. This could be used in a crowdfunding scenario, where contributors bring their txins with the purpose to attain an amount specified by the sum of the txouts. When the amount of txins reaches that amount – plus the miners fee – the transaction beomes valid
- 0x82 NONE|ANYONE CAN PAY: Signature applies to the txin where this signature is present and no txouts. The Bitcoin equivalent of a tipping jar. You bring your txin and don’t care anymore who does it go to or which transaction is it included into.
- 0x83 SINGLE|ANYONE CAN PAY: Signature applies to the txin where this signature is present and only to the txout with same index number as the txin where this signature is present. This is a tipping jar but you specify that it goes to a specific individual – maybe that waiter/waitress that served you coffee that morning
After all the txin have been encoded, it is the turn of txout. Let us see in our example how they are encoded
Transaction Lock Time
This really should be part of a different article where I discuss how we can time transactions and link their validity to time or block references (stay tuned)
Coinbase transactions have a special type of txin, as they generate bitcoins by themselves, and they are not bringing them from an existing previous txout. In that case
- Txin in a Coinbase transaction has its TxOutHash set to 0, as we are not referencing any previous transaction
- TxOutIndex set to 0xffffffff, as we are not referencing any previous transaction index
- Signature Script is replaced by arbitrary data, as we are not unlocking any previous lock script. This arbitrary data is used as extra random material for hash generation when mining the block that contains this Coinbase transaction
Segwit is a completely new way of construction transactions that goes beyond the scope of this article. It brings modifications to the transaction structure. Stay tuned for more news.
This article was written by ignacio. You can contact him at email@example.com