github.com/quinndk/ethereum_read@v0.0.0-20181211143958-29c55eec3237/go-ethereum-master_read/trie/encoding.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package trie 18 19 // Trie keys are dealt with in three distinct encodings: 20 // 21 // KEYBYTES encoding contains the actual key and nothing else. This encoding is the 22 // input to most API functions. 23 // 24 // HEX encoding contains one byte for each nibble of the key and an optional trailing 25 // 'terminator' byte of value 0x10 which indicates whether or not the node at the key 26 // contains a value. Hex key encoding is used for nodes loaded in memory because it's 27 // convenient to access. 28 // 29 // COMPACT encoding is defined by the Ethereum Yellow Paper (it's called "hex prefix 30 // encoding" there) and contains the bytes of the key and a flag. The high nibble of the 31 // first byte contains the flag; the lowest bit encoding the oddness of the length and 32 // the second-lowest encoding whether the node at the key is a value node. The low nibble 33 // of the first byte is zero in the case of an even number of nibbles and the first nibble 34 // in the case of an odd number. All remaining nibbles (now an even number) fit properly 35 // into the remaining bytes. Compact encoding is used for nodes stored on disk. 36 // Hex编码串转化为Compact编码 37 func hexToCompact(hex []byte) []byte { 38 // 如果最后一位是16,terminator为1,否则为0 39 terminator := byte(0) 40 // 包含terminator的节点为叶子节点 41 if hasTerm(hex) { 42 terminator = 1 43 // 1.0将Hex格式的尾部标记byte去掉 44 hex = hex[:len(hex)-1] 45 } 46 // 定义Compat字节数组 47 buf := make([]byte, len(hex)/2+1) 48 // 标志位默认 49 buf[0] = terminator << 5 // the flag byte 50 if len(hex)&1 == 1 { 51 // 如果Hex长度为奇数,修改标志位为odd flag 52 buf[0] |= 1 << 4 // odd flag 53 // 然后把第1个nibble放入buf[0]低四位 54 buf[0] |= hex[0] // first nibble is contained in the first byte 55 hex = hex[1:] 56 } 57 // 1.1然后将每2nibble的数据合并到1个byte 58 decodeNibbles(hex, buf[1:]) 59 return buf 60 } 61 62 // Compact编码转化为Hex编码串 63 func compactToHex(compact []byte) []byte { 64 base := keybytesToHex(compact) 65 // delete terminator flag 66 67 /*这里base[0]有4中情况 68 00000000 扩展节点偶数位 69 00000001 扩展节点奇数位 70 00000010 叶子节点偶数位 71 00000011 叶子节点偶数位 72 */ 73 74 if base[0] < 2 { 75 // 如果是扩展节点,去除最后一位 76 base = base[:len(base)-1] 77 } 78 // apply odd flag 79 // 如果是偶数位chop=2,否则chop=1 80 chop := 2 - base[0]&1 81 //去除compact标志位。偶数位去除2个字节,奇数位去除1个字节(因为奇数位的低四位放的是nibble数据) 82 return base[chop:] 83 } 84 85 // 将key字符串进行Hex编码 86 func keybytesToHex(str []byte) []byte { 87 l := len(str)*2 + 1 88 //将一个keybyte转化成两个字节 89 var nibbles = make([]byte, l) 90 for i, b := range str { 91 nibbles[i*2] = b / 16 92 nibbles[i*2+1] = b % 16 93 } 94 //末尾加入Hex标志位16 00010000 95 nibbles[l-1] = 16 96 return nibbles 97 } 98 99 // hexToKeybytes turns hex nibbles into key bytes. 100 // This can only be used for keys of even length. 101 // 将hex编码解码转为key字符串 102 func hexToKeybytes(hex []byte) []byte { 103 if hasTerm(hex) { 104 hex = hex[:len(hex)-1] 105 } 106 if len(hex)&1 != 0 { 107 panic("can't convert hex key of odd length") 108 } 109 key := make([]byte, len(hex)/2) 110 decodeNibbles(hex, key) 111 return key 112 } 113 114 func decodeNibbles(nibbles []byte, bytes []byte) { 115 for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 { 116 bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1] 117 } 118 } 119 120 // prefixLen returns the length of the common prefix of a and b. 121 func prefixLen(a, b []byte) int { 122 var i, length = 0, len(a) 123 if len(b) < length { 124 length = len(b) 125 } 126 for ; i < length; i++ { 127 if a[i] != b[i] { 128 break 129 } 130 } 131 return i 132 } 133 134 // hasTerm returns whether a hex key has the terminator flag. 135 // 是否包含Hex格式标识符(末尾byte为16 00010000) 136 func hasTerm(s []byte) bool { 137 return len(s) > 0 && s[len(s)-1] == 16 138 }