初始化和开始程序都是在neb文件下的main函数
func main() {
app := cli.NewApp()
app.Action = neb
app.Name ="neb"
app.Version = fmt.Sprintf("%s, branch %s, commit %s", version, branch, commit)
timestamp, _ := strconv.ParseInt(compileAt,10,64)
app.Compiled = time.Unix(timestamp,0)
app.Usage ="the go-nebulas command line interface"
app.Copyright ="Copyright 2017-2018 The go-nebulas Authors"
app.Flags = append(app.Flags, ConfigFlag)
app.Flags = append(app.Flags, NetworkFlags...)
app.Flags = append(app.Flags, ChainFlags...)
app.Flags = append(app.Flags, RPCFlags...)
app.Flags = append(app.Flags, AppFlags...)
app.Flags = append(app.Flags, StatsFlags...)
sort.Sort(cli.FlagsByName(app.Flags))
app.Commands = []cli.Command{
initCommand,
genesisCommand,
accountCommand,
consoleCommand,
networkCommand,
versionCommand,
licenseCommand,
configCommand,
blockDumpCommand,
}
sort.Sort(cli.CommandsByName(app.Commands))
app.Run(os.Args)
}
github.com/urfave/cli星云链使用这个包实现命令行输入。里面有一些规则
前面都是注册一些命令。到最后看到app.run进入等待命令循环。
主要看app.Action = neb进入主程序
func neb(ctx *cli.Context) error {
n, err := makeNeb(ctx)
if err != nil {
return err
}
logging.Init(n.Config().App.LogFile, n.Config().App.LogLevel, n.Config().App.LogAge)
core.SetCompatibilityOptions(n.Config().Chain.ChainId)
// enable crash report if open the switch and configure the url
if n.Config().App.EnableCrashReport && len(n.Config().App.CrashReportUrl) >0 {
InitCrashReporter(n.Config().App)
}
select {
case <-runNeb(ctx, n):
return nil
}
}
其他都不需要注意,runNeb才是程序的开始。当然Make是NEB的初始化
先看MakeNeb
func makeNeb(ctx *cli.Context) (*neblet.Neblet, error) {
conf := neblet.LoadConfig(config)
conf.App.Version = version
// load config from cli args
networkConfig(ctx, conf.Network)
chainConfig(ctx, conf.Chain)
rpcConfig(ctx, conf.Rpc)
appConfig(ctx, conf.App)
statsConfig(ctx, conf.Stats)
n, err := neblet.New(conf)
if err != nil {
return nil, err
}
return n, nil
}
n, err := neblet.New(conf)这个使用配置生成一个新的neblet
另外再看RunNeb
func runNeb(ctx *cli.Context, n *neblet.Neblet)chan bool {
c := make(chan os.Signal,1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
// start net pprof if config.App.Pprof.HttpListen configured
err := n.StartPprof(n.Config().App.Pprof.HttpListen)
if err != nil {
FatalF("start pprof failed:%s", err)
}
n.Setup()
n.Start()
quitCh := make(chan bool,1)
go func() {
<-c
n.Stop()
quitCh <- true
return
}()
return quitCh
}
n.Setup()
n.Start()
一个初始化一些网络共识等参数。然后开始star程序
然后再进到new函数
// New returns a new neblet.
func New(config *nebletpb.Config) (*Neblet, error) {
//var err error
n := &Neblet{config: config}
// try enable profile.
n.TryStartProfiling()
if chain := config.GetChain(); chain == nil {
logging.CLog().Error("Failed to find chain config in config file")
return nil, ErrConfigShouldHasChain
}
var err error
n.genesis, err = core.LoadGenesisConf(config.Chain.Genesis)
if err != nil {
logging.CLog().Error("Failed to load genesis config")
return nil, err
}
if config.Chain.Dynasty !="" {
core.LoadDynastyConf(config.Chain.Dynasty, n.genesis)
}
am, err := account.NewManager(n)
if err != nil {
return nil, err
}
n.accountManager = am
// init random seed.
rand.Seed(time.Now().UTC().UnixNano())
return n, nil
}
新生成一个Neb需要的参数。这里都是从配置文件加载的。
然后在初始化一些参数
unc (n *Neblet) Setup() {
var err error
logging.CLog().Info("Setuping Neblet...")
// storage
// n.storage, err = storage.NewDiskStorage(n.config.Chain.Datadir)
// n.storage, err = storage.NewMemoryStorage()
n.storage, err = storage.NewRocksStorage(n.config.Chain.Datadir)
if err != nil {
logging.CLog().WithFields(logrus.Fields{
"dir": n.config.Chain.Datadir,
"err": err,
}).Fatal("Failed to open disk storage.")
}
// net
n.netService, err = nebnet.NewNebService(n)
if err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup net service.")
}
// nvm
n.nvm = nvm.NewNebulasVM()
if err = n.nvm.CheckV8Run(); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup V8.")
}
// dip
if n.dip, err = dip.NewDIP(n); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup dip.")
}
// core
n.eventEmitter = core.NewEventEmitter(40960)
n.consensus = dpos.NewDpos()
n.blockChain, err = core.NewBlockChain(n)
if err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup blockchain.")
}
// consensus
if err := n.consensus.Setup(n); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup consensus.")
}
if err := n.blockChain.Setup(n); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to setup blockchain.")
}
// sync
n.syncService = nsync.NewService(n.blockChain, n.netService)
n.blockChain.SetSyncService(n.syncService)
// rpc
n.rpcServer = rpc.NewServer(n)
// nbre
n.nbre = nbre.NewNbre(n)
// nr
n.nr = nr.NewNR(n)
logging.CLog().Info("Setuped Neblet.")
}
这其中包括日志,netService,v8引擎,rpc,以及consensus的初始化。
继续往下就是各个部分的初始化了。
然后star
func (n *Neblet) Start() {
n.lock.Lock()
defer n.lock.Unlock()
logging.CLog().Info("Starting Neblet...")
if n.running {
logging.CLog().WithFields(logrus.Fields{
"err":"neblet is already running",
}).Fatal("Failed to start neblet.")
}
n.running = true
if n.config.Stats.EnableMetrics {
metrics.Start(n)
}
if err := n.netService.Start(); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to start net service.")
}
if err := n.rpcServer.Start(); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to start api server.")
}
if err := n.rpcServer.RunGateway(); err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to start api gateway.")
}
n.blockChain.Start()
n.blockChain.BlockPool().Start()
n.blockChain.TransactionPool().Start()
n.eventEmitter.Start()
n.syncService.Start()
// start consensus
chainConf := n.config.Chain
if chainConf.StartMine {
n.consensus.Start()
if chainConf.EnableRemoteSignServer == false {
passphrase := chainConf.Passphrase
if len(passphrase) ==0 {
fmt.Println("***********************************************")
fmt.Println("miner address:" + n.config.Chain.Miner)
prompt := console.Stdin
passphrase, _ = prompt.PromptPassphrase("Enter the miner's passphrase:")
fmt.Println("***********************************************")
}
}
err := n.consensus.EnableMining(chainConf.Passphrase)
if err != nil {
logging.CLog().WithFields(logrus.Fields{
"err": err,
}).Fatal("Failed to enable mining.")
}
}
一个个部分开启。是不是架构特别清晰。
但是在concensus那里判断一下是不是需要挖矿,不是的话就不开启。同步就行。目前的共识并不算共识
然后一个个关掉
func (n *Neblet) Stop() {
n.lock.Lock()
defer n.lock.Unlock()
logging.CLog().Info("Stopping Neblet...")
// try Stop Profiling.
n.TryStopProfiling()
if n.config.Chain.StartMine && n.consensus != nil {
n.consensus.Stop()
n.consensus = nil
}
if n.syncService != nil {
n.syncService.Stop()
n.syncService = nil
}
if n.eventEmitter != nil {
n.eventEmitter.Stop()
n.eventEmitter = nil
}
if n.blockChain != nil {
n.blockChain.TransactionPool().Stop()
n.blockChain.BlockPool().Stop()
n.blockChain.Stop()
n.blockChain = nil
}
if n.rpcServer != nil {
n.rpcServer.Stop()
n.rpcServer = nil
}
if n.netService != nil {
n.netService.Stop()
n.netService = nil
}
if n.config.Stats.EnableMetrics {
metrics.Stop()
}
if n.dip != nil {
n.dip.Stop()
n.dip = nil
}
if n.nbre != nil {
n.nbre.Stop()
n.nbre = nil
}
n.accountManager = nil
n.running = false
logging.CLog().Info("Stopped Neblet.")
}
哈哈。结束。
我看了星云链的commit版本。他们首先是实现P2P,然后共识(残缺的),然后V8。。。。。。。。。。
花了大半年时间。七个人好像
网友评论