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 }