This document describes the format used to serialize Elements transactions. Once a transaction has been converted into this raw, serialized form, it can be broadcast across the network.
This document assumes some familiarity with Bitcoin and Elements (UTXOs, [Script](https://en.bitcoin.it/wiki/Script), assets, peg-ins, etc.). For more information on those, please refer to the [Bitcoin Wiki](https://en.bitcoin.it/wiki/Main_Page) and the [Elements Code Tutorial](https://elementsproject.org/elements-code-tutorial/overview).
### Data Types
*Notes*:
* Fields in the following table are listed in the same order in which they are serialized.
* The *Encoding* column in the following tables indicates how the fields are serialized.
* All values are defined in terms of the smallest indivisible unit. For example, a value of 1 L-BTC would be defined as 100,000,000 (L-Satoshis).
#### Transaction
| Field | Required | Size | Data Type | Encoding | Notes |
| Version | Yes | 4 bytes | `int32_t` | Little-endian | Transaction version number. Currently version 2 (see [BIP 68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki#specification)). | |
| Flags | Yes | 1 byte | `unsigned char` | | 1 if the transaction contains a witness, otherwise 0. All other values are invalid. |
| Num Inputs | Yes | Varies | `VarInt` | | Number of inputs to the transaction. |
| Witness | Only if flags is 1 | Varies | `Witness` | | See [BIP 141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki). Note that Elements witnesses contain more data than Bitcoin witnesses. This extra data is described further below. |
Notable differences from Bitcoin:
- In Bitcoin the *Flags* field is optional and it is two bytes long. In Elements, this field is mandatory and it is reduced to one byte.
- In Bitcoin, only inputs have witnesses. In Elements, each output also has a witness section associated with it.
- In Bitcoin transactions the *Locktime* appears immediately after the witnesses, whereas in Elements transactions it appears right before them.
This is the overarching structure of a serialized transaction. The rest of this document contains further details on specific parts, as well as examples.
#### Variable Length Integer (VarInt)
This data type is derived from Bitcoin, and allows an integer to be encoded with a variable length (which depends on the represented value), in order to save space.
Variable length integers always precede a vector of a type of data that may vary in length and are used to indicate this length.
Longer numbers are encoded in little-endian.
| Value | Size | Format | Example |
| ----- | ---- | ------ | ------- |
| <`0xFD` | 1 byte | `uint8_t` | `0x0F` = 15 |
| <= `0xFFFF` | 3 bytes | `0xFD` followed by the number as a `uint16_t` | `0xFD 00FF` = 65 280 |
| <= `0xFFFF FFFF` | 5 bytes | `0xFE` followed by the number as a `uint32_t` | `0xFE 0000 00FF` = 4 278 190 080 |
| <= `0xFFFF FFFF FFFF FFFF` | 9 bytes | `0xFF` followed by the number as a `uint64_t` | `0xFF 0000 0000 0000 00FF` = 18 374 686 479 671 623 680 |
#### Vector\<Type\>
Each `Vector` begins with a `VarInt` describing the number of items it contains.
If the vector is of type `hex`, then the size / structure of each individual item is not known in advance. In this case, each item begins with a `VarInt` describing its size `s` in bytes, followed by `s` bytes which should be interpreted as the item itself.
Otherwise, size prefixes are omitted, and each item should be interpreted in accordance with the vector's type.
In other words, the vector is serialized as follows: `[Length (n)][Item #1][Item #2][...][Item #n]`.
Refer to the examples section below for more concrete examples of serialized vectors.
#### TxIn
| Field | Required | Size | Data Type | Encoding | Notes |
| Output Index | Yes | 4 bytes | `uint32_t` | Little-endian | **Input is a coinbase**: `0xffffffff`<br><br>The two most significant bits are reserved for flags.<br><br>**Input is a peg-in:** second most significant bit is 1.<br><br>**Input has an asset issuance:** most significant bit is 1. |
| ScriptSig Length | Yes | Varies | `VarInt` | | Set to `0x00` if the transaction is SegWit and the witness contains the signature. |
| ScriptSig | If ScriptSig Length is non-zero | Varies | `hex` | | |
| Asset Issuance | Only if the transaction has an issuance (as indicated by the Output Index) | Varies | `AssetIssuance` | | |
[^1]: The hex encodings of hashes by the Elements client (TXID, asset ID) are byte-reversed, and so the bytes will need to be re-reversed to match the serialized data. This is the same situation as in Bitcoin. For example, the hash `1123...deff` would be displayed by the Bitcoin and Elements clients as `ffde...2311`. This is primarily for historical reasons: the Bitcoin client has always interpreted and displayed hashes as little-endian integers and parsed their bytes in reverse order.
Notable differences from Bitcoin:
- In Elements, the *Output Index* field uses the two most significant bits to flag if the transaction is a peg-in transaction (1 <<30)orifitisanissuance(1<<31).Iftheseflagsarepresent,theymustberemovedtorefertotheoutput'sindex.
- Inputs can allow for the issuance of new assets or for reissuances of these assets. To create a new asset, any input being spent can be used and a 0 value must be used in the issuance's blinding nonce field. To reissue an asset, the asset blinding factor is used in the issuance's blinding nonce field, and the asset being spent must be of the reissuance token's asset type.
#### TxOut
| Field | Required | Size | Data Type | Encoding | Notes |
| Input Witnesses | Yes | Varies | `Vector<InputWitness>` | | There is exactly one input witness for each input in the transaction.<br><br>This number is not explicitly included in the witness — it is implied by the number of inputs. |
| Output Witnesses | Yes | Varies | `Vector<OutputWitness>` | | There is exactly one output witness for each output in the transaction.<br><br>This number is not explicitly included in the witness — it is implied by the number of outputs. |
#### InputWitness
SegWit transactions have one such witness for each input.
| Field | Required | Size | Data Type | Encoding | Notes |
| Asset Blinding Nonce | Yes | 32 bytes | `hex` | | Zero for a new asset issuance; otherwise a blinding factor for the input. |
| Asset Entropy | Yes | 32 bytes | `hex` | | **New issuances:** Freeform entropy field, no consensus-defined meaning, but is used as additional entropy to the asset tag calculation.<br><br>**Reissuances:** Required to be the asset's entropy value (from its initial issuance). |
| Amount | Yes | 1 or 9 or 33 bytes | `ConfidentialAmount` | | Amount of the asset to issue. Both explicit and blinded amounts are supported.<br><br>**Note**: cannot be explicitly set to 0 (should be null instead). |
| Num Inflation Keys | Yes | 1 or 9 or 33 bytes | `ConfidentialAmount` | | Number of inflation keys to issue. Both explicit and blinded amounts are supported.<br><br>**Notes:**<br> - Cannot be explicitly set to 0 (should be null instead).<br> - Inflation keys cannot be reissued. |
#### ConfidentialAsset
| Field | Required | Size | Data Type | Encoding | Notes |
| Header | Yes | 1 byte | | | A header byte of `0x00` indicates a “null” value with no subsequent bytes.<br><br>A header byte of `0x01` indicates an “explicit” value with the following 32 bytes denoting the key used to generate the asset ID (little-endian).<br><br>A header byte of `0x0a` or `0x0b` indicates a blinded value encoded as a compressed elliptic curve point. With the least significant bit of the header byte denoting the least significant bit of the y-coordinate, and the remaining 32 bytes denoting the x-coordinate (big-endian). The point must be a point on the curve. |
| Value | If header byte is not `0x00` | 32 bytes | `hex` | Depends on header byte | |
#### ConfidentialAmount
| Field | Required | Size | Data Type | Encoding | Notes |
| Header | Yes | 1 byte | | | A header byte of `0x00` indicates a “null” value with no subsequent bytes.<br><br>A header byte of `0x01` indicates an “explicit” value with the following 8 bytes denoting a 64-bit value (big-endian). This value must be between 0 and `MAX_MONEY` inclusive.<br><br>A header byte of `0x08` or `0x09` indicates a blinded value encoded as a compressed elliptic curve point. With the least significant bit of the header byte denoting the least significant bit of the y-coordinate, and the remaining 32 bytes denoting the x-coordinate (big-endian). The point must be a point on the curve. |
| Value | If header byte is not `0x00` | 8 or 32 bytes | `hex` | Big-endian | |
#### ConfidentialNonce
| Field | Required | Size | Data Type | Encoding | Notes |
| Header | Yes | 1 byte | | | A header byte of `0x00` indicates a “null” value with no subsequent bytes.<br><br>A header byte of `0x01` indicates an “explicit” value with the following 32 bytes denoting a value (big-endian).<br><br>A header byte of `0x02` or `0x03` indicates a compressed elliptic curve point. With the least significant bit of the header byte denoting the least significant bit of the y-coordinate, and the remaining 32 bytes denoting the x-coordinate (big-endian). This point is not required to be on the curve. |
| Value | If header byte is not `0x00` | 32 bytes | `hex` | Big-endian | |
#### Proof
| Field | Required | Size | Data Type | Encoding | Notes |
| Value | If header byte is not `0x00` | Varies | `hex` | Big-endian | The proof itself. This should be interpreted based on the context (surjection proof, range proof, etc). |
## Examples
#### Example 1
Signed transaction on liquidtestnet, moving 2 existing tL-BTC outputs into two new outputs with sizes: 0.00055 tL-BTC, 0.01 tL-BTC.