github.com/fiagdao/tendermint@v0.32.11-0.20220824195748-2087fcc480c1/lite/proxy/proxy.go (about)

     1  package proxy
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  
     7  	amino "github.com/tendermint/go-amino"
     8  
     9  	"github.com/tendermint/tendermint/libs/bytes"
    10  	"github.com/tendermint/tendermint/libs/log"
    11  	"github.com/tendermint/tendermint/rpc/client"
    12  	rpcclient "github.com/tendermint/tendermint/rpc/client"
    13  	ctypes "github.com/tendermint/tendermint/rpc/core/types"
    14  	rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
    15  	rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
    16  	"github.com/tendermint/tendermint/types"
    17  )
    18  
    19  const (
    20  	wsEndpoint = "/websocket"
    21  )
    22  
    23  // StartProxy will start the websocket manager on the client,
    24  // set up the rpc routes to proxy via the given client,
    25  // and start up an http/rpc server on the location given by bind (eg. :1234)
    26  // NOTE: This function blocks - you may want to call it in a go-routine.
    27  func StartProxy(c rpcclient.Client, listenAddr string, logger log.Logger, maxOpenConnections int) error {
    28  	err := c.Start()
    29  	if err != nil {
    30  		return err
    31  	}
    32  
    33  	cdc := amino.NewCodec()
    34  	ctypes.RegisterAmino(cdc)
    35  	r := RPCRoutes(c)
    36  
    37  	// build the handler...
    38  	mux := http.NewServeMux()
    39  	rpcserver.RegisterRPCFuncs(mux, r, cdc, logger)
    40  
    41  	unsubscribeFromAllEvents := func(remoteAddr string) {
    42  		if err := c.UnsubscribeAll(context.Background(), remoteAddr); err != nil {
    43  			logger.Error("Failed to unsubscribe from events", "err", err)
    44  		}
    45  	}
    46  	wm := rpcserver.NewWebsocketManager(r, cdc, rpcserver.OnDisconnect(unsubscribeFromAllEvents))
    47  	wm.SetLogger(logger)
    48  	// core.SetLogger(logger)
    49  	mux.HandleFunc(wsEndpoint, wm.WebsocketHandler)
    50  
    51  	config := rpcserver.DefaultConfig()
    52  	config.MaxOpenConnections = maxOpenConnections
    53  	l, err := rpcserver.Listen(listenAddr, config)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	return rpcserver.Serve(l, mux, logger, config)
    58  }
    59  
    60  // RPCRoutes just routes everything to the given client, as if it were
    61  // a tendermint fullnode.
    62  //
    63  // if we want security, the client must implement it as a secure client
    64  func RPCRoutes(c rpcclient.Client) map[string]*rpcserver.RPCFunc {
    65  	return map[string]*rpcserver.RPCFunc{
    66  		// Subscribe/unsubscribe are reserved for websocket events.
    67  		"subscribe":       rpcserver.NewWSRPCFunc(c.(Wrapper).SubscribeWS, "query"),
    68  		"unsubscribe":     rpcserver.NewWSRPCFunc(c.(Wrapper).UnsubscribeWS, "query"),
    69  		"unsubscribe_all": rpcserver.NewWSRPCFunc(c.(Wrapper).UnsubscribeAllWS, ""),
    70  
    71  		// info API
    72  		"status":                   rpcserver.NewRPCFunc(makeStatusFunc(c), ""),
    73  		"consensus_reactor_status": rpcserver.NewRPCFunc(makeConsensusReactorStatusFunc(c), ""),
    74  		"blockchain":               rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight"),
    75  		"genesis":                  rpcserver.NewRPCFunc(makeGenesisFunc(c), ""),
    76  		"block":                    rpcserver.NewRPCFunc(makeBlockFunc(c), "height"),
    77  		"commit":                   rpcserver.NewRPCFunc(makeCommitFunc(c), "height"),
    78  		"tx":                       rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove"),
    79  		"validators":               rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height"),
    80  
    81  		// broadcast API
    82  		"broadcast_tx_commit": rpcserver.NewRPCFunc(makeBroadcastTxCommitFunc(c), "tx"),
    83  		"broadcast_tx_sync":   rpcserver.NewRPCFunc(makeBroadcastTxSyncFunc(c), "tx"),
    84  		"broadcast_tx_async":  rpcserver.NewRPCFunc(makeBroadcastTxAsyncFunc(c), "tx"),
    85  
    86  		// abci API
    87  		"abci_query": rpcserver.NewRPCFunc(makeABCIQueryFunc(c), "path,data"),
    88  		"abci_info":  rpcserver.NewRPCFunc(makeABCIInfoFunc(c), ""),
    89  	}
    90  }
    91  
    92  func makeStatusFunc(c client.StatusClient) func(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
    93  	return func(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
    94  		return c.Status()
    95  	}
    96  }
    97  
    98  func makeConsensusReactorStatusFunc(c client.StatusClient) func(ctx *rpctypes.Context) (*ctypes.ResultConsensusReactorStatus, error) {
    99  	return func(ctx *rpctypes.Context) (*ctypes.ResultConsensusReactorStatus, error) {
   100  		return c.ConsensusReactorStatus()
   101  	}
   102  }
   103  
   104  func makeBlockchainInfoFunc(c rpcclient.Client) func(
   105  	ctx *rpctypes.Context,
   106  	minHeight,
   107  	maxHeight int64,
   108  ) (*ctypes.ResultBlockchainInfo, error) {
   109  	return func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
   110  		return c.BlockchainInfo(minHeight, maxHeight)
   111  	}
   112  }
   113  
   114  func makeGenesisFunc(c rpcclient.Client) func(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
   115  	return func(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
   116  		return c.Genesis()
   117  	}
   118  }
   119  
   120  func makeBlockFunc(c rpcclient.Client) func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBlock, error) {
   121  	return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBlock, error) {
   122  		return c.Block(height)
   123  	}
   124  }
   125  
   126  func makeCommitFunc(c rpcclient.Client) func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultCommit, error) {
   127  	return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultCommit, error) {
   128  		return c.Commit(height)
   129  	}
   130  }
   131  
   132  func makeTxFunc(c rpcclient.Client) func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
   133  	return func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
   134  		return c.Tx(hash, prove)
   135  	}
   136  }
   137  
   138  func makeValidatorsFunc(c rpcclient.Client) func(
   139  	ctx *rpctypes.Context,
   140  	height *int64,
   141  ) (*ctypes.ResultValidators, error) {
   142  	return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultValidators, error) {
   143  		return c.Validators(height, 0, 0)
   144  	}
   145  }
   146  
   147  func makeBroadcastTxCommitFunc(c rpcclient.Client) func(
   148  	ctx *rpctypes.Context,
   149  	tx types.Tx,
   150  ) (*ctypes.ResultBroadcastTxCommit, error) {
   151  	return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
   152  		return c.BroadcastTxCommit(tx)
   153  	}
   154  }
   155  
   156  func makeBroadcastTxSyncFunc(c rpcclient.Client) func(
   157  	ctx *rpctypes.Context,
   158  	tx types.Tx,
   159  ) (*ctypes.ResultBroadcastTx, error) {
   160  	return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   161  		return c.BroadcastTxSync(tx)
   162  	}
   163  }
   164  
   165  func makeBroadcastTxAsyncFunc(c rpcclient.Client) func(
   166  	ctx *rpctypes.Context,
   167  	tx types.Tx,
   168  ) (*ctypes.ResultBroadcastTx, error) {
   169  	return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   170  		return c.BroadcastTxAsync(tx)
   171  	}
   172  }
   173  
   174  func makeABCIQueryFunc(c rpcclient.Client) func(
   175  	ctx *rpctypes.Context,
   176  	path string,
   177  	data bytes.HexBytes,
   178  ) (*ctypes.ResultABCIQuery, error) {
   179  	return func(ctx *rpctypes.Context, path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
   180  		return c.ABCIQuery(path, data)
   181  	}
   182  }
   183  
   184  func makeABCIInfoFunc(c rpcclient.Client) func(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) {
   185  	return func(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) {
   186  		return c.ABCIInfo()
   187  	}
   188  }