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