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  }