比特币的所有信息,包括比特币的发行和交易记录都记录在一个个的区块里面,每个区块就像会计记账本里面的账页,每一页账页里都记录了新的交易信息,这里说的“新”并不是指新发生的交易,而是之前的账本中没有记录的交易,有很多在时间上先发生的交易被区块收录的时间要晚于后发生的交易,只要这两笔交易没有直接或间接关联就不会影响区块链系统的运行。
我们来看一下比特币区块的结构,如图4-3所示,区块由区块头(Header)和区块体(Body)两个部分组成,区块的头部封装了系统当前的版本号、前一个区块的哈希值、本区块所有交易的Merkle树根(Merkle Root)、时间戳、区块的难度目标值Bits(挖矿的难度)和Nonce值。如同TCP/IP协议里的payload,区块体内包含了实际的交易记录数据。比特币区块链系统规定区块内包含的第一条交易必须是Coinbase交易,Coinbase是一笔特殊的交易,又叫“铸币交易”,是系统自动产生用于奖励矿工的交易,收款人为产生此区块的矿工,Coinbase交易是比特币系统发行新比特币的唯一渠道。Coinbase交易后面记录的是普通交易,普通交易是由比特币用户发起的转账交易,通常是由用户的比特币钱包软件生成发起的。
图4-3 比特币区块结构
父区块哈希实际上存储的是前一个区块头部的哈希,是一个通过SHA-256算法对区块头部进行两次哈希计算而得到的数字指纹,而不是整个区块的哈希,这是为了减少运算量只计算了区块头部。当前区块头部的哈希值并没有被本区块存储,而是被存储在后一个区块的头部中,父区块哈希值就像C/C++中的指针一样把区块串成一条链,一条单向无环的链式结构,后面的区块能回溯到前一个区块,但前面的区块没有后面区块的信息。
Merkle Root是一个二叉树结构,是由本区块所记载的所有交易的哈希再层层做哈希所生成的,如果篡改某个区块中的交易记录,势必会造成Merkle Root的改变,鉴于哈希函数的特性,即使对源数据修改一个比特,修改后的哈希和原值的哈希值也是天壤之别。这样不仅会造成当前区块可能成为非法区块,还会造成后一个区块头部所存储的前区块哈希值和这个修改后的哈希值不一致而变成非法区块,然后依次类推,整条后续的区块链都是非法的。
为什么说当前被修改的区块有可能会成为非法的呢?原因是Merkle Root改变后会造成当前区块头部的哈希值变化,这个新的值大于、等于或小于难度所表示的难度目标值,如果改变后的头部哈希值小于难度目标值,那么这个区块倒可以蒙混过关,不过即使是基于当初中本聪设立的初始挖矿难度,改变区块数据大概率会造成区块变为非法区块的后果。
时间戳(Timestamp)记录的是从格林威治时间1970年01月01日00时00分00秒起到现在的总秒数,用以记录当前的时间,采用和UNIX时间戳一样的机制。在比特币系统中,获得记账权的节点在生成区块时需要填写当前时间,用以记录当前区块数据的写入时间。每一个后续区块的时间戳都要大于前一个区块时间戳,形成一个以时间为序列的链条,这就增强了区块链的防篡改和防伪造性,也为数据增加了时间的维度。
Nonce是一个随机数,就是矿工为了争夺记账权而争相计算的一道题的答案,即俗称“挖矿”的计算结果。简单来讲,这道题就是把当前区块头部做哈希,所得的数值要小于难度目标值,如果没有满足要求,则这个区块不是一个合法区块,会被其他节点拒绝收录,因此矿工节点会不停地将不同的值填入Nonce字段来碰撞,关于难度目标值Bits和Nonce的内容,本章后面将详细介绍。
通过利用交易记录生成的Merkle Root、区块头部哈希值作为链接的锚定物,再加上Nonce和难度值的组合,仅仅用80字节的数据就解决了区块以及整条链防篡改的问题,没有任何多余的东西在里面,设计非常精巧。比特币系统开放地运行了11年,迄今为止,比特币系统没有遭到任何有效的攻击,这也证明了比特币区块链设计的伟大之处。
class CBlockHeader { public: // header int32_t nVersion; // 版本号 uint256 hashPrevBlock; // 前一个区块的hash uint256 hashMerkleRoot; // 本区块交易的Merkle Root uint32_t nTime; // 时间戳 uint32_t nBits; // 难度目标值的bits格式 uint32_t nNonce; // 随机数 … }
系统对所能记录的最大交易数量没有限制,但对区块的大小是有限制的,在“隔离见证”被比特币激活使用之前,一个区块总的大小不能超过1MB,超过的话将会被其他节点拒绝,因此在有限的空间内每个区块所能记录的交易数量还是有限的。
从区块头部的数据结构,我们可以计算出区块头的大小一共只有80字节,比一个完整的区块所占空间要小得多。如果在移动设备上只存储区块头数据,根据头部Merkle Root的数据就可以判断某个交易是否存储在区块链上,这使得在存储空间有限的移动设备上进行比特币交易验证成为可能。