github.com/okex/exchain@v1.8.0/libs/tendermint/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/okex/exchain/libs/tendermint/libs/bytes"
    10  	"github.com/okex/exchain/libs/tendermint/libs/log"
    11  	"github.com/okex/exchain/libs/tendermint/rpc/client"
    12  	rpcclient "github.com/okex/exchain/libs/tendermint/rpc/client"
    13  	ctypes "github.com/okex/exchain/libs/tendermint/rpc/core/types"
    14  	rpcserver "github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/server"
    15  	rpctypes "github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/types"
    16  	"github.com/okex/exchain/libs/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  		"blockchain": rpcserver.NewRPCFunc(makeBlockchainInfoFunc(c), "minHeight,maxHeight"),
    74  		"genesis":    rpcserver.NewRPCFunc(makeGenesisFunc(c), ""),
    75  		"block":      rpcserver.NewRPCFunc(makeBlockFunc(c), "height"),
    76  		"commit":     rpcserver.NewRPCFunc(makeCommitFunc(c), "height"),
    77  		"tx":         rpcserver.NewRPCFunc(makeTxFunc(c), "hash,prove"),
    78  		"validators": rpcserver.NewRPCFunc(makeValidatorsFunc(c), "height"),
    79  
    80  		// broadcast API
    81  		"broadcast_tx_commit": rpcserver.NewRPCFunc(makeBroadcastTxCommitFunc(c), "tx"),
    82  		"broadcast_tx_sync":   rpcserver.NewRPCFunc(makeBroadcastTxSyncFunc(c), "tx"),
    83  		"broadcast_tx_async":  rpcserver.NewRPCFunc(makeBroadcastTxAsyncFunc(c), "tx"),
    84  
    85  		// abci API
    86  		"abci_query": rpcserver.NewRPCFunc(makeABCIQueryFunc(c), "path,data"),
    87  		"abci_info":  rpcserver.NewRPCFunc(makeABCIInfoFunc(c), ""),
    88  	}
    89  }
    90  
    91  func makeStatusFunc(c client.StatusClient) func(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
    92  	return func(ctx *rpctypes.Context) (*ctypes.ResultStatus, error) {
    93  		return c.Status()
    94  	}
    95  }
    96  
    97  func makeBlockchainInfoFunc(c rpcclient.Client) func(
    98  	ctx *rpctypes.Context,
    99  	minHeight,
   100  	maxHeight int64,
   101  ) (*ctypes.ResultBlockchainInfo, error) {
   102  	return func(ctx *rpctypes.Context, minHeight, maxHeight int64) (*ctypes.ResultBlockchainInfo, error) {
   103  		return c.BlockchainInfo(minHeight, maxHeight)
   104  	}
   105  }
   106  
   107  func makeGenesisFunc(c rpcclient.Client) func(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
   108  	return func(ctx *rpctypes.Context) (*ctypes.ResultGenesis, error) {
   109  		return c.Genesis()
   110  	}
   111  }
   112  
   113  func makeBlockFunc(c rpcclient.Client) func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBlock, error) {
   114  	return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultBlock, error) {
   115  		return c.Block(height)
   116  	}
   117  }
   118  
   119  func makeCommitFunc(c rpcclient.Client) func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultCommit, error) {
   120  	return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultCommit, error) {
   121  		return c.Commit(height)
   122  	}
   123  }
   124  
   125  func makeTxFunc(c rpcclient.Client) func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
   126  	return func(ctx *rpctypes.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
   127  		return c.Tx(hash, prove)
   128  	}
   129  }
   130  
   131  func makeValidatorsFunc(c rpcclient.Client) func(
   132  	ctx *rpctypes.Context,
   133  	height *int64,
   134  ) (*ctypes.ResultValidators, error) {
   135  	return func(ctx *rpctypes.Context, height *int64) (*ctypes.ResultValidators, error) {
   136  		return c.Validators(height, 0, 0)
   137  	}
   138  }
   139  
   140  func makeBroadcastTxCommitFunc(c rpcclient.Client) func(
   141  	ctx *rpctypes.Context,
   142  	tx types.Tx,
   143  ) (*ctypes.ResultBroadcastTxCommit, error) {
   144  	return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTxCommit, error) {
   145  		return c.BroadcastTxCommit(tx)
   146  	}
   147  }
   148  
   149  func makeBroadcastTxSyncFunc(c rpcclient.Client) func(
   150  	ctx *rpctypes.Context,
   151  	tx types.Tx,
   152  ) (*ctypes.ResultBroadcastTx, error) {
   153  	return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   154  		return c.BroadcastTxSync(tx)
   155  	}
   156  }
   157  
   158  func makeBroadcastTxAsyncFunc(c rpcclient.Client) func(
   159  	ctx *rpctypes.Context,
   160  	tx types.Tx,
   161  ) (*ctypes.ResultBroadcastTx, error) {
   162  	return func(ctx *rpctypes.Context, tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
   163  		return c.BroadcastTxAsync(tx)
   164  	}
   165  }
   166  
   167  func makeABCIQueryFunc(c rpcclient.Client) func(
   168  	ctx *rpctypes.Context,
   169  	path string,
   170  	data bytes.HexBytes,
   171  ) (*ctypes.ResultABCIQuery, error) {
   172  	return func(ctx *rpctypes.Context, path string, data bytes.HexBytes) (*ctypes.ResultABCIQuery, error) {
   173  		return c.ABCIQuery(path, data)
   174  	}
   175  }
   176  
   177  func makeABCIInfoFunc(c rpcclient.Client) func(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) {
   178  	return func(ctx *rpctypes.Context) (*ctypes.ResultABCIInfo, error) {
   179  		return c.ABCIInfo()
   180  	}
   181  }