技术教程 | 墨客UTXO和account模型

2019-10-24 15:14:55 15

在当前区块链世界中,主要有两种记录保存方式,UTXO 模式(Unspent Transaction Output) 和 Account 模式。Bitcoin 采用的是 UTXO 模型,Ethereum 采用的 Account 模型。


Bitcoin 的设计初衷是点对点的电子现金系统,在比特币中,每个交易消耗之前交易生成的 UTXO 然后生成新的 UTXO,账户的余额即所有属于该地址的未花费 UTXO 集合,Bitcoin 的全局状态即当前所有未花费的 UTXO 集合。Ethereum 意图创建一个更为通用的协议,该协议支持图灵完备的编程语言,在此协议上用户可以编写智能合约,创建各种去中心化的应用。由于 UTXO 模型在状态保存以及可编程性方面的缺陷,Ethereum 引入了 Account 模型。


1.什么是 UTXO


在比特币中,一笔交易“在黑盒子里”实际运作的方式是:花费一种东西的集合,这种东西被称为 “未被花费的交易输出”(即 “UTXO” ),这些输出由一个或多个之前的交易所创造,并在其后制造出一笔或多笔新的 UTXO ,可以在未来的交易中花费。每一笔 UTXO 可以被理解为一个 “coin(币)”:它有面额、有一个所有者。


一笔交易若要有效,必须满足的两个规则是:


1)该交易必须包含一个有效的签名,来自它所花费的 UTXO 的拥有者;


2)被花费的 UTXO 的总面额必须等于或者大于该交易产生的 UTXO 的总面额。


一个用户的余额因此并不是作为一个数字储存起来的;而是用他占有的 UTXO 的总和计算出来的。


如果一个用户想要发送一笔交易,发送 X 个币到一个特定的地址,有时候,他们拥有的 UTXO 的一些子集组合起来面值恰好是 X,在这种情况下,他们可以创造一个交易:花费他们的 UTXO 并创造出一笔新的、价值 X 的 UTXO ,由目标地址占有。当这种完美的配对不可能的时候,用户就必须打包其和值大于X 的 UTXO 输入集合,并添加一笔拥有第二个目标地址的 UTXO ,称为“零钱输出”,分配剩下的币到一个由他们自己控制的地址。


除了"比特币的网络效应",我们可以为 UTXO 模型提出一些技术上的主张;一个特别的主张是:它允许交易的并行化处理,正如一个交易发送者发送两笔独立的交易时,他们可以小心地花费独立的 UTXO ,因此这些交易也可以用任意次序来处理。这种顺序不变性与可并行化属性也许可以带来可扩展性的好处。使一个人的币可以分离开来,同样有一些隐私保护上的好处,尤其是,当一个用户接到的每一笔 UTXO 都使用了一个不同的地址的时候,因为这些地址的私钥可以确切地被所有者通过一个 master seed 生成出来;虽然这种隐私所得很容易被打破,如果该用户并没有仔细地保证他的资金相互分离的话。


如果隐私是被强烈偏好的,那么由 UTXO 提供的资金分离对于这个任务来说是远远不够的;这将需要更复杂的建构如环签名(Ring Signatures),额外的同态加密(Homomorphic Value Encryption)以及 ZK-SNARKs。



2.UTXO 的优缺点


UTXO 模型中,交易只是代表了 UTXO 集合的变更。而账户和余额的概念是在 UTXO 集合上更高的抽象,账号和余额的概念只存在于钱包中。


优点:

计算是在链外的,交易本身既是结果也是证明。节点只做验证即可,不需要对交易进行额外的计算,也没有额外的状态存储。交易本身的输出 UTXO 的计算是在钱包完成的,这样交易的计算负担完全由钱包来承担,一定程度上减少了链的负担。

除 Coinbase 交易外,交易的 Input 始终是链接在某个 UTXO 后面。交易无法被重放,并且交易的先后顺序和依赖关系容易被验证,交易是否被消费也容易被举证。

UTXO 模型是无状态的,更容易并发处理。

对于 P2SH 类型的交易,具有更好的隐私性。交易中的 Input 是互不相关联的,可以使用 CoinJoin 这样的技术,来增加一定的隐私性。


缺点:

无法实现一些比较复杂的逻辑,可编程性差。对于复杂逻辑,或者需要状态保存的合约,实现难度大,且状态空间利用率比较低。

当 Input 较多时,见证脚本也会增多。而签名本身是比较消耗 CPU 和存储空间的。

 


3.ACCOUNT 模型的优缺点


对于 Account 模型,Account 模型保存了世界状态,链的状态一般在区块中以 StateRoot 和 ReceiptRoot 等形式进行共识。交易只是事件本身,不包含结果,交易的共识和状态的共识本质上可以隔离的。

blob.png

优点:

合约以代码形式保存在 Account 中,并且 Account 拥有自身状态。这种模型具有更好的可编程性,容易开发人员理解,场景更广泛。

批量交易的成本较低。设想矿池向矿工支付手续费,UTXO 中因为每个 Input 和 Out 都需要单独 Witness script 或者 Locking script,交易本身会非常大,签名验证和交易存储都需要消耗链上宝贵的资源。而 Account 模型可以通过合约的方式极大的降低成本。


缺点:

Account 模型交易之间没有依赖性,需要解决重放问题。

对于实现闪电网络/雷电网络,Plasma 等,用户举证需要更复杂的 Proof 证明机制,子链向主链进行状态迁移需要更复杂的协议。

 


4.UTXO VS ACCOUNT


对于以上几个优点和缺点,我们再做一些分析和对比。


第一,关于计算的问题。

UTXO 交易本身对于区块链并没有复杂的计算,这样简单的讲其实并不完全准确,原因分有两个,一是 Bitcoin 本身的交易多为 P2SH,且 Witness script 是非图灵完备的,不存在循环语句。而对于 Account 模型,例如 Ethereum,由于计算多在链上,且为图灵完备,一般计算较为复杂,同时合约安全性就容易成为一个比较大的问题。当然是否图灵完备对于是否是账户模型并没有直接关联。但是账户模型引入之后,合约可以作为一个不受任何人控制的独立实体存在,这一点意义重大。


第二,关于 UTXO 更易并发的问题。

在 UTXO 模型中,世界状态即为 UTXO 的集合,节点为了更快的验证交易,需要在内存中存储所有的 UTXO 的索引,因此 UTXO 是非常昂贵的。对于长期不消费的 UTXO,会一直占用节点的内存。所以对于此种模型,理论上应该鼓励用户减少生产 UTXO,多消耗 UTXO。但是如果要使用 UTXO 进行并行交易则需要更多的 UTXO 作为输入,同时要产生更多的 UTXO 来保证并发性,这本质上是对网络进行了粉尘攻击。并且由于交易是在钱包内构造,所以需要钱包更复杂的设计。反观 Account 模型,每个账户可以看成是单独的互不影响的状态机,账户之间通过消息进行通信。所以理论上用户发起多笔交易时,当这些交易之间不会互相调用同一 Account 时,交易是完全可以并发执行的。


第三,关于 Account 模型的交易重放问题。

Ethereum 使用了在 Account 中增加 nonce 的方式,每笔交易对应一个 nonce,nonce 每次递增。这种方式虽然意在解决重放的问题,但是同时引入了顺序性问题,同时使得交易无法并行。例如在 Ethereum中,用户发送多笔交易,如果第一笔交易打包失败,将引起后续多笔交易都打包不成功。在 CITA 中我们使用了随机 nonce 的方案,这样用户的交易之间没有顺序性依赖,不会引起串联性失败,同时使得交易有并行处理的可能。


第四,存储问题。

因为 UTXO 模型中,只能在交易中保存状态。而 Account 模型的状态是在节点保存,在 Ethereum 中使用 MPT 的方式存储,Block 中只需要共识 StateRoot 等即可。这样对于链上数据,Account 模型实际更小,网络传输的量更小,同时状态在节点本地使用 MPT 方式保存,在空间使用上也更有效率。例如 A 向 B 转账,如果在 UTXO 中假设存在 2 个 Input 和2个 Output,则需要 2 个 Witness script 和 2 个 Locking script;在 Account 模型中则只需要一个签名,交易内容只包含金额即可。在最新的隔离见证实现后,Bitcoin 的交易数据量也大大减少,但是实际上对于验证节点和全节点仍然需要针对 Witness script 进行传输和验证。


第五,对于轻节点获取某一地址状态,UTXO 更复杂。

例如钱包中,需要向全节点请求所有关于某个地址的所有 UTXO,全节点可以发送部分 UTXO,钱包要验证该笔 UTXO 是否已经被消费,有一定的难度,而且钱包很难去证明 UTXO 是全集而不是部分集合。而对于 Account 模型则简单很多,根据地址找到 State 中对应状态,当前状态的 State Proof 则可以证明合约数据的真伪。当然对于 UTXO 也可以在每个区块中对 UTXO 的 root 进行验证,这一点与当前 Bitcoin 的实现有关,并非 UTXO 的特点。



5.不使用 UTXO的理由


反对 UTXO 的核心主张有下面两部分:

1)UTXO 的复杂性是没有必要的,而其复杂性在实际运行中会比在理论上还要大。

2)UTXO 是无状态的(stateless),因此并不能很好的适用于比资产的发行和保存更加复杂的应用,复杂应用一般来说是有状态的,比如不同类型的智能合约,来考察第一种主张。考虑一下你会如何实现一个 UTXO 模式下的钱包——尤其是,生成一个发出交易的函数。这一函数不仅要求一个账户的私钥作为输入,还有一些琐碎的数据,比如一个有序的数字,而不是属于该账户的 UTXO 的全集。这一函数还必须接受集合,并确定一个价值大于需要的输出数额的子集作为输入。某些时候,如果存在多个最小的子集,又会产生一些决定要花费哪个子集的复杂任务。


此外,如果一个钱包真的想要从上面提到的, UTXO 的并行化交易处理属性中获益,该钱包必须仔细地分切“变更输出”以至于该钱包总是有多个变更输出可以用作资金的来源;如果一个钱包只控制一个大的变更输出、总是从中抽取出一个小的数额来做下一笔支出,整个事情又变成连续的了。这不是纯粹理论上的问题;大部分的比特币钱包仍然不能使其最优化,与账户和连续数字模型相比,这在本质上使其 UTXO 的可并行化收益作废。


在比特币的例子(现实一点来说,任何一个公有链都是)中,交易费用以每千字节计,而 UTXO 选择算法必须额外地小心以最优化每一笔 UTXO 的长期平均交易消耗;这甚至引发了一个拒绝服务漏洞,攻击者可以使用小额的 UTXO(其价值比花费它们需要的边际手续费还要小) 来堵塞一个钱包。撇开这些,每千字节的手续费的存在在 UTXO 选择算法中引入了一些摩擦:可能有这样一种情况, UTXO 的子集 S 足以支付需要的数额 X,但大小为 S 的交易要求一笔交易手续费 F, 而 S 并不足以支付 X+F,那么 S 就需要增加到 S’ ,但然后 S' 大小的交易又要求交易手续费 F' ,要求有 UTXO 的子集 S'',等等。简而言之,使用账户和连续数字,创造一个钱包只是一个高中级别的问题;然而,使用 UTXO 它就变得很接近于一个本科生研究级别的挑战了。


UTXO 是如何地不契合于有状态的智能合约,也是清楚的:如果需要创建一个拥有多个阶段的合约,比如,必须由多方提供一些形式的输入,一段时间以后这些参与者又必须执行一些额外的操作,最后,作为他们操作的一个函数,该合约支出资金;很难看出如何拿这个模型去适应基本上无状态而只有花费和未花费的对象。然而,在一个基于账户的模型中,事情就简单了:一个人可以确认一个合约具有他所希望的代码,然后,这个合约就可以被其静态地址调用。


结论


综上来看,Account 模型在可编程性,灵活性等方面更有优势;在简单业务和跨链上,UTXO 有其非常独到和开创性的优点。对于选择何种模型,要从具体的业务场景进行出发。


主要参考资料:

https://ethfans.org/posts/compare-with-utxo-and-account-mode


(转自墨客区块链)

电话咨询
社区服务
产品展示