面向程序猿的比特币教程之数据结构基础

2018-08-15 16:18:19 浏览数 (1)

最近才开始了解区块链,花了一些时间使劲钻研了一下,大致理解了比特币区块链的基本结构和运行机制。比特币说复杂也不复杂,但是如果深究下去,绝不是非常简单。

阅读本文章并不会增加你的炒币技能,它呈现的只是区块链背后的技术细节。

首先我们来看一下区块链的基本的链条结构

区块链的这个结构和Java容器HashMap的内部结构非常类似,都是二维的结构。第一维是一个区块链表,矿工们会努力制造新区块追加到这个链表末端,制造新区块是一个非常艰难的过程,目前造成功一个区块可以获得大约12.5BTC的收益,造两个就可以在北京安个家了。第一维链表的头部就是比特币创始人中本聪先生在芬兰的赫尔辛基挖出来的第一个区块,这个区块称为创世区块【Genisis Block】。

区块链的第二维是交易记录,每个交易记录里写明了比特币交易的流转信息,张三给李四5个BTC,李四给王五3个BTC等等这样的信息,甚至可以是张三同时给李四2个BTC和王五3个BTC这样的多边交易记录。矿工平时除了努力制造新区块之外,还会接受来自广大互联网上的交易信息,待区块制造成功,就将这一段时间内收到的交易信息串起来打个包塞进新区块,加入到全局的区块链表中去。这第二维的交易记录链表有一个特殊的交易记录,这个交易没有来源,只有去向。记录的是区块的属主获得的比特币挖矿收益,是虚无的算法上帝奖励给矿工的大宝藏。它被称之为【CoinBase】,它是所有比特币的来源。所有的CoinBase记录里包含的BTC数量就是流通的比特币总量。

每个区块都有一个编号,这个编号称之为区块的高度【Height】。我们把挖矿想像成盖房子,每一个区块就是新的一层,那高度这个概念就非常好理解了。目前这个房子已经盖到了50w层,大约每隔10分钟会盖一层。这个高度没有上限,矿工会一直挖到天荒地老。我们多少知道比特币的数量是有上限的,大约是2100w枚,如果矿工能一直挖下去,一直得到CoinBase奖励,那比特币的数量不就无上限了么?这里中本聪自然就考虑到了,算法会限定随着区块的高度越高,挖矿取得的收益会减少,大约每隔几年CoinBase挖矿收益就会减半。创世纪区块中本聪拿到的是50BTC,今天这个时候挖到一个区块已经只有12.5BTC了。

图中的Transactions字段就是每个区块包含的交易记录数量。在区块链的早期,很少人使用比特币进行交易,这个数量是非常少的。最近几年人们使用比特币交易越来越频繁,这个数字也越来越大。它是有上限的,区块的最大容量为1M,每个交易记录占用的空间是不定的,有大有小,参与交易的账户越多,交易记录越大,上文已经提到交易是可以多边的。

作为程序员,我们知道数据库都有个日志记录,记录数据库所有的历史写操作。在Redis里面叫aof日志,在mysql里面叫binlog。通过重放日志,就可以恢复数据库的状态。比特币区块链也是一种分布式数据库,它对应的日志就是所有的交易记录。通过追踪所有的交易记录,我们就能明确知道某个账户到底有多少钱。

在讲解交易记录数据结构之前我们先说明一个概念叫【交易费用】。有一点经济学基础的同学都听说过这个概念,它是中介机构来钱的原动力。矿工们除了可以通过挖矿得到收益之外,还可以通过收取交易费用拿到收益。每一个交易记录里都会有一小笔费用会奖励给矿工。当矿工成功将一个新区块加入到全局区块链后,这个新区块里面包含的所有交易记录的所有交易费用都归这个矿工所有,如果内部的交易记录比较多,交易的数额比较大,矿工得到的交易费用收益也就越高。这样当未来挖矿的收益非常微小的时候,矿工们还是会通过交易费用来保持继续挖矿的动力。

交易结构是区块链最难理解的一种结构,它是一颗非常复杂的树,这颗树是由一系列交易记录串起来形成的一种跟踪树。我们可以通过跟踪树来追踪到一个账户究竟剩余多少比特币。

接下来我们看看交易记录的结构。

这个交易记录是Coinbase记录,它没有输入,也没有交易费用。它是算法上帝给勤劳的矿工的挖矿奖励,它存在于每个区块的第一个交易记录。Coinbase可以有多个输出,它表示这个区块是有多个矿工共同参与挖到的。那为什么输出不是 12.5BTC而是13.28BTC呢,因为多余的部分是本区块所有的交易付出的交易费用之和。

这个交易记录表示1.18366个BTC被分给了两个账户,一个账户得到了0.692152个BTC,另一个账户得到了0.4897个BTC,剩下的0.001808个BTC就是奖励给矿工的交易费用。

注意到这个交易记录输入和输出包含了同一个账户ID,这什么意思了。它表示在0.441个BTC打给一个账户并且扣除了交易费用之后还剩下19.14390825个BTC没有消费,返还给原先的账户。

这个交易就比较诡异了,居然有3个来自不同地址的输入。我们知道比特币发起交易的只能是一个人,怎么可以和3个账户同时拉扯上关系呢?

原因就在于输入显示的账户地址不一定是交易发起人的账户地址,而是之前给交易发起人打了钱的某个人的账户地址,这个前置交易的输出中有发起人的账户地址,表示交易发起人从前置交易中得到了一笔BTC,然后在本次交易中使用这笔BTC来支付。

那为什么需要3个输入呢,因为一个前置交易得到的BTC数量不够,需要多凑几个前置交易才能凑够交易额,所以需要多个输入。

所以我们看到交易和交易之间产生了关联。彼交易的输出是此交易的输入,此交易的输出又是另外一个交易的输出,如此交易链也就产生了。交易链非常长,从coinbase诞生的比特币一直延续到世界末日才会终止。

如果FBI想要追踪某个黑用户BTC的来源,FBI首先通过严刑拷打要出了这个用户的BTC账户地址,然后他们还需要找出最近和这个账户发生关联的所有交易,并沿着交易树回溯,回溯到所有的Coinbase记录。在现代庞大的CPU和内存的前提下,这种回溯都是可以轻易办到的。但是问题是所有的账户都是一个hash码,FBI并不知道这些账户是现实世界中谁的账户,也就无法查到交易具体关联了现实世界中的哪些人。

前文提到交易记录可以有多个输入多个输出,每个输入输出是一个账户地址。实际上并非如此,我们看看原始的交易记录结构。

以上是从http://webbtc.com网站随意找的一个交易记录的json形式展现。我们先不去管结构中的scriptSig和scriptPubKey字段,这两个字段涉及到区块链虚拟机脚本指令,以后我们再好好研究。

我们看到交易记录有一个很长的hash串,它表示当前交易的唯一ID,它是基于密码学算法计算出来的定长ID。输入字段in里面并没有address地址字段,取而代之的是prev_out里面的hash和n字段,hash字段很长,它表示的是前置交易的ID,而n代表的是前置交易的输出列表里面第2个输出项【n下标从0开始】,这个输出项对应的账号ID正好就是前文交易记录里显示的账号ID。而out字段里面有address字段,这个正好就是目标输出账号ID。

所以我们得出结论,交易链是由交易ID串接起来的树,它是有方向的,是从后驱节点指向前驱节点。我们从http://webexplorer.com网站能同时看到交易的前驱和后驱交易是因为后驱关系是由前驱关系推导形成的。所有的交易记录都有前驱交易,但是未必都有后驱交易。所有这些没有后驱交易的节点输出就是UTXO【未花费交易输出】。一个交易可以有多个输出,其中的一些输出有后驱交易,而另外一部分输出则可能没有后驱交易。这部分没有后驱交易的输出就是UXTO。一个账户所有关联的UXTO的value值的总和就是这个账户的余额。UXTO是区块链当中非常重要的一个概念,它可以理解为区块链记录活跃的中心所在,其它的SXTO【已花费交易记录】都是固化在区块链里面仅用于跟踪和查询,它们是冻死的记录。

图中输出列表项后缀状态U和S分别代表的是UXTO和SXTO。

UXTO可能存在于区块链的每一个区块中,比如中本聪先生在比特币早期的时候挖了很多币,这些币的一大部分就一直没有参与任何交易,它们就安静的躺在区块链的coinbase交易记录中。但他们是活的比特币,随时可以参与交易。还有一些UXTO则像僵尸一样躺在区块里,它们形成了2100w比特币中的黑洞,任何人也无法使用这些UXTO,因为哪些早期参与比特币项目的人没有认真对待他们账户中的比特币,那个时候比特币还不值钱,账户的秘钥被他们给搞丢了,如今他们后悔莫及,就算找到中本聪本人那也无能为力了。

0 人点赞