github.com/amazechain/amc@v0.1.3/modules/rpc/jsonrpc/types.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package jsonrpc
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"github.com/amazechain/amc/common/hexutil"
    24  	"math"
    25  	"strconv"
    26  	"strings"
    27  
    28  	"github.com/amazechain/amc/common/types"
    29  )
    30  
    31  type API struct {
    32  	Namespace     string
    33  	Service       interface{}
    34  	Authenticated bool // whether the api should only be available behind authentication.
    35  }
    36  
    37  type ServerCodec interface {
    38  	readBatch() (msgs []*jsonrpcMessage, isBatch bool, err error)
    39  	close()
    40  	jsonWriter
    41  }
    42  type jsonWriter interface {
    43  	writeJSON(context.Context, interface{}) error
    44  	// Closed returns a channel which is closed when the connection is closed.
    45  	closed() <-chan interface{}
    46  	// RemoteAddr returns the peer address of the connection.
    47  	remoteAddr() string
    48  }
    49  
    50  type BlockNumber int64
    51  
    52  const (
    53  	SafeBlockNumber      = BlockNumber(-4)
    54  	FinalizedBlockNumber = BlockNumber(-3)
    55  	PendingBlockNumber   = BlockNumber(-2)
    56  	LatestBlockNumber    = BlockNumber(-1)
    57  	EarliestBlockNumber  = BlockNumber(0)
    58  )
    59  
    60  func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
    61  	input := strings.TrimSpace(string(data))
    62  	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
    63  		input = input[1 : len(input)-1]
    64  	}
    65  
    66  	switch input {
    67  	case "earliest":
    68  		*bn = EarliestBlockNumber
    69  		return nil
    70  	case "latest":
    71  		*bn = LatestBlockNumber
    72  		return nil
    73  	case "pending":
    74  		*bn = PendingBlockNumber
    75  		return nil
    76  	case "finalized":
    77  		*bn = FinalizedBlockNumber
    78  		return nil
    79  	case "safe":
    80  		*bn = SafeBlockNumber
    81  		return nil
    82  	}
    83  
    84  	blckNum, err := DecodeUint64(input)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	if blckNum > math.MaxInt64 {
    89  		return fmt.Errorf("block number larger than int64")
    90  	}
    91  	*bn = BlockNumber(blckNum)
    92  	return nil
    93  }
    94  
    95  func (bn BlockNumber) Int64() int64 {
    96  	return (int64)(bn)
    97  }
    98  
    99  type BlockNumberOrHash struct {
   100  	BlockNumber      *BlockNumber `json:"blockNumber,omitempty"`
   101  	BlockHash        *types.Hash  `json:"blockHash,omitempty"`
   102  	RequireCanonical bool         `json:"requireCanonical,omitempty"`
   103  }
   104  
   105  func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
   106  	type erased BlockNumberOrHash
   107  	e := erased{}
   108  	err := json.Unmarshal(data, &e)
   109  	if err == nil {
   110  		if e.BlockNumber != nil && e.BlockHash != nil {
   111  			return fmt.Errorf("cannot specify both BlockHash and BlockNumber, choose one or the other")
   112  		}
   113  		bnh.BlockNumber = e.BlockNumber
   114  		bnh.BlockHash = e.BlockHash
   115  		bnh.RequireCanonical = e.RequireCanonical
   116  		return nil
   117  	}
   118  	var input string
   119  	err = json.Unmarshal(data, &input)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	switch input {
   124  	case "earliest":
   125  		bn := EarliestBlockNumber
   126  		bnh.BlockNumber = &bn
   127  		return nil
   128  	case "latest":
   129  		bn := LatestBlockNumber
   130  		bnh.BlockNumber = &bn
   131  		return nil
   132  	case "pending":
   133  		bn := PendingBlockNumber
   134  		bnh.BlockNumber = &bn
   135  		return nil
   136  	default:
   137  		if len(input) == 66 {
   138  			hash := types.Hash{}
   139  			err := UnmarshalText(hash, []byte(input))
   140  			if err != nil {
   141  				return err
   142  			}
   143  			bnh.BlockHash = &hash
   144  			return nil
   145  		} else {
   146  			blckNum, err := DecodeUint64(input)
   147  			if err != nil {
   148  				return err
   149  			}
   150  			if blckNum > math.MaxInt64 {
   151  				return fmt.Errorf("blocknumber too high")
   152  			}
   153  			bn := BlockNumber(blckNum)
   154  			bnh.BlockNumber = &bn
   155  			return nil
   156  		}
   157  	}
   158  }
   159  
   160  func (bnh *BlockNumberOrHash) Number() (BlockNumber, bool) {
   161  	if bnh.BlockNumber != nil {
   162  		return *bnh.BlockNumber, true
   163  	}
   164  	return BlockNumber(0), false
   165  }
   166  
   167  func (bnh *BlockNumberOrHash) Hash() (types.Hash, bool) {
   168  	if bnh.BlockHash != nil {
   169  		return *bnh.BlockHash, true
   170  	}
   171  	return types.Hash{}, false
   172  }
   173  
   174  func BlockNumberOrHashWithNumber(blockNr BlockNumber) BlockNumberOrHash {
   175  	return BlockNumberOrHash{
   176  		BlockNumber:      &blockNr,
   177  		BlockHash:        nil,
   178  		RequireCanonical: false,
   179  	}
   180  }
   181  
   182  func BlockNumberOrHashWithHash(hash types.Hash, canonical bool) BlockNumberOrHash {
   183  	return BlockNumberOrHash{
   184  		BlockNumber:      nil,
   185  		BlockHash:        &hash,
   186  		RequireCanonical: canonical,
   187  	}
   188  }
   189  
   190  func (bnh *BlockNumberOrHash) String() string {
   191  	if bnh.BlockNumber != nil {
   192  		return strconv.Itoa(int(*bnh.BlockNumber))
   193  	}
   194  	if bnh.BlockHash != nil {
   195  		return bnh.BlockHash.String()
   196  	}
   197  	return "nil"
   198  }
   199  
   200  // DecimalOrHex unmarshals a non-negative decimal or hex parameter into a uint64.
   201  type DecimalOrHex uint64
   202  
   203  // UnmarshalJSON implements json.Unmarshaler.
   204  func (dh *DecimalOrHex) UnmarshalJSON(data []byte) error {
   205  	input := strings.TrimSpace(string(data))
   206  	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
   207  		input = input[1 : len(input)-1]
   208  	}
   209  
   210  	value, err := strconv.ParseUint(input, 10, 64)
   211  	if err != nil {
   212  		value, err = hexutil.DecodeUint64(input)
   213  	}
   214  	if err != nil {
   215  		return err
   216  	}
   217  	*dh = DecimalOrHex(value)
   218  	return nil
   219  }