<p>There are two distinct variable-length integer encodings implemented in Bitcoin Core's serialization framework:</p>
<ol>
<li>The encoding used in the P2P protocol for the lengths of vectors (number of transactions in blocks, number of inputs/outputs in transactions, number of entries in inv/addr messages, ...) is known inside the Bitcoin Core codebase as the &quot;CompactSize&quot; encoding, though it has historically been referred to in external protocol documentation as &quot;VarInt&quot;.</li>
<li>Another encoding which is only used internally in Bitcoin Core, in e.g. its UTXO database on disk, but isn't used anywhere in the P2P protocol. This is referred to inside the Bitcoin Core codebase as &quot;VarInt&quot;.</li>
</ol>
<p>For reference, the two encodings are:</p>
<ol>
<li>The &quot;CompactSize&quot; encoding (also known as &quot;VarInt&quot; outside Bitcoin Core):</li>
</ol>
<ul>
<li><code>0</code>..<code>0xfc</code>: 1 byte (the value itself)</li>
<li><code>0xfd</code>..<code>0xffff</code>: 3 bytes (0xfd + 2 byte little endian encoding)</li>
<li><code>0x10000</code>..<code>0xffffffff</code>: 5 bytes (0xfe + 4 byte little endian encoding)</li>
<li><code>0x100000000</code>..<code>0xffffffffffffffff</code>: 9 bytes (0xff + 8 byte little endian encoding)</li>
</ul>
<ol start="2">
<li>The &quot;VarInt&quot; encoding (not used outside Bitcoin Core) is described inside the codebase as follows:</li>
</ol>
<blockquote>
<p>Variable-length integers: bytes are a MSB base-128 encoding of the number.
The high bit in each byte signifies whether another digit follows. To make
sure the encoding is one-to-one, one is subtracted from all but the last digit.
Thus, the byte sequence a[] with length len, where all but the last byte
has bit 128 set, encodes the number:</p>
<p>(a[len-1] &amp; 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] &amp; 0x7F)+1))</p>
</blockquote>
<p>It results in the following sizes:</p>
<ul>
<li><code>0</code>..<code>0x7f</code>: 1 byte</li>
<li><code>0x80</code>..<code>0x407f</code>: 2 bytes</li>
<li><code>0x4080</code>..<code>0x20407f</code>: 3 bytes</li>
<li><code>0x204080</code>..<code>0x1020407f</code>: 4 bytes</li>
<li><code>0x10204080</code>..<code>0x81020407f</code>: 5 bytes</li>
<li>...</li>
</ul>

CC BY-SA 4.0
2022-07-23T12:58:22.557Z
2022-07-23T12:58:22.557Z
Pieter Wuille
<p><a href="https://bitcoin.stackexchange.com/questions/110955/whats-the-specification-for-compact-size-service-messages/110963#110963">Pieter Wuille's definition of CompactSize encoding</a> seems to match <a href="https://learnmeabitcoin.com/technical/varint" rel="noreferrer">Greg Walker's definition of VarInt encoding</a>, yet the <a href="https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer" rel="noreferrer">BitcoinWiki claims that CompactSize is not to be confused with VarInt</a>.</p>
<p>What, if any, are the differences between the two encodings?
Or are they simply the same thing?</p>

<bitcoin-core><block><raw-transaction><raw-data><p2p>
What is the different between CompactSize and VarInt encoding?
drogos86
# What is the different between CompactSize and VarInt encoding?

(Asked by: username_0 on 2022-07-23)

[username_1 username_1's definition of CompactSize encoding](https://bitcoin.stackexchange.com/questions/110955/whats-the-specification-for-compact-size-service-messages/110963#110963) seems to match [Greg Walker's definition of VarInt encoding](https://learnmeabitcoin.com/technical/varint), yet the [BitcoinWiki claims that CompactSize is not to be confused with VarInt](https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer).

What, if any, are the differences between the two encodings?
Or are they simply the same thing?

**Tags:** bitcoin-core, block, raw-transaction, raw-data, p2p


---

## 1 answers

### Answer by username_1 on 2022-07-23. Score: 11 | Accepted answer

There are two distinct variable-length integer encodings implemented in Bitcoin Core's serialization framework:

1. The encoding used in the P2P protocol for the lengths of vectors (number of transactions in blocks, number of inputs/outputs in transactions, number of entries in inv/addr messages, ...) is known inside the Bitcoin Core codebase as the "CompactSize" encoding, though it has historically been referred to in external protocol documentation as "VarInt".
2. Another encoding which is only used internally in Bitcoin Core, in e.g. its UTXO database on disk, but isn't used anywhere in the P2P protocol. This is referred to inside the Bitcoin Core codebase as "VarInt".

For reference, the two encodings are:

1. The "CompactSize" encoding (also known as "VarInt" outside Bitcoin Core):

* `0`..`0xfc`: 1 byte (the value itself)
* `0xfd`..`0xffff`: 3 bytes (0xfd + 2 byte little endian encoding)
* `0x10000`..`0xffffffff`: 5 bytes (0xfe + 4 byte little endian encoding)
* `0x100000000`..`0xffffffffffffffff`: 9 bytes (0xff + 8 byte little endian encoding)

2. The "VarInt" encoding (not used outside Bitcoin Core) is described inside the codebase as follows:

> Variable-length integers: bytes are a MSB base-128 encoding of the number.
> The high bit in each byte signifies whether another digit follows. To make
> sure the encoding is one-to-one, one is subtracted from all but the last digit.
> Thus, the byte sequence a[] with length len, where all but the last byte
> has bit 128 set, encodes the number:
>
> (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i\*((a[len-i-1] & 0x7F)+1))

It results in the following sizes:

* `0`..`0x7f`: 1 byte
* `0x80`..`0x407f`: 2 bytes
* `0x4080`..`0x20407f`: 3 bytes
* `0x204080`..`0x1020407f`: 4 bytes
* `0x10204080`..`0x81020407f`: 5 bytes
* ...


---

