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