当前位置:   金科网 > 区块链 > 正文

比特币后端全解析

在上节课的学习中,我们了解到比特币前端的组成,今天这节课,我们继续“拆解”比特币,从比特币中一观密码货币的“后端”是什么样子。

比特币节点后端负责参与比特币网络的通信互联,维护区块链,验证区块、交易,广播、转播传递区块交易信息。比特币的后台程序主要是由bitcoind,以及挖矿节点程序构成。比特币核心bitcoin-qt实际上是包含前后端(除挖矿功能以外)的一体化节点。

1. 比特币节点后端-区块链管理

区块链管理的代码逻辑都在main.cpp程序中实现。主要包括4个部分:

下载区块链:在比特币全节点第一次加入网络运行时,先要下载并验证整条区块链. “区块报头先行”(header first),一个初始区块链下载方式,新的节点先从邻节点下载所有的区块报头,再并行地从多个邻节点同时下载不同区间的区块大大提升了整条区块链的下载速度。

接收区块链:现有节点在开启时(非第一次)会先将整个区块链的索引从LevelDB调进内存.需要注意的是,该区块链的索引不是单条的链,而可能是一个树,也就是说每个区块只有一个父区块,但可能有多个子区块,因为子区块形成暂时分叉,需要逐渐发现哪个子区块属于最长的链条。

区块链验证:在区块链管理中,连接区块函数ConnectBlock()是一个检测“双花”交易的关键.该函数对新接收的区块中的所有交易进行检测,验证是否每个交易的比特币来源都能在当前的“尚未花比特币”(Unspend Transaction Output,UTXO)记录中找到匹配。

比特币后端全解析

重组区块链:当节点发现网络中有一条不基于它当前区块链的一条更长区块链时,它需要断开现有的区块并对区块链进行重组。

大部分重组只是一个区块的重组,多发生在不同矿工几乎同时挖到合法的区块时。

断开区块、重组区块链涉及UTXO更改,被断开的区块中交易会回退到交易内存池,这个时候“回滚”记录就可以用来回滚断开区块中的交易。

2.  比特币节点后端-区块验证

· 交易验证模块会基于以下条件检查收到的比特币交易是否合规:
· 交易的格式是数据结构必须正确
· 交易的输入和输出不能为空;(Coinbase交易没有输入)。
· 交易的大小不能超过定义的区块最大值MAX_BLOCK_SIZE(最早为1MB,后来逐渐调整)。
· 每个交易的输出,以及所有输出的合计,必须在一定范围内,也就是大于0,小于2100万。
· 交易输入的哈希值不能为零,不应该转Coinbase交易。
· nLockTime小于等于INT_MAX。
· 交易的字节大小要等于或大于100。
· 交易的签名操作数要小于签名操作的上限。
· 锁定脚本(scriptPubkey)必须是标准格式。
· 和收到的交易相匹配的交易必须能在当前交易池或是主链上某个区块中找到。
· 对交易的每个输入,如果其对应的UTXO输出能在当前交易池中找到,该交易必须拒绝(双花交易),因为当前交易池是未经记录在区块链中的· 交易,而交易的每个输入应该来自确认的UTXO,如果在当前交易池中找到,那就是双花交易。
· 对交易的每个输入,如果其对应的UTXO输出不能在主链或当前交易池中找到,该交易是一个孤儿交易,应将该交易放入孤儿交易池中。
· 对交易中的每个输入,如果其对应的UTXO输出是一个挖矿初始(coinbase)交易,该初始交易应该获得100个确认区块的确认(普通交易是6个确认区块的确认)。
· 对交易中的每个输入,其对应的输出必须是UTXO(存在且没被花掉)。
· 用对应的输出交易来获得输入的值,检查每个输入的值及其合计,应该在允许的区间(0~2100万比特币)。
· 如果一个交易的输入合计小于输出总计,则拒绝该交易。
· 如果交易的费用太低,则拒绝该交易。
· 每个输入的解锁脚本(unlocking script)必须和相应输出的锁定脚本(locking script)共同验证交易的合规性。

最后这个检查是比特币平台设计的精髓,比特币的一个很大的创新是依靠脚本来验证交易的合法性,即每一个将要花掉的比特币必须有相应的来源。

锁定脚本是由一连串堆栈命令和公钥哈希组成,公钥哈希即RIPEMD160(SHA256(公钥)),大小20字节;锁定脚本格式为:

OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG 

解锁脚本是由签名与公钥组成,这就保证了必须拥有私钥的用户才能对某一笔交易进行解锁.解锁脚本格式为:<Sig> <PubKey>

比特币是将解锁脚本和锁定脚本串起来一同执行,如果最后结果是逻辑值“真”(TRUE),则验证该交易的比特币来源是合法的. 脚本执行的过程和每个脚本执行后的堆栈状态如下:

· 由于是堆栈式计算引擎,因此作为数值的<sig>和<pubKey>相继入栈.当执行脚本OP_DUP时,它将堆栈头的<pubKey>复制一份也压入堆栈。

· 脚本OP_HASH160执行,将把堆栈头的<pubKey>弹出,并用HASH160算法进行哈希处理,哈希结果放回堆栈.然后遇到<pubKeyHash?>数值,该数值也被压入堆栈。

· 脚本OP_EQUALVERIFY把堆栈头端的两个哈希值都弹出,并进行比较.如果不一样,验证就出错,交易不合法.如果验证通过,堆栈只剩下<sig>和<pubKey>。

· 最后脚本OP_CHECKSIG将两者弹出,执行检查签名的脚本,验证该交易签名是否是由拥有该公钥对应用户用其私钥签的,如果是,交易就是合法交易,否则就是不合法交易。

比特币后端全解析