github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/cmd/tendermint/commands/lite.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 "net/http" 6 "os" 7 "strings" 8 "time" 9 10 "github.com/spf13/cobra" 11 12 dbm "github.com/tendermint/tm-db" 13 14 "github.com/tendermint/tendermint/libs/log" 15 tmos "github.com/tendermint/tendermint/libs/os" 16 "github.com/tendermint/tendermint/light" 17 lproxy "github.com/tendermint/tendermint/light/proxy" 18 lrpc "github.com/tendermint/tendermint/light/rpc" 19 dbs "github.com/tendermint/tendermint/light/store/db" 20 rpchttp "github.com/tendermint/tendermint/rpc/client/http" 21 rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" 22 ) 23 24 // LightCmd represents the base command when called without any subcommands 25 var LightCmd = &cobra.Command{ 26 Use: "light [chainID]", 27 Short: "Run a light client proxy server, verifying Tendermint rpc", 28 Long: `Run a light client proxy server, verifying Tendermint rpc. 29 30 All calls that can be tracked back to a block header by a proof 31 will be verified before passing them back to the caller. Other than 32 that, it will present the same interface as a full Tendermint node. 33 34 Example: 35 36 start a fresh instance: 37 38 light cosmoshub-3 -p http://52.57.29.196:26657 -w http://public-seed-node.cosmoshub.certus.one:26657 39 --height 962118 --hash 28B97BE9F6DE51AC69F70E0B7BFD7E5C9CD1A595B7DC31AFF27C50D4948020CD 40 41 continue from latest state: 42 43 light cosmoshub-3 -p http://52.57.29.196:26657 -w http://public-seed-node.cosmoshub.certus.one:26657 44 `, 45 RunE: runProxy, 46 Args: cobra.ExactArgs(1), 47 Example: `light cosmoshub-3 -p http://52.57.29.196:26657 -w http://public-seed-node.cosmoshub.certus.one:26657 48 --height 962118 --hash 28B97BE9F6DE51AC69F70E0B7BFD7E5C9CD1A595B7DC31AFF27C50D4948020CD`, 49 } 50 51 var ( 52 listenAddr string 53 primaryAddr string 54 witnessAddrsJoined string 55 chainID string 56 home string 57 maxOpenConnections int 58 59 trustingPeriod time.Duration 60 trustedHeight int64 61 trustedHash []byte 62 63 verbose bool 64 ) 65 66 func init() { 67 LightCmd.Flags().StringVar(&listenAddr, "laddr", "tcp://localhost:8888", 68 "Serve the proxy on the given address") 69 LightCmd.Flags().StringVarP(&primaryAddr, "primary", "p", "", 70 "Connect to a Tendermint node at this address") 71 LightCmd.Flags().StringVarP(&witnessAddrsJoined, "witnesses", "w", "", 72 "Tendermint nodes to cross-check the primary node, comma-separated") 73 LightCmd.Flags().StringVar(&home, "home-dir", ".tendermint-light", "Specify the home directory") 74 LightCmd.Flags().IntVar( 75 &maxOpenConnections, 76 "max-open-connections", 77 900, 78 "Maximum number of simultaneous connections (including WebSocket).") 79 LightCmd.Flags().DurationVar(&trustingPeriod, "trusting-period", 168*time.Hour, 80 "Trusting period. Should be significantly less than the unbonding period") 81 LightCmd.Flags().Int64Var(&trustedHeight, "height", 1, "Trusted header's height") 82 LightCmd.Flags().BytesHexVar(&trustedHash, "hash", []byte{}, "Trusted header's hash") 83 LightCmd.Flags().BoolVar(&verbose, "verbose", false, "Verbose output") 84 } 85 86 func runProxy(cmd *cobra.Command, args []string) error { 87 // Initialise logger. 88 logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) 89 var option log.Option 90 if verbose { 91 option, _ = log.AllowLevel("debug") 92 } else { 93 option, _ = log.AllowLevel("info") 94 } 95 logger = log.NewFilter(logger, option) 96 97 chainID = args[0] 98 logger.Info("Creating client...", "chainID", chainID) 99 100 witnessesAddrs := strings.Split(witnessAddrsJoined, ",") 101 102 db, err := dbm.NewGoLevelDB("light-client-db", home) 103 if err != nil { 104 return fmt.Errorf("can't create a db: %w", err) 105 } 106 107 var c *light.Client 108 if trustedHeight > 0 && len(trustedHash) > 0 { // fresh installation 109 c, err = light.NewHTTPClient( 110 chainID, 111 light.TrustOptions{ 112 Period: trustingPeriod, 113 Height: trustedHeight, 114 Hash: trustedHash, 115 }, 116 primaryAddr, 117 witnessesAddrs, 118 dbs.New(db, chainID), 119 light.Logger(logger), 120 ) 121 } else { // continue from latest state 122 c, err = light.NewHTTPClientFromTrustedStore( 123 chainID, 124 trustingPeriod, 125 primaryAddr, 126 witnessesAddrs, 127 dbs.New(db, chainID), 128 light.Logger(logger), 129 ) 130 } 131 if err != nil { 132 return err 133 } 134 135 rpcClient, err := rpchttp.New(primaryAddr, "/websocket") 136 if err != nil { 137 return fmt.Errorf("http client for %s: %w", primaryAddr, err) 138 } 139 140 cfg := rpcserver.DefaultConfig() 141 cfg.MaxBodyBytes = config.RPC.MaxBodyBytes 142 cfg.MaxHeaderBytes = config.RPC.MaxHeaderBytes 143 cfg.MaxOpenConnections = maxOpenConnections 144 // If necessary adjust global WriteTimeout to ensure it's greater than 145 // TimeoutBroadcastTxCommit. 146 // See https://github.com/tendermint/tendermint/issues/3435 147 if cfg.WriteTimeout <= config.RPC.TimeoutBroadcastTxCommit { 148 cfg.WriteTimeout = config.RPC.TimeoutBroadcastTxCommit + 1*time.Second 149 } 150 151 p := lproxy.Proxy{ 152 Addr: listenAddr, 153 Config: cfg, 154 Client: lrpc.NewClient(rpcClient, c), 155 Logger: logger, 156 } 157 // Stop upon receiving SIGTERM or CTRL-C. 158 tmos.TrapSignal(logger, func() { 159 p.Listener.Close() 160 }) 161 162 logger.Info("Starting proxy...", "laddr", listenAddr) 163 if err := p.ListenAndServe(); err != http.ErrServerClosed { 164 // Error starting or closing listener: 165 logger.Error("proxy ListenAndServe", "err", err) 166 } 167 168 return nil 169 }