github.com/klaytn/klaytn@v1.12.1/storage/statedb/encoding.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from trie/encoding.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package statedb 22 23 import ( 24 "github.com/klaytn/klaytn/common" 25 ) 26 27 // Trie keys are dealt with in three distinct encodings: 28 // 29 // KEYBYTES encoding contains the actual key and nothing else. This encoding is the 30 // input to most API functions. 31 // 32 // HEX encoding contains one byte for each nibble of the key and an optional trailing 33 // 'terminator' byte of value 0x10 which indicates whether or not the node at the key 34 // contains a value. Hex key encoding is used for nodes loaded in memory because it's 35 // convenient to access. 36 // 37 // COMPACT encoding is defined by the Ethereum Yellow Paper (it's called "hex prefix 38 // encoding" there) and contains the bytes of the key and a flag. The high nibble of the 39 // first byte contains the flag; the lowest bit encoding the oddness of the length and 40 // the second-lowest encoding whether the node at the key is a value node. The low nibble 41 // of the first byte is zero in the case of an even number of nibbles and the first nibble 42 // in the case of an odd number. All remaining nibbles (now an even number) fit properly 43 // into the remaining bytes. Compact encoding is used for nodes stored on disk. 44 45 func hexToCompact(hex []byte) []byte { 46 terminator := byte(0) 47 if hasTerm(hex) { 48 terminator = 1 49 hex = hex[:len(hex)-1] 50 } 51 buf := make([]byte, len(hex)/2+1) 52 buf[0] = terminator << 5 // the flag byte 53 if len(hex)&1 == 1 { 54 buf[0] |= 1 << 4 // odd flag 55 buf[0] |= hex[0] // first nibble is contained in the first byte 56 hex = hex[1:] 57 } 58 decodeNibbles(hex, buf[1:]) 59 return buf 60 } 61 62 // hexToCompactInPlace places the compact key in input buffer, returning the length 63 // needed for the representation 64 func hexToCompactInPlace(hex []byte) int { 65 var ( 66 hexLen = len(hex) // length of the hex input 67 firstByte = byte(0) 68 ) 69 // Check if we have a terminator there 70 if hexLen > 0 && hex[hexLen-1] == 16 { 71 firstByte = 1 << 5 72 hexLen-- // last part was the terminator, ignore that 73 } 74 var ( 75 binLen = hexLen/2 + 1 76 ni = 0 // index in hex 77 bi = 1 // index in bin (compact) 78 ) 79 if hexLen&1 == 1 { 80 firstByte |= 1 << 4 // odd flag 81 firstByte |= hex[0] // first nibble is contained in the first byte 82 ni++ 83 } 84 for ; ni < hexLen; bi, ni = bi+1, ni+2 { 85 hex[bi] = hex[ni]<<4 | hex[ni+1] 86 } 87 hex[0] = firstByte 88 return binLen 89 } 90 91 func compactToHex(compact []byte) []byte { 92 if len(compact) == 0 { 93 return compact 94 } 95 base := keybytesToHex(compact) 96 base = base[:len(base)-1] 97 // apply terminator flag 98 if base[0] >= 2 { 99 base = append(base, 16) 100 } 101 // apply odd flag 102 chop := 2 - base[0]&1 103 return base[chop:] 104 } 105 106 func keybytesToHex(str []byte) []byte { 107 l := len(str)*2 + 1 108 nibbles := make([]byte, l) 109 for i, b := range str { 110 nibbles[i*2] = b / 16 111 nibbles[i*2+1] = b % 16 112 } 113 nibbles[l-1] = 16 114 return nibbles 115 } 116 117 // hexToKeybytes turns hex nibbles into key bytes. 118 // This can only be used for keys of even length. 119 func hexToKeybytes(hex []byte) []byte { 120 if hasTerm(hex) { 121 hex = hex[:len(hex)-1] 122 } 123 if len(hex)&1 != 0 { 124 panic("can't convert hex key of odd length") 125 } 126 key := make([]byte, len(hex)/2) 127 decodeNibbles(hex, key) 128 return key 129 } 130 131 func decodeNibbles(nibbles []byte, bytes []byte) { 132 for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 { 133 bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1] 134 } 135 } 136 137 // prefixLen returns the length of the common prefix of a and b. 138 func prefixLen(a, b []byte) int { 139 i, length := 0, len(a) 140 if len(b) < length { 141 length = len(b) 142 } 143 for ; i < length; i++ { 144 if a[i] != b[i] { 145 break 146 } 147 } 148 return i 149 } 150 151 // hasTerm returns whether a hex key has the terminator flag. 152 func hasTerm(s []byte) bool { 153 return len(s) > 0 && s[len(s)-1] == 16 154 } 155 156 // HexPathToString turns hex nibbles of trie path key into string of the trie path key. 157 func HexPathToString(path []byte) string { 158 if hasTerm(path) { 159 path = path[:len(path)-1] 160 } 161 byteKey := hexToKeybytes(common.RightPadBytes(path, 64)) 162 rst := common.BytesToHash(byteKey).String() 163 return rst[:2+len(path)] 164 }