bitcoin 源代码分析中p2p的代码在哪个文件中

sponsored links
比特币Bitcoin源代码安装编译
       比特币 (货币符号: ?;英文名:B英文缩写: BTC),是一种用于开源的P2P软件而产生的电子货币。比特币全局图是这样的:
在这儿主要介绍Linux下的比特币安装,我们选择 12.04的环境,安装相对容易得多。Windows下并不推荐,因为基于配置相以繁琐。
同时也可以参考build。
  先拉下源代码:
安装Berkeley DB 4.8以上版本:
sudo apt-get install libdb5.1++-dev
然后进入到相关目录:
cd bitcoin ./autogen.sh
./configure
如果你遇到这样的提示:configure: error: Found Berkeley DB other than 4.8, required for portable wallets 那就可以这样:
./configure --with-incompatible-bdb
如查遇到到这样的提示:checking for boostlib &= 1.20.0… configure: We could not detect the boost libraries (version 1.20 or higher). 那这样:
sudo apt-get install libboost-all-dev
然后再次configure,如果你需要bitcoin-qt前端,那需要安装
sudo apt-get install libqt4-core libqt4-gui libqt4-dev
再次configure,这次可以了
开始编译,大约5分钟,然后安装编译好的二进制文件
make install
想运行前端那执行
bitcoin-qt
bitcoind  -server –printtoconcole
接到下,是否挖矿就看您自己了。以当前时间为起点,连接testnet有9G的blockchain数据需要下载,livesite有35G的数据需要下载。
也可以从这里文件,以加快速度。后续会介绍关于比特币的更多内容。有兴趣可以阅读它的源代码。
资料LINK:
BitCoin比特币 wiki
Bitcoin比特币 源代码文档
Bitcoin比特币 中国
作者:Petter Liu
出处:/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。
1. 安装 libx11-dev(详见 http://blog.csdn.net/leonzhouwei/article/details/. 到 http://www.imagemagick.org/download/delegates/ 下载 jpegsrc.v9.tar.gz 3. 解压缩.编译安装 jpeg-9 4. 按照 http ...
Linux下源代码的编译安装 使用源代码安装软件的优点 获得最新的软件版本,及时修复bug 根据用户需要,灵活定制软件功能 应用场合举例 安装较新版本的应用程序时 自由软件的最新版本大都以源码的形式最先发布 当前安装的程序无法满足需要时 编译安装可由用户自行修改.定制功能 需要为应用程序添加新的功能时 用户可以重新配置.自由修改源代码,加入新的功能 源代码包 ...
使用包管理方式安装软件与编译源代码的区别,包管理方式提供的(以rpm为例)软件大多只保留了一部分常用功能,如果我们需要使用软件其它功能而rpm包没有,这咱情况下就需要编译源代码了.编译源代码的方式安装的软件,可以自由选择安装那些功能,而rpm是固定好的.源代码安装选择功能的灵活性好,rpm包安装则比较简便.而且大多数情况下,软件以源代码方式发行比rpm包要快 ...
linux下程序的编译安装我一直感觉很神秘,总是搞不懂为什么执行以下./configure加相关配置,然后make,make install一个程序就算安装完毕了.今天特意在网上搜索了一下相关的资料,大概了解了一下. 通常我们下载的源代码包,都是xxx.tar.gz或者xxx.tar.bz格式的,总之下载的软件包需要解压缩,会生成一个对应的目录xxx,然后呢 ...
Linux 源代码 安装vsftpd 2.3.4
分类: Unix/Linux 笔记 |
标签:linux
||字号 订阅 wget ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.3.4.tar.gz(官方地址,下载很慢,不推荐这个地址)bitcoin源码解析 - 交易 Transcation (一)10 months ago这两个关键成员变量。这两个成员变量分别代表着比特币交易的 “收入” 与 “支出”。比特币的交易并不是记录账户形的数据变化(比如我们采用银行的模型来描述 A 向 B 转账100元,那么银行在记录这个转账的过程中会出现3个记录,这三个记录连成了一个 Transaction (事务)过程:A 的账户减少100元,记录的id为 tid1,B的账户加上100元,记录的id为 tid2,一笔转账记录记录了tid1向tid2转账了100元,成为A账户减少与B账户增加的“关系连接”。),而是日志形:比特币的Tx 只记录A 向 B 转账的这个“关系连接”,这条日志记录只包含了 A 向 B 转账了 100 元这条信息。而这里的 in 就是记录着 从 ‘’谁“ 来(目前先简单的这样看,实际完全不止这样,后文会慢慢重新解释), out 就是转给了谁,而转账了多少钱是包含在 out 中的。在中本聪的命名风格是使用一个前缀代表这个属性的类型,如果是flag还会加上一个f。所以这里的 vin/vout 就是指代in 和 out 都是 vector 类型,所以这里我们可以看到,一个 Tx 的 in/out 是可以有多个的。在后文中,我们称呼 in 为 TxIn,out 为 TxOut (注意这里把 in out 比作两个人是完全不恰当的,之后会重新描述)而这两个类的另外两个属性int nVersion;
int nTimeLock;
前者显然是用来控制版本的(这个涉及到另一个区块链系统的核心缺陷问题 --
分叉 , 本系列可能暂时不会对这方面做出分析)而后者在 bitcoin v0.1 源码中并没有起到什么作用。但是这个属性在今后的 bitcoin 版本中提供了一个转账过程中能够约定时间的能力,因为这个版本不涉及就不进行分析描述了(从这里也可以看出中本聪的前瞻性)CTxIn / CTxOut从这步起,我们直接抛弃 ”两个人之间进行交易“这样的概念,直接认为在比特币的交易系统中是不具备”所有人“这样概念(这样肯定很奇怪因为都没有所有人了比特币还有什么意义,但之后会解释),而只是把 ”交易“ 看作 ”比特币流“ 的中转的中转节点,就像水流分叉合并的那些节点一样:典型的 bitcoin 交易链:(from )水流流量分叉图:而每个交易就是一个中转(分叉)节点,而每个交易的 in / out 就是 这个中转(分叉)节点的流入和流出。bitcoin 有一个相当相当重要的规定就是 每个 Tx 的 所有 In 进入了货币流必须在这个交易中全部流出去(流出去不代表成为其他Tx的In,而是必须要成为一个 TxOut。)举例来说:如果A 转账 100 给 B,但是现在A能控制的Out 有2个,一个是Out1是60,一个是Out2是50,那么A一检查自己的Out就会发现,60和50都不够100,那么就只能把 Out1 和 Out2 都作为当前要生产的 Tx 的 In。但是这种情况下,所有In的和就大于要支出的 100了。那么如果不付交易费的话,除去转账给 B 的 100 所对应的当前Tx的 Out,那么还会多出10。在bitcoin中就强行规定,这多出的10也要创建一个
Out 来锁住这10 块,以规定每笔交易的 In 和 Out 的总数都要相同。那么因为这 10 相当于我们通俗意义上的“找零”,所以这个 10 块的 Out 的锁当然就是 A 自己可以控制的锁,相当于这个Out指向了自己。所以这样我们可以看到,一个交易只含有一个输入和一个输出,那么这个交易并不是看作一个人转账到了另一个人身上,而是把比特币看作像流水一样的货币流,从某个地方流入到了这个交易的输入,由从这个交易的输出流到另一个地方去。那么接下来的问题就显而易见了--如何控制货币流的流动?答案你就是 CTxIn 和 CTxOut 的属性。我们来看下这两个类有些什么属性:class CTxIn{
COutPoint prevout;
CScript scriptSig;
unsigned int nSequence;
class CTxOut{
int64 nValue;
CScript scriptPubKey;
对于 CTxIn:COutPoint 这个类如其名,就是起到 Point 的作用,但是它的命名是 OutPoint, 最初接触的时肯定会感到迷惑。但这个名字确实起得十分正确:TxIn 虽然按照之前的分析可知它是 Tx 的 流入,而流入 Tx 必定来自于 另一个 Tx。 TxIn 只是 Tx 的一个属性,描述了 本 Tx 的 ”流入“ 的情况,但它本身也是个壳,而从哪个Tx流入的信息就是由 COutPoint 所记录。所以对于本 Tx 来说,TxIn 所含有的 ”从哪流入的“ 那个(上一个) Tx 对于本 Tx 来说 就是上一个 Tx 的 Out 的指向。而本 Tx 是不能持有上一个 Tx 的 out 的,所以就使用了 Point 指针来记录。nSequence 在 v0.1 中没有起到什么作用,也不会用来作校验,但是这个字段今后被作为了其他用途,而且成为了bitcoin的一个软分叉的最佳例子。对于 CTxOut:value 就是记录着”从这个出口会流出多少“的信息。简单的来说就是可以理解为通俗意义上的转账了。但是我们这里还是强调,首先理解bitcoin先抛开 支付交易 等概念,而是把 bitcoin 看成流动的水,而这里的 value 就是记录从这里会流出多少 bitcoin 的意思。显然一个 Tx 的所有 TxOut 的 value 的和 应该等于 所有 TxIn 流入的总和 (不考虑手续费,弱考虑手续费就是小于等于),否则这笔交易就应该认为是非法的(不能凭空多出钱来)。scriptSig / scriptPubkey那么没有介绍的 scriptSig 和 scriptPubkey 就是控制 ”凭什么从这里流出“ 的机制。这块绝对是 中本聪 创立 比特币的 又一大惊为天人的发明,这两个属性就是 导致今后著名的”智能合约“的雏形。今后将会花费详细的一篇文章仔细介绍。在这里我们先简单的介绍如下:在刚才的讨论中我们知道,比特币流从一个交易流动到了另一个交易,像这样一直传递下去。但是这样显然是不行的,因为没有人宣告这个”流“的归属。换句话说,我们在日常中使用100块钱进行交易,核心是因为这100块的纸币从一个人的手上流动到了另个一个人的手上。但是当你持有了这100块的纸币时,你就确认了这100块纸币流的归属。但是在比特币的体系中,请你直接抛弃这种思想,而是使用另一种方式来思考,而这种方式当你换个角度看的时候它就和你交易100块的纸币是相同的。这种思想那就是当我们重新审视交易的时候,我们发现货币流是从一个(多个)交易流向一个(多个)交易的过程。那么如果我们有独特的手段能够控制它为什么能流动,比如说在流出去的时候我们采取一个手段给这个出口 out 上一个锁,而当你想控制这个从这个出口出去的流的时候你就创造一把能打开这个锁的钥匙,作为下一个交易的 in 。也就是说我们连续的看2个交易的中间部分:前一个交易的 out 和 后一个交易的 in。如果我们能把 前一个 out 加一个锁,然后规定后一个 in 要能成立的条件是 in 附带的 钥匙 能够打开out锁。(维护为什么能开锁这个过程是由矿工挖矿保证,现在只说交易不说区块,所以可以先理解为这是天然存在的规则。)那么因为上锁和开锁是“个人”行为,但一个交易的out被上了一把只有一个特别的人才能打开的锁,那么就像本应该从这个out流出去的货币被“锁在了这个out”里面(注:这个上锁的过程不需要这个特别的人参与,这个特别的人只需要提供一点信息代表这把锁只能他打开就行(就是指地址))。那么这种行为就等价于只有这个特别的人才能“控制”这个Tx的Out,也就是只有这个特别的人才能 “占有” Out 里面被锁住的钱。虽然这个钱并不像现实生活中能够实实在在的把这100块钱拿到手上,而只能是通过 in/out 的锁控制 钱的流动。但是我们换个方向想,虽然我们只能提供这个“钥匙”,但是这个“钥匙和锁”能够控制 out 所含有的 货币流动,那么这个 in/out 的上锁开锁机制 是不是就相当于你占有了这笔钱?(因为虽然这个钱不是真正的在你手里(比如银行账户有个针对你的账户而bitcoin 系统没有),但是你可以控制一些 针对你的锁所锁定的钱的流动权利,那么就像水流的分叉点的出口只有你能开锁,虽然别人都看得到,但是因为别人不能开锁,那么别人也无可奈何,因为他们控制不了)。 所以我们可以看到,我们所谓的转账在bitcoin的系统当中,例如A转账100给B,那么就需要 B 向A 提供一些信息(bitcoin地址),这个信息不会暴露B的个人情况,但是可以表面B能够控制由这个信息产生的锁。随后 A 就可以创建一个交易,这个交易的out 就可以用B 提供的这个信息上了一把只有B能够控制的锁,然后这个交易的 in 就是 由 A 提供 A 能够控制的其他交易的Out 的 对应的钥匙。 如下图所示:好了,之上面这么大段的陈述过后,我们终于可以提出,CTxIn 和 CTxOut 的属性 scriptSig 和 scriptPubkey 就是刚在我们讨论中的 钥匙 和 锁。 scriptSig 就是用于对应签名的钥匙,而 scriptPubkey就是 B 提供了地址而生成的锁。而我们所说的实现钥匙和锁的功能,依靠的就是 这两个属性的类型 -& CScript从命名上可以看出,中本聪在设计之初就认为具有这样功能的东西应该是像”脚本“一样可以被”执行“,熟悉计算机的人当看到script 的命名就可以想象到 这个机制 是可以 ”被编程的”。而在bitcoin 的系统中也确实如此,bitcoin 提供了一系列的操作指令,可以让使用者自行编程。而验证的过程实际上就是执行了脚本。在此先不做过多描述,之后会有文章详细描述bitcoin的script系统。COutPoint这个类含有两个属性class COutPoint{
uint256 hash;
unsigned int n;
按照上文的解释,我们可以得到这里的 hash 指代的就是 txin 所来自的那个Tx的 hash, 而n指代这个 in 是来自上一个交易的第 n 个 out, 如下图所示:CInPoint这个类在我们对 bitcoin 的讨论中不是很重要,这个类只出现在一个维护 COutPoint与CInPoint的 map 中。所以我们认为 CInPoint 和 COutPoint 是 键值对应关系。当我们确认了一个 COutPoint 的时候,我们可以假装把这个COutPoint看作是上一个 Tx 的 Out, 那么 这个 map 对应的 CInPoint 意思就是指代为 上一个 Tx的Out 指向的 下一个它持有的属性 class CInPoint{
CTransaction* ptx;
unsigned int n;
CTransaction* 是一个 针对
COutPoint 这个Out 指向的 In 所在的那个交易。那么在COutPoint那个图的例子中就是指代当前的Tx 这个 Tx 的指针。而这里的 n 就是指代 这个 In 是当前的 Tx 的 第 n 个 In, 在上图中也同样是 0 (因为只有1个In)CScriptCScript 实际上就是一个 vector&unsigned char& 也就是说 Script 实际上就是一串 Bytes 流。只不过这个字节流 是可以被解析为 &指令& 或者 &指令& &数据& 这样的一个一个元信息。而一个 Script 就是这些元信息组成的字节流。所以 CScript 本身这个类 不重要,重要的是 Script 说代表的指令和数据,以及这些指令的组合关系以达到相应的效果。它的验证需要一个 VM 来执行(脚本),而执行(解析)指令的方式和指令的含义与规则就是VM的规则与实现CTxIndex / CDiskTxPos这两个类和bitcoin的协议也就没什么关系了,他们是用来Tx 在本地的存储与索引使用的。不过这里要注意,在bitcoin的源码中,CTxIndex 是很重要的一个类,它的存储,更新和删除控制这能否在本地存储中找到这个对应的 Tx 数据,以及标注这个Tx 是否被花费。class CTxIndex{
CDiskTxPos pos;
vector&CDiskTxPos& vSpent;
class CDiskTxPos{
unsigned int nFile;
unsigned int nBlockPos;
unsigned int nTxPos;
在存储中,bitcoin 使用 Tx 的hash 为键,CTxIndex 为值进行存储。所以在拿到一个 CTransaction(或其子类)可以通过得到这个Tx的 hash 索引本地的存储得到这个Tx 所对应的 TxIndex。而 TxIndex 的属性 vSpent 就是一个相当重要的属性,因为这关系到一个 Tx 的Out 是否是 UTXO(Unspent Transaction Output)。由前文的讨论可知,那么一个 UTXO 就是一个被上锁了但是没有被开锁过的 Out。而这个TxIndex 的 vSpent 是一个 vector ,它和当前 Tx 的 vout 相对应。这里我们要强调,Tx 的产生和 确认 不是同一个决定的,是之前所讨论的 Client 和 Server。产生Tx 的称为 client ,接受确认这个Tx 合法的是 Server, Client 和 Server 存储的CTxIndex 是不会进行传输的!所以CTxIndex 在 C/S 上是分别生成的。那么我们使用 CTxIndex 的 vSpent 来标识这个 Out 是不是一个 UTXO 就相当重要了。因为 C / S 分别的存储都是根据自己的历史生成的,所以如果 Client 要欺骗别人, 是不能在 别人自己的验证中通过的。举例来说就是 A 产生了Tx 并告诉别人来确认这个 Tx 是合法的,但是 A 使用的一个 in 来自的一个 Out 是已经被花费过的,比如我们假设这个Out所在的Tx叫做 Tx_prev,这个Out是第3个Out,但是A不管,仍然使用了这个被花费过的Out。那么当别人收到这个Tx进行验证的时候,他们就检查自己Tx_prev所对应的自己的本地存储的 Tx_index_prev ,然后一检查 vSpent[3] 是否是null, 如果是null 那么就是合法的,如果不是Null,那么就代表这个Out已经被花费过了。可见这里的验证是和A的本地存储无关的,A不可能修改自己的本地存储来欺骗别人。因为传输的内容只有 Tx, 而 TxIndex 是各个节点根据收到的Tx或block 自己生成的。所以节点们一检查发现 vSpent[3] 不是个 null, 那么就会认为 A的那个 Tx 是非法的。而 CDiskTxPos 是代表这这个 Tx 在本地存储的位置。 在bitcoin 源码中,Tx 的存储是紧密的排列在文件当中的,而找到这个Tx就是首先找到存储的文件,再找到这个Tx在这个文件中的偏移。所以 nFile和 nTxPos 就分别代表着是哪一个文件和在文件中的偏移位置。nBlockPos 代表这个 Tx 在 Block 中的位置。CMerkleTx这个类是 Tx 的子类,这个类使用来在Block 中相关处理的时候用的。CMerkleTx 是矿工(前文指代的server)所保存Tx时相关的类它在原本的Tx的基础上添加了class CMerkleTx : public CTransaction{
uint256 hashBlock;
vector&uint256& vMerkleBranch;
int nIndex;
3个属性,hashBlock代表着当前的 Tx 所在的Block 的hash(作为索引),vMerkleBranch是该Tx 在 merkle tree 中 所配对的所有hash值(这个配对的hash值在以后的文章会解释),这里是用来验证Tx 在block中的附加信息。index代表着该Tx在block中的位置。CWalletTx这个类是 CMerkleTx 的子类,实际上就是我们产生Tx以及和wallet相关的Tx。这里我们着重介绍Tx,和wallet的信息以及产生的过程就暂时不先在这里介绍。结尾以上就是对bitcoin中 Tx 相关的类的介绍。只能先说明 bitcoin 实现 Tx 的过程中使用了哪些类及类中的属性可能起到的作用。在下一篇文章中我将会介绍 Tx 的运作原理。而之后关于 Tx 的文章就是根据原理看源码是如何处理的。10收藏分享举报文章被以下专栏收录推荐阅读{&debug&:false,&apiRoot&:&&,&paySDK&:&https:\u002F\\u002Fapi\u002Fjs&,&wechatConfigAPI&:&\u002Fapi\u002Fwechat\u002Fjssdkconfig&,&name&:&production&,&instance&:&column&,&tokens&:{&X-XSRF-TOKEN&:null,&X-UDID&:null,&Authorization&:&oauth c3cef7c66aa9e6a1e3160e20&}}{&database&:{&Post&:{&&:{&isPending&:false,&contributes&:[{&sourceColumn&:{&lastUpdated&:,&description&:&&,&permission&:&COLUMN_PUBLIC&,&memberId&:6764027,&contributePermission&:&COLUMN_PUBLIC&,&translatedCommentPermission&:&all&,&canManage&:true,&intro&:&&,&urlToken&:&c_&,&id&:27284,&imagePath&:&4b70deef7&,&slug&:&c_&,&applyReason&:&0&,&name&:&金狗喵喵喵的区块链研习&,&title&:&金狗喵喵喵的区块链研习&,&url&:&https:\u002F\\u002Fc_&,&commentPermission&:&COLUMN_ALL_CAN_COMMENT&,&canPost&:true,&created&:,&state&:&COLUMN_NORMAL&,&followers&:385,&avatar&:{&id&:&4b70deef7&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&activateAuthorRequested&:false,&following&:false,&imageUrl&:&https:\u002F\\u002F4b70deef7_l.jpg&,&articlesCount&:10},&state&:&accepted&,&targetPost&:{&titleImage&:&https:\u002F\\u002Fv2-5d17e02b1db832cea284_r.jpg&,&lastUpdated&:,&imagePath&:&v2-5d17e02b1db832cea284.png&,&permission&:&ARTICLE_PUBLIC&,&topics&:[12,11145],&summary&:&比特币中的交易可谓是比特币的最核心部分。比特币由交易产生,而区块就是用来存储交易的。所以,交易是比特币存在的载体,同时也是比特币中最复杂的部分。交易的运作层层相扣,各个部分缺一不可,十分严密,由此体现出了中本聪高超的设计技巧。接下来将会花…&,&copyPermission&:&ARTICLE_COPYABLE&,&translatedCommentPermission&:&all&,&likes&:0,&origAuthorId&:0,&publishedTime&:&T20:17:49+08:00&,&sourceUrl&:&&,&urlToken&:,&id&:2363968,&withContent&:false,&slug&:,&bigTitleImage&:false,&title&:&bitcoin源码解析 - 交易 Transcation (一)&,&url&:&\u002Fp\u002F&,&commentPermission&:&ARTICLE_ALL_CAN_COMMENT&,&snapshotUrl&:&&,&created&:,&comments&:0,&columnId&:27284,&content&:&&,&parentId&:0,&state&:&ARTICLE_PUBLISHED&,&imageUrl&:&https:\u002F\\u002Fv2-5d17e02b1db832cea284_r.jpg&,&author&:{&bio&:&我超级懒的&,&isFollowing&:false,&hash&:&cb3b97fbae2e613fba0f76e7bd23fc76&,&uid&:08,&isOrg&:false,&slug&:&jin-xiao-94-7&,&isFollowed&:false,&description&:&&,&name&:&金晓&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fjin-xiao-94-7&,&avatar&:{&id&:&v2-a03f59f4f9d3ad3f3a4db6fc186c4c83&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},&memberId&:6764027,&excerptTitle&:&&,&voteType&:&ARTICLE_VOTE_CLEAR&},&id&:560606}],&title&:&bitcoin源码解析 - 交易 Transcation (一)&,&author&:&jin-xiao-94-7&,&content&:&\u003Cp\u003E比特币中的交易可谓是比特币的最核心部分。比特币由交易产生,而区块就是用来存储交易的。所以,交易是比特币存在的载体,同时也是比特币中最复杂的部分。交易的运作层层相扣,各个部分缺一不可,十分严密,由此体现出了中本聪高超的设计技巧。接下来将会花费多个章节逐步介绍bitcoin中的交易\u003C\u002Fp\u003E\u003Cp\u003E比特币或者类似的分布式系统在设计的时候会有一个和普通设计中有极大区别的地方:\u003C\u002Fp\u003E\u003Cp\u003E分布式中的每个节点既是 client 也是 server。\u003C\u002Fp\u003E\u003Cp\u003E所以在分布式系统的设计中,使用类来描述对象的时候,有时就要分清哪些情况下这个类是作为client使用的,哪些时候是作为server收到client的这个类使用。因为client和server运行的是同一套代码,而在实际运作过程中如果按照C\u002FS的这种模型(其实不应该这样看待,应该转换自己的思维变为设计p2p节点的思维)来看待,就会看到C产出的 Tx\u002FBlock 和 S 收到的 Tx\u002FBlock。所以这时候就需要分清类中的属性哪些是属于client\u002Fserver都等价对待的属性,哪些属性是分情况使用的。否则在看源码的过程中就很容易迷失自己的定位。\u003C\u002Fp\u003E\u003Ch2\u003E本章介绍交易在bitcoin源码当中的总体概况\u003C\u002Fh2\u003E\u003Cp\u003E本文只介绍 bitcoin 的 交易 在源码中是由哪几个类组合得到的,做个总体的介绍。而对于交易的原理,我们放在下一篇文章做详细介绍。本文会提前出现一些bitcoin的概念,但是目前并不需要知道指代什么,只需要先明白有这样的东西就足够了。\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-3cc82d8fade163f42575_b.jpg\& data-rawwidth=\&1072\& data-rawheight=\&924\& class=\&origin_image zh-lightbox-thumb\& width=\&1072\& data-original=\&https:\u002F\\u002Fv2-3cc82d8fade163f42575_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='1072'%20height='924'&&\u002Fsvg&\& data-rawwidth=\&1072\& data-rawheight=\&924\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&1072\& data-original=\&https:\u002F\\u002Fv2-3cc82d8fade163f42575_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fv2-3cc82d8fade163f42575_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Cp\u003E如上图的类图所示,这个UML图中包含了bitcoin交易相关的所有关键类。\u003C\u002Fp\u003E\u003Ch3\u003ECTransaction\u003C\u002Fh3\u003E\u003Cp\u003E在图中,最为核心的类的是 CTransaction 这个类就是我们常说的bitcoin的 “交易” (一般称为 Tx, 后文也会沿用这种说法)\u003C\u002Fp\u003E\u003Cp\u003E其实对于这个 Tx 类,这里只是一个壳,本身这个类并没有什么作用。这个类起作用的是\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Evector&CTxIn&\nvector&CTxOut&\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E这两个关键成员变量。这两个成员变量分别代表着比特币交易的 “收入” 与 “支出”。比特币的交易并不是记录账户形的数据变化(比如我们采用银行的模型来描述 A 向 B 转账100元,那么银行在记录这个转账的过程中会出现3个记录,这三个记录连成了一个 Transaction (事务)过程:A 的账户减少100元,记录的id为 tid1,B的账户加上100元,记录的id为 tid2,一笔转账记录记录了tid1向tid2转账了100元,成为A账户减少与B账户增加的“关系连接”。),而是日志形:比特币的Tx 只记录A 向 B 转账的这个“关系连接”,这条日志记录只包含了 A 向 B 转账了 100 元这条信息。而这里的 in 就是记录着 从 ‘’谁“ 来(目前先简单的这样看,实际完全不止这样,后文会慢慢重新解释), out 就是转给了谁,而转账了多少钱是包含在 out 中的。在中本聪的命名风格是使用一个前缀代表这个属性的类型,如果是flag还会加上一个f。所以这里的 vin\u002Fvout 就是指代in 和 out 都是 vector 类型,所以这里我们可以看到,一个 Tx 的 in\u002Fout 是可以有多个的。在后文中,我们称呼 in 为 TxIn,out 为 TxOut (注意这里把 in out 比作两个人是完全不恰当的,之后会重新描述)\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E而这两个类的另外两个属性\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnVersion\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnTimeLock\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E前者显然是用来控制版本的(这个涉及到另一个区块链系统的核心缺陷问题 --
分叉 , 本系列可能暂时不会对这方面做出分析)\u003C\u002Fp\u003E\u003Cp\u003E而后者在 bitcoin v0.1 源码中并没有起到什么作用。但是这个属性在今后的 bitcoin 版本中提供了一个转账过程中能够约定时间的能力,因为这个版本不涉及就不进行分析描述了(从这里也可以看出中本聪的前瞻性)\u003C\u002Fp\u003E\u003Ch3\u003ECTxIn \u002F CTxOut\u003C\u002Fh3\u003E\u003Cp\u003E从这步起,我们直接抛弃 ”两个人之间进行交易“这样的概念,直接认为在比特币的交易系统中是不具备”所有人“这样概念(这样肯定很奇怪因为都没有所有人了比特币还有什么意义,但之后会解释),而只是把 ”交易“ 看作 ”比特币流“ 的中转的中转节点,就像水流分叉合并的那些节点一样:\u003C\u002Fp\u003E\u003Cp\u003E典型的 bitcoin 交易链:(from \u003Ca href=\&http:\u002F\\u002F?target=https%3A\u002F\u002Fbitcoin.org\u002Fen\u002Fdeveloper-guide%23block-chain-overview\& class=\& wrap external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003EDeveloper Guide - Bitcoin\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E)\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-e7ca1cf71ec01a79cbf3e_b.jpg\& data-rawwidth=\&797\& data-rawheight=\&605\& class=\&origin_image zh-lightbox-thumb\& width=\&797\& data-original=\&https:\u002F\\u002Fv2-e7ca1cf71ec01a79cbf3e_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='797'%20height='605'&&\u002Fsvg&\& data-rawwidth=\&797\& data-rawheight=\&605\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&797\& data-original=\&https:\u002F\\u002Fv2-e7ca1cf71ec01a79cbf3e_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fv2-e7ca1cf71ec01a79cbf3e_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Cp\u003E水流流量分叉图:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-bba245a3f52aeafc1ebdc4_b.jpg\& data-rawwidth=\&747\& data-rawheight=\&393\& class=\&origin_image zh-lightbox-thumb\& width=\&747\& data-original=\&https:\u002F\\u002Fv2-bba245a3f52aeafc1ebdc4_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='747'%20height='393'&&\u002Fsvg&\& data-rawwidth=\&747\& data-rawheight=\&393\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&747\& data-original=\&https:\u002F\\u002Fv2-bba245a3f52aeafc1ebdc4_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fv2-bba245a3f52aeafc1ebdc4_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E而每个交易就是一个中转(分叉)节点,而每个交易的 in \u002F out 就是 这个中转(分叉)节点的流入和流出。\u003C\u002Fp\u003E\u003Cp\u003Ebitcoin 有一个相当相当重要的规定就是 每个 Tx 的 所有 In 进入了货币流必须在这个交易中全部流出去(流出去不代表成为其他Tx的In,而是必须要成为一个 TxOut。)\u003C\u002Fp\u003E\u003Cp\u003E举例来说:如果A 转账 100 给 B,但是现在A能控制的Out 有2个,一个是Out1是60,一个是Out2是50,那么A一检查自己的Out就会发现,60和50都不够100,那么就只能把 Out1 和 Out2 都作为当前要生产的 Tx 的 In。但是这种情况下,所有In的和就大于要支出的 100了。那么如果不付交易费的话,除去转账给 B 的 100 所对应的当前Tx的 Out,那么还会多出10。在bitcoin中就强行规定,这多出的10也要创建一个
Out 来锁住这10 块,以规定每笔交易的 In 和 Out 的总数都要相同。那么因为这 10 相当于我们通俗意义上的“找零”,所以这个 10 块的 Out 的锁当然就是 A 自己可以控制的锁,相当于这个Out指向了自己。\u003C\u002Fp\u003E\u003Cp\u003E所以这样我们可以看到,一个交易只含有一个输入和一个输出,那么这个交易并不是看作一个人转账到了另一个人身上,而是把比特币看作像流水一样的货币流,从某个地方流入到了这个交易的输入,由从这个交易的输出流到另一个地方去。那么接下来的问题就显而易见了--如何控制货币流的流动?答案你就是 CTxIn 和 CTxOut 的属性。\u003C\u002Fp\u003E\u003Cp\u003E我们来看下这两个类有些什么属性:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECTxIn\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003ECOutPoint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Eprevout\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003ECScript\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EscriptSig\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eunsigned\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnSequence\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E
\n\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECTxOut\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Eint64\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnValue\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003ECScript\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EscriptPubKey\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E\u003Cstrong\u003E对于 CTxIn:\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003ECOutPoint 这个类如其名,就是起到 Point 的作用,但是它的命名是 OutPoint, 最初接触的时肯定会感到迷惑。但这个名字确实起得十分正确:TxIn 虽然按照之前的分析可知它是 Tx 的 流入,而流入 Tx 必定来自于 另一个 Tx。 TxIn 只是 Tx 的一个属性,描述了 本 Tx 的 ”流入“ 的情况,但它本身也是个壳,而从哪个Tx流入的信息就是由 COutPoint 所记录。所以对于本 Tx 来说,TxIn 所含有的 ”从哪流入的“ 那个(上一个) Tx 对于本 Tx 来说 就是上一个 Tx 的 Out 的指向。而本 Tx 是不能持有上一个 Tx 的 out 的,所以就使用了 Point 指针来记录。\u003C\u002Fp\u003E\u003Cp\u003EnSequence 在 v0.1 中没有起到什么作用,也不会用来作校验,但是这个字段今后被作为了其他用途,而且成为了bitcoin的一个软分叉的最佳例子。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cstrong\u003E对于 CTxOut:\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003Evalue 就是记录着”从这个出口会流出多少“的信息。简单的来说就是可以理解为通俗意义上的转账了。但是我们这里还是强调,首先理解bitcoin先抛开 支付交易 等概念,而是把 bitcoin 看成流动的水,而这里的 value 就是记录从这里会流出多少 bitcoin 的意思。显然一个 Tx 的所有 TxOut 的 value 的和 应该等于 所有 TxIn 流入的总和 (不考虑手续费,弱考虑手续费就是小于等于),否则这笔交易就应该认为是非法的(不能凭空多出钱来)。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cstrong\u003EscriptSig \u002F scriptPubkey\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\u003Cp\u003E那么没有介绍的 scriptSig 和 scriptPubkey 就是控制 ”凭什么从这里流出“ 的机制。这块绝对是 中本聪 创立 比特币的 又一大惊为天人的发明,这两个属性就是 导致今后著名的”智能合约“的雏形。今后将会花费详细的一篇文章仔细介绍。在这里我们先简单的介绍如下:\u003C\u002Fp\u003E\u003Cp\u003E在刚才的讨论中我们知道,比特币流从一个交易流动到了另一个交易,像这样一直传递下去。但是这样显然是不行的,因为没有人宣告这个”流“的归属。换句话说,我们在日常中使用100块钱进行交易,核心是因为这100块的纸币从一个人的手上流动到了另个一个人的手上。但是当你持有了这100块的纸币时,你就确认了这100块纸币流的归属。\u003C\u002Fp\u003E\u003Cp\u003E但是在比特币的体系中,请你直接抛弃这种思想,而是使用另一种方式来思考,而这种方式当你换个角度看的时候它就和你交易100块的纸币是相同的。\u003C\u002Fp\u003E\u003Cp\u003E这种思想那就是当我们重新审视交易的时候,我们发现货币流是从一个(多个)交易流向一个(多个)交易的过程。那么如果我们有独特的手段能够控制它为什么能流动,比如说在流出去的时候我们采取一个手段给这个出口 out 上一个锁,而当你想控制这个从这个出口出去的流的时候你就创造一把能打开这个锁的钥匙,作为下一个交易的 in 。也就是说我们连续的看2个交易的中间部分:前一个交易的 out 和 后一个交易的 in。如果我们能把 前一个 out 加一个锁,然后规定后一个 in 要能成立的条件是 in 附带的 钥匙 能够打开out锁。(维护为什么能开锁这个过程是由矿工挖矿保证,现在只说交易不说区块,所以可以先理解为这是天然存在的规则。)那么因为上锁和开锁是“个人”行为,但一个交易的out被上了一把只有一个特别的人才能打开的锁,那么就像本应该从这个out流出去的货币被“锁在了这个out”里面(注:这个上锁的过程不需要这个特别的人参与,这个特别的人只需要提供一点信息代表这把锁只能他打开就行(就是指地址))。那么这种行为就等价于只有这个特别的人才能“控制”这个Tx的Out,也就是只有这个特别的人才能 “占有” Out 里面被锁住的钱。\u003C\u002Fp\u003E\u003Cp\u003E虽然这个钱并不像现实生活中能够实实在在的把这100块钱拿到手上,而只能是通过 in\u002Fout 的锁控制 钱的流动。但是我们换个方向想,虽然我们只能提供这个“钥匙”,但是这个“钥匙和锁”能够控制 out 所含有的 货币流动,那么这个 in\u002Fout 的上锁开锁机制 是不是就相当于你占有了这笔钱?(因为虽然这个钱不是真正的在你手里(比如银行账户有个针对你的账户而bitcoin 系统没有),但是你可以控制一些 针对你的锁所锁定的钱的流动权利,那么就像水流的分叉点的出口只有你能开锁,虽然别人都看得到,但是因为别人不能开锁,那么别人也无可奈何,因为他们控制不了)。 \u003C\u002Fp\u003E\u003Cp\u003E所以我们可以看到,我们所谓的转账在bitcoin的系统当中,例如A转账100给B,那么就需要 B 向A 提供一些信息(bitcoin地址),这个信息不会暴露B的个人情况,但是可以表面B能够控制由这个信息产生的锁。随后 A 就可以创建一个交易,这个交易的out 就可以用B 提供的这个信息上了一把只有B能够控制的锁,然后这个交易的 in 就是 由 A 提供 A 能够控制的其他交易的Out 的 对应的钥匙。 如下图所示:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-e6ca1bdc937ab2db203d9e7_b.jpg\& data-rawwidth=\&692\& data-rawheight=\&598\& class=\&origin_image zh-lightbox-thumb\& width=\&692\& data-original=\&https:\u002F\\u002Fv2-e6ca1bdc937ab2db203d9e7_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='692'%20height='598'&&\u002Fsvg&\& data-rawwidth=\&692\& data-rawheight=\&598\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&692\& data-original=\&https:\u002F\\u002Fv2-e6ca1bdc937ab2db203d9e7_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fv2-e6ca1bdc937ab2db203d9e7_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Cp\u003E好了,之上面这么大段的陈述过后,我们终于可以提出,CTxIn 和 CTxOut 的属性 scriptSig 和 scriptPubkey 就是刚在我们讨论中的 钥匙 和 锁。 scriptSig 就是用于对应签名的钥匙,而 scriptPubkey就是 B 提供了地址而生成的锁。\u003C\u002Fp\u003E\u003Cp\u003E而我们所说的实现钥匙和锁的功能,依靠的就是 这两个属性的类型 -& CScript\u003C\u002Fp\u003E\u003Cp\u003E从命名上可以看出,中本聪在设计之初就认为具有这样功能的东西应该是像”脚本“一样可以被”执行“,熟悉计算机的人当看到script 的命名就可以想象到 这个机制 是可以 ”被编程的”。而在bitcoin 的系统中也确实如此,bitcoin 提供了一系列的操作指令,可以让使用者自行编程。而验证的过程实际上就是执行了脚本。在此先不做过多描述,之后会有文章详细描述bitcoin的script系统。\u003C\u002Fp\u003E\u003Ch3\u003ECOutPoint\u003C\u002Fh3\u003E\u003Cp\u003E这个类含有两个属性\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECOutPoint\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Euint256\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Ehash\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eunsigned\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003En\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E按照上文的解释,我们可以得到这里的 hash 指代的就是 txin 所来自的那个Tx的 hash, 而n指代这个 in 是来自上一个交易的第 n 个 out, 如下图所示:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cnoscript\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-0fbbf_b.jpg\& data-rawwidth=\&684\& data-rawheight=\&267\& class=\&origin_image zh-lightbox-thumb\& width=\&684\& data-original=\&https:\u002F\\u002Fv2-0fbbf_r.jpg\&\u003E\u003C\u002Fnoscript\u003E\u003Cimg src=\&data:image\u002Fsvg+utf8,&svg%20xmlns='http:\u002F\u002Fwww.w3.org\u002FFsvg'%20width='684'%20height='267'&&\u002Fsvg&\& data-rawwidth=\&684\& data-rawheight=\&267\& class=\&origin_image zh-lightbox-thumb lazy\& width=\&684\& data-original=\&https:\u002F\\u002Fv2-0fbbf_r.jpg\& data-actualsrc=\&https:\u002F\\u002Fv2-0fbbf_b.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cbr\u003E\u003Ch3\u003ECInPoint\u003C\u002Fh3\u003E\u003Cp\u003E这个类在我们对 bitcoin 的讨论中不是很重要,这个类只出现在一个维护 COutPoint与CInPoint的 map 中。\u003C\u002Fp\u003E\u003Cp\u003E所以我们认为 CInPoint 和 COutPoint 是 键值对应关系。当我们确认了一个 COutPoint 的时候,我们可以假装把这个COutPoint看作是上一个 Tx 的 Out, 那么 这个 map 对应的 CInPoint 意思就是指代为 上一个 Tx的Out 指向的 下一个\u003C\u002Fp\u003E\u003Cp\u003E它持有的属性 \u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECInPoint\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003ECTransaction\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E*\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Eptx\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eunsigned\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003En\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003ECTransaction* 是一个 针对
COutPoint 这个Out 指向的 In 所在的那个交易。那么在COutPoint那个图的例子中就是指代当前的Tx 这个 Tx 的指针。而这里的 n 就是指代 这个 In 是当前的 Tx 的 第 n 个 In, 在上图中也同样是 0 (因为只有1个In)\u003C\u002Fp\u003E\u003Ch3\u003ECScript\u003C\u002Fh3\u003E\u003Cp\u003ECScript 实际上就是一个 vector&unsigned char& 也就是说 Script 实际上就是一串 Bytes 流。只不过这个字节流 是可以被解析为 &指令& 或者 &指令& &数据& 这样的一个一个元信息。而一个 Script 就是这些元信息组成的字节流。\u003C\u002Fp\u003E\u003Cp\u003E所以 CScript 本身这个类 不重要,重要的是 Script 说代表的指令和数据,以及这些指令的组合关系以达到相应的效果。\u003C\u002Fp\u003E\u003Cp\u003E它的验证需要一个 VM 来执行(脚本),而执行(解析)指令的方式和指令的含义与规则就是VM的规则与实现\u003C\u002Fp\u003E\u003Ch3\u003ECTxIndex \u002F CDiskTxPos\u003C\u002Fh3\u003E\u003Cp\u003E这两个类和bitcoin的协议也就没什么关系了,他们是用来Tx 在本地的存储与索引使用的。不过这里要注意,在bitcoin的源码中,CTxIndex 是很重要的一个类,它的存储,更新和删除控制这能否在本地存储中找到这个对应的 Tx 数据,以及标注这个Tx 是否被花费。\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECTxIndex\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003ECDiskTxPos\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003Epos\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Evector\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003ECDiskTxPos\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E&\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EvSpent\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECDiskTxPos\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eunsigned\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnFile\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eunsigned\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnBlockPos\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eunsigned\u003C\u002Fspan\u003E \u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnTxPos\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E在存储中,bitcoin 使用 Tx 的hash 为键,CTxIndex 为值进行存储。所以在拿到一个 CTransaction(或其子类)可以通过得到这个Tx的 hash 索引本地的存储得到这个Tx 所对应的 TxIndex。\u003C\u002Fp\u003E\u003Cp\u003E而 TxIndex 的属性 vSpent 就是一个相当重要的属性,因为这关系到一个 Tx 的Out 是否是 UTXO(Unspent Transaction Output)。由前文的讨论可知,那么一个 UTXO 就是一个被上锁了但是没有被开锁过的 Out。而这个TxIndex 的 vSpent 是一个 vector ,它和当前 Tx 的 vout 相对应。\u003C\u002Fp\u003E\u003Cp\u003E这里我们要强调,Tx 的产生和 确认 不是同一个决定的,是之前所讨论的 Client 和 Server。产生Tx 的称为 client ,接受确认这个Tx 合法的是 Server, Client 和 Server 存储的CTxIndex 是不会进行传输的!所以CTxIndex 在 C\u002FS 上是分别生成的。那么我们使用 CTxIndex 的 vSpent 来标识这个 Out 是不是一个 UTXO 就相当重要了。因为 C \u002F S 分别的存储都是根据自己的历史生成的,所以如果 Client 要欺骗别人, 是不能在 别人自己的验证中通过的。\u003C\u002Fp\u003E\u003Cp\u003E举例来说就是 A 产生了Tx 并告诉别人来确认这个 Tx 是合法的,但是 A 使用的一个 in 来自的一个 Out 是已经被花费过的,比如我们假设这个Out所在的Tx叫做 Tx_prev,这个Out是第3个Out,但是A不管,仍然使用了这个被花费过的Out。那么当别人收到这个Tx进行验证的时候,他们就检查自己Tx_prev所对应的自己的本地存储的 Tx_index_prev ,然后一检查 vSpent[3] 是否是null, 如果是null 那么就是合法的,如果不是Null,那么就代表这个Out已经被花费过了。可见这里的验证是和A的本地存储无关的,A不可能修改自己的本地存储来欺骗别人。因为传输的内容只有 Tx, 而 TxIndex 是各个节点根据收到的Tx或block 自己生成的。所以节点们一检查发现 vSpent[3] 不是个 null, 那么就会认为 A的那个 Tx 是非法的。\u003C\u002Fp\u003E\u003Cp\u003E而 CDiskTxPos 是代表这这个 Tx 在本地存储的位置。 在bitcoin 源码中,Tx 的存储是紧密的排列在文件当中的,而找到这个Tx就是首先找到存储的文件,再找到这个Tx在这个文件中的偏移。所以 nFile和 nTxPos 就分别代表着是哪一个文件和在文件中的偏移位置。\u003C\u002Fp\u003E\u003Cp\u003EnBlockPos 代表这个 Tx 在 Block 中的位置。\u003C\u002Fp\u003E\u003Ch3\u003ECMerkleTx\u003C\u002Fh3\u003E\u003Cp\u003E这个类是 Tx 的子类,这个类使用来在Block 中相关处理的时候用的。CMerkleTx 是矿工(前文指代的server)所保存Tx时相关的类\u003C\u002Fp\u003E\u003Cp\u003E它在原本的Tx的基础上添加了\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&k\&\u003Eclass\u003C\u002Fspan\u003E \u003Cspan class=\&nc\&\u003ECMerkleTx\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E \u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003ECTransaction\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E{\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Epublic\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E:\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Euint256\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EhashBlock\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Evector\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Euint256\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E&\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EvMerkleBranch\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n
\u003Cspan class=\&kt\&\u003Eint\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EnIndex\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E;\u003C\u002Fspan\u003E\n\u003Cspan class=\&p\&\u003E};\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E3个属性,hashBlock代表着当前的 Tx 所在的Block 的hash(作为索引),vMerkleBranch是该Tx 在 merkle tree 中 所配对的所有hash值(这个配对的hash值在以后的文章会解释),这里是用来验证Tx 在block中的附加信息。index代表着该Tx在block中的位置。\u003C\u002Fp\u003E\u003Ch3\u003ECWalletTx\u003C\u002Fh3\u003E\u003Cp\u003E这个类是 CMerkleTx 的子类,实际上就是我们产生Tx以及和wallet相关的Tx。这里我们着重介绍Tx,和wallet的信息以及产生的过程就暂时不先在这里介绍。\u003C\u002Fp\u003E\u003Ch2\u003E结尾\u003C\u002Fh2\u003E\u003Cp\u003E以上就是对bitcoin中 Tx 相关的类的介绍。只能先说明 bitcoin 实现 Tx 的过程中使用了哪些类及类中的属性可能起到的作用。在下一篇文章中我将会介绍 Tx 的运作原理。而之后关于 Tx 的文章就是根据原理看源码是如何处理的。\u003C\u002Fp\u003E&,&updated&:new Date(&T12:17:49.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:5,&collapsedCount&:0,&likeCount&:10,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&titleImage&:&https:\u002F\\u002Fv2-5d17e02b1db832cea284_r.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&reviewers&:[],&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&区块链(Blockchain)&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&比特币 (Bitcoin)&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&同济大学&}],&adminClosedComment&:false,&titleImageSize&:{&width&:1200,&height&:889},&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&column&:{&slug&:&c_&,&name&:&金狗喵喵喵的区块链研习&},&tipjarState&:&inactivated&,&annotationAction&:[],&sourceUrl&:&&,&pageCommentsCount&:5,&hasPublishingDraft&:false,&snapshotUrl&:&&,&publishedTime&:&T20:17:49+08:00&,&url&:&\u002Fp\u002F&,&lastestLikers&:[{&bio&:&个人站长,BAT攻城狮&,&isFollowing&:false,&hash&:&a0976ba148&,&uid&:16,&isOrg&:false,&slug&:&zhihubuy&,&isFollowed&:false,&description&:&个人站长,做最极客的事情 !&,&name&:&Razzit&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fzhihubuy&,&avatar&:{&id&:&v2-f96f2b5a61c720f2c956a56d937f5ae5&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&seize the day&,&isFollowing&:false,&hash&:&358af5d3b69dfe139ef37a755fc53884&,&uid&:48,&isOrg&:false,&slug&:&woo-woo&,&isFollowed&:false,&description&:&力量boy&,&name&:&utanbo&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fwoo-woo&,&avatar&:{&id&:&f6e24f3ab&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:null,&isFollowing&:false,&hash&:&26d812daeff07ed59bb5b861eda0439b&,&uid&:168000,&isOrg&:false,&slug&:&cai-liang-du&,&isFollowed&:false,&description&:&&,&name&:&蔡良度&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fcai-liang-du&,&avatar&:{&id&:&v2-5e3c5b57c84aa93bd7576dec5d3d343c&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&&,&isFollowing&:false,&hash&:&ac29cd1a723d828d39d612&,&uid&:673200,&isOrg&:false,&slug&:&xing-shuang-huan-de-fu-sheng-meng&,&isFollowed&:false,&description&:&沉迷区块链&,&name&:&星霜换得浮生梦&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fxing-shuang-huan-de-fu-sheng-meng&,&avatar&:{&id&:&v2-a8ca21ed1f58dc91d8055d7&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&A new bee of IT&,&isFollowing&:false,&hash&:&776b499bdc0aee150adbeaf700d1de61&,&uid&:16,&isOrg&:false,&slug&:&shen-lin-hong&,&isFollowed&:false,&description&:&&,&name&:&hawkinggg&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fshen-lin-hong&,&avatar&:{&id&:&04d12d87af&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false}],&summary&:&\u003Cimg src=\&http:\u002F\\u002Fv2-3cc82d8fade163f2.png\& data-rawwidth=\&1072\& data-rawheight=\&924\& class=\&origin_image inline-img zh-lightbox-thumb\& data-original=\&http:\u002F\\u002Fv2-3cc82d8fade163f42575_r.png\&\u003E比特币中的交易可谓是比特币的最核心部分。比特币由交易产生,而区块就是用来存储交易的。所以,交易是比特币存在的载体,同时也是比特币中最复杂的部分。交易的运作层层相扣,各个部分缺一不可,十分严密,由此体现出了中本聪高超的设计技巧。接下来将会花…&,&reviewingCommentsCount&:0,&meta&:{&previous&:{&isTitleImageFullScreen&:false,&rating&:&none&,&titleImage&:&https:\u002F\\u002F50\u002Fv2-eb3b91aabd0c4f0f3f99_xl.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&区块链(Blockchain)&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&比特币 (Bitcoin)&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&同济大学&}],&adminClosedComment&:false,&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&author&:{&bio&:&我超级懒的&,&isFollowing&:false,&hash&:&cb3b97fbae2e613fba0f76e7bd23fc76&,&uid&:08,&isOrg&:false,&slug&:&jin-xiao-94-7&,&isFollowed&:false,&description&:&&,&name&:&金晓&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fjin-xiao-94-7&,&avatar&:{&id&:&v2-a03f59f4f9d3ad3f3a4db6fc186c4c83&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},&content&:&\u003Cp\u003E上一篇文章详细描述的如何让bitcoin v1.0源码通过编译,本篇将描述第一次运行过程中修改出现过的问题。\u003C\u002Fp\u003E\u003Ch2\u003E一、数据库dll加载出错\u003C\u002Fh2\u003E\u003Cp\u003E不清楚这个问题是不是个例,bitcoin使用的数据库 Berkeley DB v4.8 在oracle官网上下载安装后\u003C\u002Fp\u003E\u003Ch2\u003E1. 使用release版本的lib和dll\u003C\u002Fh2\u003E\u003Cp\u003E直接使用release版本的dll在debug下运行bitcoin源码会第184行左右,在ReadAtCursor函数中的 free 处崩溃:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E
\u003Cspan class=\&c1\&\u003E\u002F\u002F Clear and free memory\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Ememset\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EdatKey\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eget_data\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(),\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EdatKey\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eget_size\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E());\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Ememset\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EdatValue\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eget_data\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(),\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EdatValue\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eget_size\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E());\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Efree\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EdatKey\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eget_data\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E());\u003C\u002Fspan\u003E \u003Cspan class=\&c1\&\u003E\u002F\u002F 很可能在这个地方崩溃\u003C\u002Fspan\u003E\n
\u003Cspan class=\&n\&\u003Efree\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EdatValue\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E.\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Eget_data\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E());\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E产生的原因是:\u003C\u002Fp\u003E\u003Cblockquote\u003EHEAP[bitcoin-v0.1.exe]: Invalid address specified to RtlValidateHeap( 177208 )\u003C\u002Fblockquote\u003E\u003Cp\u003E呃··· 其实我不知道产生的原因是什么,简单的搜索可能的原因是:\u003C\u002Fp\u003E\u003Cblockquote\u003E在不同模块(工程)之间传递 C++ 类,\u003Cb\u003E而这两个模块用了不同的运行时库(Runtime Library)设置\u003C\u002Fb\u003E。\u003Cbr\u003E例如:EXE 模块调用 DLL 模块里传递 C++ 类的函数,但 DLL 模块使用静态链接(Release 是 Multi-threaded (\u002FMT)、Debug 是 Multi-threaded Debug (\u002FMTd))方式编译,而 EXE 模块使用动态链接(Release 是 Multi-threaded DLL (\u002FMD)、Debug 是 Multi-threaded Debug DLL (\u002FMDd))方式编译。\u003Cbr\u003E&来自这个链接
\u003Ca href=\&http:\u002F\\u002F?target=http%3A\u002F\u002Fblog.csdn.net\u002FchenyujingFarticle\u002Fdetails\u002F8244718\& class=\& wrap external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003EHEAP[xxx.exe]:Invalid Address specified to RtlValidateHeap 错误的解决方法总结\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E&\u003C\u002Fblockquote\u003E\u003Cp\u003E我也不清楚是不是这个原因啦,这个问题先搁置下···· \u003C\u002Fp\u003E\u003Ch2\u003E2. 使用debug版本的 lib 和 dll\u003C\u002Fh2\u003E\u003Cp\u003E直接使用安装包中自带的那个 libdb48d.lib 和 libdb48d.dll运行是\u003Cb\u003E直接崩溃!\u003C\u002Fb\u003E如图:\u003C\u002Fp\u003E\u003Cfigure\u003E\u003Cimg src=\&https:\u002F\\u002Fv2-5f3fe51dcd68e2f4aaa29a6_b.jpg\& data-rawwidth=\&472\& data-rawheight=\&177\& class=\&origin_image zh-lightbox-thumb\& width=\&472\& data-original=\&https:\u002F\\u002Fv2-5f3fe51dcd68e2f4aaa29a6_r.jpg\&\u003E\u003C\u002Ffigure\u003E\u003Cp\u003E至今不知道原因!!! 我给oracle神教的产品给跪了。。。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E[更新]\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E原因已经找到:\u003C\u002Fp\u003E\u003Cp\u003Eoracle在提供berkeley db windows 的包的时候,所编译出来的libdb48d.dll是在vs2005或者是vs2008平台下构建的。它在构建这个libdb48.dll和 libdb48d.dll的时候分别依赖了8.0.版本的libdb48.dll和libdb48d.dll。这丫是个历史遗留问题,参考:\u003C\u002Fp\u003E\u003Cp\u003E\u003Ca href=\&http:\u002F\\u002F?target=https%3A\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSide-by-side_assembly\& class=\& wrap external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003ESide-by-side assembly\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E\u003C\u002Fp\u003E\u003Cp\u003E这2个dll只会在安装vs2005和vs2008的时候存在,以后都只会以兼容库的形式存在。但是关键是这个现在绑定版本,所以就造成了crash。解决方法就是下面的第3点,重新编译。至于release为什么会自动存在,那是因为我在安装berkeley db的时候安装包把安装的
填写到了 path 变量当中,而在这个 \\bin 目录下已经提供了8.0. 版本的libdb48.dll。但是它丫却没有在 \\bin\\debug 目录下提供 libdb48d.dll。所以就造成了 release 能运行,但是因为其他原因崩溃,而debug是直接运行不起来的。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ch2\u003E3. 解决方法\u003C\u002Fh2\u003E\u003Cp\u003E因为安装包中的release和debug都无法运行,所以只能自己编译出Berkeley DB的lib和dll\u003C\u002Fp\u003E\u003Cp\u003E假设现在的 berkeley db 的根目录是
\\&bdbroot&\u003C\u002Fp\u003E\u003Cp\u003E那么在
\\&bdbroot&\\db-4.8.30\\build_windows 目录下可以找到 Berkeley_DB.sln\u003C\u002Fp\u003E\u003Cp\u003E打开它向上兼容后,进行项目构建,然后将一个example项目设为主项目进行运行。如果能运行成功就是构建成功并且能够正常运行。\u003C\u002Fp\u003E\u003Cp\u003E此时在
\\&bdbroot&\\db-4.8.30\\build_windows\\Win32\\Debug\\ 目录下可以发现 libdb48d.lib 和 libdb48d.dll 这两个文件。而这两个文件就是在自己平台上编译出来的动态链接库。\u003C\u002Fp\u003E\u003Cp\u003E之后把bitcoin源码的关于Berkeley DB 的依赖库修改为新的路径,然后就可以正常运行了。。。\u003C\u002Fp\u003E\u003Cp\u003E这里修改的路径就是 $(BDBPath)\\db-4.8.30\\build_windows\\Win32\\Debug\\
(参照上一篇)\u003C\u002Fp\u003E\u003Cp\u003E然后把
libdb48d.dll 拷贝到 bitcoin项目的 libs 目录下。\u003C\u002Fp\u003E\u003Ch2\u003E二、wxWidgets 高版本兼容问题\u003C\u002Fh2\u003E\u003Cp\u003E\u003Cb\u003Eps: 以下的崩溃很可能是因为wxWidgets版本高的原因,要是版本低于3.0\u002F或者2.8?(可能)很可能就没这些问题\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ch2\u003E1. 运行崩溃\u003C\u002Fh2\u003E\u003Cp\u003E崩溃的原因主要是由于在wxWidgets 3.0 还是 2.8 收紧了 Sizer
布局的 Align 规则检查的严格性。当布局的flag出现:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EwxEXPAND\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E|\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EwxALIGN_CENTER_XXX\u003C\u002Fspan\u003E \n\u003Cspan class=\&c1\&\u003E\u002F\u002F 或者是\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 当 Sizer 设置成 Verical 而子元素在 Add 进入 Sizer 的时候设置为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EwxALIGN_CENTER_VERICAL\u003C\u002Fspan\u003E
\u003Cspan class=\&c1\&\u003E\u002F\u002F horizontal 同理\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E所以出现问题的地方为:\u003C\u002Fp\u003E\u003Cp\u003E文件
uibase.cpp\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&c1\&\u003E\u002F\u002F 133L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F bSizer3-&Add(m_panel14, 1, wxEXPAND|wxALIGN_BOTTOM|wxALL, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer3\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Em_panel14\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E1\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxEXPAND\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E|\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxALL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 357L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F bSizer57-&Add(m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer57\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Em_staticText32\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxALL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 363L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002FbSizer56-&Add(m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer56\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Em_staticText31\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxTOP\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E|\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxBOTTOM\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E|\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxLEFT\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 366L
\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002FbSizer56-&Add(m_textCtrlTransactionFee, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer56\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Em_textCtrlTransactionFee\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxALL\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F461L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002FbSizer60-&Add(bSizer61, 0, wxALIGN_RIGHT|wxEXPAND, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer60\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EbSizer61\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxEXPAND\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 1751L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002FbSizer81-&Add(m_textCtrl1, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer81\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Em_textCtrl1\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxALL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E|\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxEXPAND\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 1762L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002FbSizer81-&Add(m_textCtrl2, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EbSizer81\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EAdd\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003Em_textCtrl2\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E0\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxALL\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E|\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxEXPAND\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E5\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E同时,在该文件中有其他瑕疵点:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-cpp\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003E\u003Cspan class=\&c1\&\u003E\u002F\u002F 463L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002Fthis-&SetSizer(bSizer60);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Ethis\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003ESetSizerAndFit\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EbSizer60\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 604L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F this-&SetSizer(bSizer21);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Ethis\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003ESetSizerAndFit\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EbSizer21\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 1786L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002Fthis-&SetSizer(bSizer79);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&k\&\u003Ethis\u003C\u002Fspan\u003E\u003Cspan class=\&o\&\u003E-&\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003ESetSizerAndFit\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&n\&\u003EbSizer79\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E);\u003C\u002Fspan\u003E\n\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 487L\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002FfgSizer1 = new wxFlexGridSizer(3, 2, 0, 0);\u003C\u002Fspan\u003E\n\u003Cspan class=\&c1\&\u003E\u002F\u002F 修改为\u003C\u002Fspan\u003E\n\u003Cspan class=\&n\&\u003EfgSizer1\u003C\u002Fspan\u003E \u003Cspan class=\&o\&\u003E=\u003C\u002Fspan\u003E \u003Cspan class=\&k\&\u003Enew\u003C\u002Fspan\u003E \u003Cspan class=\&n\&\u003EwxFlexGridSizer\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E(\u003C\u002Fspan\u003E\u003Cspan class=\&mi\&\u003E4\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E \u003Cspan class=\&mi\&\u003E2\u003C\u002Fspan\u003E\u003Cspan class=\&p\&\u003E,\u003C\u002Fspan\u003E

我要回帖

更多关于 bitcoin源代码解析pdf 的文章

 

随机推荐