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

当前位置:首页 > 币圈百科 > 从零开始学习区块链技术(二):怎么样接入比特币网络以及其原理分析

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

2022-12-28币圈百科655

1。如何接入比特币网络?

其实访问比特币网络很简单。我说出来你不会相信的。只需启动比特币客户端:

输入启动命令:命令行终端的/src/bitcoin-testnet

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

数据同步

2。启动过程鸟瞰图数据同步

虽然一个命令就可以完成,但是代码运行背后的逻辑并不简单~

来,我给大家分析一下在命令行终端输入启动命令时的

://src/bitcoind -testnet?之后操作系统会在这个文件中找到主函数,开始比特币客户端的启动。

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

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

具体代码如下:

int main (int argc,char * argv[]){ setup environment();//连接bitcoind信号处理程序noui _ Connect();return (AppInit(argc,argv)?退出_成功:退出_失败);}

这段代码简单描述如下:

SetupEnvironment?函数,主要用于设置系统环境变量,包括:malloc?内存分配行为、区域设置、文件路径的本地化设置等。noui_connect?用于设置连接到bitcoind的信号处理的函数。AppInit?函数来启动系统。

下面重点说说?AppInit?函数执行

调用?SetupServerArgs?函数来设置系统可接受的所有命令行参数。然后开始解析命令行传递的各种参数。系统执行中的一个重要步骤是设置可以接收的参数,并在启动时解析用户传递的各种参数。SetupServerArgs?功能就是为了完成这个目的。让我们来看看这个函数的执行流程。第一,打电话?CreateBaseChainParams?函数生成默认的基本参数,包括:使用的数据目录和监听的端口。根据网络类型不同,主网使用指定目录下的端口8332和当前目录,测试网使用指定目录下的端口18332和testnet3子目录,回归测试网使用指定目录下的端口18443和regtest子目录。然后,打电话?CreateChainParams?函数来生成默认的区块链参数。这种方法也将区分不同的网络。如果是主网,生成?CMainParams?初始化的对象。在构造函数中,进行以下设置:将网络ID设置为?主要;设置共识参数(Consensus:Params)的每个值:每块数(nSubsidyHalvingInterval)后续比特币的奖励将减半,值为210000。根据创造块的奖励数量(50),按照等比例序列求和公式:50?(1/(1?0.5))?210000 " role=" presentation " style=" box-sizing:border-box;大纲:0px显示:内嵌;行高:正常;字间距:正常;溢出-换行:正常;空白:nowrap浮动:无;方向:ltr最大宽度:无;最大高度:无;最小宽度:0px最小高度:0px边框:0px填充:0px边距:0px断字:全断;位置:相对;”50?(1/(1?0.5))?21000050?(1/(1?0.5))?20000

,可计算货币总量为2100W比特币。BIP34的激活高度(BIP34Height)是227931。BIP34激活哈希(BIP34Hash)是?0x 00000000000000024 b 89 b 42 a 942 Fe 0d 9 Fe a3 bb 44 ab 7 BD 1 b 19115 DD 6a 759 c 0808 b 8 .BIP65激活高度(BIP65Height)是388381。BIP66激活高度(BIP66Height)为363725。工作负荷功率限制是一个大整数。难度变化周期(nPowTargetTimespan)为2周。平均阻塞时间(nPowTargetSpacing)为10分钟。共识改变所需的块数(nRuleChangeActivationThreshold)为1916,即2016的95%。nMinerConfirmationWindow为2016,等于难度变化周期除以取出方块的平均时间。 接下来,设置与区块链相关的部署状态,包括:DEPLOYMENT_TESTDUMMY、CSV软分叉(与BIP68、BIP112和BIP113相关)和隔离见证(与BIP141、BIP143和BIP147相关)。最佳区块链的最小工作量。将默认端口(nDefaultPort)设置为8333。块修剪前达到多少块(nPruneAfterHeight),当前值为100000。接下来,打电话?CreateGenesisBlock?方法来生成创建块。这个方法的参数是固定的,指定时间,随机数,难度值,版本号,奖励等。创造板块的。在该方法中,生成创世块的输出脚本和输入脚本。中本聪的著名评论出现在创世集团第一笔交易的签名中,他写道:《泰晤士报》2009年1月3日,银行濒临第二次保释的地窖。将创建块的哈希设置为新生成的启动块的哈希。设置DNS种子节点?vSeeds?包含的DNS种子有:seed.bitcoin.sipa.be、dnsseed.bluematt.me、dnsseed.bitcoin.dashjr.org、seed.bitcoin.sipa.be、seed.bitcoin.jonasschnelli.ch、seed.btc.petertodd.org、seed.bitcoin.sprovoost.nl?等等。通过解析DNS种子节点,比特币节点在启动时可以找到更多的对等节点进行连接。接下来,设置相关的检查点数据。

如果是测试网络,生成?CTestNetParams?初始化的对象。(用于开发完成后的测试。)

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

对于这两个测试网,处理基本和主网一样,只是部分参数有所不同。

上面提到的3个对象?CMainParams?CTestNetParams?CRegTestParams的定义都在?chainparams.cpp?在文件里。感兴趣的同学可以进一步探究源代码。接下来,设置系统可以接收的所有参数。部分参数解释如下:显示帮助信息;-version,打印版本信息,退出系统。-assumevalid=十六进制。如果指定的块存在于区块链中,则假定它及其祖先是有效的,并且可以跳过其脚本验证。-blocksdir=dir,指定存储区块链的目录。-blocknotify=cmd,指定主链上的块发生变化时要执行的命令。-conf=file,它指定配置文件的目录,相对于下面指定的数据目录。-datadir=dir,指定数据目录。-dbcache=n,设置数据库缓存大小。-debuglogfile=file,设置调试文件的位置。-feefilter,告诉其他节点通过最小交易成本过滤发给我们的库存消息。-loadblock=file,启动时,来自外部blk000?dat文件导入块。-maxmempool=n,指定交易池的最大内存,以兆字节为单位。-maxorphantx=n,指定内存中孤立事务的最大数量。-mempoolexpiry=n,指定不跟踪事务池中超过指定时间(小时)的事务。-par=n,指定脚本签名的线程数。-persistmempool,指定是否将事务保存在事务池中,并在启动时恢复加载。-pid=file,指定进程文件。-prune=n,这通过启用旧块的修剪(删除)来降低存储要求。这允许打电话?pruneblockchain?RPC来删除特定的块,如果提供了目标大小,则会启用旧块的自动清理。这种模式和?-txindex?然后呢。重新扫描?不兼容。-reindex根据硬盘记录?黑色*。dat?文件重建区块链状态和区块索引。-Reindex-Chain,根据当前块的索引重建区块链的状态。-txindex,维护所有事务的索引,是?getrawtransaction?RPC命令调用。-addnode=ip,添加一个节点,然后连接它,并保持连接。-banscore=n,打破品行不端同伴的门槛。-bantime=n,不诚实节点重新连接所需的秒数。-bind=addr,绑定到指定的IP并始终连接到该地址。-connect=ip,它只连接到指定的节点。如果是0而不是ip,说明禁止自动连接。-发现,是否找到了自己的IP地址。-dns,为了什么?-addnode 、-seednode 、-connect?总是使用DNS查找。 -dnsseed,它指定如果现有地址很少,则执行DNS查找以获得对等节点。-enableBIP61,允许发送BIP61定义的拒绝消息。-externalip=ip,指定自己的外部ip地址。-forcednsseed,始终通过DNS查找获取对等节点的地址。-侦听,接收外部对等节点的连接。-listenonion,自动创建Tor隐藏服务。-maxconnections=n,保持与其他节点的最大连接数。-maxreceivebuffer=n,每个对等节点的最大接收缓存。-maxsendbuffer=n,每个对等节点的最大发送缓冲区。-onion=ip:port,设置SOCKS5代理。-peerbloomfilters,支持bloomfilters过滤块和事务。-Permitbaremultsig,中继非P2SH多重签名。-port=port,指定默认监听端口。-proxy=ip:port,通过SOCKS5代理连接。-proxyrandomize,随机化每个代理连接的凭据。从而分离Tor流。-seednode=ip,指定一个节点检索其他节点,然后断开与此联系人的连接。-torcontrol=ip:port,如果启用了onion,则指定Tor控制器使用的端口。-Torpassword=pass,tor控制器的密码。-checkblocks=n,启动时检查多少个块。-checklevel=n,checkblocks?块被验证的程度。-checkblockindex,用于完整的一致性检查,包括:mapBlockIndex、SetBlockIndex、chainActive、mapBlocksUnlinked等。-checkmempool=n,检查了多少个事务。-检查点,提供检查点,不检查已知链的历史。-deprecatedrpc=method,使用的rpc方法已被否决。-limitancestorcount=n,如果事务池中的祖先事务达到或超过指定值,将不再接收事务。-limitancestorsize=n,如果事务池中的祖先事务大小达到或超过指定值,将不再接收事务。-limitdescendanceantcount=n,如果交易池中祖先交易的后代已达到或超过指定值,将不再接收更多交易。-blockmaxweight=n,设置BIP141块的最大重量。-blockmintxfee=amt,设置创建块时包含的最小交易成本。-rpcuser=user,进行RPC调用的用户名。-rpcpassword=pw,发出RPC调用的用户的密码。-rpcport=port,进行RPC调用的端口

。以上是一些常用的参数,通过这些参数可以影响比特币核心的命令。应用程序开发人员更关注RPC相关的设置。通过RPC接口,调用比特币核心提供的各种服务。这些命令通常在配置文件中设置,而不是在命令行中指定。接下来,检查用户指定的命令参数是否正确。如果(!葛格斯。ParseParameters(argc,argv,error)) { fprintf(stderr,'解析命令行参数时出错:%s 'Error . c _ str());返回false}如果传递了帮助和版本参数,将显示帮助或版本信息,然后退出。检查数据目录(可指定或默认)是否存在。否则,打印一条错误消息,然后退出。如果(!fs:is _ directory(get datadir(false)){ fprintf(stderr,'错误:指定的数据目录\'%s '不存在。 '加格斯。GetArg('-datadir '' ')。c _ str());返回false}

in?GetDataDir?方法,这取决于用户是否在命令行提供它。datadir?参数来确定是使用默认数据目录还是用户指定的数据目录。读取并解析配置文件,并检查指定的数据目录是否存在。如果任何一步出错,打印一条错误消息,然后退出。如果(!葛格斯。ReadConfigFiles(错误,真)){fprintf(stderr, "Error reading configuration file: %s\n", error.c_str()); return false; }

其中?ReadConfigFiles?方法具体处理如下:

首先,调用?GetArg?方法,获取配置文件名称,默认为?bitcoin.conf。然后,通过?GetConfigFile?方法获取配置文件的绝对路径(方法内部会委托?AbsPathForConfigVal?方法进行处理,后者决定根据用户指定的路径或使用默认路径来生成配置文件的绝对路径)。在得到配置文件的绝对路径之后,构造文件输入流,从而读取配置文件?fs::ifstream stream(GetConfigFile(confPath))。在成功构造输入流之后,调用?ReadConfigStream?方法开始读取配置文件的内容。方法内部按行读取配置文件,并以键值对的形式保存在?m_config_args?集合中。调用?SelectParams(gArgs.GetChainName())?函数,生成全局的区块链参数,并设置系统的网络类型。如果有错误,则打印错误,然后退出。gArgs.GetChainName()?方法会返回当前使用的网络。针对主网络,返回字符串?main;测试网络,返回字符串?test;回归测试网络,返回字符串?regtest。SelectParams?方法的实现如下所示:void SelectParams(const std::string& network){ SelectBaseParams(network); globalChainParams = CreateChainParams(network);}

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

CreateChainParams?方法会根据不同的网络参数生成?CChainParams?类的子对象,可能为以下三种:CMainParams、CTestNetParams、CRegTestParams。CChainParams?对象包含了区块链对象的所有重要信息,比如:共识规则、部署状态、检查点、创世区块等。检查所有命令行参数,如果有错误,则打印错误,并退出。设置参数?-server?默认为真。bitcoind 守护进程默认?server?为真。调用?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 蓑衣网小编2022 = 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?函数,比特币主要的启动过程。具体解读见第二部分。如果应用初始化主函数出错,则调用?Interrupt?函数进行中止,否则调用?WaitForShutdown?函数等待系统结束。WaitForShutdown?函数是一个无限循环函数。

我是区小白,Ulord全球社区联盟(优得社区)核心区块链开发者,区块链技术爱好者,深入研究比特币,以太坊,EOS Dash,Rsk,Java, Nodejs,PHP,Python,C++ 我希望能聚集更多区块链开发者,一起学习共同进步。

敬请期待下一篇文章:从零开始学蓑衣网小编2022习区块链技术(三)–怎么样接入比特币网络的关键步骤解析、创建比特币钱包,以及重要rpc指令?

从零开始学习区块链技术(二):怎么样接入比特币网络以及其原理分析 | 分享给朋友: