源碼以下:
func hexToCompact(hex []byte) []byte {
terminator := byte(0)
if hasTerm(hex) {
terminator = 1
hex = hex[:len(hex)-1]
}
buf := make([]byte, len(hex)/2+1)
buf[0] = terminator << 5 // the flag byte
if len(hex)&1 == 1 {
buf[0] |= 1 << 4 // odd flag
buf[0] |= hex[0] // first nibble is contained in the first byte
hex = hex[1:]
}
decodeNibbles(hex, buf[1:])
return buf
}
MPT樹存儲的是鍵值對,須要對hex格式的Key轉化成byte類型。
爲何要進行編碼?(https://ethfans.org/hpcoder/articles/961)
在以太坊協議中,無論是地址仍是hash,都是一個16進制串,如"0x5b3edbcf7d0a97e95e57a4554a29ea66601b71ad",數據最小的表示單位爲一位16進制,如一、a等,但在編程實現中,數據的最小表示單位每每是byte(8bit,2位16進制數),這樣在用byte來表示一串奇數長度的16進制串時會出現問題,如"5b3"和"5b30",直接轉成byte都是5b30。還有一種簡單直觀的轉換方式,"5b3"->"050b03",這種方式雖然簡單,可是數據量會翻倍,不利於大量hash的計算,同時也會增長tree的大小,下降同步性能。Hex-Prefix Encoding能解決這些問題。
- 輸入 key 結尾爲 0x10,則去掉這個終止符。
- key 以前補一個二進制flag四元組(Nibble), 這個四元組第 0 位區分奇偶信息,第 1 位區分節點類型。
- 若是輸入 key 的長度是偶數,則再添加一個四元組 0x0 在 flag 四元組後。
- 將原來的 key 內容壓縮,將分離的兩個 hex(Nibble) 以高四位低四位進行合併成一個byte。