github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/common/hexutil/json.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  package hexutil
    18  
    19  import (
    20  	"encoding/hex"
    21  	"encoding/json"
    22  	"fmt"
    23  	"math/big"
    24  	"reflect"
    25  	"strconv"
    26  
    27  	"github.com/holiman/uint256"
    28  )
    29  
    30  var (
    31  	bytesT  = reflect.TypeOf(Bytes(nil))
    32  	bigT    = reflect.TypeOf((*Big)(nil))
    33  	uintT   = reflect.TypeOf(Uint(0))
    34  	uint64T = reflect.TypeOf(Uint64(0))
    35  	u256T   = reflect.TypeOf((*uint256.Int)(nil))
    36  )
    37  
    38  // Bytes marshals/unmarshals as a JSON string with 0x prefix.
    39  // The empty slice marshals as "0x".
    40  type Bytes []byte
    41  
    42  // MarshalText implements encoding.TextMarshaler
    43  func (b Bytes) MarshalText() ([]byte, error) {
    44  	result := make([]byte, len(b)*2+2)
    45  	copy(result, `0x`)
    46  	hex.Encode(result[2:], b)
    47  	return result, nil
    48  }
    49  
    50  // UnmarshalJSON implements json.Unmarshaler.
    51  func (b *Bytes) UnmarshalJSON(input []byte) error {
    52  	if !isString(input) {
    53  		return errNonString(bytesT)
    54  	}
    55  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
    56  }
    57  
    58  // UnmarshalText implements encoding.TextUnmarshaler.
    59  func (b *Bytes) UnmarshalText(input []byte) error {
    60  	raw, err := checkText(input, true)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	dec := make([]byte, len(raw)/2)
    65  	if _, err = hex.Decode(dec, raw); err != nil {
    66  		err = mapError(err)
    67  	} else {
    68  		*b = dec
    69  	}
    70  	return err
    71  }
    72  
    73  // String returns the hex encoding of b.
    74  func (b Bytes) String() string {
    75  	return Encode(b)
    76  }
    77  
    78  // ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
    79  func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
    80  
    81  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
    82  func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
    83  	var err error
    84  	switch input := input.(type) {
    85  	case string:
    86  		data, err := Decode(input)
    87  		if err != nil {
    88  			return err
    89  		}
    90  		*b = data
    91  	default:
    92  		err = fmt.Errorf("unexpected type %T for Bytes", input)
    93  	}
    94  	return err
    95  }
    96  
    97  // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
    98  // determines the required input length. This function is commonly used to implement the
    99  // UnmarshalJSON method for fixed-size types.
   100  func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
   101  	if !isString(input) {
   102  		return errNonString(typ)
   103  	}
   104  	return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
   105  }
   106  
   107  // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
   108  // determines the required input length. This function is commonly used to implement the
   109  // UnmarshalText method for fixed-size types.
   110  func UnmarshalFixedText(typname string, input, out []byte) error {
   111  	raw, err := checkText(input, true)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	if len(raw)/2 != len(out) {
   116  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   117  	}
   118  	// Pre-verify syntax before modifying out.
   119  	for _, b := range raw {
   120  		if decodeNibble(b) == badNibble {
   121  			return ErrSyntax
   122  		}
   123  	}
   124  	hex.Decode(out, raw)
   125  	return nil
   126  }
   127  
   128  // UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
   129  // length of out determines the required input length. This function is commonly used to
   130  // implement the UnmarshalText method for fixed-size types.
   131  func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
   132  	raw, err := checkText(input, false)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	if len(raw)/2 != len(out) {
   137  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   138  	}
   139  	// Pre-verify syntax before modifying out.
   140  	for _, b := range raw {
   141  		if decodeNibble(b) == badNibble {
   142  			return ErrSyntax
   143  		}
   144  	}
   145  	hex.Decode(out, raw)
   146  	return nil
   147  }
   148  
   149  // Big marshals/unmarshals as a JSON string with 0x prefix.
   150  // The zero value marshals as "0x0".
   151  //
   152  // Negative integers are not supported at this time. Attempting to marshal them will
   153  // return an error. Values larger than 256bits are rejected by Unmarshal but will be
   154  // marshaled without error.
   155  type Big big.Int
   156  
   157  // MarshalText implements encoding.TextMarshaler
   158  func (b Big) MarshalText() ([]byte, error) {
   159  	return []byte(EncodeBig((*big.Int)(&b))), nil
   160  }
   161  
   162  // UnmarshalJSON implements json.Unmarshaler.
   163  func (b *Big) UnmarshalJSON(input []byte) error {
   164  	if !isString(input) {
   165  		return errNonString(bigT)
   166  	}
   167  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
   168  }
   169  
   170  // UnmarshalText implements encoding.TextUnmarshaler
   171  func (b *Big) UnmarshalText(input []byte) error {
   172  	raw, err := checkNumberText(input)
   173  	if err != nil {
   174  		return err
   175  	}
   176  	if len(raw) > 64 {
   177  		return ErrBig256Range
   178  	}
   179  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   180  	end := len(raw)
   181  	for i := range words {
   182  		start := end - bigWordNibbles
   183  		if start < 0 {
   184  			start = 0
   185  		}
   186  		for ri := start; ri < end; ri++ {
   187  			nib := decodeNibble(raw[ri])
   188  			if nib == badNibble {
   189  				return ErrSyntax
   190  			}
   191  			words[i] *= 16
   192  			words[i] += big.Word(nib)
   193  		}
   194  		end = start
   195  	}
   196  	var dec big.Int
   197  	dec.SetBits(words)
   198  	*b = (Big)(dec)
   199  	return nil
   200  }
   201  
   202  // ToInt converts b to a big.Int.
   203  func (b *Big) ToInt() *big.Int {
   204  	return (*big.Int)(b)
   205  }
   206  
   207  // String returns the hex encoding of b.
   208  func (b *Big) String() string {
   209  	return EncodeBig(b.ToInt())
   210  }
   211  
   212  // ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
   213  func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
   214  
   215  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
   216  func (b *Big) UnmarshalGraphQL(input interface{}) error {
   217  	var err error
   218  	switch input := input.(type) {
   219  	case string:
   220  		return b.UnmarshalText([]byte(input))
   221  	case int32:
   222  		var num big.Int
   223  		num.SetInt64(int64(input))
   224  		*b = Big(num)
   225  	default:
   226  		err = fmt.Errorf("unexpected type %T for BigInt", input)
   227  	}
   228  	return err
   229  }
   230  
   231  // U256 marshals/unmarshals as a JSON string with 0x prefix.
   232  // The zero value marshals as "0x0".
   233  type U256 uint256.Int
   234  
   235  // MarshalText implements encoding.TextMarshaler
   236  func (b U256) MarshalText() ([]byte, error) {
   237  	u256 := (*uint256.Int)(&b)
   238  	return []byte(u256.Hex()), nil
   239  }
   240  
   241  // UnmarshalJSON implements json.Unmarshaler.
   242  func (b *U256) UnmarshalJSON(input []byte) error {
   243  	// The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be
   244  	// more strict, hence we check string and invoke SetFromHex directly.
   245  	if !isString(input) {
   246  		return errNonString(u256T)
   247  	}
   248  	// The hex decoder needs to accept empty string ("") as '0', which uint256.Int
   249  	// would reject.
   250  	if len(input) == 2 {
   251  		(*uint256.Int)(b).Clear()
   252  		return nil
   253  	}
   254  	err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1]))
   255  	if err != nil {
   256  		return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T}
   257  	}
   258  	return nil
   259  }
   260  
   261  // UnmarshalText implements encoding.TextUnmarshaler
   262  func (b *U256) UnmarshalText(input []byte) error {
   263  	// The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be
   264  	// more strict, hence we check string and invoke SetFromHex directly.
   265  	return (*uint256.Int)(b).SetFromHex(string(input))
   266  }
   267  
   268  // String returns the hex encoding of b.
   269  func (b *U256) String() string {
   270  	return (*uint256.Int)(b).Hex()
   271  }
   272  
   273  // Uint64 marshals/unmarshals as a JSON string with 0x prefix.
   274  // The zero value marshals as "0x0".
   275  type Uint64 uint64
   276  
   277  // MarshalText implements encoding.TextMarshaler.
   278  func (b Uint64) MarshalText() ([]byte, error) {
   279  	buf := make([]byte, 2, 10)
   280  	copy(buf, `0x`)
   281  	buf = strconv.AppendUint(buf, uint64(b), 16)
   282  	return buf, nil
   283  }
   284  
   285  // UnmarshalJSON implements json.Unmarshaler.
   286  func (b *Uint64) UnmarshalJSON(input []byte) error {
   287  	if !isString(input) {
   288  		return errNonString(uint64T)
   289  	}
   290  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
   291  }
   292  
   293  // UnmarshalText implements encoding.TextUnmarshaler
   294  func (b *Uint64) UnmarshalText(input []byte) error {
   295  	raw, err := checkNumberText(input)
   296  	if err != nil {
   297  		return err
   298  	}
   299  	if len(raw) > 16 {
   300  		return ErrUint64Range
   301  	}
   302  	var dec uint64
   303  	for _, byte := range raw {
   304  		nib := decodeNibble(byte)
   305  		if nib == badNibble {
   306  			return ErrSyntax
   307  		}
   308  		dec *= 16
   309  		dec += nib
   310  	}
   311  	*b = Uint64(dec)
   312  	return nil
   313  }
   314  
   315  // String returns the hex encoding of b.
   316  func (b Uint64) String() string {
   317  	return EncodeUint64(uint64(b))
   318  }
   319  
   320  // ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
   321  func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
   322  
   323  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
   324  func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
   325  	var err error
   326  	switch input := input.(type) {
   327  	case string:
   328  		return b.UnmarshalText([]byte(input))
   329  	case int32:
   330  		*b = Uint64(input)
   331  	default:
   332  		err = fmt.Errorf("unexpected type %T for Long", input)
   333  	}
   334  	return err
   335  }
   336  
   337  // Uint marshals/unmarshals as a JSON string with 0x prefix.
   338  // The zero value marshals as "0x0".
   339  type Uint uint
   340  
   341  // MarshalText implements encoding.TextMarshaler.
   342  func (b Uint) MarshalText() ([]byte, error) {
   343  	return Uint64(b).MarshalText()
   344  }
   345  
   346  // UnmarshalJSON implements json.Unmarshaler.
   347  func (b *Uint) UnmarshalJSON(input []byte) error {
   348  	if !isString(input) {
   349  		return errNonString(uintT)
   350  	}
   351  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
   352  }
   353  
   354  // UnmarshalText implements encoding.TextUnmarshaler.
   355  func (b *Uint) UnmarshalText(input []byte) error {
   356  	var u64 Uint64
   357  	err := u64.UnmarshalText(input)
   358  	if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
   359  		return ErrUintRange
   360  	} else if err != nil {
   361  		return err
   362  	}
   363  	*b = Uint(u64)
   364  	return nil
   365  }
   366  
   367  // String returns the hex encoding of b.
   368  func (b Uint) String() string {
   369  	return EncodeUint64(uint64(b))
   370  }
   371  
   372  func isString(input []byte) bool {
   373  	return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
   374  }
   375  
   376  func bytesHave0xPrefix(input []byte) bool {
   377  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   378  }
   379  
   380  func checkText(input []byte, wantPrefix bool) ([]byte, error) {
   381  	if len(input) == 0 {
   382  		return nil, nil // empty strings are allowed
   383  	}
   384  	if bytesHave0xPrefix(input) {
   385  		input = input[2:]
   386  	} else if wantPrefix {
   387  		return nil, ErrMissingPrefix
   388  	}
   389  	if len(input)%2 != 0 {
   390  		return nil, ErrOddLength
   391  	}
   392  	return input, nil
   393  }
   394  
   395  func checkNumberText(input []byte) (raw []byte, err error) {
   396  	if len(input) == 0 {
   397  		return nil, nil // empty strings are allowed
   398  	}
   399  	if !bytesHave0xPrefix(input) {
   400  		return nil, ErrMissingPrefix
   401  	}
   402  	input = input[2:]
   403  	if len(input) == 0 {
   404  		return nil, ErrEmptyNumber
   405  	}
   406  	if len(input) > 1 && input[0] == '0' {
   407  		return nil, ErrLeadingZero
   408  	}
   409  	return input, nil
   410  }
   411  
   412  func wrapTypeError(err error, typ reflect.Type) error {
   413  	if _, ok := err.(*decError); ok {
   414  		return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
   415  	}
   416  	return err
   417  }
   418  
   419  func errNonString(typ reflect.Type) error {
   420  	return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
   421  }