主页 > imtoken客服在哪 > 从零开始学习区块链技术(二):如何接入比特币网络及其原理分析

从零开始学习区块链技术(二):如何接入比特币网络及其原理分析

imtoken客服在哪 2024-01-26 05:11:19

1、如何连接比特币网络?事实上,访问比特币网络非常简单。我说你千万不要相信,直接启动比特币客户端:

在命令行终端输入启动命令:./src/bitcoind -testnet

进入后会有一个与网络同步数据的过程,你会看到:

数据同步

数据同步

这个过程需要一点时间。数据同步完成后,连接到比特币网络。2、启动过程鸟瞰图虽然单条命令就可以搞定,但代码操作背后的逻辑并不简单~

来吧,让我为你分析一下

当你在命令行终端输入启动命令:./src/bitcoind -testnet,操作系统会在这个文件中找到main函数,启动比特币客户端启动。

对于所有 C++ 代码,整个程序都是从 main 函数执行的。bitcoind 的主要功能位于 src/bitcoind.cpp。代码拉到最后找到我们的main函数。

main 函数本身并没有太多内容。它主要调用三个函数来执行。它们的主要功能是设置环境变量、设置信号处理和启动系统。

具体代码如下:

int main(int argc, char* argv[])
{
    SetupEnvironment();

// Connect bitcoind signal handlers noui_connect();

return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE); }

这段代码简单描述如下: SetupEnvironment函数主要用于设置系统的环境变量,包括:malloc分配内存的行为、Locale、文件路径的本地化设置等。 noui_connect函数,其中设置连接到 bitcoind 的信号的处理。AppInit 函数启动系统。下面重点关注AppInit函数的执行从零学比特币合约,调用SetupServerArgs函数来设置系统可接受的所有命令行参数。然后开始解析命令行传递的各种参数。系统实现中的一个重要步骤是设置可以接收的参数,并解析用户在启动时传递的各种参数。SetupServerArgs 函数就是为了完成这个目的。让' 来看看这个函数的执行流程。如果是测试网络,则生成一个 CTestNetParams 对象进行初始化。(用于开发完成后的测试。)

如果是回归测试网络,则生成一个 CRegTestParams 对象进行初始化。(用于开发期间的连接使用。)

对于这两个测试网络,处理与主网络基本相同,只是一些参数不同。

上面提到的三个对象CMainParamsCTestNetParamsCRegTestParams的定义在chainparams.cpp文件中。有兴趣的同学可以进一步探索源码。接下来,设置系统可以接收的所有参数。部分参数说明如下: 以上是一些常用的参数,会影响Bitcoin Core的命令。应用程序开发人员更关心 RPC 相关的设置。通过 RPC 接口,我们调用 Bitcoin Core 提供的各种服务。这些命令通常在配置文件中设置,不需要在命令行中指定。接下来,检查用户指定的命令参数是否正确。

 if (!gArgs.ParseParameters(argc, argv, error)) {
     fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str());
     return false;
 }

如果传递了帮助和版本参数,则显示帮助或版本信息并退出。检查数据目录(可选或默认)是否存在。如果不是,则打印错误消息并退出。

 if (!fs::is_directory(GetDataDir(false)))
 {
     fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
     return false;
 }

在GetDataDir方法中,根据用户是否在命令行中提供datadir参数来确定默认的数据目录还是用户指定的数据目录。读取并解析配置文件,同时检查指定的数据目录是否存在。如果任何步骤失败,则打印错误消息并退出。

 if (!gArgs.ReadConfigFiles(error, true)) {
     fprintf(stderr, "Error reading configuration file: %s\n", error.c_str());
     return false;
 }

ReadConfigFiles方法的具体处理如下:调用SelectParams(gArgs.GetChainName())函数生成全局区块链参数并设置系统的网络类型。如果有错误从零学比特币合约,打印错误,然后退出。gArgs.GetChainName() 方法返回当前使用的网络。对于主网络,返回字符串 main;对于测试网络,返回字符串 test;对于回归测试网络,返回字符串 regtest。SelectParams 方法的实现如下所示:

void SelectParams(const std::string& network)
{
   SelectBaseParams(network);
   globalChainParams = CreateChainParams(network);
}

SelectBaseParams 方法会根据指定的网络参数生成一个 CBaseChainParams 对象,保存在 globalChainBaseParams 变量中,并将网络类型(m_network 属性)保存在指定的 gArgs 对象中。CBaseChainParams 对象只保存了系统的数据目录和运行的端口,所以称为区块链基础参数对象。

CreateChainParams方法会根据不同的网络参数生成CChainParams类的子对象,可能有以下三种:CMainParams、CTestNetParams、CRegTestParams。CChainParams 对象包含区块链对象的所有重要信息,例如:共识规则、部署状态、检查点、创世块等。检查所有命令行参数,如果有则打印错误并退出。将参数 -server 默认设置为 true。bitcoind 守护进程默认将 server 设置为 true。调用InitLogging函数初始化系统使用的日志,打印系统的版本信息。具体代码如下,根据是否指定了debuglogfile、printtoconsole等来判断日志是打印到文件还是控制台。

void InitLogging()
{
   g_logger->m_print_to_file = !gArgs.IsArgNegated("-debuglogfile");
   g_logger->m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));

LogPrintf("\n\n\n\n\n");

g_logger->m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false)); g_logger->m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); g_logger->m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);

fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);

std::string version_string = FormatFullVersion();

LogPrintf(PACKAGE_NAME " version %s\n", version_string); }

调用InitParameterInteraction函数,根据参数之间的关系检查所有交互参数。调用 AppInitBasicSetup 函数进行基本设置。如果有错误,打印错误,然后退出。经过长时间的检查和设置,我终于开始应用基本设置。详情见第二部分。调用 AppInitSanityChecks 函数处理底层加密函数的内容。详情见第二部分。调用 AppInitLockDataDirectory 函数检查并锁定数据目录。详情见第二部分。调用AppInitMain函数,比特币的主要启动过程。详情见第二部分。如果应用初始化main函数出错,调用Interrupt函数终止,否则调用WaitForShutdown函数等待系统结束。WaitForShutdown 函数是一个无限循环函数。我是欧小白,Ulord全球社区联盟(优德社区)核心区块链开发者,区块链技术爱好者,对比特币、以太坊、EOS Dash、Rsk、Java、Nodejs、PHP、Python、C++有深入研究希望聚集更多区块链开发者,共同学习,共同进步。

敬请期待下一篇:从零开始学习区块链技术(三)——解析如何连接比特币网络、创建比特币钱包、重要rpc指令的关键步骤?