写在文章之前
之前我们介绍过一篇比特币的工作原理的文章。
文章链接:30分钟看懂比特币和区块链。
这篇文章基本能把比特币的基本工作机制讲明白了,而且老王觉得对于一些细节还是有点困扰,思索许久后,老王决定用他的一点微弱代码知识带你们一上去通读比特币源代码,深入代码世界一探究竟。
为了进一步理解比特币的工作机制,接出来我们将通过阅读其源代码来进一步理解比特币的工作原理。”比特币源码通读”系列文章比较偏专业性,针对的是具备一定的编码能力且对比特币特别感兴趣的读者,其他读者可阅读本文开始的那篇即可。
因为老王专业知识有限,文中如有错误,欢迎见谅,十分欢迎这方面的专业人士和老王一起阐述。
自从中本聪在2009年发布比特币源码以来比特币挖矿程序 linux,比特币的源码经过了多年的建立,引入了好多重要的改进,笔者下载的时侯早已是0.15.0版本了,因而下边的剖析也是以该版本的代码为根据。
下载地址:github
代码语言:c++
源码版本:0.15.0
目录结构:
这其中有些重要的文件夹,doc文件夹是一些说明文件比特币挖矿程序 linux,包括代码版本说明,编译文档等,src就是源码目录,是我们接出来要剖析的文件夹,test文件夹是一些功能测试文件夹。因为代码量十分大,若果全复制下来会吞没文章的主体,因而好多情况我还会采用更易阅读的伪代码的方式来展示,尽量不贴源码,假如想了解具体的细节的读者可以自己下载源码阅读。
好了,源码剖析第一篇:比特币环境的初始化过程。
在看代码之前让我们想想,当比特币程序启动时应当须要做什么事:
初始化网路,打算接收来自其他人的tx(transaction,英文称交易)或block(英文称之为区块,blockchain就是英文说的区块链),或则发送存在本机的tx或挖矿刚生成的block初始化我的皮夹,整理出帐户下的比特币及每位币的使用情况
下边我们瞧瞧比特币的代码是如何做的:
学过c或c++的读者应当都晓得程序启动的入口是main函数,该函数定义在bitcoind.cpp文件中,main函数定义如下:
intmain(intargc,char*argv[])
SetupEnvironment();
//Connectbitcoindsignalhandlers
noui_connect();
return(AppInit(argc,argv)?EXIT_SUCCESS:EXIT_FAILURE);
我们逐个看这几个方式,SetupEnvironment和noui_connect方式都是做一些打算工作,比如设置程序运行环境为windows,linux等,注册日志处理,我们来看AppInit技巧。
AppInit方式大约有几个过程:
首先检测参数,文件目录等AppInitBasicSetup方式初始化一些基本设置AppInitSanityChecks检测所有依赖的库是否齐全AppInitMain方式是我们重点关注的
下边我们继续看AppInitMain方式:
InitSignatureCache方式将签名缓存初始化,每次的签名会保存在缓存中InitScriptExecutionCache方式将脚本执行缓存初始化AppInitServers方式初始化httpserverVerifyWallets方式检测皮夹数据库的一致性newCBlockTreeDB().writeReIndexing()方式加载blockchain并检测创世块LoadBlockIndex方式从硬碟加载一些block索引到显存中StartWallets方式启动我的皮夹,我们须要了解它是怎样启动的
下边我们接着看StartWallets方式:
ReacceptWalletTransaction方式把皮夹关联的tx加载到显存中。它是怎样找寻tx并检测的呢?scheduler.scheduleEvery(MaybeCompactWalletDB,500)定义了一个线程,定期去刷新皮夹
下边我们瞧瞧ReacceptWalletTransactions源码:
voidCWallet::ReacceptWalletTransactions()
//Iftransactionsaren'tbeingbroadcasted,don'tletthemintolocalmempooleither
if(!fBroadcastTransactions)
return;
LOCK2(cs_main,cs_wallet);
std::mapmapSorted;
//Sortpendingwallettransactionsbasedontheirinitialwalletinsertionorder
for(std::pair&item:mapWallet)
constuint256&wtxid=item.first;
CWalletTx&wtx=item.second;
assert(wtx.GetHash()==wtxid);
intnDepth=wtx.GetDepthInMainChain();
if(!wtx.IsCoinBase()&&(nDepth==0&&!wtx.isAbandoned())){
mapSorted.insert(std::make_pair(wtx.nOrderPos,&wtx));
//Trytoaddwallettransactionstomemorypool
for(std::pair&item:mapSorted)
CWalletTx&wtx=*(item.second);
LOCK(mempool.cs);
CValidationStatestate;
wtx.AcceptToMemoryPool(maxTxFee,state);
该方式首先检测是否已设置成可以广播,之后对mapWallet中的tx进行遍历,做如下检测:
检测tx的hash值检测tx在区块链中的深度。检测tx是否是coinbase,是否是已遗弃状态。若果这种检测通过后把这种tx按次序装入到显存池中(memorypool)
在下一篇进一步介绍前,我先解释这儿提及的几个概念:
深度nDepth。深度指的是tx所在block与苯环上最新block的间隔block数量。侧链mainchain。侧链指的是当前比特币网路中公认的最长的那条区块链,在顾客端同时还存在有活跃链chainActive。Coinbasetx。这是tx的一种,在每位block中第一个都是coinbasetx,coinbasetx一般没有关联任何inputtxlinux操作系统下载,只有output,最典型的事例就是挖矿得到的系统奖励货币就是置于coinbase中的。Memorypool。在代码中是用mempool表示的,它保存着这些还不在block中的tx,在前面的运行中常常会碰到。
好了,本篇就到这儿了redhat linux下载,从下一篇开始我们来细读怎样创建一个新的tx。