github.com/number571/tendermint@v0.34.11-gost/rpc/client/http/http.go (about) 1 package http 2 3 import ( 4 "context" 5 "net/http" 6 "time" 7 8 "github.com/number571/tendermint/libs/bytes" 9 "github.com/number571/tendermint/libs/log" 10 rpcclient "github.com/number571/tendermint/rpc/client" 11 ctypes "github.com/number571/tendermint/rpc/core/types" 12 jsonrpcclient "github.com/number571/tendermint/rpc/jsonrpc/client" 13 "github.com/number571/tendermint/types" 14 ) 15 16 /* 17 HTTP is a Client implementation that communicates with a Tendermint node over 18 JSON RPC and WebSockets. 19 20 This is the main implementation you probably want to use in production code. 21 There are other implementations when calling the Tendermint node in-process 22 (Local), or when you want to mock out the server for test code (mock). 23 24 You can subscribe for any event published by Tendermint using Subscribe method. 25 Note delivery is best-effort. If you don't read events fast enough or network is 26 slow, Tendermint might cancel the subscription. The client will attempt to 27 resubscribe (you don't need to do anything). It will keep trying every second 28 indefinitely until successful. 29 30 Request batching is available for JSON RPC requests over HTTP, which conforms to 31 the JSON RPC specification (https://www.jsonrpc.org/specification#batch). See 32 the example for more details. 33 34 Example: 35 36 c, err := New("http://192.168.1.10:26657") 37 if err != nil { 38 // handle error 39 } 40 41 // call Start/Stop if you're subscribing to events 42 err = c.Start() 43 if err != nil { 44 // handle error 45 } 46 defer c.Stop() 47 48 res, err := c.Status() 49 if err != nil { 50 // handle error 51 } 52 53 // handle result 54 */ 55 type HTTP struct { 56 remote string 57 rpc *jsonrpcclient.Client 58 59 *baseRPCClient 60 *wsEvents 61 } 62 63 // BatchHTTP provides the same interface as `HTTP`, but allows for batching of 64 // requests (as per https://www.jsonrpc.org/specification#batch). Do not 65 // instantiate directly - rather use the HTTP.NewBatch() method to create an 66 // instance of this struct. 67 // 68 // Batching of HTTP requests is thread-safe in the sense that multiple 69 // goroutines can each create their own batches and send them using the same 70 // HTTP client. Multiple goroutines could also enqueue transactions in a single 71 // batch, but ordering of transactions in the batch cannot be guaranteed in such 72 // an example. 73 type BatchHTTP struct { 74 rpcBatch *jsonrpcclient.RequestBatch 75 *baseRPCClient 76 } 77 78 // rpcClient is an internal interface to which our RPC clients (batch and 79 // non-batch) must conform. Acts as an additional code-level sanity check to 80 // make sure the implementations stay coherent. 81 type rpcClient interface { 82 rpcclient.ABCIClient 83 rpcclient.HistoryClient 84 rpcclient.NetworkClient 85 rpcclient.SignClient 86 rpcclient.StatusClient 87 } 88 89 // baseRPCClient implements the basic RPC method logic without the actual 90 // underlying RPC call functionality, which is provided by `caller`. 91 type baseRPCClient struct { 92 caller jsonrpcclient.Caller 93 } 94 95 var _ rpcClient = (*HTTP)(nil) 96 var _ rpcClient = (*BatchHTTP)(nil) 97 var _ rpcClient = (*baseRPCClient)(nil) 98 99 //----------------------------------------------------------------------------- 100 // HTTP 101 102 // New takes a remote endpoint in the form <protocol>://<host>:<port>. An error 103 // is returned on invalid remote. 104 func New(remote string) (*HTTP, error) { 105 c, err := jsonrpcclient.DefaultHTTPClient(remote) 106 if err != nil { 107 return nil, err 108 } 109 return NewWithClient(remote, c) 110 } 111 112 // NewWithTimeout does the same thing as New, except you can set a Timeout for 113 // http.Client. A Timeout of zero means no timeout. 114 func NewWithTimeout(remote string, t time.Duration) (*HTTP, error) { 115 c, err := jsonrpcclient.DefaultHTTPClient(remote) 116 if err != nil { 117 return nil, err 118 } 119 c.Timeout = t 120 return NewWithClient(remote, c) 121 } 122 123 // NewWithClient allows you to set a custom http client. An error is returned 124 // on invalid remote. The function panics when client is nil. 125 func NewWithClient(remote string, c *http.Client) (*HTTP, error) { 126 if c == nil { 127 panic("nil http.Client") 128 } 129 return NewWithClientAndWSOptions(remote, c, DefaultWSOptions()) 130 } 131 132 // NewWithClientAndWSOptions allows you to set a custom http client and 133 // WebSocket options. An error is returned on invalid remote. The function 134 // panics when client is nil. 135 func NewWithClientAndWSOptions(remote string, c *http.Client, wso WSOptions) (*HTTP, error) { 136 if c == nil { 137 panic("nil http.Client") 138 } 139 rpc, err := jsonrpcclient.NewWithHTTPClient(remote, c) 140 if err != nil { 141 return nil, err 142 } 143 144 wsEvents, err := newWsEvents(remote, wso) 145 if err != nil { 146 return nil, err 147 } 148 149 httpClient := &HTTP{ 150 rpc: rpc, 151 remote: remote, 152 baseRPCClient: &baseRPCClient{caller: rpc}, 153 wsEvents: wsEvents, 154 } 155 156 return httpClient, nil 157 } 158 159 var _ rpcclient.Client = (*HTTP)(nil) 160 161 // SetLogger sets a logger. 162 func (c *HTTP) SetLogger(l log.Logger) { 163 c.wsEvents.SetLogger(l) 164 } 165 166 // Remote returns the remote network address in a string form. 167 func (c *HTTP) Remote() string { 168 return c.remote 169 } 170 171 // NewBatch creates a new batch client for this HTTP client. 172 func (c *HTTP) NewBatch() *BatchHTTP { 173 rpcBatch := c.rpc.NewRequestBatch() 174 return &BatchHTTP{ 175 rpcBatch: rpcBatch, 176 baseRPCClient: &baseRPCClient{ 177 caller: rpcBatch, 178 }, 179 } 180 } 181 182 //----------------------------------------------------------------------------- 183 // BatchHTTP 184 185 // Send is a convenience function for an HTTP batch that will trigger the 186 // compilation of the batched requests and send them off using the client as a 187 // single request. On success, this returns a list of the deserialized results 188 // from each request in the sent batch. 189 func (b *BatchHTTP) Send(ctx context.Context) ([]interface{}, error) { 190 return b.rpcBatch.Send(ctx) 191 } 192 193 // Clear will empty out this batch of requests and return the number of requests 194 // that were cleared out. 195 func (b *BatchHTTP) Clear() int { 196 return b.rpcBatch.Clear() 197 } 198 199 // Count returns the number of enqueued requests waiting to be sent. 200 func (b *BatchHTTP) Count() int { 201 return b.rpcBatch.Count() 202 } 203 204 //----------------------------------------------------------------------------- 205 // baseRPCClient 206 207 func (c *baseRPCClient) Status(ctx context.Context) (*ctypes.ResultStatus, error) { 208 result := new(ctypes.ResultStatus) 209 _, err := c.caller.Call(ctx, "status", map[string]interface{}{}, result) 210 if err != nil { 211 return nil, err 212 } 213 214 return result, nil 215 } 216 217 func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) { 218 result := new(ctypes.ResultABCIInfo) 219 _, err := c.caller.Call(ctx, "abci_info", map[string]interface{}{}, result) 220 if err != nil { 221 return nil, err 222 } 223 224 return result, nil 225 } 226 227 func (c *baseRPCClient) ABCIQuery( 228 ctx context.Context, 229 path string, 230 data bytes.HexBytes, 231 ) (*ctypes.ResultABCIQuery, error) { 232 return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.DefaultABCIQueryOptions) 233 } 234 235 func (c *baseRPCClient) ABCIQueryWithOptions( 236 ctx context.Context, 237 path string, 238 data bytes.HexBytes, 239 opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) { 240 result := new(ctypes.ResultABCIQuery) 241 _, err := c.caller.Call(ctx, "abci_query", 242 map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove}, 243 result) 244 if err != nil { 245 return nil, err 246 } 247 248 return result, nil 249 } 250 251 func (c *baseRPCClient) BroadcastTxCommit( 252 ctx context.Context, 253 tx types.Tx, 254 ) (*ctypes.ResultBroadcastTxCommit, error) { 255 result := new(ctypes.ResultBroadcastTxCommit) 256 _, err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]interface{}{"tx": tx}, result) 257 if err != nil { 258 return nil, err 259 } 260 return result, nil 261 } 262 263 func (c *baseRPCClient) BroadcastTxAsync( 264 ctx context.Context, 265 tx types.Tx, 266 ) (*ctypes.ResultBroadcastTx, error) { 267 return c.broadcastTX(ctx, "broadcast_tx_async", tx) 268 } 269 270 func (c *baseRPCClient) BroadcastTxSync( 271 ctx context.Context, 272 tx types.Tx, 273 ) (*ctypes.ResultBroadcastTx, error) { 274 return c.broadcastTX(ctx, "broadcast_tx_sync", tx) 275 } 276 277 func (c *baseRPCClient) broadcastTX( 278 ctx context.Context, 279 route string, 280 tx types.Tx, 281 ) (*ctypes.ResultBroadcastTx, error) { 282 result := new(ctypes.ResultBroadcastTx) 283 _, err := c.caller.Call(ctx, route, map[string]interface{}{"tx": tx}, result) 284 if err != nil { 285 return nil, err 286 } 287 return result, nil 288 } 289 290 func (c *baseRPCClient) UnconfirmedTxs( 291 ctx context.Context, 292 limit *int, 293 ) (*ctypes.ResultUnconfirmedTxs, error) { 294 result := new(ctypes.ResultUnconfirmedTxs) 295 params := make(map[string]interface{}) 296 if limit != nil { 297 params["limit"] = limit 298 } 299 _, err := c.caller.Call(ctx, "unconfirmed_txs", params, result) 300 if err != nil { 301 return nil, err 302 } 303 return result, nil 304 } 305 306 func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) { 307 result := new(ctypes.ResultUnconfirmedTxs) 308 _, err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]interface{}{}, result) 309 if err != nil { 310 return nil, err 311 } 312 return result, nil 313 } 314 315 func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) { 316 result := new(ctypes.ResultCheckTx) 317 _, err := c.caller.Call(ctx, "check_tx", map[string]interface{}{"tx": tx}, result) 318 if err != nil { 319 return nil, err 320 } 321 return result, nil 322 } 323 324 func (c *baseRPCClient) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) { 325 result := new(ctypes.ResultNetInfo) 326 _, err := c.caller.Call(ctx, "net_info", map[string]interface{}{}, result) 327 if err != nil { 328 return nil, err 329 } 330 return result, nil 331 } 332 333 func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) { 334 result := new(ctypes.ResultDumpConsensusState) 335 _, err := c.caller.Call(ctx, "dump_consensus_state", map[string]interface{}{}, result) 336 if err != nil { 337 return nil, err 338 } 339 return result, nil 340 } 341 342 func (c *baseRPCClient) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) { 343 result := new(ctypes.ResultConsensusState) 344 _, err := c.caller.Call(ctx, "consensus_state", map[string]interface{}{}, result) 345 if err != nil { 346 return nil, err 347 } 348 return result, nil 349 } 350 351 func (c *baseRPCClient) ConsensusParams( 352 ctx context.Context, 353 height *int64, 354 ) (*ctypes.ResultConsensusParams, error) { 355 result := new(ctypes.ResultConsensusParams) 356 params := make(map[string]interface{}) 357 if height != nil { 358 params["height"] = height 359 } 360 _, err := c.caller.Call(ctx, "consensus_params", params, result) 361 if err != nil { 362 return nil, err 363 } 364 return result, nil 365 } 366 367 func (c *baseRPCClient) Health(ctx context.Context) (*ctypes.ResultHealth, error) { 368 result := new(ctypes.ResultHealth) 369 _, err := c.caller.Call(ctx, "health", map[string]interface{}{}, result) 370 if err != nil { 371 return nil, err 372 } 373 return result, nil 374 } 375 376 func (c *baseRPCClient) BlockchainInfo( 377 ctx context.Context, 378 minHeight, 379 maxHeight int64, 380 ) (*ctypes.ResultBlockchainInfo, error) { 381 result := new(ctypes.ResultBlockchainInfo) 382 _, err := c.caller.Call(ctx, "blockchain", 383 map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight}, 384 result) 385 if err != nil { 386 return nil, err 387 } 388 return result, nil 389 } 390 391 func (c *baseRPCClient) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) { 392 result := new(ctypes.ResultGenesis) 393 _, err := c.caller.Call(ctx, "genesis", map[string]interface{}{}, result) 394 if err != nil { 395 return nil, err 396 } 397 return result, nil 398 } 399 400 func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*ctypes.ResultGenesisChunk, error) { 401 result := new(ctypes.ResultGenesisChunk) 402 _, err := c.caller.Call(ctx, "genesis_chunked", map[string]interface{}{"chunk": id}, result) 403 if err != nil { 404 return nil, err 405 } 406 return result, nil 407 } 408 409 func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) { 410 result := new(ctypes.ResultBlock) 411 params := make(map[string]interface{}) 412 if height != nil { 413 params["height"] = height 414 } 415 _, err := c.caller.Call(ctx, "block", params, result) 416 if err != nil { 417 return nil, err 418 } 419 return result, nil 420 } 421 422 func (c *baseRPCClient) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) { 423 result := new(ctypes.ResultBlock) 424 params := map[string]interface{}{ 425 "hash": hash, 426 } 427 _, err := c.caller.Call(ctx, "block_by_hash", params, result) 428 if err != nil { 429 return nil, err 430 } 431 return result, nil 432 } 433 434 func (c *baseRPCClient) BlockResults( 435 ctx context.Context, 436 height *int64, 437 ) (*ctypes.ResultBlockResults, error) { 438 result := new(ctypes.ResultBlockResults) 439 params := make(map[string]interface{}) 440 if height != nil { 441 params["height"] = height 442 } 443 _, err := c.caller.Call(ctx, "block_results", params, result) 444 if err != nil { 445 return nil, err 446 } 447 return result, nil 448 } 449 450 func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) { 451 result := new(ctypes.ResultCommit) 452 params := make(map[string]interface{}) 453 if height != nil { 454 params["height"] = height 455 } 456 _, err := c.caller.Call(ctx, "commit", params, result) 457 if err != nil { 458 return nil, err 459 } 460 return result, nil 461 } 462 463 func (c *baseRPCClient) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) { 464 result := new(ctypes.ResultTx) 465 params := map[string]interface{}{ 466 "hash": hash, 467 "prove": prove, 468 } 469 _, err := c.caller.Call(ctx, "tx", params, result) 470 if err != nil { 471 return nil, err 472 } 473 return result, nil 474 } 475 476 func (c *baseRPCClient) TxSearch( 477 ctx context.Context, 478 query string, 479 prove bool, 480 page, 481 perPage *int, 482 orderBy string, 483 ) (*ctypes.ResultTxSearch, error) { 484 485 result := new(ctypes.ResultTxSearch) 486 params := map[string]interface{}{ 487 "query": query, 488 "prove": prove, 489 "order_by": orderBy, 490 } 491 492 if page != nil { 493 params["page"] = page 494 } 495 if perPage != nil { 496 params["per_page"] = perPage 497 } 498 499 _, err := c.caller.Call(ctx, "tx_search", params, result) 500 if err != nil { 501 return nil, err 502 } 503 504 return result, nil 505 } 506 507 func (c *baseRPCClient) BlockSearch( 508 ctx context.Context, 509 query string, 510 page, perPage *int, 511 orderBy string, 512 ) (*ctypes.ResultBlockSearch, error) { 513 514 result := new(ctypes.ResultBlockSearch) 515 params := map[string]interface{}{ 516 "query": query, 517 "order_by": orderBy, 518 } 519 520 if page != nil { 521 params["page"] = page 522 } 523 if perPage != nil { 524 params["per_page"] = perPage 525 } 526 527 _, err := c.caller.Call(ctx, "block_search", params, result) 528 if err != nil { 529 return nil, err 530 } 531 532 return result, nil 533 } 534 535 func (c *baseRPCClient) Validators( 536 ctx context.Context, 537 height *int64, 538 page, 539 perPage *int, 540 ) (*ctypes.ResultValidators, error) { 541 result := new(ctypes.ResultValidators) 542 params := make(map[string]interface{}) 543 if page != nil { 544 params["page"] = page 545 } 546 if perPage != nil { 547 params["per_page"] = perPage 548 } 549 if height != nil { 550 params["height"] = height 551 } 552 _, err := c.caller.Call(ctx, "validators", params, result) 553 if err != nil { 554 return nil, err 555 } 556 return result, nil 557 } 558 559 func (c *baseRPCClient) BroadcastEvidence( 560 ctx context.Context, 561 ev types.Evidence, 562 ) (*ctypes.ResultBroadcastEvidence, error) { 563 result := new(ctypes.ResultBroadcastEvidence) 564 _, err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result) 565 if err != nil { 566 return nil, err 567 } 568 return result, nil 569 }