github.com/theQRL/go-zond@v0.2.1/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 Zond 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/big" 37 "strconv" 38 ) 39 40 const ( 41 Prefix0x = "0x" 42 PrefixZ = "Z" 43 44 uintBits = 32 << (uint64(^uint(0)) >> 63) 45 ) 46 47 // Errors 48 var ( 49 ErrEmptyString = &decError{"empty hex string"} 50 ErrSyntax = &decError{"invalid hex string"} 51 ErrMissingPrefix = &decError{"hex string without 0x prefix"} 52 ErrMissingPrefixZ = &decError{"hex string without Z prefix"} 53 ErrOddLength = &decError{"hex string of odd length"} 54 ErrEmptyNumber = &decError{"hex string \"0x\""} 55 ErrLeadingZero = &decError{"hex number with leading zero digits"} 56 ErrUint64Range = &decError{"hex number > 64 bits"} 57 ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)} 58 ErrBig256Range = &decError{"hex number > 256 bits"} 59 ) 60 61 type decError struct{ msg string } 62 63 func (err decError) Error() string { return err.msg } 64 65 // Decode decodes a hex string with 0x prefix. 66 func Decode(input string) ([]byte, error) { 67 if len(input) == 0 { 68 return nil, ErrEmptyString 69 } 70 if !has0xPrefix(input) { 71 return nil, ErrMissingPrefix 72 } 73 b, err := hex.DecodeString(input[2:]) 74 if err != nil { 75 err = mapError(err) 76 } 77 return b, err 78 } 79 80 // MustDecode decodes a hex string with 0x prefix. It panics for invalid input. 81 func MustDecode(input string) []byte { 82 dec, err := Decode(input) 83 if err != nil { 84 panic(err) 85 } 86 return dec 87 } 88 89 // Encode encodes b as a hex string with 0x prefix. 90 func Encode(b []byte) string { 91 enc := make([]byte, len(b)*2+2) 92 copy(enc, Prefix0x) 93 hex.Encode(enc[2:], b) 94 return string(enc) 95 } 96 97 // DecodeUint64 decodes a hex string with 0x prefix as a quantity. 98 func DecodeUint64(input string) (uint64, error) { 99 raw, err := checkNumber(input) 100 if err != nil { 101 return 0, err 102 } 103 dec, err := strconv.ParseUint(raw, 16, 64) 104 if err != nil { 105 err = mapError(err) 106 } 107 return dec, err 108 } 109 110 // MustDecodeUint64 decodes a hex string with 0x prefix as a quantity. 111 // It panics for invalid input. 112 func MustDecodeUint64(input string) uint64 { 113 dec, err := DecodeUint64(input) 114 if err != nil { 115 panic(err) 116 } 117 return dec 118 } 119 120 // EncodeUint64 encodes i as a hex string with 0x prefix. 121 func EncodeUint64(i uint64) string { 122 enc := make([]byte, 2, 10) 123 copy(enc, Prefix0x) 124 return string(strconv.AppendUint(enc, i, 16)) 125 } 126 127 var bigWordNibbles int 128 129 func init() { 130 // This is a weird way to compute the number of nibbles required for big.Word. 131 // The usual way would be to use constant arithmetic but go vet can't handle that. 132 b, _ := new(big.Int).SetString("FFFFFFFFFF", 16) 133 switch len(b.Bits()) { 134 case 1: 135 bigWordNibbles = 16 136 case 2: 137 bigWordNibbles = 8 138 default: 139 panic("weird big.Word size") 140 } 141 } 142 143 // DecodeBig decodes a hex string with 0x prefix as a quantity. 144 // Numbers larger than 256 bits are not accepted. 145 func DecodeBig(input string) (*big.Int, error) { 146 raw, err := checkNumber(input) 147 if err != nil { 148 return nil, err 149 } 150 if len(raw) > 64 { 151 return nil, ErrBig256Range 152 } 153 words := make([]big.Word, len(raw)/bigWordNibbles+1) 154 end := len(raw) 155 for i := range words { 156 start := end - bigWordNibbles 157 if start < 0 { 158 start = 0 159 } 160 for ri := start; ri < end; ri++ { 161 nib := decodeNibble(raw[ri]) 162 if nib == badNibble { 163 return nil, ErrSyntax 164 } 165 words[i] *= 16 166 words[i] += big.Word(nib) 167 } 168 end = start 169 } 170 dec := new(big.Int).SetBits(words) 171 return dec, nil 172 } 173 174 // MustDecodeBig decodes a hex string with 0x prefix as a quantity. 175 // It panics for invalid input. 176 func MustDecodeBig(input string) *big.Int { 177 dec, err := DecodeBig(input) 178 if err != nil { 179 panic(err) 180 } 181 return dec 182 } 183 184 // EncodeBig encodes bigint as a hex string with 0x prefix. 185 func EncodeBig(bigint *big.Int) string { 186 if sign := bigint.Sign(); sign == 0 { 187 return Prefix0x + "0" 188 } else if sign > 0 { 189 return Prefix0x + bigint.Text(16) 190 } else { 191 return "-" + Prefix0x + bigint.Text(16)[1:] 192 } 193 } 194 195 // DecodeZ decodes a hex string with Z prefix. 196 func DecodeZ(input string) ([]byte, error) { 197 if len(input) == 0 { 198 return nil, ErrEmptyString 199 } 200 if !hasZPrefix(input) { 201 return nil, ErrMissingPrefixZ 202 } 203 b, err := hex.DecodeString(input[1:]) 204 if err != nil { 205 err = mapError(err) 206 } 207 return b, err 208 } 209 210 // EncodeZ encodes b as a hex string with Z prefix. 211 func EncodeZ(b []byte) string { 212 enc := make([]byte, len(b)*2+1) 213 copy(enc, PrefixZ) 214 hex.Encode(enc[1:], b) 215 return string(enc) 216 } 217 218 // MustDecodeZ decodes a hex string with Z prefix. It panics for invalid input. 219 func MustDecodeZ(input string) []byte { 220 dec, err := DecodeZ(input) 221 if err != nil { 222 panic(err) 223 } 224 return dec 225 } 226 227 func has0xPrefix(input string) bool { 228 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 229 } 230 231 func hasZPrefix(input string) bool { 232 return len(input) >= 1 && input[0] == 'Z' 233 } 234 235 func checkNumber(input string) (raw string, err error) { 236 if len(input) == 0 { 237 return "", ErrEmptyString 238 } 239 if !has0xPrefix(input) { 240 return "", ErrMissingPrefix 241 } 242 input = input[2:] 243 if len(input) == 0 { 244 return "", ErrEmptyNumber 245 } 246 if len(input) > 1 && input[0] == '0' { 247 return "", ErrLeadingZero 248 } 249 return input, nil 250 } 251 252 const badNibble = ^uint64(0) 253 254 func decodeNibble(in byte) uint64 { 255 switch { 256 case in >= '0' && in <= '9': 257 return uint64(in - '0') 258 case in >= 'A' && in <= 'F': 259 return uint64(in - 'A' + 10) 260 case in >= 'a' && in <= 'f': 261 return uint64(in - 'a' + 10) 262 default: 263 return badNibble 264 } 265 } 266 267 func mapError(err error) error { 268 if err, ok := err.(*strconv.NumError); ok { 269 switch err.Err { 270 case strconv.ErrRange: 271 return ErrUint64Range 272 case strconv.ErrSyntax: 273 return ErrSyntax 274 } 275 } 276 if _, ok := err.(hex.InvalidByteError); ok { 277 return ErrSyntax 278 } 279 if err == hex.ErrLength { 280 return ErrOddLength 281 } 282 return err 283 }