之前我们介绍了比特币系统的设计思想:
比特币技术入门1(去中心化和数字签名)
。今天介绍比特币系统的数据模型,这个数据模型是逻辑概念。不包括磁盘是怎么存储这些数据的。
钱包
每个人在使用比特币的时候,都需要有个钱包,这个钱包其实就是一个地址,可以理解为 QQ号,与每个钱包绑定的是一对公钥和私钥,每个人只保管自己的私钥,钱包地址和公钥是公开的。
公钥≈钱包地址。
账单、账单链
在中本聪的比特币白皮书中介绍了什么是账单(Transaction),以下是原图:
电子货币就是一个电子签名链,我们以一些比特币的拥有者 1 为例,对应上图中间的 Transaction:1 想将这些比特币转移给 2,需要做两件事:将上一笔交易和下家 2 的公钥进行 hash,并用 1 的私钥将这个 hash 签名。这笔账单包含了 1 的比特币的由来(上一笔交易),并且包含 1 的签名。其他人可以通过 1 的公钥验证这笔账单的来源和去向。
其实就是将一笔账单的所有内容算个 hash,然后在 hash 上签名,这张图比较笼统。下面给出第二个版本:
账单主要包含输入和输出:
输入:每笔账单可以有多个输入。输入可以是一个大金额的比特币,或者是很多少量的比特币。每个输入的内容为:账单号+输出号。
输出:每笔账单最多有两个输出。一个输出是收款方,另一个输出是找零,如果没有找零就只有一个输出了。输出包含金额,以及转给的账户公钥。
关于账单有一个限制:上一笔账单的输出,如果要用到下一笔账单中,就需要全部消费掉。比如我有 3 笔账单分别收入 0.2 个比特币,现在需要将 0.5 个比特币转给 A,这时这笔账单就有 3 个输入,分别是之前三笔账单的输出;这笔账单有 2 个输出,其中一个是将 0.5 个比特币输出给 A。多余的 0.1 个比特币找零给我。如下图(来自中本聪比特币白皮书):
中本聪还规定,当一笔账单的输入总和大于输出总和时,差值会当做手续费付给处理这比交易的中介。因此,一般不会将所有零钱返回给付款方,还会支付一些手续费。
再看一张更清楚的图:
以上图中账单4为例,D是一个人,他拥有一对公钥和私钥,私钥可以用来签名,这里签名是对整个账单4的内容hash进行签名。保证输入和输出都不被篡改。在账单3的输出中,D收到了2.5个比特币,在账单4中,他要把这2.5个比特币花掉,转2个给E,0.5个给F,于是他签名授权了账单4,账单4就和账单3连上了,这就是账单链,在账单链上记录了比特币从开始运行到现在的所有账单,每一笔账单都可溯源。
账单还会包含时间戳之类的属性信息,但是时间戳不是用来唯一确定一笔账单的,是用来给用户展示的业务逻辑。在数据库中很少有人用时间戳来标识一个数据,因为分布式系统不存在统一的全局时钟。唯一标识一笔账单的是账单ID。
详细的账单结构介绍可以参考:http://learnmeabitcoin.com/glossary/transaction-data
区块、区块链
一笔账单就写一次区块链太浪费资源,数据库都喜欢批量写。比特币也不例外,多笔账单会打成一个包,叫做区块,区块链的基本单位就是区块。
每一个区块主要包括区块体和区块头:
区块体:包含一笔笔账单。
区块头:主要包括当前区块的 hash,上一个区块的 hash,Root Hash(将区块体中的每笔账单当做 Merkle Tree 的叶子节点,逐层计算出根节点的 hash, 记做 Root Hash,如果不成对就和自己做 hash。),和一个可以随意填充的数:nonce(关于这个数的作用我们下篇介绍,和挖矿有关)。
完整的区块(Block)示意图如下(来自中本聪比特币白皮书):
区块通过头部的 hash 值连起来了,注意区块链只能后边连前边的。完整的区块链示意图如下图。不仅区块连起来了,内部的账单也可以连起来,网上没有这种示意图,但我认为这才是最完整的示意图(这里简化每笔账单只有一个输入和一个输出)。
从比特币系统上线之日起,这个链就在不断增加。这个链包含了比特币系统的所有账单信息,并且在比特币系统的每个节点都会存一份。完整的比特币系统如下图,各个节点之间都可以互联互通,且各个节点是平等的(节点之间的连线省略了)。
通常,每笔交易的大小是 500 字节,而每个区块的大小在代码中写死了不超过1MB,这样,基本每个区块可以装 2000 笔交易。
总结
比特币区块链的数据结构主要包括:账单和区块。其中账单是有链的,这个链根据账单地址单向连接。每个区块包含多笔交易,区块也是有链的,同样根据区块ID单向连接。区块链所有节点包含区块链的所有数据。
致谢:DPer。研究信息安全,有兴趣可以关注公众号《差分隐私》:
领取专属 10元无门槛券
私享最新 技术干货