github.com/cheng762/platon-go@v1.8.17-0.20190529111256-7deff2d7be26/common/hexutil/hexutil.go (about) 1 // Copyright 2016 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 /* 18 Package hexutil implements hex encoding with 0x prefix. 19 This encoding is used by the Ethereum RPC API to transport binary data in JSON payloads. 20 21 Encoding Rules 22 23 All hex data must have prefix "0x". 24 25 For byte slices, the hex data must be of even length. An empty byte slice 26 encodes as "0x". 27 28 Integers are encoded using the least amount of digits (no leading zero digits). Their 29 encoding may be of uneven length. The number zero encodes as "0x0". 30 */ 31 package hexutil 32 33 import ( 34 "encoding/hex" 35 "fmt" 36 "math" 37 "math/big" 38 "strconv" 39 "strings" 40 ) 41 42 const uintBits = 32 << (uint64(^uint(0)) >> 63) 43 44 // Errors 45 var ( 46 ErrEmptyString = &decError{"empty hex string"} 47 ErrSyntax = &decError{"invalid hex string"} 48 ErrMissingPrefix = &decError{"hex string without 0x prefix"} 49 ErrOddLength = &decError{"hex string of odd length"} 50 ErrEmptyNumber = &decError{"hex string \"0x\""} 51 ErrLeadingZero = &decError{"hex number with leading zero digits"} 52 ErrUint64Range = &decError{"hex number > 64 bits"} 53 ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)} 54 ErrBig256Range = &decError{"hex number > 256 bits"} 55 ) 56 57 type decError struct{ msg string } 58 59 func (err decError) Error() string { return err.msg } 60 61 // Decode decodes a hex string with 0x prefix. 62 func Decode(input string) ([]byte, error) { 63 if len(input) == 0 { 64 return nil, ErrEmptyString 65 } 66 if !has0xPrefix(input) { 67 return nil, ErrMissingPrefix 68 } 69 b, err := hex.DecodeString(input[2:]) 70 if err != nil { 71 err = mapError(err) 72 } 73 return b, err 74 } 75 76 // MustDecode decodes a hex string with 0x prefix. It panics for invalid input. 77 func MustDecode(input string) []byte { 78 dec, err := Decode(input) 79 if err != nil { 80 panic(err) 81 } 82 return dec 83 } 84 85 // Encode encodes b as a hex string with 0x prefix. 86 func Encode(b []byte) string { 87 enc := make([]byte, len(b)*2+2) 88 copy(enc, "0x") 89 hex.Encode(enc[2:], b) 90 return string(enc) 91 } 92 93 // DecodeUint64 decodes a hex string with 0x prefix as a quantity. 94 func DecodeUint64(input string) (uint64, error) { 95 raw, err := checkNumber(input) 96 if err != nil { 97 return 0, err 98 } 99 dec, err := strconv.ParseUint(raw, 16, 64) 100 if err != nil { 101 err = mapError(err) 102 } 103 return dec, err 104 } 105 106 // MustDecodeUint64 decodes a hex string with 0x prefix as a quantity. 107 // It panics for invalid input. 108 func MustDecodeUint64(input string) uint64 { 109 dec, err := DecodeUint64(input) 110 if err != nil { 111 panic(err) 112 } 113 return dec 114 } 115 116 // EncodeUint64 encodes i as a hex string with 0x prefix. 117 func EncodeUint64(i uint64) string { 118 enc := make([]byte, 2, 10) 119 copy(enc, "0x") 120 return string(strconv.AppendUint(enc, i, 16)) 121 } 122 123 var bigWordNibbles int 124 125 func init() { 126 // This is a weird way to compute the number of nibbles required for big.Word. 127 // The usual way would be to use constant arithmetic but go vet can't handle that. 128 b, _ := new(big.Int).SetString("FFFFFFFFFF", 16) 129 switch len(b.Bits()) { 130 case 1: 131 bigWordNibbles = 16 132 case 2: 133 bigWordNibbles = 8 134 default: 135 panic("weird big.Word size") 136 } 137 } 138 139 // DecodeBig decodes a hex string with 0x prefix as a quantity. 140 // Numbers larger than 256 bits are not accepted. 141 func DecodeBig(input string) (*big.Int, error) { 142 raw, err := checkNumber(input) 143 if err != nil { 144 return nil, err 145 } 146 if len(raw) > 64 { 147 return nil, ErrBig256Range 148 } 149 words := make([]big.Word, len(raw)/bigWordNibbles+1) 150 end := len(raw) 151 for i := range words { 152 start := end - bigWordNibbles 153 if start < 0 { 154 start = 0 155 } 156 for ri := start; ri < end; ri++ { 157 nib := decodeNibble(raw[ri]) 158 if nib == badNibble { 159 return nil, ErrSyntax 160 } 161 words[i] *= 16 162 words[i] += big.Word(nib) 163 } 164 end = start 165 } 166 dec := new(big.Int).SetBits(words) 167 return dec, nil 168 } 169 170 // MustDecodeBig decodes a hex string with 0x prefix as a quantity. 171 // It panics for invalid input. 172 func MustDecodeBig(input string) *big.Int { 173 dec, err := DecodeBig(input) 174 if err != nil { 175 panic(err) 176 } 177 return dec 178 } 179 180 // EncodeBig encodes bigint as a hex string with 0x prefix. 181 // The sign of the integer is ignored. 182 func EncodeBig(bigint *big.Int) string { 183 nbits := bigint.BitLen() 184 if nbits == 0 { 185 return "0x0" 186 } 187 return fmt.Sprintf("%#x", bigint) 188 } 189 190 func has0xPrefix(input string) bool { 191 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 192 } 193 194 func checkNumber(input string) (raw string, err error) { 195 if len(input) == 0 { 196 return "", ErrEmptyString 197 } 198 if !has0xPrefix(input) { 199 return "", ErrMissingPrefix 200 } 201 input = input[2:] 202 if len(input) == 0 { 203 return "", ErrEmptyNumber 204 } 205 if len(input) > 1 && input[0] == '0' { 206 return "", ErrLeadingZero 207 } 208 return input, nil 209 } 210 211 const badNibble = ^uint64(0) 212 213 func decodeNibble(in byte) uint64 { 214 switch { 215 case in >= '0' && in <= '9': 216 return uint64(in - '0') 217 case in >= 'A' && in <= 'F': 218 return uint64(in - 'A' + 10) 219 case in >= 'a' && in <= 'f': 220 return uint64(in - 'a' + 10) 221 default: 222 return badNibble 223 } 224 } 225 226 func mapError(err error) error { 227 if err, ok := err.(*strconv.NumError); ok { 228 switch err.Err { 229 case strconv.ErrRange: 230 return ErrUint64Range 231 case strconv.ErrSyntax: 232 return ErrSyntax 233 } 234 } 235 if _, ok := err.(hex.InvalidByteError); ok { 236 return ErrSyntax 237 } 238 if err == hex.ErrLength { 239 return ErrOddLength 240 } 241 return err 242 } 243 244 func HexDec(h string) (n float64) { 245 s := strings.Split(strings.ToUpper(h), "") 246 l := len(s) 247 i := 0 248 d := float64(0) 249 hex := map[string]string{"A": "10", "B": "11", "C": "12", "D": "13", "E": "14", "F": "15"} 250 for i = 0; i < l; i++ { 251 c := s[i] 252 if v, ok := hex[c]; ok { 253 c = v 254 } 255 f, err := strconv.ParseFloat(c, 10) 256 if err != nil { 257 return -1 258 } 259 d += f * math.Pow(16, float64(l-i-1)) 260 } 261 return d 262 }