github.com/turingchain2020/turingchain@v1.1.21/util/cli/turingchain.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build go1.8 6 7 // package cli RunTuringchain函数会加载各个模块,组合成区块链程序 8 //主循环由消息队列驱动。 9 //消息队列本身可插拔,可以支持各种队列 10 //同时共识模式也是可以插拔的。 11 //rpc 服务也是可以插拔的 12 13 package cli 14 15 import ( 16 "flag" 17 "fmt" 18 "net/http" 19 _ "net/http/pprof" // 20 "os" 21 "path/filepath" 22 "runtime" 23 24 "github.com/turingchain2020/turingchain/common/crypto" 25 26 "github.com/turingchain2020/turingchain/p2p" 27 28 "github.com/turingchain2020/turingchain/metrics" 29 30 "time" 31 32 "github.com/turingchain2020/turingchain/blockchain" 33 "github.com/turingchain2020/turingchain/util" 34 35 "github.com/turingchain2020/turingchain/common" 36 "github.com/turingchain2020/turingchain/common/limits" 37 clog "github.com/turingchain2020/turingchain/common/log" 38 log "github.com/turingchain2020/turingchain/common/log/log15" 39 "github.com/turingchain2020/turingchain/common/version" 40 "github.com/turingchain2020/turingchain/consensus" 41 "github.com/turingchain2020/turingchain/executor" 42 "github.com/turingchain2020/turingchain/mempool" 43 "github.com/turingchain2020/turingchain/queue" 44 "github.com/turingchain2020/turingchain/rpc" 45 "github.com/turingchain2020/turingchain/store" 46 "github.com/turingchain2020/turingchain/types" 47 "github.com/turingchain2020/turingchain/wallet" 48 "google.golang.org/grpc/grpclog" 49 ) 50 51 var ( 52 cpuNum = runtime.NumCPU() 53 configPath = flag.String("f", "", "configfile") 54 datadir = flag.String("datadir", "", "data dir of turingchain, include logs and datas") 55 versionCmd = flag.Bool("v", false, "version") 56 fixtime = flag.Bool("fixtime", false, "fix time") 57 waitPid = flag.Bool("waitpid", false, "p2p stuck until seed save info wallet & wallet unlock") 58 rollback = flag.Int64("rollback", 0, "rollback block. WARNNING this command is only for test") 59 save = flag.Bool("save", false, "rollback save temporary block") 60 importFile = flag.String("import", "", "import block file name") 61 exportTitle = flag.String("export", "", "export block title name") 62 fileDir = flag.String("filedir", "", "import/export block file dir,defalut current path") 63 startHeight = flag.Int64("startheight", 0, "export block start height") 64 ) 65 66 //RunTuringchain : run Turingchain 67 func RunTuringchain(name, defCfg string) { 68 flag.Parse() 69 if *versionCmd { 70 fmt.Println(version.GetVersion()) 71 return 72 } 73 if *configPath == "" { 74 if name == "" { 75 *configPath = "turingchain.toml" 76 } else { 77 *configPath = name + ".toml" 78 } 79 } 80 d, err := os.Getwd() 81 if err != nil { 82 panic(err) 83 } 84 log.Info("current dir:", "dir", d) 85 err = os.Chdir(pwd()) 86 if err != nil { 87 panic(err) 88 } 89 d, err = os.Getwd() 90 if err != nil { 91 panic(err) 92 } 93 log.Info("current dir:", "dir", d) 94 err = limits.SetLimits() 95 if err != nil { 96 panic(err) 97 } 98 //set config: turingchaincoin 用 turingchaincoin.toml 这个配置文件 99 turingchainCfg := types.NewTuringchainConfig(types.MergeCfg(types.ReadFile(*configPath), defCfg)) 100 cfg := turingchainCfg.GetModuleConfig() 101 if *datadir != "" { 102 util.ResetDatadir(cfg, *datadir) 103 } 104 if *fixtime { 105 cfg.FixTime = *fixtime 106 } 107 if *waitPid { 108 cfg.P2P.WaitPid = *waitPid 109 } 110 111 if len(cfg.NtpHosts) <= 0 { 112 cfg.NtpHosts = append(cfg.NtpHosts, types.NtpHosts...) 113 } 114 if cfg.FixTime { 115 go fixtimeRoutine(cfg.NtpHosts) 116 } 117 //compare minFee in wallet, mempool, exec 118 //set file log 119 clog.SetFileLog(cfg.Log) 120 //set grpc log 121 f, err := createFile(cfg.P2P.GrpcLogFile) 122 if err != nil { 123 glogv2 := grpclog.NewLoggerV2(os.Stdout, os.Stdout, os.Stdout) 124 grpclog.SetLoggerV2(glogv2) 125 } else { 126 glogv2 := grpclog.NewLoggerV2WithVerbosity(f, f, f, 10) 127 grpclog.SetLoggerV2(glogv2) 128 } 129 //set watching 130 t := time.Tick(10 * time.Second) 131 go func() { 132 for range t { 133 watching() 134 } 135 }() 136 //set pprof 137 go func() { 138 if cfg.Pprof != nil { 139 err := http.ListenAndServe(cfg.Pprof.ListenAddr, nil) 140 if err != nil { 141 log.Info("ListenAndServe", "listen addr", cfg.Pprof.ListenAddr, "err", err) 142 } 143 } else { 144 err := http.ListenAndServe("localhost:6060", nil) 145 if err != nil { 146 log.Info("ListenAndServe", "listen addr localhost:6060 err", err) 147 } 148 } 149 }() 150 //set maxprocs 151 runtime.GOMAXPROCS(cpuNum) 152 //开始区块链模块加载 153 //channel, rabitmq 等 154 crypto.Init(turingchainCfg.GetModuleConfig().Crypto, turingchainCfg.GetSubConfig().Crypto) 155 version.SetLocalDBVersion(cfg.Store.LocalDBVersion) 156 version.SetStoreDBVersion(cfg.Store.StoreDBVersion) 157 version.SetAppVersion(cfg.Version) 158 log.Info(cfg.Title + "-app:" + version.GetAppVersion() + " turingchain:" + version.GetVersion() + " localdb:" + version.GetLocalDBVersion() + " statedb:" + version.GetStoreDBVersion()) 159 log.Info("loading queue") 160 q := queue.New("channel") 161 q.SetConfig(turingchainCfg) 162 163 log.Info("loading mempool module") 164 mem := mempool.New(turingchainCfg) 165 mem.SetQueueClient(q.Client()) 166 167 log.Info("loading execs module") 168 exec := executor.New(turingchainCfg) 169 exec.SetQueueClient(q.Client()) 170 171 log.Info("loading blockchain module") 172 cfg.BlockChain.RollbackBlock = *rollback 173 cfg.BlockChain.RollbackSave = *save 174 chain := blockchain.New(turingchainCfg) 175 chain.SetQueueClient(q.Client()) 176 177 log.Info("loading store module") 178 s := store.New(turingchainCfg) 179 s.SetQueueClient(q.Client()) 180 181 chain.Upgrade() 182 183 log.Info("loading consensus module") 184 cs := consensus.New(turingchainCfg) 185 cs.SetQueueClient(q.Client()) 186 187 //jsonrpc, grpc, channel 三种模式 188 rpcapi := rpc.New(turingchainCfg) 189 rpcapi.SetQueueClient(q.Client()) 190 191 log.Info("loading wallet module") 192 walletm := wallet.New(turingchainCfg) 193 walletm.SetQueueClient(q.Client()) 194 195 chain.Rollbackblock() 196 //导入/导出区块通过title 197 if *importFile != "" { 198 chain.ImportBlockProc(*importFile, *fileDir) 199 } 200 if *exportTitle != "" { 201 chain.ExportBlockProc(*exportTitle, *fileDir, *startHeight) 202 } 203 log.Info("loading p2p module") 204 var network queue.Module 205 if cfg.P2P.Enable { 206 network = p2p.NewP2PMgr(turingchainCfg) 207 } else { 208 network = &util.MockModule{Key: "p2p"} 209 } 210 network.SetQueueClient(q.Client()) 211 212 health := util.NewHealthCheckServer(q.Client()) 213 health.Start(cfg.Health) 214 metrics.StartMetrics(turingchainCfg) 215 defer func() { 216 //close all module,clean some resource 217 log.Info("begin close health module") 218 health.Close() 219 log.Info("begin close blockchain module") 220 chain.Close() 221 log.Info("begin close mempool module") 222 mem.Close() 223 log.Info("begin close P2P module") 224 network.Close() 225 log.Info("begin close execs module") 226 exec.Close() 227 log.Info("begin close store module") 228 s.Close() 229 log.Info("begin close consensus module") 230 cs.Close() 231 log.Info("begin close rpc module") 232 rpcapi.Close() 233 log.Info("begin close wallet module") 234 walletm.Close() 235 log.Info("begin close queue module") 236 q.Close() 237 238 }() 239 q.Start() 240 } 241 242 func createFile(filename string) (*os.File, error) { 243 f, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) 244 if err != nil { 245 return nil, err 246 } 247 return f, nil 248 } 249 250 func watching() { 251 var m runtime.MemStats 252 runtime.ReadMemStats(&m) 253 log.Info("info:", "NumGoroutine:", runtime.NumGoroutine()) 254 log.Info("info:", "Mem:", m.Sys/(1024*1024)) 255 log.Info("info:", "HeapAlloc:", m.HeapAlloc/(1024*1024)) 256 } 257 258 func pwd() string { 259 dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 260 if err != nil { 261 panic(err) 262 } 263 return dir 264 } 265 266 func fixtimeRoutine(hosts []string) { 267 for i := 0; i < len(hosts); i++ { 268 t, err := common.GetNtpTime(hosts[i]) 269 if err == nil { 270 log.Info("time", "host", hosts[i], "now", t) 271 } else { 272 log.Error("time", "err", err) 273 } 274 } 275 t := common.GetRealTimeRetry(hosts, 10) 276 if !t.IsZero() { 277 //update 278 types.SetTimeDelta(int64(time.Until(t))) 279 log.Info("change time", "delta", time.Until(t), "real.now", types.Now()) 280 } 281 //时间请求频繁一点: 282 ticket := time.NewTicker(time.Minute * 1) 283 for range ticket.C { 284 t = common.GetRealTimeRetry(hosts, 10) 285 if !t.IsZero() { 286 //update 287 log.Info("change time", "delta", time.Until(t)) 288 types.SetTimeDelta(int64(time.Until(t))) 289 } 290 } 291 }