github.com/theQRL/go-zond@v0.2.1/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 Zond 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/big"
    37  	"strconv"
    38  )
    39  
    40  const (
    41  	Prefix0x = "0x"
    42  	PrefixZ  = "Z"
    43  
    44  	uintBits = 32 << (uint64(^uint(0)) >> 63)
    45  )
    46  
    47  // Errors
    48  var (
    49  	ErrEmptyString    = &decError{"empty hex string"}
    50  	ErrSyntax         = &decError{"invalid hex string"}
    51  	ErrMissingPrefix  = &decError{"hex string without 0x prefix"}
    52  	ErrMissingPrefixZ = &decError{"hex string without Z prefix"}
    53  	ErrOddLength      = &decError{"hex string of odd length"}
    54  	ErrEmptyNumber    = &decError{"hex string \"0x\""}
    55  	ErrLeadingZero    = &decError{"hex number with leading zero digits"}
    56  	ErrUint64Range    = &decError{"hex number > 64 bits"}
    57  	ErrUintRange      = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
    58  	ErrBig256Range    = &decError{"hex number > 256 bits"}
    59  )
    60  
    61  type decError struct{ msg string }
    62  
    63  func (err decError) Error() string { return err.msg }
    64  
    65  // Decode decodes a hex string with 0x prefix.
    66  func Decode(input string) ([]byte, error) {
    67  	if len(input) == 0 {
    68  		return nil, ErrEmptyString
    69  	}
    70  	if !has0xPrefix(input) {
    71  		return nil, ErrMissingPrefix
    72  	}
    73  	b, err := hex.DecodeString(input[2:])
    74  	if err != nil {
    75  		err = mapError(err)
    76  	}
    77  	return b, err
    78  }
    79  
    80  // MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
    81  func MustDecode(input string) []byte {
    82  	dec, err := Decode(input)
    83  	if err != nil {
    84  		panic(err)
    85  	}
    86  	return dec
    87  }
    88  
    89  // Encode encodes b as a hex string with 0x prefix.
    90  func Encode(b []byte) string {
    91  	enc := make([]byte, len(b)*2+2)
    92  	copy(enc, Prefix0x)
    93  	hex.Encode(enc[2:], b)
    94  	return string(enc)
    95  }
    96  
    97  // DecodeUint64 decodes a hex string with 0x prefix as a quantity.
    98  func DecodeUint64(input string) (uint64, error) {
    99  	raw, err := checkNumber(input)
   100  	if err != nil {
   101  		return 0, err
   102  	}
   103  	dec, err := strconv.ParseUint(raw, 16, 64)
   104  	if err != nil {
   105  		err = mapError(err)
   106  	}
   107  	return dec, err
   108  }
   109  
   110  // MustDecodeUint64 decodes a hex string with 0x prefix as a quantity.
   111  // It panics for invalid input.
   112  func MustDecodeUint64(input string) uint64 {
   113  	dec, err := DecodeUint64(input)
   114  	if err != nil {
   115  		panic(err)
   116  	}
   117  	return dec
   118  }
   119  
   120  // EncodeUint64 encodes i as a hex string with 0x prefix.
   121  func EncodeUint64(i uint64) string {
   122  	enc := make([]byte, 2, 10)
   123  	copy(enc, Prefix0x)
   124  	return string(strconv.AppendUint(enc, i, 16))
   125  }
   126  
   127  var bigWordNibbles int
   128  
   129  func init() {
   130  	// This is a weird way to compute the number of nibbles required for big.Word.
   131  	// The usual way would be to use constant arithmetic but go vet can't handle that.
   132  	b, _ := new(big.Int).SetString("FFFFFFFFFF", 16)
   133  	switch len(b.Bits()) {
   134  	case 1:
   135  		bigWordNibbles = 16
   136  	case 2:
   137  		bigWordNibbles = 8
   138  	default:
   139  		panic("weird big.Word size")
   140  	}
   141  }
   142  
   143  // DecodeBig decodes a hex string with 0x prefix as a quantity.
   144  // Numbers larger than 256 bits are not accepted.
   145  func DecodeBig(input string) (*big.Int, error) {
   146  	raw, err := checkNumber(input)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  	if len(raw) > 64 {
   151  		return nil, ErrBig256Range
   152  	}
   153  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   154  	end := len(raw)
   155  	for i := range words {
   156  		start := end - bigWordNibbles
   157  		if start < 0 {
   158  			start = 0
   159  		}
   160  		for ri := start; ri < end; ri++ {
   161  			nib := decodeNibble(raw[ri])
   162  			if nib == badNibble {
   163  				return nil, ErrSyntax
   164  			}
   165  			words[i] *= 16
   166  			words[i] += big.Word(nib)
   167  		}
   168  		end = start
   169  	}
   170  	dec := new(big.Int).SetBits(words)
   171  	return dec, nil
   172  }
   173  
   174  // MustDecodeBig decodes a hex string with 0x prefix as a quantity.
   175  // It panics for invalid input.
   176  func MustDecodeBig(input string) *big.Int {
   177  	dec, err := DecodeBig(input)
   178  	if err != nil {
   179  		panic(err)
   180  	}
   181  	return dec
   182  }
   183  
   184  // EncodeBig encodes bigint as a hex string with 0x prefix.
   185  func EncodeBig(bigint *big.Int) string {
   186  	if sign := bigint.Sign(); sign == 0 {
   187  		return Prefix0x + "0"
   188  	} else if sign > 0 {
   189  		return Prefix0x + bigint.Text(16)
   190  	} else {
   191  		return "-" + Prefix0x + bigint.Text(16)[1:]
   192  	}
   193  }
   194  
   195  // DecodeZ decodes a hex string with Z prefix.
   196  func DecodeZ(input string) ([]byte, error) {
   197  	if len(input) == 0 {
   198  		return nil, ErrEmptyString
   199  	}
   200  	if !hasZPrefix(input) {
   201  		return nil, ErrMissingPrefixZ
   202  	}
   203  	b, err := hex.DecodeString(input[1:])
   204  	if err != nil {
   205  		err = mapError(err)
   206  	}
   207  	return b, err
   208  }
   209  
   210  // EncodeZ encodes b as a hex string with Z prefix.
   211  func EncodeZ(b []byte) string {
   212  	enc := make([]byte, len(b)*2+1)
   213  	copy(enc, PrefixZ)
   214  	hex.Encode(enc[1:], b)
   215  	return string(enc)
   216  }
   217  
   218  // MustDecodeZ decodes a hex string with Z prefix. It panics for invalid input.
   219  func MustDecodeZ(input string) []byte {
   220  	dec, err := DecodeZ(input)
   221  	if err != nil {
   222  		panic(err)
   223  	}
   224  	return dec
   225  }
   226  
   227  func has0xPrefix(input string) bool {
   228  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   229  }
   230  
   231  func hasZPrefix(input string) bool {
   232  	return len(input) >= 1 && input[0] == 'Z'
   233  }
   234  
   235  func checkNumber(input string) (raw string, err error) {
   236  	if len(input) == 0 {
   237  		return "", ErrEmptyString
   238  	}
   239  	if !has0xPrefix(input) {
   240  		return "", ErrMissingPrefix
   241  	}
   242  	input = input[2:]
   243  	if len(input) == 0 {
   244  		return "", ErrEmptyNumber
   245  	}
   246  	if len(input) > 1 && input[0] == '0' {
   247  		return "", ErrLeadingZero
   248  	}
   249  	return input, nil
   250  }
   251  
   252  const badNibble = ^uint64(0)
   253  
   254  func decodeNibble(in byte) uint64 {
   255  	switch {
   256  	case in >= '0' && in <= '9':
   257  		return uint64(in - '0')
   258  	case in >= 'A' && in <= 'F':
   259  		return uint64(in - 'A' + 10)
   260  	case in >= 'a' && in <= 'f':
   261  		return uint64(in - 'a' + 10)
   262  	default:
   263  		return badNibble
   264  	}
   265  }
   266  
   267  func mapError(err error) error {
   268  	if err, ok := err.(*strconv.NumError); ok {
   269  		switch err.Err {
   270  		case strconv.ErrRange:
   271  			return ErrUint64Range
   272  		case strconv.ErrSyntax:
   273  			return ErrSyntax
   274  		}
   275  	}
   276  	if _, ok := err.(hex.InvalidByteError); ok {
   277  		return ErrSyntax
   278  	}
   279  	if err == hex.ErrLength {
   280  		return ErrOddLength
   281  	}
   282  	return err
   283  }