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