Bitcoin-Core-Development

CVarint 序列化格式

  • February 25, 2017

最近我開始分析每個完整節點儲存在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

引用自:https://bitcoin.stackexchange.com/questions/51620