Compact Variable Length Integer
A variable-width data format for unsigned integers allowing a more compact representation for smaller values. This is sometimes referred to as "compact size" or "var int"*.
* - Caution should be used when refering to this integer format as "var int" (or "VarInt"), however, in that it may create an ambiguity. The "Core" family of software (BCHN, BU, and Flowee) all have an internal "VARINT" format that is distinct from this integer format. In that "Core" lineage of software, COMPACTSIZE or CompactSize is used to refer to the protocol's variable length integer format, while "VarInt" refers specifically to their internal variable length integer format and is not a part of the Bitcoin Cash P2P protocol.
Format
Numbers are encoded with the first rule that applies of the following:
- If the number is 0 to 252 (0xFC), store it in 1 byte: the value itself.
- If the number is 253 to 65,535 (0xFFFF), store it in 3 bytes: a 1-byte value 253 (0xFD) followed by the 2 byte little-endian number.
| Byte Index | C-Style Calculation |
|---|---|
| 0 | 0xFD |
| 1 | value & 255 |
| 2 | value >> 8 |
- If the number is 65,536 to 4,294,967,295 (0xFFFFFFFF), store it in 5 bytes: a 1-byte value 254 (0xFE) followed by the 4 byte little-endian number
| Byte Index | C-Style Calculation |
|---|---|
| 0 | 0xFE |
| 1 | value & 255 |
| 2 | (value >> 8) & 255 |
| 3 | (value >> 16) & 255 |
| 4 | (value >> 24) & 255 |
- Otherwise (4,294,967,296 or greater), store it in 9 bytes: a 1-byte value 255 (0xFF) followed by the 8 byte little-endian number
| Byte Index | C-Style Calculation |
|---|---|
| 0 | 0xFF |
| 1 | value & 255 |
| 2 | (value >> 8) & 255 |
| 3 | (value >> 16) & 255 |
| 4 | (value >> 24) & 255 |
| 5 | (value >> 32) & 255 |
| 6 | (value >> 40) & 255 |
| 7 | (value >> 48) & 255 |
| 8 | (value >> 56) & 255 |
Examples:
| Value | Encoding (hex) |
|---|---|
| 252 | fc |
| 253 | fd fd 00 |
| 65535 | fd ff ff |
| 65536 | fe 00 00 01 00 |
The bytes after the prefix are little-endian (least significant byte first), so fe 00 00 01 00 is the prefix fe followed by the 4-byte value 0x00010000 = 65536.
Decoding Rules
Decoders must reject non-minimal (non-canonical) encodings: a 0xFD prefix followed by a value less than 253, a 0xFE prefix followed by a value less than 0x10000, or a 0xFF prefix followed by a value less than 0x100000000 is invalid.
For example, fd 05 00 is invalid and must be encoded as 05.
In addition, by default the reference implementation's ReadCompactSize rejects values greater than 0x02000000 (33,554,432, MAX_SIZE), since CompactSize is primarily used as the length or element count of a serialized vector or string.