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  }