Lectura del código fuente 2 de Bitcoin

La última vez que leí AppInit en src / bitcoind.cpp, el proceso aproximado es

1,解析-?,-h,-help,-version,输出帮助和版本信息
2,解析-datadir参数,GetDataDir函数判定所指定数据目录是否合法
3,通过-conf参数,ReadConfigFile函数读取配置文件
4,通过-testnet和-regtest参数,ChainNameFromCommandLine函数设置的当前程序运行的网络
5,通过-printtoconsole等参数,InitLogging函数初始化日志记录以及打印方式
6,InitParameterInteraction函数初始化网络参数
7,AppInitBasicSetup函数注册相应的消息以及处理方式
8,AppInitParameterInteraction函数设置区块链运行参数
9,AppInitSanityChecks函数检查比特币运行时所需要的所有的库是否都运行正常
10,通过-daemon参数设置是否后台运行
11,AppInitMain函数运行主应用程序
12,启动失败中断操作和清理工作

El código de la función AppInit es el siguiente: El
código es el siguiente:

    54	//////////////////////////////////////////////////////////////////////////////
    55	//
    56	// Start
    57	//
    58	bool AppInit(int argc, char* argv[])
    59	{
    60	    bool fRet = false;
    61	
    62	    //
    63	    // Parameters
    64	    //
    65	    // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
    66	    gArgs.ParseParameters(argc, argv);
    67	     //如果命令行参数是-?,-h,-help,-version的话首先构造版本和usage信息
    68	    // Process help and version before taking care about datadir
    69	    if (gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") ||  gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version"))
    70	    {
                //构造版本字符串,例如:Bitcoin Core Daemon version v0.16.0rc2
    71	        std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";
    72	
                  //如果是-version,构造追加license信息
    73	        if (gArgs.IsArgSet("-version"))
    74	        {
    75	            strUsage += FormatParagraph(LicenseInfo());
    76	        }
                 //如果是-?,-h,-help,构造追加usage信息
    77	        else
    78	        {
    79	            strUsage += "\n" + _("Usage:") + "\n" +
    80	                  "  bitcoind [options]                     " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";
    81	
    82	            strUsage += "\n" + HelpMessage(HMM_BITCOIND);
    83	        }
    84	
    85	        fprintf(stdout, "%s", strUsage.c_str());
    86	        return true;
    87	    }
    88	
             //检测数据目录
    89	    try
    90	    {
            //解析-datadir参数,通过GetDataDir检测和处理-datadir参数指定的目录
    91	        if (!fs::is_directory(GetDataDir(false)))
    92	        {
    93	            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
    94	            return false;
    95	        }
              //通过-conf读取配置文件
    96	        try
    97	        {
    98	            gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
    99	        } catch (const std::exception& e) {
   100	            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
   101	            return false;
   102	        }
               //检测-testnet和-regtest设置的当前程序运行的网络
   103	        // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
   104	        try {
   105	            SelectParams(ChainNameFromCommandLine());
   106	        } catch (const std::exception& e) {
   107	            fprintf(stderr, "Error: %s\n", e.what());
   108	            return false;
   109	        }
   110	
              //不合法的参数字符检测
   111	        // Error out when loose non-argument tokens are encountered on command line
   112	        for (int i = 1; i < argc; i++) {
   113	            if (!IsSwitchChar(argv[i][0])) {
   114	                fprintf(stderr, "Error: Command line contains unexpected token '%s', see bitcoind -h for a list of options.\n", argv[i]);
   115	                return false;
   116	            }
   117	        }
   118

                 //设置-server参数为true,而-server参数表示是否接收RPC命令,
                 //这里因为是bitcoind,默认作为核心服务器接收bitcoin-cli以及bitcoin-tx传送的命令	
   119	        // -server defaults to true for bitcoind but not for the GUI so do this here
   120	        gArgs.SoftSetBoolArg("-server", true);
   121	        // Set this early so that parameter interactions go to console
                  //初始化日志记录以及打印方式
   122	        InitLogging();
                    //初始化网络参数
   123	        InitParameterInteraction();
                   //注册相应的消息以及处理方式
   124	        if (!AppInitBasicSetup())
   125	        {
   126	            // InitError will have been called with detailed error, which ends up on console
   127	            return false;
   128	        }
                 //设置区块链运行参数
   129	        if (!AppInitParameterInteraction())
   130	        {
   131	            // InitError will have been called with detailed error, which ends up on console
   132	            return false;
   133	        }
               //Sanity Check是用来检查比特币运行时所需要的所有的库是否都运行正常
   134	        if (!AppInitSanityChecks())
   135	        {
   136	            // InitError will have been called with detailed error, which ends up on console
   137	            return false;
   138	        }
             //通过-daemon参数设置是否后台运行
   139	        if (gArgs.GetBoolArg("-daemon", false))
   140	        {
   141	#if HAVE_DECL_DAEMON
   142	            fprintf(stdout, "Bitcoin server starting\n");
   143	
   144	            // Daemonize
   145	            if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
   146	                fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno));
   147	                return false;
   148	            }
   149	#else
   150	            fprintf(stderr, "Error: -daemon is not supported on this operating system\n");
   151	            return false;
   152	#endif // HAVE_DECL_DAEMON
   153	        }
                  //后台运行后锁定数据目录
   154	        // Lock data directory after daemonization
   155	        if (!AppInitLockDataDirectory())
   156	        {
   157	            // If locking the data directory failed, exit immediately
   158	            return false;
   159	        }
                   //运行主应用程序
   160	        fRet = AppInitMain();
   161	    }
   162	    catch (const std::exception& e) {
   163	        PrintExceptionContinue(&e, "AppInit()");
   164	    } catch (...) {
   165	        PrintExceptionContinue(nullptr, "AppInit()");
   166	    }
   167
              //如果返回值fRet为false,那么强制结束所有线程;否则就等待所有线程运行结束
   168	    if (!fRet)
   169	    {
   170	        Interrupt();
   171	    } else {
   172	        WaitForShutdown();
   173	    }
            //最后通过ShutDown()完成清理工作
   174	    Shutdown();
   175	
   176	    return fRet;
   177	}
   178	

Probablemente examinó la realización de la siguiente función AppInit, y descubrió que la mayoría de ellos están analizando los parámetros de la línea de comandos de bitcoind. Primero, analice la información de ayuda de ayuda? Legal, establecido por el parámetro -datadir, el directorio almacena principalmente información de bloque sincronizada, información de cartera, información de configuración, etc. Casi toda la información de operación de blockchain se guarda aquí, esta función se implementa en src / util.cpp , El código es el siguiente:

581	static fs::path pathCached;
   582	static fs::path pathCachedNetSpecific;
   583	static CCriticalSection csPathCached;
   584	
   585	const fs::path &GetDataDir(bool fNetSpecific)
   586	{
   587	
   588	    LOCK(csPathCached);
   589	
             //判断fNetSpecific是否为true,true使用pathCachedNetSpecific(网络路径),否则使用
             //pathCached(本地路径)
   590	    fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
   591	
              //如果path不为空,返回path
   592	    // This can be called during exceptions by LogPrintf(), so we cache the
   593	    // value so we don't have to do memory allocations after that.
   594	    if (!path.empty())
   595	        return path;
   596	
              //如果有通过-datadir参数指定目录
   597	    if (gArgs.IsArgSet("-datadir")) {
   598	        path = fs::system_complete(gArgs.GetArg("-datadir", ""));
                        //检测参数传入的路径是否为目录,不为目录的话,置空path返回
   599	        if (!fs::is_directory(path)) {
   600	            path = "";
   601	            return path;
   602	        }
              //如果没有通过-datadir参数指定目录,使用GetDefaultDataDir获取默认目录
   603	    } else {
   604	        path = GetDefaultDataDir();
   605	    }
              //如果事网络路径,修改path为BaseParams().DataDir();
   606	    if (fNetSpecific)
   607	        path /= BaseParams().DataDir();
   608	
                     //创建wallets目录
   609	    if (fs::create_directories(path)) {
   610	        // This is the first run, create wallets subdirectory too
   611	        fs::create_directories(path / "wallets");
   612	    }
   613	
   614	    return path;
   615	}

Línea de función AppInit 105: SelectParams (ChainNameFromCommandLine ()); Hay tres tipos de redes que ejecuta el programa actual: Main, Testnet,
función Regtest ChainNameFromCommandLine, implementada en src / chainparamsbase.cpp, el código es el siguiente

    90	std::string ChainNameFromCommandLine()
    91	{
            //获取命令行-regtest参数,是否为私有网
    92	    bool fRegTest = gArgs.GetBoolArg("-regtest", false);
            //获取命令行-testnet参数,是否为测试网
    93	    bool fTestNet = gArgs.GetBoolArg("-testnet", false);
    94     //不能同时配置两个参数
    95	    if (fTestNet && fRegTest)
    96	        throw std::runtime_error("Invalid combination of -regtest and -testnet.");
           //如果为私网,返回私网
    97	    if (fRegTest)
    98	        return CBaseChainParams::REGTEST;
           //如果为测试网,返回测试网
    99	    if (fTestNet)
   100	        return CBaseChainParams::TESTNET;
           //不是以上两种的返回主网
   101	    return CBaseChainParams::MAIN;
   102	}

ChainNameFromCommandLine
AppInit función línea 122: función InitLogging, registro inicial y método de impresión, implementado en src / init.cpp, el código es el siguiente

void InitLogging()
{
   //通过-printtoconsole参数设置是否打印日志到终端
    fPrintToConsole = gArgs.GetBoolArg("-printtoconsole", false);
    //通过-logtimestamps参数设置每一条输出信息附带时间戳,默认值为附带
    fLogTimestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
   //通过-logtimemicros设置时间戳精确到微秒精度,默认不附加
    fLogTimeMicros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
   //通过-logips设置输出信息中附加ip地址,默认不附加
    fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);

    LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
    std::string version_string = FormatFullVersion();
#ifdef DEBUG
    version_string += " (debug build)";
#else
    version_string += " (release build)";
#endif
    LogPrintf(PACKAGE_NAME " version %s\n", version_string);
}

Línea de función AppInit 123: InitParameterInteraction (); Otras funciones después de inicializar la función de parámetro de red, continúe con el siguiente capítulo

30 artículos originales publicados · elogiados 74 · 230,000 vistas +

Supongo que te gusta

Origin blog.csdn.net/ruiyiin/article/details/104633236
Recomendado
Clasificación