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