Peel the comparison to the original code 01: where is the configuration file generated when initializing

Source: Internet
Author: User

Author: freewind

Compared to the original project warehouse:

GitHub Address: Https://github.com/Bytom/bytom

Gitee Address: Https://gitee.com/BytomBlockc ...

It is often said that "reading source code" is an important way to learn programming. As programmers, we should read a lot of source code in our normal study work. But for most people, reading may be more of a code snippet, an example, or, under the guidance of a teacher or colleague, a general understanding of the project code to be read, followed by a targeted reading.

But if we are faced with a larger project than the original, and no one around to guide, can only rely on their own to see, then how to read it? Maybe everyone can find their own way, or efficient, or inefficient, or give up.

In the course of this reading than the original source code, I tried this method: from the outside, through the data interaction with the original node, to understand the internal principle of the previous step. Just like a pomegranate, a little bit of careful hands, finally to eat the delicious flesh.

So this article series is called "stripping the original look code".

Description

In each chapter of the series, I usually start with one or several related questions, and then analyze the source code to illustrate how the original code is implemented. For code that has little to do with the current problem, it will simply be taken, and then explained in detail when it really needs to be played.

To ensure the stability of the quoted code in the article, I will analyze it based on the v1.0.1 code of the original. Over time, the code will be updated faster than the original, but I think it would be an easy task to understand the code and look at the new code.

In the article, there will be some links directly to Bytom source code on GitHub. For convenience, I specifically put Bytom v1.0.1 's code into a new warehouse, which is not easily confused with the latest code than the original official. The warehouse address is: https://github.com/freewind/b ...

Of course, you don't have to clone this repository (clone official repository Http://github.com/Bytom/bytom is enough), and then, when necessary, use the following command to switch the code to v1.0.1 the tag that matches the code referenced in this series:

git fetchgit checkout -b v1.0.1

Whichever reading method I use, I think the first step should be to run the original node locally and try various functions.

For questions about how to download, configure, and install, please see the official document Https://github.com/Bytom/byto directly ... (Note that I'm giving a v1.0.1 document here), not much to say here.

This article questions

make bytomdwe can use the following command to initialize the original after we have compiled it locally:

./bytomd init --chain_id testnet

This specifies the chain that is used testnet (there are other options, such as, mainnet and so on). After successful operation, it will generate some configuration files on the local file system for use at the original startup.

So my question is:

What configuration file was generated when the original was initialized, and in what directory?

Here I will combine the source code to answer this question.

Directory Location

First, there will be a directory dedicated to placing a variety of data, such as keys, configuration files, database files, and so on. The code corresponding to this directory is located in config/config.go#l190-l205:

func DefaultDataDir() string {    // Try to place the data folder in the user's home dir    home := homeDir()    dataDir := "./.bytom"    if home != "" {        switch runtime.GOOS {        case "darwin":            dataDir = filepath.Join(home, "Library", "Bytom")        case "windows":            dataDir = filepath.Join(home, "AppData", "Roaming", "Bytom")        default:            dataDir = filepath.Join(home, ".bytom")        }    }    return dataDir}

As you can see, the location of the data directory is different on different operating systems:

    1. Apple System ( darwin ):~/Library/Bytom
    2. Windows ( windows ):~/AppData/Roaming/Bytom
    3. Other (e.g. Linux):~/.bytom

Configuration file Contents

We open the corresponding directory according to our own operating system (my is ~/Library/Bytom ), you can see that there is a config.toml , content about the following:

$ cat config.toml# This is a TOML config file.# For more information, see https://github.com/toml-lang/tomlfast_sync = truedb_backend = "leveldb"api_addr = "0.0.0.0:9888"chain_id = "testnet"[p2p]laddr = "tcp://0.0.0.0:46656"seeds = "47.96.42.1:46656,172.104.224.219:46656,45.118.132.164:46656"

It has already told us some basic information, such as:

    • db_backend = "leveldb": Leveldb as a database (used to store block data, account number, transaction information, etc.) than originally used internally
    • api_addr = "0.0.0.0:9888": We can open in the browser http://localhost:9888 to access the dashboard page, to view and manage
    • chain_id = "testnet": The current connection is testnet , that is, the test network, dug out of the original currency is not valuable
    • laddr = "tcp://0.0.0.0:46656": Local listening 46656 port, other nodes if you want to connect me, you need to access my 46656 port
    • seeds = "47.96.42.1:46656,172.104.224.219:46656,45.118.132.164:46656": After the original boot, will actively connect to these addresses to obtain data

Content templates

When different initializations are used chain_id , a different content configuration file is generated, so where does it come from?

Originally in Config/toml.go#l22-l45, the different template content was pre-defined:

var defaultConfigTmpl = `# This is a TOML config file.# For more information, see https://github.com/toml-lang/tomlfast_sync = truedb_backend = "leveldb"api_addr = "0.0.0.0:9888"`var mainNetConfigTmpl = `chain_id = "mainnet"[p2p]laddr = "tcp://0.0.0.0:46657"seeds = "45.79.213.28:46657,198.74.61.131:46657,212.111.41.245:46657,47.100.214.154:46657,47.100.109.199:46657,47.100.105.165:46657"`var testNetConfigTmpl = `chain_id = "testnet"[p2p]laddr = "tcp://0.0.0.0:46656"seeds = "47.96.42.1:46656,172.104.224.219:46656,45.118.132.164:46656"`var soloNetConfigTmpl = `chain_id = "solonet"[p2p]laddr = "tcp://0.0.0.0:46658"seeds = ""`

As you can see, these port numbers and the address of seed are written beforehand in the template.

Furthermore, by observing these configurations, we can see that, if chain_id different, the listening ports and the seed of the connection are different:

    1. Mainnet (connected to the main network): 46657 active connection of 6 seeds
    2. Testnet (connected to test Network): 46656 active connection of 3 seeds
    3. Solonet (Local individual node): 46658 , will not be actively connected to others (and therefore will not be connected to others), suitable for single-machine research

Write file

Here we need to quickly put bytomd init the execution process over again, in order to understand the timing of the configuration file, but also the previous content string together.

First, when we run bytomd init it, it corresponds to the code entry for cmd/bytomd/main.go#l54:

func main() {    cmd := cli.PrepareBaseCmd(commands.RootCmd, "TM", os.ExpandEnv(config.DefaultDataDir()))    cmd.Execute()}

config.DefaultDataDir()it corresponds to the previous reference data directory location.

Then execute cmd.Execute() , according to the parameters passed in init , select the following function to execute: CMD/BYTOMD/COMMANDS/INIT.GO#L25-L24

func initFiles(cmd *cobra.Command, args []string) {    configFilePath := path.Join(config.RootDir, "config.toml")    if _, err := os.Stat(configFilePath); !os.IsNotExist(err) {        log.WithField("config", configFilePath).Info("Already exists config file.")        return    }    if config.ChainID == "mainnet" {        cfg.EnsureRoot(config.RootDir, "mainnet")    } else if config.ChainID == "testnet" {        cfg.EnsureRoot(config.RootDir, "testnet")    } else {        cfg.EnsureRoot(config.RootDir, "solonet")    }    log.WithField("config", configFilePath).Info("Initialized bytom")}

One of these configFilePath is the config.toml write address, which is the file under the data directory that we mentioned earlier config.toml .

cfg.EnsureRootwill be used to confirm that the data directory is valid and will chain_id generate different content to be written to the configuration file, depending on the incoming.

The code that corresponds to it is CONFIG/TOML.GO#L10

func EnsureRoot(rootDir string, network string) {    cmn.EnsureDir(rootDir, 0700)    cmn.EnsureDir(rootDir+"/data", 0700)    configFilePath := path.Join(rootDir, "config.toml")    // Write default config file if missing.    if !cmn.FileExists(configFilePath) {        cmn.MustWriteFile(configFilePath, []byte(selectNetwork(network)), 0644)    }}

As you can see, it confirms the permissions on the data directory and finds that no changes are made when the configuration file exists. So if we need to generate a new configuration file, we need to remove (or rename) the old ones.

One of the selectNetwork(network) functions, implemented according to chain_id the different to assemble different configuration file content, it corresponds to master/config/toml.go#l48:

func selectNetwork(network string) string {    if network == "testnet" {        return defaultConfigTmpl + testNetConfigTmpl    } else if network == "mainnet" {        return defaultConfigTmpl + mainNetConfigTmpl    } else {        return defaultConfigTmpl + soloNetConfigTmpl    }}

Sure enough is a simple string concatenation, where the defaultConfigTmpl and *NetConfgTmpl in front has appeared, here is not repeated.

Finally, a third-party function cmn.MustWriteFile(configFilePath, []byte(selectNetwork(network)), 0644) is called, which writes the contents of the spliced configuration file to the 0644 specified file address with permissions.

When we get here, we have answered the question.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.