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