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:

Byte Index C-Style Calculation
0 0xFD
1 value & 255
2 value >> 8
Byte Index C-Style Calculation
0 0xFE
1 value & 255
2 (value >> 8) & 255
3 (value >> 16) & 255
4 (value >> 24) & 255
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.