UTXO 代表 Unspent Transaction Output。
在比特币社区里,Transaction 被简称为 TX,所以上面这个短语缩写为 UTXO。一般会认为 UTXO 是比特币区块链设计当中的一部分,但事实上 UTXO 和区块链没有必然的联系,你可以完全照搬比特币区块链,但不使用 UTXO。
HyperLedger 和Ethereum 一开始并没有采用 UTXO,现在前者已经切换回 UTXO,后者打算增加这个选项。我觉得这也是中本聪的过人之处——后来者照着临摹,中间想搞点小改进,结果做到后面,发现还是人家原版的水平高,纷纷又改回来…..
那么到底什么是 UTXO 呢?
前不久我听“卓老板谈科技”里“比特币”那一集,里面讲到比特币的付款过程,说他要给付给奶茶妹妹5个比特币,于是系统在他的账户里减掉5,在奶茶妹妹的账户里增加5,然后把这笔交易记入区块链总账,完成。虽然这个节目做得不错,不过在这一点上卓老板完全搞错了,他描述的是基于账户的方案,而不是比特币实际采用的 UTXO 方案。
如果让我们设计一个支付系统,一定会跟卓老板想到一起去,给张三一个账户,里面有余额 100 元,李四有一个账户,里面有余额50元。当张三要付给李四20元时,做以下操作:
1. 检查张三账户余额是否充足,如果不足20元就终止交易,向张三报“余额不足”
2. 在张三账户里减去20元(假设零手续费)
3. 在李四账户里增加20元
现在的银行也好、信用卡也好、证券交易系统也好,互联网第三方支付系统也好,其核心都是基于账户(account based)的设计,由关系数据库支撑。
数据库要确保两点,第一是你要确保业务规则得到遵守,张三的余额充足。第二是确保事务性,也就是原子性、一致性、隔离性、持久性(ACID)。这些都是数据库的常识性知识,这里不赘述。这种基于账户的设计,简单直观,而且在 IT 系统设计里用了几十年,应该说没有什么问题。
但比特币没有设计成基于账户的系统,而是发明了 UTXO 方案。
要理解UTXO,最简单的办法就是把一枚比特币从诞生到在商海中沉浮的经历描述一下。我们假设一个这样的场景:张三挖到12.5 枚比特币。过了几天,他把其中 2.5 枚支付给李四。又过了几天,他和李四各出资 2.5 比特币凑成 5 比特币付给王五。
如果是基于账户的设计,张、李、王三人在数据库中各有一个账户,则他们三人的账户变化如下图所示:
但在比特币中,这个过程是通过 UTXO 实现的,图示如下:
比特币的区块链账本里记录的是一笔又一笔的交易。
每笔交易都有若干交易输入,也就是资金来源,也都有若干笔交易输出,也就是资金去向。一般来说,每一笔交易都要花费(spend)一笔输入,产生一笔输出,而其所产生的输出,就是“未花费过的交易输出”,也就是 UTXO。
比特币交易遵守几个规则。
第一,除了 coinbase 交易之外,所有的资金来源都必须来自前面某一个或者几个交易的 UTXO,就像接水管一样,一个接一个,此出彼入,此入彼出,生生不息,钱就在交易之间流动起来了。
第二,任何一笔交易的交易输入总量必须等于交易输出总量,等式两边必须配平。
上图第一个交易 #1001 号交易是 coinbase 交易。比特币是矿工挖出来的。当一个矿机费尽九牛二虎之力找到一个合格的区块之后,它就获得一个特权,能够创造一个 coinbase 交易,在其中放入一笔新钱,并且在交易输出的收款人地址一栏,堂堂正正的写上自己的地址。在我写文章的这一天(2016年8月9日),这笔比特币的数额规定为 12.5 枚,市价 48,576元人民币。这个 coinbase 交易随着张三挖出来的区块被各个节点接受,经过六个确认以后永远的烙印在历史中。
过了几天,张三打算付 2.5 个比特币给李四,张三就发起一#2001号交易,这个交易的资金来源项写着“#1001(1)”,也就是 #1001 号交易——张三挖出矿的那个 coinbase 交易——的第一项 UTXO。然后在本交易的交易输出 UTXO 项中,把2.5个比特币的收款人地址设为李四的地址。
请注意,这一笔交易必须将前面产生那一项 12.5 个比特币的输出项全部消耗,而由于张三只打算付给李四 2.5 个比特币,为了要消耗剩下的10比特币,他只好把剩余的那 10 个比特币支付给自己,这样才能符合输入与输出配平的规则。
再过几天,张三和李四打算AA制合起来给王五付 5 枚比特币。那么张三或李四发起 #3001 号交易,在交易输入部分,有两个资金来源,分别是#2001(1) 和 #2001(2),代表第 #2001 号交易的第 (1) 和第 (2) 项 UTXO。然后在这个交易的输出部分里如法炮制,给王五5比特币,把张三剩下的 7.5 比特币发还给自己。以后王五若要再花他这5比特币,就必须在他的交易里注明资金的来源是 #3001(1)。
所以,其实并没有什么比特币,只有 UTXO。当我们说张三拥有 10 枚比特币的时候,我实际上是说,当前区块链账本中,有若干笔交易的 UTXO 项收款人写的是张三的地址,而这些 UTXO 项的数额总和是 10。因为在比特币系统里,一个人可以拥有的地址资源,可谓取之不尽用之不竭。要知道自己的一大堆地址里一共收了多少 UTXO,人是算不过来的,需要由比特币钱包代为跟踪计算。
以上即为 UTXO 的一个简要的介绍。
那么UTXO高在哪里?
比特币的很多技术点都不是中本聪的原创。比如基于“工作量证明(Proof-of-Work)”的共识达成机制是 Adam Back 在 Hashcash 里提出来的,将全部交易计入一本总账、并给交易打时间戳来防范双花攻击(double-spend attack)的思想是 Wei Dai 的 b-money 和 Nick Szabo 的 Bitgold提出来的,更不用说比特币网络是零优化的大水漫灌式P2P网络,仅就 P2P 技术而言,很多方面还赶不上2001年出现的 BitTorrent 。
但是有三个技术点绝对是中本聪原创,一个是区块链的设计,一个是UTXO,一个是智能合约。而这三个设计是极为天才的,被斯坦福大学密码学和计算机安全教授 Dan Boneh 评价为“extremely brilliant”,“必将激发无穷的创新”。
当然,但中本聪最了不起的地方并不是这三个单点创新,而是将所有这些技术点跟密码学货币自身特点相结合,设计了一套“惩恶扬善”的经济激励制度,将技术创新与制度设计糅合成一个严丝合缝的体系。
在这个体系里,任何人都可以建立一个匿名节点,编写破坏性的代码,然后实施匿名攻击,即便你攻击得手、偷来大笔财富,也不会暴露身份,所以可以逍遥法外。
这个系统赤身裸体,开门揖盗,任由你攻击破坏,甚至如果你成功的突破防线偷来一大笔财富,整个比特币体系不但不会惩罚你,还会坚定的保障你的赃款。然后悬赏100亿美金,运行七年,至今为止,在主干区块链上,没有发生一起成功的攻击,一次都没有。
中本聪把比特币设计得跟数学原理一样漂亮,很多后来者连抄都抄不到这个水平。我想这就是为什么加州大学洛杉矶分校的金融学教授 Bhagwan Chowdhry会提名中本聪为2016年度诺贝尔经济学奖候选人。我相信中本聪在比特币里的很多设计思想,以及整个比特币开发者社区所做的大量改进,不仅是区块链的开山之作,而且也会成为IT系统设计的一个创新思想源泉。
UTXO 的设计就很值得玩味。在《什么是UTXO》一文中对其设计方案进行了介绍。本文要讨论的是UTXO 的优点和不足。
中本聪为什么要把比特币设计成这样呢?考虑到他应该也不是从未来穿越回来的人物,以常理推论,他一开始应该也是从基于账户的系统出发来设计的,但他后来决定切换到UTXO方案,一定是遇到什么问题。
很遗憾,比特币的源代码里找不到这些问题的答案。比特币的开发始于2007年5月,目前在Github 上最早的一版比特币源代码是2009年9月16日中本聪 push 上去的 0.1.5 版,但其中 UTXO 的设计已经成型。
后来有人翻出自己的老邮件,找到了比特币2008年9月版的代码。那份代码是比特币区块链上线之前几个星期发布的,应该非常接近比特币创世纪运行的那个版本。可如果你仔细去看的话,其中 UTXO 也已经定型。我们注定无法通过代码考据来发现 UTXO 的设计脉络了。
其他文献材料呢?也不行。中本聪在发表比特币之前,主要是与一些密码学专家邮件交流,这些邮件外界看不到。而他积极参加论坛讨论,主要发生在比特币已经发表以后。我找不到他在 UTXO 设计形成过程之中发表过任何相关的只言片语。
既然这些办法都不行,我们就只好靠猜了。
我猜测,中本聪一开始设计比特币时,也采用了账户方案。但在2007年下半年或2008年上半年的某一个时刻,中本聪发现基于账户的方案有问题,于是创造了 UTXO 方案。
那么基于账户的方案会遇到哪些问题呢?
如果采用基于账户的方案,可以肯定的是,你需要一个数据库。这个数据库能够让你很方便的查到张三、李四各自的账户余额。
而 UTXO 方案当然也需要一个数据库,这个数据库记录着当前系统里每一笔“没有花出去的交易输出”,也是就比特币。当节点接收到一笔交易的时候,它需要去 UTXO 数据库里查,看看这笔交易所引用的 UTXO 是否存在,它的收款人(拥有者)是不是当前新交易的付款者。而交易结束之后,数据库要做相应的更新。
首先要明确,无论是账户数据库还是 UTXO 数据库,必须是分散的,每结点一个克隆,一定不能是中心化的。如果比特币系统有一个中心数据库,不管你有多少节点,每一笔交易都要跑去中心数据库验证一下、然后再执行“转账”的事务操作,那就完全谈不上“去中心化”,比特币就毫无价值了,不如老老实实用支付宝。
既然都是每个节点克隆一个数据库,根据交易过程同步修改,那么一个账户数据库跟一个 UTXO 数据库,又有什么分别呢?
进一步思考,我们会发现还是有很大分别。
首先,长期来看,账户数据库会无限膨胀,而UTXO 数据库体积会小很多。
要知道,比特币是个匿名体系,它的账户就是“地址”。每一个比特币用户可以拥有几乎无限多的地址,在比特币系统来看,它完全不知道两个地址背后对应的是不是同一个人。
而且比特币鼓励用户开设大量地址,有些钱包软件甚至每进行一次交易都新开一个账户,每收一次钱都开一堆账户来分散资金,以确保匿名性。这还不算,有很多用户出于好奇,下载一个比特币钱包,嘭嘭嘭申请它几十个地址,然后冷冷的趴在那里,永远也不用。又或者有些地址用过以后,再也不用了,甚至干脆被拥有者遗忘了。但所有这些有用的没用的地址,咱们的账户数据库都得不折不扣的记着。
时间越久了,账户数据库里“废账户”所占的比例越大,体积无限膨胀,这个怎么吃得消呢?要知道,比特币矿机每处理一笔交易,都需要查询这个数据库,当数据库规模无限膨胀的时候,查询速度也会放慢,耽误比特币矿机的挖矿竞争,这是无法接受的。
相比之下,UTXO里面存放的都是“有用的”数据,也就是目前没有被消费的比特币。矿工需要查询和操作 UTXO 数据库才能够验证交易,这个过程一定要快,越快越好,这样在挖矿竞赛中才能够抢在别人前头胜出。
多亏 UTXO方案,目前比特币运行了近八年,整个数据库还不算太大,到2016年五月,压缩体积约1.5GB,估计解压后体积大约是8GB,能够完整的放在内存里。如果是账户数据库,我估计内存早就放不下了。
其次,UTXO 数据库允许并行事务操作。在账户数据库中,张三要转20元给李四,需要进行一个数据库事务,在张三账户里减20,在李四账户里加20。如果与此同时,王五要转30元给张三,那这个交易就得排队,无法并行。
之所以这样,归根结底是因为这两笔交易都需要跟“张三的账户余额”这个共享状态打交道。而在 UTXO 中,数据库跟踪的是比特币的所有权转移,而不是账户的状态。不管张三本人正在发生多少收支交易,这些收支交易都是发生在不同的比特币上的,更重要的是这些交易之间并不共享任何状态,因此不会相互干扰,所有这些交易可以并发执行。这带来好处不光是快,更重要的是可扩展,可分布。
在很多大规模互联网企业中,处理分布式事务是核心技术竞争力之一,非得需要极强的精英技术团队、大量长时间持之以恒的投入和维护改进,才能在这个领域站住脚。是不是可以基于 UTXO 发明一个技术体系,使得交易性事务处理也能充分分布?UTXO 是否具有更广泛的适用领域?
比如,当你在天比特商城里上花10比特币买一件衣服,而支比特宝不是在你的账户里扣钱,而是在一个交易当中把衣服的所有权和10比特币的所有权对调,让衣服的所有者从商家变成你,而让比特币的所有者从你变成商家。
注意,这个过程不与同时进行的任何其他交易共享状态,而且一个交易一个事务,事务完整性可以轻松确保。这样一个交易过程,可以很容易地进行大规模分布。交易量大了,就加节点,交易量小了,就减节点。在这样的体系结构下,我们完全不用为天比特商城和天比特宝一天完成多少百亿的交易额而兴奋激动、顶礼膜拜了,因为技术上这不再是什么多了不起的事情了。当然,这只是一个猜想。真的会是这样么?有没有其他的坑?这是极其有吸引力的话题,值得未来不断探讨。
当然,UTXO 也有一些缺点。
首先,UTXO 方案实现起来不是太容易,比较复杂。这也是为什么 Ethereum 一开始没有采用 UTXO 方案的原因。
其次,UTXO 数据库现在膨胀得也很厉害。2015年五月,UTXO数据库压缩以后650MB,解压后占内存里 4GB。一年之后,压缩体积1.3GB,解压后占内存 8GB,这一年翻一个翻的速度,谁也受不了。比特币大牛 Galvin Andersen 做过一个估算,到2025年,要想把 UTXO 数据库放进节点内存里,光买内存就得花4,000美元。
UTXO 膨胀问题也使得人们对于比特币区块扩容顾虑重重。如果比特币区块从1MB扩容到 2MB,那么UTXO会加速膨胀。
现在也有一些人提出了解决问题的建议,有的说通过激励机制鼓励节点进行 UTXO 合并,有的建议放松一些验证要求,允许节点将 UTXO 放在磁盘上。Peter Todd 做了一个完整的建议,有兴趣的人可以戳这里(https://petertodd.org/2016/delayed-txo-commitments)。
我个人在翻故纸堆的过程当中,看到2010年一个叫 Red 的黑客跟中本聪的一段讨论。Red 建议数据库里不再存放当前UTXO集合,而只是存放铸币记录:这几枚比特币是什么时间挖出来的、收款人是谁。然后,每当发生交易的时候,由钱包软件负责将所开支的比特币从其被挖出的那个时刻开始一直到当前交易的全部换手记录提交给节点,节点只要验证所有这些记录环环相扣,数字签名都对得上,就可以批准交易。
做一个比方,这个就好像买卖二手房。
政府那里只有这处房产的原始地契,而张三李四买卖双方需要把原始地契和历史上所有的转手合同一张一张带好,最后把自己这次买卖的合同拟好,来到办事处。办事员先从档案库里调出该处房产的原始地契存档,比对原始地契,证明此处房产确实从落成之日起,即为本区政府认可之合法物业,然后再一张一张核实换手合同,看转手过程是否环环相扣,看签名是否为真,直到最近一份合同,确认目前该物业确实为张三所有,然后核查最新的这份“张三将此处房产卖给李四”的合同,主要是查签名,当然也要核对其他条件。核查通过后,就在上加盖公章,认可交易。注意这份合同政府不必存档,而应由李四带回去妥善保管。下次当李四在要将房产卖给王五时,他需要带着从原始地契直到“张三将此处房产卖给李四”的合同一起出示给政府办事员,证明自己确实是当前房产的所有人。
这个方案的好处在于,原始铸币记录(相当于原始房契)数量是线性增长的,每个区块只产生一份这样的记录,所以相应的数据库不会出现体积膨胀。而且等到比特币全部挖光之后,这个数据库就停止增长了。
缺点呢,则是把复杂性完全嫁祸给了钱包软件和节点验证过程。每一笔交易,钱包都要向节点提交一个长长的、而且越来越长的比特币换手记录。而节点也要从这些比特币的诞生时刻开始一笔一笔的核查,交易验证的性能会大大下降。
正是因为这个原因,当时中本聪没有接受这个方案。但是,这主要是因为货币的流通速度太快。同样这个方案在其他的应用场景下,或许是可行的。所以我在这里详细论述了一番。