geth的启动之区块链的生成

区块链的生成

//go-ethereum/cmd/geth/main.go
func init() {
    // Initialize the CLI app and start Geth
    app.Action = geth
    app.HideVersion = true // we have a command to print the version
    app.Copyright = "Copyright 2013-2017 The go-ethereum Authors"
    app.Commands = []cli.Command{
        // See chaincmd.go:
        initCommand,
        importCommand,
        exportCommand,
        copydbCommand,
        removedbCommand,
        dumpCommand,
        // See monitorcmd.go:
        monitorCommand,
        // See accountcmd.go:
        accountCommand,
        walletCommand,
        // See consolecmd.go:
        consoleCommand,
        attachCommand,
        javascriptCommand,
        // See misccmd.go:
        makecacheCommand,
        makedagCommand,
        versionCommand,
        bugCommand,
        licenseCommand,
        // See config.go
        dumpConfigCommand,
    }
    sort.Sort(cli.CommandsByName(app.Commands))

    app.Flags = append(app.Flags, nodeFlags...)
    app.Flags = append(app.Flags, rpcFlags...)
    app.Flags = append(app.Flags, consoleFlags...)
    app.Flags = append(app.Flags, debug.Flags...)
    app.Flags = append(app.Flags, whisperFlags...)

    app.Before = func(ctx *cli.Context) error {
        runtime.GOMAXPROCS(runtime.NumCPU())
        if err := debug.Setup(ctx); err != nil {
            return err
        }
        // Start system runtime metrics collection
        go metrics.CollectProcessMetrics(3 * time.Second)

        utils.SetupNetwork(ctx)
        return nil
    }

    app.After = func(ctx *cli.Context) error {
        debug.Exit()
        console.Stdin.Close() // Resets terminal mode.
        return nil
    }
}

init()调用来源待深入
init()方法注册了多个命令,这些命令如initCommand会调用区块链的创建

//go-ethereum/cmd/geth/chaincmd.go
func importChain(ctx *cli.Context) error {
    if len(ctx.Args()) < 1 {
        utils.Fatalf("This command requires an argument.")
    }
    stack := makeFullNode(ctx)
    chain, chainDb := utils.MakeChain(ctx, stack)
    defer chainDb.Close()
.......

//go-ethereum/cmd/utils/flags.go
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
    var err error
    chainDb = MakeChainDatabase(ctx, stack)

    config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
    if err != nil {
        Fatalf("%v", err)
    }
    var engine consensus.Engine
    if config.Clique != nil {
        engine = clique.New(config.Clique, chainDb)
    } else {
        engine = ethash.NewFaker()
        if !ctx.GlobalBool(FakePoWFlag.Name) {
            engine = ethash.New(ethash.Config{
                CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
                CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
                CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
                DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
                DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
                DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
            })
        }
    }
    if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
        Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
    }
    cache := &core.CacheConfig{
        Disabled:      ctx.GlobalString(GCModeFlag.Name) == "archive",
        TrieNodeLimit: eth.DefaultConfig.TrieCache,
        TrieTimeLimit: eth.DefaultConfig.TrieTimeout,
    }
    if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
        cache.TrieNodeLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
    }
    vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
    chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg)
    if err != nil {
        Fatalf("Can't create BlockChain: %v", err)
    }
    return chain, chainDb
}

最后blockchain的创建来到了

//go-ethereum/core/blockchain.go中

func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config) (*BlockChain, error) {
    if cacheConfig == nil {
        cacheConfig = &CacheConfig{
            TrieNodeLimit: 256 * 1024 * 1024,
            TrieTimeLimit: 5 * time.Minute,
        }
    }
    bodyCache, _ := lru.New(bodyCacheLimit)
    bodyRLPCache, _ := lru.New(bodyCacheLimit)
    blockCache, _ := lru.New(blockCacheLimit)
    futureBlocks, _ := lru.New(maxFutureBlocks)
    badBlocks, _ := lru.New(badBlockLimit)

    bc := &BlockChain{
        chainConfig:  chainConfig,
        cacheConfig:  cacheConfig,
        db:           db,
        triegc:       prque.New(),
        stateCache:   state.NewDatabase(db),
        quit:         make(chan struct{}),
        bodyCache:    bodyCache,
        bodyRLPCache: bodyRLPCache,
        blockCache:   blockCache,
        futureBlocks: futureBlocks,
        engine:       engine,
        vmConfig:     vmConfig,
        badBlocks:    badBlocks,
    }
    bc.SetValidator(NewBlockValidator(chainConfig, bc, engine))
    bc.SetProcessor(NewStateProcessor(chainConfig, bc, engine))

    var err error
    bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.getProcInterrupt)
    if err != nil {
        return nil, err
    }
    bc.genesisBlock = bc.GetBlockByNumber(0)
    if bc.genesisBlock == nil {
        return nil, ErrNoGenesis
    }
    if err := bc.loadLastState(); err != nil {
        return nil, err
    }
    // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
    for hash := range BadHashes {
        if header := bc.GetHeaderByHash(hash); header != nil {
            // get the canonical block corresponding to the offending header's number
            headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64())
            // make sure the headerByNumber (if present) is in our current canonical chain
            if headerByNumber != nil && headerByNumber.Hash() == header.Hash() {
                log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash)
                bc.SetHead(header.Number.Uint64() - 1)
                log.Error("Chain rewind was successful, resuming normal operation")
            }
        }
    }
    // Take ownership of this particular state
    go bc.update()
    return bc, nil
}
    原文作者:古则
    原文地址: https://www.jianshu.com/p/55f4b0f5a0cc
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞