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 }