types.go 7.1 KB

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