github.com/theQRL/go-zond@v0.2.1/rpc/types.go (about)

     1  // Copyright 2015 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 rpc
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"math"
    24  	"strconv"
    25  	"strings"
    26  
    27  	"github.com/theQRL/go-zond/common"
    28  	"github.com/theQRL/go-zond/common/hexutil"
    29  )
    30  
    31  // API describes the set of methods offered over the RPC interface
    32  type API struct {
    33  	Namespace     string      // namespace under which the rpc methods of Service are exposed
    34  	Service       interface{} // receiver instance which holds the methods
    35  	Authenticated bool        // whether the api should only be available behind authentication.
    36  }
    37  
    38  // ServerCodec implements reading, parsing and writing RPC messages for the server side of
    39  // a RPC session. Implementations must be go-routine safe since the codec can be called in
    40  // multiple go-routines concurrently.
    41  type ServerCodec interface {
    42  	peerInfo() PeerInfo
    43  	readBatch() (msgs []*jsonrpcMessage, isBatch bool, err error)
    44  	close()
    45  
    46  	jsonWriter
    47  }
    48  
    49  // jsonWriter can write JSON messages to its underlying connection.
    50  // Implementations must be safe for concurrent use.
    51  type jsonWriter interface {
    52  	// writeJSON writes a message to the connection.
    53  	writeJSON(ctx context.Context, msg interface{}, isError bool) error
    54  
    55  	// Closed returns a channel which is closed when the connection is closed.
    56  	closed() <-chan interface{}
    57  	// RemoteAddr returns the peer address of the connection.
    58  	remoteAddr() string
    59  }
    60  
    61  type BlockNumber int64
    62  
    63  const (
    64  	SafeBlockNumber      = BlockNumber(-4)
    65  	FinalizedBlockNumber = BlockNumber(-3)
    66  	LatestBlockNumber    = BlockNumber(-2)
    67  	PendingBlockNumber   = BlockNumber(-1)
    68  	EarliestBlockNumber  = BlockNumber(0)
    69  )
    70  
    71  // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
    72  // - "safe", "finalized", "latest", "earliest" or "pending" as string arguments
    73  // - the block number
    74  // Returned errors:
    75  // - an invalid block number error when the given argument isn't a known strings
    76  // - an out of range error when the given block number is either too little or too large
    77  func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
    78  	input := strings.TrimSpace(string(data))
    79  	if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
    80  		input = input[1 : len(input)-1]
    81  	}
    82  
    83  	switch input {
    84  	case "earliest":
    85  		*bn = EarliestBlockNumber
    86  		return nil
    87  	case "latest":
    88  		*bn = LatestBlockNumber
    89  		return nil
    90  	case "pending":
    91  		*bn = PendingBlockNumber
    92  		return nil
    93  	case "finalized":
    94  		*bn = FinalizedBlockNumber
    95  		return nil
    96  	case "safe":
    97  		*bn = SafeBlockNumber
    98  		return nil
    99  	}
   100  
   101  	blckNum, err := hexutil.DecodeUint64(input)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	if blckNum > math.MaxInt64 {
   106  		return fmt.Errorf("block number larger than int64")
   107  	}
   108  	*bn = BlockNumber(blckNum)
   109  	return nil
   110  }
   111  
   112  // Int64 returns the block number as int64.
   113  func (bn BlockNumber) Int64() int64 {
   114  	return (int64)(bn)
   115  }
   116  
   117  // MarshalText implements encoding.TextMarshaler. It marshals:
   118  // - "safe", "finalized", "latest", "earliest" or "pending" as strings
   119  // - other numbers as hex
   120  func (bn BlockNumber) MarshalText() ([]byte, error) {
   121  	return []byte(bn.String()), nil
   122  }
   123  
   124  func (bn BlockNumber) String() string {
   125  	switch bn {
   126  	case EarliestBlockNumber:
   127  		return "earliest"
   128  	case LatestBlockNumber:
   129  		return "latest"
   130  	case PendingBlockNumber:
   131  		return "pending"
   132  	case FinalizedBlockNumber:
   133  		return "finalized"
   134  	case SafeBlockNumber:
   135  		return "safe"
   136  	default:
   137  		if bn < 0 {
   138  			return fmt.Sprintf("<invalid %d>", bn)
   139  		}
   140  		return hexutil.Uint64(bn).String()
   141  	}
   142  }
   143  
   144  type BlockNumberOrHash struct {
   145  	BlockNumber      *BlockNumber `json:"blockNumber,omitempty"`
   146  	BlockHash        *common.Hash `json:"blockHash,omitempty"`
   147  	RequireCanonical bool         `json:"requireCanonical,omitempty"`
   148  }
   149  
   150  func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
   151  	type erased BlockNumberOrHash
   152  	e := erased{}
   153  	err := json.Unmarshal(data, &e)
   154  	if err == nil {
   155  		if e.BlockNumber != nil && e.BlockHash != nil {
   156  			return fmt.Errorf("cannot specify both BlockHash and BlockNumber, choose one or the other")
   157  		}
   158  		bnh.BlockNumber = e.BlockNumber
   159  		bnh.BlockHash = e.BlockHash
   160  		bnh.RequireCanonical = e.RequireCanonical
   161  		return nil
   162  	}
   163  	var input string
   164  	err = json.Unmarshal(data, &input)
   165  	if err != nil {
   166  		return err
   167  	}
   168  	switch input {
   169  	case "earliest":
   170  		bn := EarliestBlockNumber
   171  		bnh.BlockNumber = &bn
   172  		return nil
   173  	case "latest":
   174  		bn := LatestBlockNumber
   175  		bnh.BlockNumber = &bn
   176  		return nil
   177  	case "pending":
   178  		bn := PendingBlockNumber
   179  		bnh.BlockNumber = &bn
   180  		return nil
   181  	case "finalized":
   182  		bn := FinalizedBlockNumber
   183  		bnh.BlockNumber = &bn
   184  		return nil
   185  	case "safe":
   186  		bn := SafeBlockNumber
   187  		bnh.BlockNumber = &bn
   188  		return nil
   189  	default:
   190  		if len(input) == 66 {
   191  			hash := common.Hash{}
   192  			err := hash.UnmarshalText([]byte(input))
   193  			if err != nil {
   194  				return err
   195  			}
   196  			bnh.BlockHash = &hash
   197  			return nil
   198  		} else {
   199  			blckNum, err := hexutil.DecodeUint64(input)
   200  			if err != nil {
   201  				return err
   202  			}
   203  			if blckNum > math.MaxInt64 {
   204  				return fmt.Errorf("blocknumber too high")
   205  			}
   206  			bn := BlockNumber(blckNum)
   207  			bnh.BlockNumber = &bn
   208  			return nil
   209  		}
   210  	}
   211  }
   212  
   213  func (bnh *BlockNumberOrHash) Number() (BlockNumber, bool) {
   214  	if bnh.BlockNumber != nil {
   215  		return *bnh.BlockNumber, true
   216  	}
   217  	return BlockNumber(0), false
   218  }
   219  
   220  func (bnh *BlockNumberOrHash) String() string {
   221  	if bnh.BlockNumber != nil {
   222  		return strconv.Itoa(int(*bnh.BlockNumber))
   223  	}
   224  	if bnh.BlockHash != nil {
   225  		return bnh.BlockHash.String()
   226  	}
   227  	return "nil"
   228  }
   229  
   230  func (bnh *BlockNumberOrHash) Hash() (common.Hash, bool) {
   231  	if bnh.BlockHash != nil {
   232  		return *bnh.BlockHash, true
   233  	}
   234  	return common.Hash{}, false
   235  }
   236  
   237  func BlockNumberOrHashWithNumber(blockNr BlockNumber) BlockNumberOrHash {
   238  	return BlockNumberOrHash{
   239  		BlockNumber:      &blockNr,
   240  		BlockHash:        nil,
   241  		RequireCanonical: false,
   242  	}
   243  }
   244  
   245  func BlockNumberOrHashWithHash(hash common.Hash, canonical bool) BlockNumberOrHash {
   246  	return BlockNumberOrHash{
   247  		BlockNumber:      nil,
   248  		BlockHash:        &hash,
   249  		RequireCanonical: canonical,
   250  	}
   251  }