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