github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/common/hexutil/hexutil.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:34</date> 10 //</624450073538859008> 11 12 13 /* 14 包HexUtil使用0x前缀实现十六进制编码。 15 Ethereum RPC API使用此编码在JSON有效负载中传输二进制数据。 16 17 编码规则 18 19 所有十六进制数据必须有前缀“0x”。 20 21 对于字节片,十六进制数据的长度必须是偶数。空字节片 22 编码为“0x”。 23 24 整数使用最少的位数(没有前导零位数)进行编码。他们 25 编码长度可能不均匀。数字0编码为“0x0”。 26 **/ 27 28 package hexutil 29 30 import ( 31 "encoding/hex" 32 "fmt" 33 "math/big" 34 "strconv" 35 ) 36 37 const uintBits = 32 << (uint64(^uint(0)) >> 63) 38 39 //错误 40 var ( 41 ErrEmptyString = &decError{"empty hex string"} 42 ErrSyntax = &decError{"invalid hex string"} 43 ErrMissingPrefix = &decError{"hex string without 0x prefix"} 44 ErrOddLength = &decError{"hex string of odd length"} 45 ErrEmptyNumber = &decError{"hex string \"0x\""} 46 ErrLeadingZero = &decError{"hex number with leading zero digits"} 47 ErrUint64Range = &decError{"hex number > 64 bits"} 48 ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)} 49 ErrBig256Range = &decError{"hex number > 256 bits"} 50 ) 51 52 type decError struct{ msg string } 53 54 func (err decError) Error() string { return err.msg } 55 56 //decode解码带0x前缀的十六进制字符串。 57 func Decode(input string) ([]byte, error) { 58 if len(input) == 0 { 59 return nil, ErrEmptyString 60 } 61 if !has0xPrefix(input) { 62 return nil, ErrMissingPrefix 63 } 64 b, err := hex.DecodeString(input[2:]) 65 if err != nil { 66 err = mapError(err) 67 } 68 return b, err 69 } 70 71 //must decode解码带0x前缀的十六进制字符串。它会因输入无效而恐慌。 72 func MustDecode(input string) []byte { 73 dec, err := Decode(input) 74 if err != nil { 75 panic(err) 76 } 77 return dec 78 } 79 80 //将B编码为带0x前缀的十六进制字符串。 81 func Encode(b []byte) string { 82 enc := make([]byte, len(b)*2+2) 83 copy(enc, "0x") 84 hex.Encode(enc[2:], b) 85 return string(enc) 86 } 87 88 //decodeuint64将前缀为0x的十六进制字符串解码为一个数量。 89 func DecodeUint64(input string) (uint64, error) { 90 raw, err := checkNumber(input) 91 if err != nil { 92 return 0, err 93 } 94 dec, err := strconv.ParseUint(raw, 16, 64) 95 if err != nil { 96 err = mapError(err) 97 } 98 return dec, err 99 } 100 101 //mustdecodeuint64将前缀为0x的十六进制字符串解码为一个数量。 102 //它会因输入无效而恐慌。 103 func MustDecodeUint64(input string) uint64 { 104 dec, err := DecodeUint64(input) 105 if err != nil { 106 panic(err) 107 } 108 return dec 109 } 110 111 //encodeuint64将i编码为带0x前缀的十六进制字符串。 112 func EncodeUint64(i uint64) string { 113 enc := make([]byte, 2, 10) 114 copy(enc, "0x") 115 return string(strconv.AppendUint(enc, i, 16)) 116 } 117 118 var bigWordNibbles int 119 120 func init() { 121 //这是一种计算big.word所需的半字节数的奇怪方法。 122 //通常的方法是使用常量算术,但是Go-Vet不能处理这个问题。 123 b, _ := new(big.Int).SetString("FFFFFFFFFF", 16) 124 switch len(b.Bits()) { 125 case 1: 126 bigWordNibbles = 16 127 case 2: 128 bigWordNibbles = 8 129 default: 130 panic("weird big.Word size") 131 } 132 } 133 134 //decodebig将前缀为0x的十六进制字符串解码为一个数量。 135 //不接受大于256位的数字。 136 func DecodeBig(input string) (*big.Int, error) { 137 raw, err := checkNumber(input) 138 if err != nil { 139 return nil, err 140 } 141 if len(raw) > 64 { 142 return nil, ErrBig256Range 143 } 144 words := make([]big.Word, len(raw)/bigWordNibbles+1) 145 end := len(raw) 146 for i := range words { 147 start := end - bigWordNibbles 148 if start < 0 { 149 start = 0 150 } 151 for ri := start; ri < end; ri++ { 152 nib := decodeNibble(raw[ri]) 153 if nib == badNibble { 154 return nil, ErrSyntax 155 } 156 words[i] *= 16 157 words[i] += big.Word(nib) 158 } 159 end = start 160 } 161 dec := new(big.Int).SetBits(words) 162 return dec, nil 163 } 164 165 //mustdecodebig将前缀为0x的十六进制字符串解码为一个数量。 166 //它会因输入无效而恐慌。 167 func MustDecodeBig(input string) *big.Int { 168 dec, err := DecodeBig(input) 169 if err != nil { 170 panic(err) 171 } 172 return dec 173 } 174 175 //encodebig将bigint编码为带0x前缀的十六进制字符串。 176 //整数的符号被忽略。 177 func EncodeBig(bigint *big.Int) string { 178 nbits := bigint.BitLen() 179 if nbits == 0 { 180 return "0x0" 181 } 182 return fmt.Sprintf("%#x", bigint) 183 } 184 185 func has0xPrefix(input string) bool { 186 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 187 } 188 189 func checkNumber(input string) (raw string, err error) { 190 if len(input) == 0 { 191 return "", ErrEmptyString 192 } 193 if !has0xPrefix(input) { 194 return "", ErrMissingPrefix 195 } 196 input = input[2:] 197 if len(input) == 0 { 198 return "", ErrEmptyNumber 199 } 200 if len(input) > 1 && input[0] == '0' { 201 return "", ErrLeadingZero 202 } 203 return input, nil 204 } 205 206 const badNibble = ^uint64(0) 207 208 func decodeNibble(in byte) uint64 { 209 switch { 210 case in >= '0' && in <= '9': 211 return uint64(in - '0') 212 case in >= 'A' && in <= 'F': 213 return uint64(in - 'A' + 10) 214 case in >= 'a' && in <= 'f': 215 return uint64(in - 'a' + 10) 216 default: 217 return badNibble 218 } 219 } 220 221 func mapError(err error) error { 222 if err, ok := err.(*strconv.NumError); ok { 223 switch err.Err { 224 case strconv.ErrRange: 225 return ErrUint64Range 226 case strconv.ErrSyntax: 227 return ErrSyntax 228 } 229 } 230 if _, ok := err.(hex.InvalidByteError); ok { 231 return ErrSyntax 232 } 233 if err == hex.ErrLength { 234 return ErrOddLength 235 } 236 return err 237 } 238