Bitcoin-Core-Development
CVarint 序列化格式
最近我開始分析每個完整節點儲存在
chainstate
文件夾(LevelDB
數據庫)中的 UTXO 集數據。通過查看程式碼,您可以或多或少地了解數據條目的格式。但是,為了盡可能節省空間,一些數據被壓縮並編碼為
varint
.可以在程式碼中找到並分析數據是如何壓縮的。但是,我正在努力理解如何執行 varint 編碼/解碼。根據開發人員指南,負責這樣做的類是
CVarint
,我已經能夠追踪我認為這樣做的方法。但是,由於我不知道數據編碼的格式,我無法理解它在做什麼。有人知道儲存數據的格式嗎?
澄清:我指的是比特幣核心的 UTXO 中使用的 CVarint 格式,而不是用於在 txs 腳本中編碼資訊的 varint 格式。
CVarInt 格式在serialize.h中實現
由於評論很廣泛,我將在這裡引用它:
可變長度整數:字節是數字的 MSB base-128 編碼。每個字節中的高位表示後面是否有另一個數字。為了確保編碼是一對一的,除最後一位外,所有數字都減去一個。因此,長度為 len 的字節序列 a[](除了最後一個字節之外的所有字節都設置了第 128 位)對數字進行編碼:
(a [len-1] & 0x7F) + sum (i = 1..len-1, 128 ^ i * (a [len-i-1] & 0x7F +1))
特性:
- 非常小(0-127:1 個字節,128-16511:2 個字節,16512-2113663:3 個字節)
- 每個整數都只有一種編碼
- 編碼不依賴於原始整數類型的大小
- 無冗餘:每個(無限)字節序列對應於一個編碼整數列表。
例子:
- 0:[0x00]
- 1:[0x01]
- 127:[0x7F]
- 128:[0x80 0x00]
- 255:[0x80 0x7F]
- 256:[0x81 0x00]
- 16383:[0xFE 0x7F]
- 16384:[0xFF 0x00]
- 16511:[0xFF 0x7F]
- 65535:[0x82 0xFE 0x7F]
- 2^32: [0x8E 0xFE 0xFE 0xFF 0x00]
為了儲存 CAmount 值(代表 satoshis 數量的整數),預先應用了一個轉換,首先將更常見的數字(10 的倍數)轉換為更小的數字:
- 如果金額為0,則輸出0。
- 否則,將金額(以基本單位為單位)除以可能的 10 的最大冪;呼叫指數 e(e 最大為 9)
- 如果e<9,則結果數的最後一位不能為0;將其儲存為 d,然後將其刪除(除以 10),呼叫結果 n。然後,輸出 1 + 10*(9*n + d - 1) + e
- 如果e==9,我們只知道結果數不為零,所以輸出1 + 10*(n - 1) + 9