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