github.com/klaytn/klaytn@v1.10.2/common/hexutil/hexutil.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from common/hexutil/hexutil.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package hexutil
    22  
    23  import (
    24  	"encoding/hex"
    25  	"fmt"
    26  	"math/big"
    27  	"strconv"
    28  )
    29  
    30  const uintBits = 32 << (uint64(^uint(0)) >> 63)
    31  
    32  var (
    33  	ErrEmptyString   = &decError{"empty hex string"}
    34  	ErrSyntax        = &decError{"invalid hex string"}
    35  	ErrMissingPrefix = &decError{"hex string without 0x prefix"}
    36  	ErrOddLength     = &decError{"hex string of odd length"}
    37  	ErrEmptyNumber   = &decError{"hex string \"0x\""}
    38  	ErrLeadingZero   = &decError{"hex number with leading zero digits"}
    39  	ErrUint64Range   = &decError{"hex number > 64 bits"}
    40  	ErrUintRange     = &decError{fmt.Sprintf("hex number > %d bits", uintBits)}
    41  	ErrBig256Range   = &decError{"hex number > 256 bits"}
    42  )
    43  
    44  type decError struct{ msg string }
    45  
    46  func (err decError) Error() string { return err.msg }
    47  
    48  // Decode decodes a hex string with 0x prefix.
    49  func Decode(input string) ([]byte, error) {
    50  	if len(input) == 0 {
    51  		return nil, ErrEmptyString
    52  	}
    53  	if !has0xPrefix(input) {
    54  		return nil, ErrMissingPrefix
    55  	}
    56  	b, err := hex.DecodeString(input[2:])
    57  	if err != nil {
    58  		err = mapError(err)
    59  	}
    60  	return b, err
    61  }
    62  
    63  // MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
    64  func MustDecode(input string) []byte {
    65  	dec, err := Decode(input)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  	return dec
    70  }
    71  
    72  // Encode encodes b as a hex string with 0x prefix.
    73  func Encode(b []byte) string {
    74  	enc := make([]byte, len(b)*2+2)
    75  	copy(enc, "0x")
    76  	hex.Encode(enc[2:], b)
    77  	return string(enc)
    78  }
    79  
    80  // DecodeUint64 decodes a hex string with 0x prefix as a quantity.
    81  func DecodeUint64(input string) (uint64, error) {
    82  	raw, err := checkNumber(input)
    83  	if err != nil {
    84  		return 0, err
    85  	}
    86  	dec, err := strconv.ParseUint(raw, 16, 64)
    87  	if err != nil {
    88  		err = mapError(err)
    89  	}
    90  	return dec, err
    91  }
    92  
    93  // MustDecodeUint64 decodes a hex string with 0x prefix as a quantity.
    94  // It panics for invalid input.
    95  func MustDecodeUint64(input string) uint64 {
    96  	dec, err := DecodeUint64(input)
    97  	if err != nil {
    98  		panic(err)
    99  	}
   100  	return dec
   101  }
   102  
   103  // EncodeUint64 encodes i as a hex string with 0x prefix.
   104  func EncodeUint64(i uint64) string {
   105  	enc := make([]byte, 2, 10)
   106  	copy(enc, "0x")
   107  	return string(strconv.AppendUint(enc, i, 16))
   108  }
   109  
   110  var bigWordNibbles int
   111  
   112  func init() {
   113  	// This is a weird way to compute the number of nibbles required for big.Word.
   114  	// The usual way would be to use constant arithmetic but go vet can't handle that.
   115  	b, _ := new(big.Int).SetString("FFFFFFFFFF", 16)
   116  	switch len(b.Bits()) {
   117  	case 1:
   118  		bigWordNibbles = 16
   119  	case 2:
   120  		bigWordNibbles = 8
   121  	default:
   122  		panic("weird big.Word size")
   123  	}
   124  }
   125  
   126  // DecodeBig decodes a hex string with 0x prefix as a quantity.
   127  // Numbers larger than 256 bits are not accepted.
   128  func DecodeBig(input string) (*big.Int, error) {
   129  	raw, err := checkNumber(input)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	if len(raw) > 64 {
   134  		return nil, ErrBig256Range
   135  	}
   136  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   137  	end := len(raw)
   138  	for i := range words {
   139  		start := end - bigWordNibbles
   140  		if start < 0 {
   141  			start = 0
   142  		}
   143  		for ri := start; ri < end; ri++ {
   144  			nib := decodeNibble(raw[ri])
   145  			if nib == badNibble {
   146  				return nil, ErrSyntax
   147  			}
   148  			words[i] *= 16
   149  			words[i] += big.Word(nib)
   150  		}
   151  		end = start
   152  	}
   153  	dec := new(big.Int).SetBits(words)
   154  	return dec, nil
   155  }
   156  
   157  // MustDecodeBig decodes a hex string with 0x prefix as a quantity.
   158  // It panics for invalid input.
   159  func MustDecodeBig(input string) *big.Int {
   160  	dec, err := DecodeBig(input)
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  	return dec
   165  }
   166  
   167  // EncodeBig encodes bigint as a hex string with 0x prefix.
   168  // The sign of the integer is ignored.
   169  func EncodeBig(bigint *big.Int) string {
   170  	nbits := bigint.BitLen()
   171  	if nbits == 0 {
   172  		return "0x0"
   173  	}
   174  	return fmt.Sprintf("%#x", bigint)
   175  }
   176  
   177  func has0xPrefix(input string) bool {
   178  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   179  }
   180  
   181  func checkNumber(input string) (raw string, err error) {
   182  	if len(input) == 0 {
   183  		return "", ErrEmptyString
   184  	}
   185  	if !has0xPrefix(input) {
   186  		return "", ErrMissingPrefix
   187  	}
   188  	input = input[2:]
   189  	if len(input) == 0 {
   190  		return "", ErrEmptyNumber
   191  	}
   192  	if len(input) > 1 && input[0] == '0' {
   193  		return "", ErrLeadingZero
   194  	}
   195  	return input, nil
   196  }
   197  
   198  const badNibble = ^uint64(0)
   199  
   200  func decodeNibble(in byte) uint64 {
   201  	switch {
   202  	case in >= '0' && in <= '9':
   203  		return uint64(in - '0')
   204  	case in >= 'A' && in <= 'F':
   205  		return uint64(in - 'A' + 10)
   206  	case in >= 'a' && in <= 'f':
   207  		return uint64(in - 'a' + 10)
   208  	default:
   209  		return badNibble
   210  	}
   211  }
   212  
   213  func mapError(err error) error {
   214  	if err, ok := err.(*strconv.NumError); ok {
   215  		switch err.Err {
   216  		case strconv.ErrRange:
   217  			return ErrUint64Range
   218  		case strconv.ErrSyntax:
   219  			return ErrSyntax
   220  		}
   221  	}
   222  	if _, ok := err.(hex.InvalidByteError); ok {
   223  		return ErrSyntax
   224  	}
   225  	if err == hex.ErrLength {
   226  		return ErrOddLength
   227  	}
   228  	return err
   229  }