序言
区块链是状态机 —— 它们跟踪状态(例如,每个钱包持有多少比特币)和状态随时间的变化。
每笔交易(因此每一个区块)都会改变区块链的状态。在区块链中跟踪和管理状态的两种最流行的方法是: 未使用的交易输出(UTxO
)模型和Account
(账户)模型。
UTxO
模型是由比特币开创的,可以直观地认为是类似现金的(下面将进一步详述),而账户模型是由以太坊推广的,可以直观地认为是类似银行账户的。与所有工程和设计决策一样,UTxO
和账户模型需要权衡取舍。 例如,账户模型比UTxO
模型具有更多的表达能力,但具有更差的确定性(当底层区块链使用账户模型时,交易更有可能失败)。
支持Cardano
项目的科学和研究机构IOHK
的团队已经创新了一种新的状态管理系统,他们称之为扩展的UTxO模型(eUTxO
)。eUTxO
模型是UTxO
模型和账户模型的综合,它结合了账户模型的表达能力和UTxO
模型的隐私性、安全性、并发性和确定性。
有很多 文章 比较 比特币的UTxO 模型 和 以太坊的帐户模型 但很少有文章将这种比较扩展到eUTxO
模型。本文将快速介绍UTxO
和Account
模型的基础知识,并尝试彻底解释eUTxO
模型。
UTxO模型
首先,让我们为比特币开创的UTxO
模型建立一些直觉。请记住,UTxO
代表未使用/未花费的交易输出。让我们从一个基于上述直觉的例子开始,即UTxO
模型类似于现金。
假设Alice
有一张100美元的钞票,她需要付给Bob
3美元。 Alice
将她的100美元钞票交给Bob
,然后Bob
将返还给Alice
97美元。
在此示例中,Alice
以价值100美元的未花费交易输出(UTxO
)开始。然后,她在一笔交易中(花费/消费)了该输出(100美元的钞票),从而产生了2个新的未花费交易输出(UTxOs
),一个为3美元(由Bob
拥有),另一个为97美元(由Alice
拥有)。现在请注意,原来的100美元的UTxO
不能再次(消费/花费)。
每个UTxO
只能使用一次,并且可以生成一个或多个新的UTxOs
。 UTxO
模型中的每笔交易都会接收一个UTxOs
输入列表,消费它们,并创建一个新的UTxOs
列表,这些新的UTxOs
可以稍后在新的交易中(使用/花费)。 UTxO
的另一个值得注意的特性是,交易的输入值必须始终等于输出值(减去区块链为处理交易而收取的任何费用)。
UTxO
模型具有很好的并发性,因为状态是本地的(与下面描述的Account
模型的全局状态相比)。这种本地状态的概念源自这样一个事实: UTxO
特定于每个钱包。如果Alice
与Charlie
进行交易,这不可能影响Bob
的交易能力,因为Alice
无法消费Bob
的UTxOs
。账户模型中并非如此,我们将在下一节中详细说明。因为Alice
和Bob
进行的交易之间没有任何依赖关系,所以他们的交易可以更有效地并行化。
有人认为UTxO
模型具有更好的隐私属性,但我还不相信。据称,UTxO
模型具有更好的隐私性,因为用户可以为每笔交易使用新钱包,并在收到他们发起的交易的零钱时(即: Alice
在上面的示例中获得了97美元的零钱)。虽然Account
模型没有change
(找零)的概念,但用户也可以选择为Account
模型中的每笔交易创建一个新钱包。在为每笔交易创建新钱包时,UTxO
模型的一个好处是,分布在多个钱包中的价值可以比在账户模型中更容易地(整合/合并)。UTxO
模型中的整合理论上可以在单个交易中完成,因为可以一次消耗所有UTxO
并创建单个输出(但是块大小的实际限制将限制这一点,例如,一次最多消耗6个UTxO
)。
UTxO
模型的一个缺点是交易的大小。在UTxO
模型中,每笔交易都指定一个输入列表和一个输出列表。这意味着一些有很多输入和输出的交易可能会变得非常大。
帐户模型中的交易较小,这将在下文更详细地描述。另一个很大的缺点是模型的概念困难 - 大多数人比UTxO
模型更容易理解和概念化帐户模型,这意味着用户和开发人员都有更大的错误空间。 UTxO
模型的最后一个问题是它的智能合约能力有限。比特币对多重签名、时间锁定交易和P2SH等智能合约的支持有限。但是,比特币UTxO
模型不支持图灵完备的脚本。
Account模型
与UTxO
模型相比,账户模型可以直观地被认为类似于银行账户。账户模型中的交易指定debits
(借方)和credits
(贷方),而不是消费和创建UTxO
。让我们再次假设Alice
有100美元并想向Bob
发送3美元,尽管这次钱不是现金形式,而是存在银行账户中。为了让Alice
将这笔钱汇给Bob
,她要求她的银行从她的账户中debit
(借记)3美元,并在Bob
的账户中credit
(贷记)3美元。请注意这里没有change
(找零)的概念,以及银行如何管理这些credits
(贷方)和debits
(借方)。
我们在上面提到了UTxO
模型对于大多数用户来说是如何不那么直观的,希望这个例子能说明为什么会这样。从概念上来说,用”未花费的交易输出”来思考是很困难的,但从贷方和借方的角度来看却很容易。我们还提到了当有很多的输入和输出时,UTxO
模型中的交易如何变得非常大。账户模型中的交易更简单、更小,因为每笔交易都指定了一个简单的贷记/借记方案 —— “向Bob
发送 x ETH
“。
与UTxO
模型相比,账户模型更具表现力。账户模型支持区块链上的long lived
(长期)合约,可以为生态系统中的每个账户保留自己的状态。UTxO
模型支持长期合约,但UTxO
模型的原语不允许图灵完备的表达能力。例如,Alice
可以在账户模型区块链上编写智能合约,该合约发行代币并充当银行跟踪持有代币的每个钱包,并在代币持有人使用代币进行交易时执行借记和贷记。
智能合约充当银行管理和调解交易的想法极大影响了账户模型的并发属性。由于存在中央中介(充当银行的智能合约)的概念,Alice
与Charlie
进行的交易可能会影响到Bob
的交易能力。
作为一个人为的例子,智能合约可能有一个条款,如果所有账户余额小于10,则阻止任何人进行交易。假设Alice
的余额为11,Bob
的余额为5。还假设Alice
和Bob
都想向Charlie
发送2个硬币。如果Alice
的交易首先执行,Bob
的交易将失败,因为Alice
的余额为9
,Bob
的余额为5,Charlie
的余额为2,这种分配违反了智能合约的”所有余额必须为10或更多”的条件。但是,如果Bob
的交易先执行,它会成功,因为Alice
将拥有超过10个硬币(当前还是11
)。Bob
的第一笔交易成功不会影响Alice
的交易能力,因为仍然会有一个人(Alice
)的余额大于10。这展示了Alice
的交易如何影响Bob
的交易能力(与UTxO
模型相反),这意味着账户模型中的交易不能像UTxO
模型那样有效地并行化。账户模型中的交易顺序远比UTxO
模型重要。
账户模型的另一个后果是它使多代币交易比eUTxO
模型更困难(我们将在下一节中详细说明)。 如果Alice
有10个AliceCoin
和10个BobCoin
,并且想将每个硬币中的5个发送给Bob
,她通常会通过2次单独的交易来做到这一点,一笔交易发送5AliceCoin
,另一笔交易发送5BobCoin
。 发生这种情况是因为AliceCoin
和BobCoin
都由独立的智能合约管理,并且它们都彼此独立地管理代币余额。必须独立联系每个合约以执行适当的借贷,通常在两个单独的交易中.
但是,可以在账户模型中编写第三个智能合约,该合约在执行时会向AliceCoin
和BobCoin
智能合约发出正确的请求。 Alice
理论上可以与AliceAndBobCoinWrapper
合约进行交互,该合约将执行对AliceCoin
和BobCoin
合约的适当调用,但这种范例有几个缺点,例如安全性(Alice
必须授予AliceAndBobCoinWrapper
合约与她的代币交互的权限)、费用(可能这种情况下,使用包装合同比向各自的智能合同发出两个独立的交易更昂贵)、确定性(当合约变得更复杂时更有可能发生故障)和全面性(如果Alice
有第三或第四个想要发送的硬币怎么办?)。
eUTxO模型
扩展的UTxO
模型旨在将账户模型中的智能合约的表现力与UTxO
模型的确定性和可并行性结合起来。 eUTxO
模型具有与UTxO
模型相同的类似现金的直觉,但在构建交易时可以更好地控制如何消耗输入。可以在Cardano开发人员文档中找到eUTxO
模型的快速摘要,并且可以在IOHK博客上找到介绍该想法及其形式属性的完整科学论文。除了这两个,IOHK
在他们的博客上发表了一篇论文,将eUTxO模型与账户模型进行了比较,但这篇论文在数学上非常密集。IOHK
教育总监Lars Brujnes
的这段视频很好地概述了UTxO
模型、账户模型和eUTxO
模型。
它是如何工作的
让我们首先回顾一下UTxO
模型的一些更深层的机制。 每个UTxO
都有3个字段: 一个表示UTxO
的”大小”的value
、一个帐户的公钥(已授权可以花费该utxo
)和一个验证器函数v
,它接受一个我们称为redeemer
的参数p
。 当一个交易试图消费一个UTxO
时,它必须提供一个redeemer
,使得v(value, p)=true
。通常,此redeemer
是由钱包私钥签名的交易的哈希值。
验证者将(大约)检查交易是否由与UTxO
中的公钥对应的私钥签署,确保UTxO
只能由授权钱包使用。 可以使用更复杂的validators
(验证器)和redeemers
,但它们仍然无法提供完整的智能合约功能。 使用这种轻量级模型可以执行的脚本类型是有限的。
eUTxO
模型通过几个关键机制扩展了这个模型:
- 每个
UTxO
都会有一个称为datum
的额外字段d
,它可以持有任意数据(用于跟踪一系列交易中的嵌入状态) - 除了
redeemer
之外,每笔交易tx
的完整信息都会传递给验证者(用于称为合约连续性的概念) validator
(验证器)可以有任意逻辑
在eUTxO
模型中,为了消耗UTxO
,必须满足v(value, p, d, tx)=true
。这意味着UTxO
的validator
(验证器)必须批准交易tx
可以消费带有redeemer p
和datum d
的value
。
请记住,可以将区块链视为状态机。我们可以用同样的方式来思考一系列连续的交易。每笔交易都可以演化出一个嵌入在区块链这个更大的状态机中的状态机。为了使一系列交易连续,它们必须强制执行相同的约束。 该datum
使一系列连续的交易能够管理它们自己的状态。将完整交易tx
传递给validator
(验证器)使验证器能够强制交易的输出使用相同的合约代码。
示例
让我们通过一个示例来说明eUTxO
模型如何为datum
、validator
(验证器)和合约连续性的概念建立更多的直觉。 让我们来看看n-of-m
多重签名合约。多重签名合约是一个”具有m
个授权人但只需要n
个授权人进行签署就可以执行合约”的合约. 假设Alice
和Bob
想付钱给Charlie
做一些工作。而Charlie
想知道Alice
和Bob
有足够的钱付给他。 在Charlie
完成之前,Alice
和Bob
不想支付工作费用。他们三人可以签订2-of-3
多重签名合同,该合同将持有用于支付Charlie
的资金。 这使Charlie
能够确认Alice
和Bob
拥有足够的资金,同时也让Alice
和Bob
控制资金,直到工作完成。 为了进行支付,3人中的任何2人都可以签署合同以释放托管资金。 下面是一个状态转换图,取自eUTxO论文,它概述了多重签名合约的行为方式:
Holding
状态是尚未提出付款的情况。从这个状态,合约可以通过Propose
函数转换到Collect
状态。一旦进入Collect
状态,就有三种可能的转换: 通过Add
函数返回Collect
,通过Pay
函数返回Holding
,通过Cancel
函数返回Holding
。
Transaction | 消费的UTxO | Redeemer | 产生的UTxO | Datum |
---|---|---|---|---|
创建合约 | a | {} | ||
Propose (提议)付钱给Charlie | a | Propose(100, Charlie, 10) | b | Collecting((100, Charlie, 10), {}) |
Charlie签署多签 | b | Add(sig_charlie) | c | Collecting((100, Charlie, 10), {sig_charlie}) |
Alice签署多签 | c | Add(sig_alice) | d | Collecting((100, Charlie, 10), {sig_charlie, sig_alice}) |
Charlie完成付款 | d | Pay | e | {} |
上面的表格总结了一系列潜在的交易,这些交易使用了上面所示的多签智能合约状态机。下面我将对这些交易进行描述和阐述。
当Alice
、Bob
和Charlie
达成协议,例如向Charlie
支付100 ADA
时,他们可以启动合约,合约将以Holding
状态开始(此时datum
为空)。Alice
、Bob
和Charlie
的签名被写入到合约代码中,n
的值(等于2)也是如此。此合约启动的结果将是一个UTxO
,我们将其称为UTxO a
,它有一个强制执行有效状态转换的验证器、我们刚刚解释的空的datum
以及最终支付给Charlie
的值。
一旦Charlie
认为他已经完成了工作,就可以使用redeemer Propose(100, Charlie, 10)
来消费UTxO a
,这意味着Charlie
提议在时间10
之前向自己支付所有100 ADA
。这将创建一个新的UTxO
,我们称之为b
,它有一个值近似Collecting((100, Charlie, 10), {})
的datum
,这意味着Charlie
正试图在时间10之前收集100
个ADA
,但还没有人提交签名。UTxO b
将具有与UTxO
相同的验证器(这是合约的连续性)。
Charlie
现在可以使用redeemer Add(sig_charlie)
提交一个消耗UTxO b
的新交易。由于Charlie
是该合约的授权消费者,这将创建一个新的UTxO c
,其datum
为Collecting((100, Charlie, 10),{sig_charlie})
. 现在datum
表明三个签名者中的一个已授权向Charlie
发送100 ADA
.
如果Charlie
现在尝试用redeemer Pay
来消费UTxO c
(因为他很贪婪并且想要他的钱),那么交易将会失败,因为验证器将看到在需要2个签名时却只存在1个签名。同样,如果Charlie
尝试重新添加他的签名以满足2
个签名阈值,他只会浪费他的钱,因为合同会确保不会多次添加相同的签名。Charlie
也可以在生成UTxO c
时尝试更改验证器,但如果他尝试这样做,UTxO b
的验证器会看到这一点并拒绝交易(请记住,在消费以前的输出时,整个交易都会传递给验证器,包括输出)。
现在,Alice
或Bob
都可以提交带有他们签名的交易来推进状态图。 假设Alice
提交了一笔交易,使用redeemer Add(sig_alice)
来消费UTxO c
。这将创建一个新的UTxO d
,其datum
为Collecting((100, Charlie, 10), {sig_charlie, sig_alice})
。像以前一样,UTxO d
将具有与UTxO c
相同的验证器。
现在,Charlie
可以使用redeemer Pay
提交消费UTxO d
的交易,以完成对自己的付款。之所以会发生这种情况,是因为redeemer Pay
的唯一条件是有足够多的授权签名已经签署了合同,在本例子中,Alice
和Charlie
都已经成功签署了合同。
如果付款未在时间10
之前完成,那么任何人都可以通过使用redeemer Cancel
来提交交易以取消付款。这会将合约转换回具有一个空的redeemer
的Holding
状态。然后可以再次开始proposal
(提议)过程。
eUTxO的特性
eUTxO
模型保留了UTxO
模型的许多相同属性,例如可扩展性、确定性、隐私性,同时将脚本功能扩展为图灵完备。eUTxO
模型的一个有趣方面是它可能从根本上比帐户模型更具表现力。
这在IOHK博客上的论文中说:
尽管
translations
(翻译/转换)暗示了accounting
(会计/账户)等价性,但命题2和Sec的translation
(翻译)表明,5.2表明通常需要创建多个基于帐户的交易来模拟单个基于UTXO
的交易的效果。这一点很重要: 虽然单个基于UTXO
的交易中的所有价值转移都是以原子方式同时处理的,但不能保证相应的基于账户的交易也是如此, 从理论上讲,他们的执行之间可能存在很大的时间差距。
这篇论文文不讨论eUTxO
模型,但与介绍eUTxO模型的论文相结合时,可以合理地得出结论,eUTxO
模型至少与帐户模型一样具有表现力(并且可能更具表现力)。
这种表现力的一个例子可以在Cardano
上开发的现实世界实用程序中找到。一项名为DripDropz的服务允许生态系统中的参与者从单一界面领取可供他们使用的空投。
这在账户模型中是不可能的(我不确定这一点,但我从未见过这样的工具用于基于账户的区块链)。DripDropz能够在一次交易中向3
个不同的参与者发送超过10
种不同的资产。这意味着多达30
个独特的资产(没有两个参与者索取相同的空投)在一次交易中被转移。
这在账户模型中基本上是不可能的。有可能构建可以执行类似事情的包装合约,但这些包装合同将受到组合爆炸的影响,以涵盖所有可能的资产索赔组合。
eUTxO
模型比Account
模型更易于静态分析和形式验证。这是因为eUTxO
模型中的状态是局部的(即:绑定到每个地址),而不是全局的。由于帐户模型的全局状态,对帐户模型中给定的智能合约进行形式化分析需要对给定智能合约与之交互的每个合约进行建模。
例如, 智能合约a
调用智能合约b
调用智能合约c
在b
仍在等待c
完成时回调智能合约b
的形式化分析将非常困难(特别是如果状态可以在各种智能合约调用之间改变).我在形式分析方面的背景不够深入,无法详细描述为什么这很难分析。
但是,请记住,要使任何交易在eUTxO
模型中有效,必须满足以下条件: v(value, p, d, tx)=true
。验证器是纯函数 —— 它们是幂等的并且没有副作用。尽管datum
可以从一个UTxO
更改为下一个,但将其视为产生新状态更为合理,因为”旧”UTxO
上的datum
不能再被消耗。当进行交易时,旧datum
实际上被丢弃,并在其位置上创建了一个新datum
。纯函数特别适用于形式化和静态分析.
我们已经多次讨论过帐户模型中的交易必须如何串行完成(因为存在全局状态,智能合约可以相互交互,改变全局状态)。
我们还将其与常规UTxO
模型进行了比较,该模型支持更多并行处理,因为不共享相同输入(使用相同UTxO
)的交易彼此完全独立。这也适用于eUTxO
模型。不消耗相同输入的交易可以并行处理。这为朴素的第1
层处理能力提供了显着的性能改进,但也使分片在未来更容易实现。 对于绝大多数(也许是全部?)区块链,每个节点和矿工/验证者处理每一笔交易,与分片模式相比,这相对低效和昂贵。分片通过分割区块链的状态,使每个分片负责区块链的一小部分,从而降低节点和矿工/验证器的数据存储和处理需求。由于帐户模型的全局状态,与UTxO
模型相比,使用帐户模型进行分片相对更加困难。
例如,以太坊有一个相当复杂的分片路线图,该路线图将于2023年发布(但根据之前估计的及时性,该路线图可能会推迟很久)。Cardano
目前没有详细的分片路线图,但该项目的Basho阶段(我们目前正在进行)将使用侧链进行分片解决方案。Milkomeda是一个由DcSpark
开发的侧链,目前在主网上处于测试阶段。
如前所述,UTxO
模型不如账户模型直观。这意味着制作智能合约的开发人员可能会在使用eUTxO
模型时遇到困难。除了开发人员遇到困难之外,用户在与eUTxO
链上的智能合约交互时可能很难概念化他们在做什么。 不可否认,这两个事实都会减缓eUTxO
模型的采用。但是,由于我们在上面已经表明,eUTxO
模型至少与帐户模型一样具有表达能力,因此有一条清晰的帐户模型兼容性路径。事实上,有几个项目正在筹备中,这将使开发人员从帐户模型迁移到eUTxO
模型变得更加容易: Milkomeda
(EVM
侧链)、IELE(将为Mamba
提供动力)和Avoum(使开发人员能够直接为eUTxO
模型编写基于帐户的智能合约)。 一个有益的观察是,曾几何时,在从单核计算到多核计算的过渡期间,编写利用多核的代码很困难,但最终构建了新的工具和抽象,从而显着降低了新的多核范式的复杂性.从基于账户的区块链到基于eUTxO
的区块链的过渡(如果发生的话)也是如此 —— 将构建和发现简化开发过程的工具和抽象。
结论
Extended UTxO
模型是IOHK
的一项新创新,IOHK
是Cardano
区块链背后的科学和工程公司。eUTxO
模型结合了智能合约在账户模型中的表现力和UTxO
模型的可并行性和确定性。IOHK
的研究表明,eUTxO
模型实际上可能比账户模型更具表现力,这要归功于交易与UTxO
的交互方式的独特属性。除此之外,eUTxO
模型更容易进行形式化和静态分析,这将为用户提供更高程度的保证,即他们与之交互的合约将按预期运行。尽管eUTxO
模型不如帐户模型直观,但目前正在构建工具和抽象,这将有助于弥合差距并简化学习和过渡过程。