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