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