github.com/Oyster-zx/tendermint@v0.34.24-fork/test/e2e/node/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "os" 9 "path/filepath" 10 "strconv" 11 "strings" 12 "time" 13 14 "github.com/spf13/viper" 15 16 "github.com/tendermint/tendermint/abci/server" 17 "github.com/tendermint/tendermint/config" 18 "github.com/tendermint/tendermint/crypto/ed25519" 19 tmflags "github.com/tendermint/tendermint/libs/cli/flags" 20 "github.com/tendermint/tendermint/libs/log" 21 tmnet "github.com/tendermint/tendermint/libs/net" 22 "github.com/tendermint/tendermint/light" 23 lproxy "github.com/tendermint/tendermint/light/proxy" 24 lrpc "github.com/tendermint/tendermint/light/rpc" 25 dbs "github.com/tendermint/tendermint/light/store/db" 26 "github.com/tendermint/tendermint/node" 27 "github.com/tendermint/tendermint/p2p" 28 "github.com/tendermint/tendermint/privval" 29 "github.com/tendermint/tendermint/proxy" 30 rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" 31 "github.com/tendermint/tendermint/test/e2e/app" 32 e2e "github.com/tendermint/tendermint/test/e2e/pkg" 33 mcs "github.com/tendermint/tendermint/test/maverick/consensus" 34 maverick "github.com/tendermint/tendermint/test/maverick/node" 35 ) 36 37 var logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) 38 39 // main is the binary entrypoint. 40 func main() { 41 if len(os.Args) != 2 { 42 fmt.Printf("Usage: %v <configfile>", os.Args[0]) 43 return 44 } 45 configFile := "" 46 if len(os.Args) == 2 { 47 configFile = os.Args[1] 48 } 49 50 if err := run(configFile); err != nil { 51 logger.Error(err.Error()) 52 os.Exit(1) 53 } 54 } 55 56 // run runs the application - basically like main() with error handling. 57 func run(configFile string) error { 58 cfg, err := LoadConfig(configFile) 59 if err != nil { 60 return err 61 } 62 63 // Start remote signer (must start before node if running builtin). 64 if cfg.PrivValServer != "" { 65 if err = startSigner(cfg); err != nil { 66 return err 67 } 68 if cfg.Protocol == "builtin" { 69 time.Sleep(1 * time.Second) 70 } 71 } 72 73 // Start app server. 74 switch cfg.Protocol { 75 case "socket", "grpc": 76 err = startApp(cfg) 77 case "builtin": 78 if len(cfg.Misbehaviors) == 0 { 79 if cfg.Mode == string(e2e.ModeLight) { 80 err = startLightClient(cfg) 81 } else { 82 err = startNode(cfg) 83 } 84 } else { 85 err = startMaverick(cfg) 86 } 87 default: 88 err = fmt.Errorf("invalid protocol %q", cfg.Protocol) 89 } 90 if err != nil { 91 return err 92 } 93 94 // Apparently there's no way to wait for the server, so we just sleep 95 for { 96 time.Sleep(1 * time.Hour) 97 } 98 } 99 100 // startApp starts the application server, listening for connections from Tendermint. 101 func startApp(cfg *Config) error { 102 app, err := app.NewApplication(cfg.App()) 103 if err != nil { 104 return err 105 } 106 server, err := server.NewServer(cfg.Listen, cfg.Protocol, app) 107 if err != nil { 108 return err 109 } 110 err = server.Start() 111 if err != nil { 112 return err 113 } 114 logger.Info("start app", "msg", log.NewLazySprintf("Server listening on %v (%v protocol)", cfg.Listen, cfg.Protocol)) 115 return nil 116 } 117 118 // startNode starts a Tendermint node running the application directly. It assumes the Tendermint 119 // configuration is in $TMHOME/config/tendermint.toml. 120 // 121 // FIXME There is no way to simply load the configuration from a file, so we need to pull in Viper. 122 func startNode(cfg *Config) error { 123 app, err := app.NewApplication(cfg.App()) 124 if err != nil { 125 return err 126 } 127 128 tmcfg, nodeLogger, nodeKey, err := setupNode() 129 if err != nil { 130 return fmt.Errorf("failed to setup config: %w", err) 131 } 132 133 n, err := node.NewNode(tmcfg, 134 privval.LoadOrGenFilePV(tmcfg.PrivValidatorKeyFile(), tmcfg.PrivValidatorStateFile()), 135 nodeKey, 136 proxy.NewLocalClientCreator(app), 137 node.DefaultGenesisDocProviderFunc(tmcfg), 138 node.DefaultDBProvider, 139 node.DefaultMetricsProvider(tmcfg.Instrumentation), 140 nodeLogger, 141 ) 142 if err != nil { 143 return err 144 } 145 return n.Start() 146 } 147 148 func startLightClient(cfg *Config) error { 149 tmcfg, nodeLogger, _, err := setupNode() 150 if err != nil { 151 return err 152 } 153 154 dbContext := &node.DBContext{ID: "light", Config: tmcfg} 155 lightDB, err := node.DefaultDBProvider(dbContext) 156 if err != nil { 157 return err 158 } 159 160 providers := rpcEndpoints(tmcfg.P2P.PersistentPeers) 161 162 c, err := light.NewHTTPClient( 163 context.Background(), 164 cfg.ChainID, 165 light.TrustOptions{ 166 Period: tmcfg.StateSync.TrustPeriod, 167 Height: tmcfg.StateSync.TrustHeight, 168 Hash: tmcfg.StateSync.TrustHashBytes(), 169 }, 170 providers[0], 171 providers[1:], 172 dbs.New(lightDB, "light"), 173 light.Logger(nodeLogger), 174 ) 175 if err != nil { 176 return err 177 } 178 179 rpccfg := rpcserver.DefaultConfig() 180 rpccfg.MaxBodyBytes = tmcfg.RPC.MaxBodyBytes 181 rpccfg.MaxHeaderBytes = tmcfg.RPC.MaxHeaderBytes 182 rpccfg.MaxOpenConnections = tmcfg.RPC.MaxOpenConnections 183 // If necessary adjust global WriteTimeout to ensure it's greater than 184 // TimeoutBroadcastTxCommit. 185 // See https://github.com/tendermint/tendermint/issues/3435 186 if rpccfg.WriteTimeout <= tmcfg.RPC.TimeoutBroadcastTxCommit { 187 rpccfg.WriteTimeout = tmcfg.RPC.TimeoutBroadcastTxCommit + 1*time.Second 188 } 189 190 p, err := lproxy.NewProxy(c, tmcfg.RPC.ListenAddress, providers[0], rpccfg, nodeLogger, 191 lrpc.KeyPathFn(lrpc.DefaultMerkleKeyPathFn())) 192 if err != nil { 193 return err 194 } 195 196 logger.Info("Starting proxy...", "laddr", tmcfg.RPC.ListenAddress) 197 if err := p.ListenAndServe(); err != http.ErrServerClosed { 198 // Error starting or closing listener: 199 logger.Error("proxy ListenAndServe", "err", err) 200 } 201 202 return nil 203 } 204 205 // FIXME: Temporarily disconnected maverick until it is redesigned 206 // startMaverick starts a Maverick node that runs the application directly. It assumes the Tendermint 207 // configuration is in $TMHOME/config/tendermint.toml. 208 func startMaverick(cfg *Config) error { 209 app, err := app.NewApplication(cfg.App()) 210 if err != nil { 211 return err 212 } 213 214 tmcfg, logger, nodeKey, err := setupNode() 215 if err != nil { 216 return fmt.Errorf("failed to setup config: %w", err) 217 } 218 219 misbehaviors := make(map[int64]mcs.Misbehavior, len(cfg.Misbehaviors)) 220 for heightString, misbehaviorString := range cfg.Misbehaviors { 221 height, _ := strconv.ParseInt(heightString, 10, 64) 222 misbehaviors[height] = mcs.MisbehaviorList[misbehaviorString] 223 } 224 225 n, err := maverick.NewNode(tmcfg, 226 maverick.LoadOrGenFilePV(tmcfg.PrivValidatorKeyFile(), tmcfg.PrivValidatorStateFile()), 227 nodeKey, 228 proxy.NewLocalClientCreator(app), 229 maverick.DefaultGenesisDocProviderFunc(tmcfg), 230 maverick.DefaultDBProvider, 231 maverick.DefaultMetricsProvider(tmcfg.Instrumentation), 232 logger, 233 misbehaviors, 234 ) 235 if err != nil { 236 return err 237 } 238 239 return n.Start() 240 } 241 242 // startSigner starts a signer server connecting to the given endpoint. 243 func startSigner(cfg *Config) error { 244 filePV := privval.LoadFilePV(cfg.PrivValKey, cfg.PrivValState) 245 246 protocol, address := tmnet.ProtocolAndAddress(cfg.PrivValServer) 247 var dialFn privval.SocketDialer 248 switch protocol { 249 case "tcp": 250 dialFn = privval.DialTCPFn(address, 3*time.Second, ed25519.GenPrivKey()) 251 case "unix": 252 dialFn = privval.DialUnixFn(address) 253 default: 254 return fmt.Errorf("invalid privval protocol %q", protocol) 255 } 256 257 endpoint := privval.NewSignerDialerEndpoint(logger, dialFn, 258 privval.SignerDialerEndpointRetryWaitInterval(1*time.Second), 259 privval.SignerDialerEndpointConnRetries(100)) 260 err := privval.NewSignerServer(endpoint, cfg.ChainID, filePV).Start() 261 if err != nil { 262 return err 263 } 264 logger.Info("start signer", "msg", log.NewLazySprintf("Remote signer connecting to %v", cfg.PrivValServer)) 265 return nil 266 } 267 268 func setupNode() (*config.Config, log.Logger, *p2p.NodeKey, error) { 269 var tmcfg *config.Config 270 271 home := os.Getenv("TMHOME") 272 if home == "" { 273 return nil, nil, nil, errors.New("TMHOME not set") 274 } 275 276 viper.AddConfigPath(filepath.Join(home, "config")) 277 viper.SetConfigName("config") 278 279 if err := viper.ReadInConfig(); err != nil { 280 return nil, nil, nil, err 281 } 282 283 tmcfg = config.DefaultConfig() 284 285 if err := viper.Unmarshal(tmcfg); err != nil { 286 return nil, nil, nil, err 287 } 288 289 tmcfg.SetRoot(home) 290 291 if err := tmcfg.ValidateBasic(); err != nil { 292 return nil, nil, nil, fmt.Errorf("error in config file: %w", err) 293 } 294 295 if tmcfg.LogFormat == config.LogFormatJSON { 296 logger = log.NewTMJSONLogger(log.NewSyncWriter(os.Stdout)) 297 } 298 299 nodeLogger, err := tmflags.ParseLogLevel(tmcfg.LogLevel, logger, config.DefaultLogLevel) 300 if err != nil { 301 return nil, nil, nil, err 302 } 303 304 nodeLogger = nodeLogger.With("module", "main") 305 306 nodeKey, err := p2p.LoadOrGenNodeKey(tmcfg.NodeKeyFile()) 307 if err != nil { 308 return nil, nil, nil, fmt.Errorf("failed to load or gen node key %s: %w", tmcfg.NodeKeyFile(), err) 309 } 310 311 return tmcfg, nodeLogger, nodeKey, nil 312 } 313 314 // rpcEndpoints takes a list of persistent peers and splits them into a list of rpc endpoints 315 // using 26657 as the port number 316 func rpcEndpoints(peers string) []string { 317 arr := strings.Split(peers, ",") 318 endpoints := make([]string, len(arr)) 319 for i, v := range arr { 320 urlString := strings.SplitAfter(v, "@")[1] 321 hostName := strings.Split(urlString, ":26656")[0] 322 // use RPC port instead 323 port := 26657 324 rpcEndpoint := "http://" + hostName + ":" + fmt.Sprint(port) 325 endpoints[i] = rpcEndpoint 326 } 327 return endpoints 328 }