Raw Transaction Format
Bitcoin transactions travel as raw bytes, and anyone writing software that reads or builds them needs to know exactly what those bytes mean. This documents that layout, field by field.
Reference for an AI
Everything an assistant needs to answer questions about BRC-12 accurately, including what it depends on.
Summary
- Why
- Software that builds, signs, broadcasts or parses Bitcoin transactions needs one unambiguous byte-for-byte layout to agree on, and a way to package that layout for transport over the network.
- What
- BRC-12 defines the exact byte layout of a raw hex BSV transaction (version, inputs, outputs, locktime) and the wire frame header used to transport it over the network.
- How
- A developer parses or builds the fields in order, using variable-length integers for counts and sizes, then wraps the serialized transaction in a 44-byte frame header (magic bytes, protocol version, frame version, TXID, payload length) before sending it, or strips that header when receiving one.
What this lets you do
- Parse a raw hex transaction into its fields
- Serialize a transaction into the exact bytes nodes expect
- Compute a transaction's TXID via double-SHA256
- Read and write variable-length integers for counts and script lengths
- Wrap a transaction in the wire frame header for network transport
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
The specification
Abstract
This BRC specifies the format used for raw hex Bitcoin transactions, which are a widely-used way of representing Bitcoin transactions on the network. The specification includes details on the layout and various fields within Bitcoin transactions.
Motivation
Bitcoin transactions are the mechanism for transferring custody of bitcoin tokens from one party to another. It is crucial to have a clear and unambiguous specification for their format. The raw hex format is widely-used and understanding its structure is important for developers and other stakeholders in the Bitcoin ecosystem.
Specification
A Bitcoin transaction consists of a version number, a locktime value, a list of inputs, and a list of outputs. The format for a raw hex Bitcoin transaction is as follows:
- Version: 4-byte integer (little-endian)
- Input Count: variable-length integer
- Inputs: a list of input objects, where each input object has the following fields:
- Previous Transaction Hash: 32-byte hash (little-endian)
- Previous Transaction Output Index: 4-byte integer (little-endian)
- Script Length: variable-length integer
- Unlocking Script: variable-length script
- Sequence Number: 4-byte integer (little-endian)
- Output Count: variable-length integer
- Outputs: a list of output objects, where each output object has the following fields:
- Value: 8-byte integer (little-endian)
- Script Length: variable-length integer
- Locking Script: variable-length script
- Locktime: 4-byte integer (little-endian)
Variable Integers
The variable-length integer is a compact representation of an integer value. The first byte of the integer determines the format of the integer:
- If the first byte is less than 0xfd, then the integer is that byte value.
- If the first byte is 0xfd, then the integer is the next two bytes in little-endian format.
- If the first byte is 0xfe, then the integer is the next four bytes in little-endian format.
- If the first byte is 0xff, then the integer is the next eight bytes in little-endian format.
The script fields in the input and output objects are interpreted as bytecode for a Bitcoin Script, which is a stack-based language used to define spending conditions for bitcoin.
The transaction hash (referred to as the "TXID") is calculated by taking the double-SHA256 hash of the entire transaction. This hash is used as a unique identifier for the transaction on the Bitcoin network.
Wire Frame Format
Raw transactions are transported over the network inside a frame envelope. The frame consists of a fixed-size header followed by the raw transaction payload described above. All multi-byte integers in the header are big-endian.
Frame Header (44 bytes)
| Offset | Size | Field | Value / Notes |
|--------|------|------------------|--------------------------------------------------|
| 0 | 4 | Network Magic | `0xE3E1F3E8` (BSV mainnet P2P magic) |
| 4 | 2 | Protocol Version | `0x02BF` (703, BSV large-block baseline) |
| 6 | 1 | Frame Version | `0x01` (BRC-12 legacy) |
| 7 | 1 | Reserved | Must be `0x00` |
| 8 | 32 | Transaction ID | Raw 256-bit TXID in internal byte order |
| 40 | 4 | Payload Length | `uint32` BE; byte count of payload that follows |
| 44 | * | Payload | Raw serialized transaction (this specification) |
Total header size: 44 bytes.
Field Definitions
Network Magic (bytes 0–3)
The value 0xE3E1F3E8, the BSV mainnet P2P network magic. This allows standard BSV firewall rules and network monitoring tools to classify frames correctly. Receivers must reject frames with any other value.
Protocol Version (bytes 4–5)
The value 0x02BF (703 decimal), the BSV node protocol version that introduced the large-block policy. This field is informational; receivers do not validate it.
Frame Version (byte 6)
The value 0x01 for frames following this specification. Receivers must reject frames with unknown version bytes.
Reserved (byte 7)
Must be 0x00. Reserved for future protocol extensions.
Transaction ID (bytes 8–39)
The 32-byte transaction hash in internal byte order as used in the BSV P2P protocol. This is the byte-reversed form of the display TXID shown by block explorers.
Payload Length (bytes 40–43)
A 32-bit unsigned integer (big-endian) specifying the number of bytes in the payload immediately following the header.
Payload (byte 44 onward)
The raw serialized BSV transaction as defined in the Specification section above.
Example Frame Hex Dump
A BRC-12 frame carrying a 200-byte transaction:
// Header (44 bytes)
E3E1F3E8 // Network Magic
02BF // Protocol Version
01 // Frame Version (0x01 = BRC-12)
00 // Reserved
11c6900eee6e68d191cd25034a5f872ed29e3b69273906a10e021f39ed866471 // Transaction ID
000000C8 // Payload Length (200)
// Payload (200 bytes of raw transaction data)
0200000001...00000000