Anatomy of Bitcoin's Raw Transactions

Recently I added a feature in nioctib.tech to display bitcoin transactions in their hexadecimal format, with internal structure illustrated by different colors and tooltips describing what those numbers actually represent. The hope is that this could offer a direct visual impression about how serialized transactions look like and can potentially be used as a debugging tool as well.

So how do raw bitcoin transactions look like? Nothing is more authoritative than the code:

colorized bitcoin transaction
Extracted from Bitcoin Core’s primitive/transaction.h

In the rest of the post, let’s dissect both a pre-segwit transaction and a segwit transaction down to the bytes.

Basic transaction serialization (pre-segwit)

Following is the hexadecimal format of a basic transaction displayed in a colorized and structured way, let’s break it down one color at a time.

colorized bitcoin transaction
View this transaction at nioctib.tech

Version

01000000 is a 4 bytes data that represents the transaction data format version. Current possible values are 1 and 2. Version 2 was introduced as part of BIP 68, which repurposes the meaning of nSequence to prevent mining of a transaction until a certain age of the spent output in blocks or timespan. In this particular example the transaction data format version is 1.

Transaction inputs

The following byte 01 represents the number of transaction inputs, which means that this particular transaction contains exactly one transaction input.

047fe7104d14f2e0dd3aed130379b09ef934f36a2647daac99f4ef5e0a54ccc5 is the id of the transaction has one output that was spent by this input. The index of that output is represented by the next 4 bytes 01000000, or 1 in decimal, which suggests that it is the 2nd output of the transaction since index is zero based.

The long purple colored string afterwards 8a4730440220…e287940eb2dd4f35c3ee2a3 encodes the unlocking script defined in this transaction input. As we can see here it is supposed to unlock a P2PKH locking script, therefore these number represent a signture and a public key.

feffffff is the sequence number of the transaction input, for a comprehensive discussion about what it means and its evolution over the time, please take a look at this excellent Bitcoin StackExchange anwser.

Transaction outputs

The following byte 02 represents the number of transaction outputs. As the number suggests, there are two outputs in this particular transaction.

Each transaction output is represented by two fields. In the case of the first transaction output, 00ca9a3b00000000 represents the bitcoin value carried by this output, which is 10 btc in decimal. 17a9147a1b6b1dbd9840fcf590e13a8a6e2ce6d55ecb8987 is a hex representation of a standard P2PKH locking script.

The structure of the second transaction output looks exactly the same as the first one.

Locktime

e3b50700 is the locktime of the transaction, which dictates the block number or timestamp until which the transaction is locked. For a more in depth explanation please checkout this great post on learnmeabitcoin.com.

Segwit transaction serialization

colorized bitcoin transaction
View this transaction at nioctib.tech

For version, transaction inputs, transaction outputs and locktime, they have exactly the same structure as basic transaction serialization. Please use the previous section as a reference and the tooltip feature for raw transactions at nioctib.tech if it is not clear.

Instead, let’s discuss flag and witnesses that are unique to segwit transactions.

Flag

0001 is unique to segwit transactions. The first byte 00 is dummy data that looks to the pre-segwit node like empty input from an invalid transaction, which means that the old node will discard it if it is received. For post-segwit nodes, it signals that this is potentially a segwit transaction.

The second byte 01 looks to the pre-segwit node like a transaction with 1 output, but since empty input is not allowed, it’s not really important. For post-segwit nodes though, it confirms that this is a segwit transaction. It will then expect the following bytes to encode transaction inputs, transaction outputs as well as a sequence of witnesses (one for each transaction input) and the locktime.

Witnesses

In segwit transactions, each input would have a sequence of witnesses to help unlock the corresponding output. In this particular transaction, we only have one sequence of witnesses since we only have one input.

04 represents the number of witnesses in the sequence. 00, 483045022…8aa901, 483045022…d02d01 and 4752210261…0452ae encodes those four witnesses respectively.

It is worth noting that this format is only acceptable for post-segwit nodes. However, when post-segwit nodes processed transaction in this format and relay it to pre-segwit nodes, it will strip away the Flag and Witness part. Therefore for pre-segwit nodes, these transactions look like transactions that any one can spend because signatures are in witnesses which are stripped away. That is why segwit is a softfork.


References:


Edit:

Reddit discussion

Written on December 19, 2019