比特币源码解读十 加载钱包

2018-03-19  quasiceo


这篇我们看init.cpp中的AppInit2中的第八步:Step 8: load wallet 加载钱包。

加载钱包

上面这部分就是加载钱包的核心代码,首先通过判断fDisableWallet变量进行是否加载钱包的判断。这个变量在第三步(step 3参数传入内部标记)中获取的用户参数。

是否使用钱包

在这里我们需要说明一下zapwallettxes指令。这也是用户可选的参数。这个指令的意思是:清除钱包交易数据。我们已经知道一个交易的确认是要收交易手续费的。如果没有手续费或手续费过低。可能会造成这条交易数据在网络中游荡,不会被记录下来。所以我们可以通过清除自己的结点交易,并重新下载整个区块链来查找这条交易数据。所以这是一个供用户自己处理可选项。

我们可以看下钱包类的ZapWalletTx函数:

钱包类的清除交易函数

可以看到这个函数是通过CWalletDB类对象的ZapWalletTx()清除交易的。因为CWalletDB类是对钱包数据进行封装的操作类。而我们的钱包数据就存储在wallet.data中。CwalletDB类是继承自CDB类。CDB是对Berkeley 数据库操作的封装。

Berkeley DB是一个开源的文件数据库,介于关系数据库与内存数据库之间,使用方式与内存数据库类似,它提供的是一系列直接访问数据库的函数,而不是像关系数据库那样需要网络通讯、SQL解析等步骤。

CDB.h定义在db.h中,CWalletDB定义在walletdb.h中。大家可以自己去看下全体的代码。我们这里主要看下ZapWalletTx函数。

清除钱包的交易数据

可以看到此函数调用FindWalletTx函数查找此钱包的交易数据并存储在vTxHash中。最后调用EraseTx函数清除了所有的交易。

下面的代码又重新new 了个CWallet 钱包对象。并通过调用LoadWallet()下载钱包数据。当然LoadWallet最后也是调用的CWalletDB中的LoadWallet函数从数据库中重新加载数据。如果加载失败,则进行了相应的提示。

关于钱包就是我们创建交易的地方,这里存储了我们的密钥,和一些交易数据。这些内容就够我们分析好久的了。这里我们先了解一下。我们接着下面的代码进行分析。

升级钱包

这段代码通过判断用户是否使用upgradewallet命令进行钱包升级,具体逻辑是获取用户使用upgradewallet的版本参数也就是版本号进行判断,如果nMaxVersion为0(也就是没有输入要升级到的版本号,则使用CLIENT_VERSION系统定义的版本号。通过调用SetMinVersion进行升级。最后将当前版本设置为nMaxVersion.关于这个版本号我们有必要了解下。我们先看源码在version.h中。

版本号计算
clientversion.h中版本宏定义

通过源码可以看到CLIENT_VERSION是通过主版本号,次版本号,修订版本号和构建版本号共同构成。

我们接着看下面的代码:

生成钱包种子私钥

我在我的《比特币学习之钱包》中介绍过。比特币钱包是一堆包含私钥的地方。现在的钱包都是确定性钱包。所以需要一个种子私钥来生成后面的很多私钥。现在我们这个RandAddSeedPerfmon()就是生成种子私钥的。我们看下它的生成过程,在util.cpp中

种子私钥生成过程

这段代码是在WINDOWS系统中的生成过程。而且可以发现这个生成过程是很花费时间的。我们了解了种子私钥的过程,现在返回init.cpp中继续下面的代码可以看到pwalletMain钱包对象通过调用GetKeyFromPool从密钥池中得到一个公钥,并设置为默认的公钥,最后通过CPubkey对象的GetID()生成比特币地址并调用SetAddressBook()函数记录下来。我们知道比特币地址是通过哈希算法加密公钥生成的,现在我们看下代码的实现方式

生成比特币地址

可以看到比特币地址是使用Hash160加密算法得到的。这就是比特币地址的生成真面目了。关于理论基础可以看我之前写的《比特币学习之比特币地址》,此方法在key.h中。是我们所有密钥算法的源码实现的地方。Hash160就是我们平常说的双哈希也就是RIPEMD160(SHA256(K))这两个加密算法共同的实现。

我们看加载钱包最后的部分:

扫描钱包数据

第一部分RegisterWallet和我们在《比特币源码解读五》中的方式一样,是signal对象实现的对交易数据的各种侦听处理。具体大家可以自行阅读了。

注册钱包

下面的代码就是对钱包数据进行了一遍扫描处理。调用的具体函数是ScanForWalletTransactions()我们看下这个函数的具体实现,来了解下区块链的数据结构和遍历方式:

扫描钱包数据

通过这段代码我们可以看到所有的区块数据是存储在硬盘中的。而我们的chainActive是存储的区块的位置信息链,通过遍历位置链来获取相应的区块数据及交易数据。

好了。我们第八步的代码也就解析到这里。还是那句话,分析的可能不太准确,但是希望能带领自己和大家进入源码的世界,共同进步。



作者:区块链研习社比特币源码研读班,black



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。如发现有害或侵权内容,请点击这里 或 拨打24小时举报电话:4000070609 与我们联系。

    猜你喜欢
    发表评论评论公约
    喜欢该文的人也喜欢 更多