了解Cardano的EUTXOs模型

Cardano提出的创新之一是对比特币的会计模式进行了扩展。比特币本质上是简单的,但这并不意味着它的各个部分不能被改进。作为Cardano项目的一部分,技术上的进步正在进行中。来探索会计模型的历史和它们的演变。

中本聪使用了许多技术来建立比特币。其中之一是使用未支出交易输出(UTxO)的会计模型。Vitalik Buterin和他的团队决定使用一种基于账户的不同会计模型,因为它似乎是执行智能合约的更好的解决方案。在文章中,我们将其称为基于账户的模型。

现在,许多项目如Solana、Polkadot和Algorand都使用与以太坊相同的会计模型。这两种方法都有优点和缺点,开发人员在基础层之上构建时面临不同的挑战。构建Cardano的IOG团队决定走一条不同的路线,并扩展了比特币的原始模型–UTXO。新的模型被命名为Extended-UTXO。

会计模型
会计是当今金融世界的基础。每个金融实体都需要跟踪个人账户余额和现金流。账本也是区块链网络的基础,因为它的核心是一个全球资产负债表,为我们提供谁在什么时间拥有什么资产的答案。

区块链记录了整个交易的历史。在区块链中审计记录是非常容易的。区块链有一个很大的优势。它允许我们在没有不必要的中间人的情况下拥有资产,并确保系统中没有人可以作弊。

一个区块链网络本质上有两个基本任务. 维护账本,并通过交易实现价值从账户到账户的转移。第一代区块链网络只允许无条件地发送交易(从爱丽丝的账户推送到鲍勃的账户)。第二代增加了可编程性 ,即有条件地发送交易的能力。有一些工具可供第三方开发者使用,允许他们编写和部署程序(智能合约/脚本),网络可以以去中心化的方式执行。第一代区块链网络可以被看作是PayPal。第二代将实现一个全面的银行系统。

在传统的金融世界里,人们依赖会计师和复杂的中心化系统。为了确保会计师不作弊,有必要监测资金流动,积极实施防欺诈措施 ,并审计分类账。

区块链网络依赖于写进源代码的规则。假设源代码被正确实施,并且行为符合大多数人的期望,那么就不需要采取预防措施,所有数据都可以被所有人使用。每个人都可以在自己的电脑上拥有一个全球账本,并直接与网络互动。它允许用户之间进行点对点的互动,其中去中心化的网络是一个可信的中间人.

如何从区块链的角度理解区块链
区块链本质上是一个特定的数据库,能够确保历史记录的不可更改性。这些记录与用户之间通过交易发生的价值转移有关。区块链总是知道哪个用户X在Z时间拥有代币Y这个问题的确切答案。因为区块链是伪匿名的,所以使用区块链地址而不是具体用户。区块链保留了从一开始到现在的所有交易的历史。此外,它确保历史不能被覆盖。

区块链在技术上是一个状态机,因为它记住了以前的事件,这些事件被称为系统状态。这些事件是用户之间的互动。在预定的条件下,状态可以被改变。每个协议都实现了一个逻辑,允许状态从S-0过渡到S+1。每隔一段时间,网络就会创建新的区块,在其中发生所谓的状态转换。

UTXO和基于会计的模型之间的区别在于处理记账的方式。从添加新块的角度来看,它与状态转换无关。一个新区块是由一个节点创建的,必须广播给网络。每个新区块都包含一组交易,如果它被网络中的大多数参与者接受(严格来说是被积极参与网络共识的全部节点接受),就会发生状态转换。如果一个区块被接受,所有包含的交易也被接受。新的区块将被永久地储存在区块链中,随着它的加入,资产所有者将完全按照被接受的交易所规定的方式改变。

从本质上讲,区块链网络的作用是验证交易,将有效交易插入新区块,验证区块并将其加入区块链的历史中。让我们补充一下,这个过程是以去中心化的方式发生的 ,所以新的交易和区块需要广播给整个网络,由网络处理验证。

区块链地址
资产所有权(硬币和代币)是通过拥有一个给定地址的私人加密密钥来表示的,它来自公共加密密钥。通常情况下,地址是散列的。你可以把交易看作是向网络发送的特定信息,其中发送者指示将选定数量的资产从发送者的地址转移到接收者的地址。一个有效的交易必须包含证明发件人是代币的真正所有者。为了做到这一点,一个私人加密密钥被用来签署交易。网络,或者说每个节点,能够验证签名并评估交易是否有效。对于简单的交易,验证是基于一个私人和公共密钥对。

1*eC2qRDaM4lNPSWDfwVOiEA

图片:钱包将帮助用户生成区块链地址并发送签名交易。网络将通过公钥验证交易,如果交易有效,它将被包含在新的区块中。

如果交易被接受并包含在已添加到区块链的区块中,资产将由收件人地址的所有者拥有。只有新的所有者可以花费它们,同样是通过用私钥进行的签名。用户当然也可以将资产发送给自己。

这个概念对于UTXO和基于会计的模式都是一样的,因为它是基于公钥密码学(非对称密码学)的。

重要的是要记住,用户所认为的硬币或代币实际上只是与区块链地址相关的数字。交易的目的是将一个数字从发送方地址转移,并将相同的价值分配给一个地址,或在多个接收方地址之间分割。由于需要收费,所以价值通常会被分割到多个地址。在交易的输入和输出处的价值必须始终是相同的 。一个价值不能在共同的交易中被创造或丢失。网络通常定义创建新价值的规则。

每当人们谈论硬币或代币时,包括在这篇文章中,他们实际上是在谈论数字。代币只是一个数字的抽象,用户很容易理解。

用户把他们的资产当作他们账户中的余额。钱包生成所有的私钥和私钥对,所以他们知道所有用户的公共地址。所有创建的地址都可以包含资产。钱包将所有地址的代币相加(将所有数字相加),并将其作为余额显示给用户。一个钱包可以只有一个单一的地址,一切工作都是完全一样的。

UTXO和基于账户的模式之间的区别
UTXO和基于账户的模式之间的区别在于资产是如何存储在地址上的,以及如何在交易中处理它们。换句话说,这两种不同的模型如何处理余额以及如何记录系统的状态。在更广泛的背景下,重要的是当一个新的区块被创建时,什么规则和条件被定义(并在节点的源代码中实现)。网络的验证是价值转移的一个组成部分。

未使用的交易输出( UTXO )是一个技术术语,指的是在处理完交易后剩余的数字资产的数量。UTXO是一个数字,你可以把它看成是一个资产的数量。在UTXO模型中,你可以交替使用UTXO和资产(硬币或代币)这些术语。

Cardano使用一个扩展的UTXO模型,称为Extended-UTXO ( EUTXO )。在EUTXO模型中,资产的转移被记录为地址之间的有向无环图(DAG)。虽然听起来很吓人,但没有必要害怕。事实上,这很容易理解。

正如我们所说,每个UTXO由一个数字表示,是一个硬币或代币的抽象。你可以把UTXO看作是实体钞票或硬币,但不同的是,UTXO不需要有确定的面额。例如,10个ADA可以是一个UTXO。12张ADA也可以是一个UTXO。甚至,116.85也可以是一个UTXO。

现在想象一下,爱丽丝的钱包里有所有三个UTXO。如果她把这三个UTXO放在同一个地址,或者每个UTXO都在自己的地址,这都不重要。如果她想知道她的余额,她必须将所有的UTXO加起来。她的钱包会帮她做到这一点。她的余额是10+12+116.85=138.85 ADA。

1*7KqPtBMQqpRygzmHp9D1qw

图片:当涉及到UTXO在地址上的分布时,你钱包中的相同余额可以有不同的表现。你可以在一个地址上有3个UTXO,或者在3个地址上有3个UTXO。

让我们看看当爱丽丝决定发送15个ADA给鲍勃时会发生什么。鲍勃在他的钱包里有21个ADA在一个地址上。他决定创建一个新的地址来接收爱丽丝的15个ADA。爱丽丝的钱包必须使用2个UTXO。钱包选择了有10和12 ADA的UTXO。带有10 ADA的UTXO被全部花光。只有5 ADA + 0.2 ADA(交易费)被从12 ADA的UTXO中取出。

在交易被接受后,爱丽丝将只有2个有6.8和116.85 ADA的UTXO。总的来说,爱丽丝将拥有123.65 ADA。鲍勃将有2个UTXO,分别为21和15个UTXO。总的来说,鲍勃将有36个ADA。0.2 ADA将被添加到收费地址。

1*qdOM4WY5XHVe5xL6AUsbDQ

图片:两个状态之间的转换已经通过一个交易执行。该事务是在状态N(块N)中创建的,并被包含在块N+1中。

两个状态(区块)之间的转换是通过一个事务执行的。事务的组成是很重要的。一个事务有输入和输出。请注意,根据交易的需要,输入端上的值如何转化为输出端上的值,完全按照发送方(钱包)的构造。交易中的每一个UTXO都必须作为一个整体来使用,因为之前区块的记录不能被编辑。输入是一组要花费的UTXO,即总价值将被交易用来创造输出。交易的输出也是一组UTXO,将被分配到一个新的地址。另外,一些或所有的UTXO可以被分配到同一地址,但数值不同。一个用户可以在一个地址有3个UTXO,而希望在同一地址只有1个UTXO。总值保持不变。

在我们的例子中,我们有两个输入和三个输出。输入是属于Alice的3个UTXO。输出是3个UTXO。具体来说,一个为Bob准备的有15 ADA的UTXO,一个有0.2 ADA的UTXO作为交易费用,还有一个有6.8 ADA的UTXO,这是返回给Alice的金额。为了使交易有效,输入的硬币数量必须与输出的硬币数量一致。在我们的例子中,这就是22个ADA币。

人们可能会觉得奇怪,有必要把6.8 ADA还给Alice。这类似于如果你用比你购买的总价更高的钞票付款,商店的收银员会还给你。同样,每个UTXO必须全额花费 ,所以有必要确保剩余部分作为交易的一部分返还给爱丽丝(如果有一些剩余)。

请注意,UTXO模型在创建交易过程中使用单个UTXO操作。当花费一定数量的代币时,必须选择必要数量的合适UTXO。如果选择的UTXO中的代币之和大于要花费的代币数量,剩余的部分必须作为新的UTXO返回到发送者的地址。

UTXO的待遇与真钱一样。如果你在一家商店要支付85美元,你可以用100美元的纸币支付,收银员会给你返还15美元(10美元和5美元的纸币)。你不能莫名其妙地从一张100美元的纸币上剪下85美元,然后用它付款。你可以在你的钱包里找到17张5美元的纸币,然后用它们付款。你还不如在你的Cardano钱包里有17个UTXO与5个ADA。

每个UTXO只能花一次,将来也不能再花。一旦它被花掉,一个或多个新的UTXO被创造出来,随后可以被花掉。这个循环是不断重复的。UTXO模型是组织区块链的一种方式,这样就不会有资产被花费两次。区块链每隔一段时间就会过渡到一个新的状态。用户可以在未来的任何状态下花费未花费的UTXO。例如,Bob可能在N状态下收到UTXO,并决定在14天后花费它,这可能是N+60,480状态。花掉UTXO基本上意味着将价值转移到另一个地址。

每个区块都有几个交易,所以有很多UTXO被花费。所有的交易一起形成一个集合(一个块),代表了状态之间的转换。在UTXO模型中,交易输出的整个图,花掉的和未花掉的,代表了全局状态。可以区分当前状态和所有早期状态,这基本上是自第一个创世块以来的整个交易历史。

如果你对当前状态下可以花费的所有代币的数量感兴趣,你将不得不计算所有未花费的产出(UTXO)。找到它们基本上意味着要翻阅从创世区块到现在的所有交易。完整的节点在与网络同步期间验证所有的交易,所以他们知道当前的UTXO集。

1*6t4HPuzXbFVF_MgTh0t8cg

图片:各州之间的UTXO位置。图片上有6个蓝色的UTXO是未使用的。

现在让我们来看看基于账户的模式。这类似于一个银行账户。与UTXO模型一样,资产是与区块链地址相关的数字。在基于账户的模型中,对于特定类型的资产,只有当前的余额被保存在地址中。交易以这样的方式调整地址上的余额,即从一个地址减去一个值,并将其添加到另一个地址。

让我们用一个例子来说明这一点。爱丽丝有138.85个ETH,决定向鲍勃发送15个ETH。鲍勃在他的余额中有21个ETH。

1*FcKIec5Or0EAZjb57Ggrqg

图片:交易在状态转换期间改变了两个地址的余额。

该交易从Alice的余额中减去15ETH,并将其加入Bob的余额。接下来,从Alice的余额(GAS)中扣除了0.15ETH的交易费用。

在基于账户的模型中,全局状态可以被理解为一个所有账户的数据库,以及它们在网络上不同资产的当前余额。每增加一个新的区块,系统的状态就会根据该区块中包含的所有交易进行更新。只要用户的数量保持不变,账户的数量就保持不变,并且与进行的交易数量无关。

1*_ZLZmYJ8o-dQADQlmQyKWg

图片:最后一个状态N+3是当前的全局状态。

注意这两个概念之间的差异。UTXO模型在协议层面上并不使用钱包或余额的概念。该模型只基于交易历史。用户的余额必须根据UTXO的转账历史在本地确定。

回到区块
现在让我们回到区块,解释它们在状态之间转换的重要性。每笔交易基本上都是一个改变全局状态的请求。在区块链网络的情况下,网络中必要的大多数节点应该同意并接受新的状态。用每一笔交易来同步整个网络将是非常低效的资源。节点的全球同步是一个耗时的过程,因为信息必须广播给整个世界。随着交易数量的增加,网络将无法及时同步。解决方案是一个包含多个交易的区块。多个用户请求通过区块在同步范围内进行处理。

区块是区块链网络的心脏。比特币平均每10分钟从当前状态过渡到一个新的状态。Cardano大约每20秒一次。

由于每个单独的交易都是一个状态变化的请求,一个区块,连同它所包含的所有交易,成为一个状态变化请求,是同步网络的手段。如果要改变全局状态,网络中的大多数节点必须接受整个区块的要求。这意味着区块中的所有交易必须是单独和相互有效的。例如,当验证一个新区块时,每个节点都必须确保同一资产不会被花费两次 . 如果不符合验证规则,整个区块将被网络拒绝。

1*dveUHwy1u4C08gdfy786BQ

图片:区块链网络在不断同步。状态之间的转换是通过区块发生的。

区块链基本上是一个区块的序列,这些区块以一种不能改变顺序的方式相互联系。在当前大多数网络中,一个随机选择的节点将产生一个新的区块。然后这个区块被广播给网络中的所有其他节点。重要的是,在另一个随机选择的节点创建另一个新区块之前,新区块要在整个网络中传播,以便新区块可以与前一个区块相连接。如果新区块的传播速度太慢,就会产生分叉,这是一种不需要的状态。当另一个区块被添加到前一个区块时,有必要从两个区块中选择一个,这意味着其中一个区块将永远保留在区块链中,另一个区块将成为孤儿(与所有交易)。

UTXO和基于账户的模型在过渡到基于区块的新状态的概念上没有区别。根本的区别在于全局状态的更新。在UTXO模型中,全局状态只通过创建新的UTXO来扩展,而在基于账户的模型中,全局状态在余额变化的层面上被更新。

这两个模型在处理交易的方式上也有所不同。UTXO模型是一个验证模型。交易指定了一个状态转换的预期结果。结果被定义为一个新的UTXO,它是根据交易的输入创建的。节点验证输入是否未花费,交易的数字签名或其他花费条件是否有效。 基于账户的模型是一个计算模型。交易是指示状态转换应该是什么样子的。节点根据指示来计算新的状态。在这两种情况下,状态的改变可能需要执行一个智能合约。智能合约可以被看作是状态转换指令的延伸。

当涉及到区块的验证、智能合约的执行和可扩展性时,UTXO和基于账户的模型的差异有影响。

了解基础知识
在进入扩展UTXO之前,有必要简单解释一些基本的概念,这些概念对开发者来说是众所周知的,但对普通大众来说却不是。

让我们从并发性和并行性这两个术语开始。

并发意味着多个计算 "几乎 "在同一时间发生。用户可以感觉到任务是在同时进行的,但在后台只有一个演员在任务之间快速切换。如果你有一台单处理器的计算机,就会发生这种情况。并发允许文本编辑器和音乐播放器在同一时间运行。该进程对每个进程都投入了很短的时间,因此从用户的角度来看,它们似乎是在同时运行。这是因为处理器的速度比人类的感知快得多。如果计算机有多个处理器,它可以将单个任务委托给一个专门的处理器。因此,任务可以并行运行。

为了在一个大任务或一堆任务(可能相关,也可能不相关)中实现并发,必须有可能将工作分成较小的部分,这样才有可能在子任务上独立工作。

当一个行为体要处理一堆任务时,它可以在开始下一个任务之前完成一个任务。在这种情况下,行动者将按顺序处理这些任务。或者,单个行为体可以在一个合适的时刻依次切换任务。单个行为体可以在大致相同的时间内完成所有的任务。问题是,对于给定的任务,切换是否更有效。在这种情况下,任务是同时处理的,但不是并行的。

当有多个代理能够处理一堆任务时,它可能更有效。在这种情况下,多个代理必须能够同时在任务上取得进展而不互相干扰。这些任务将被同时处理,也是并行的,因此它们将更快地完成。

1*8QqDxYufUztecoUZXaXDRA

图片:让我们有更多必须处理的任务。单个行为者可以一个一个地完成任务,也就是按顺序完成。或者,单个行为者可以在同时处理的任务之间进行切换。你可以看到,这些任务可以由3个代理来处理。在这种情况下,任务被并发处理,也被平行处理。

有时,将工作分成多个可以单独处理的任务可能很困难。这取决于输入是否可以分割成独立的单元,或者多个代理需要同时使用一个独特的资源。在这种情况下,代理会出现争夺。这意味着更多的代理想在同一时间使用独特的资源,但实际上只有一个人可以成功 . 赢家可以永久地消耗资源,或者在它不再需要时将其释放给其他人。争夺可以通过代理的某种形式的同步来解决。代理人在处理其子任务时可能会受到限制。

一般来说,当我们关注一个任务或一堆小任务的处理速度时,努力实现最大程度的并行化是有利的。从可扩展性的角度来看,如果有可能实现更高的并行化,即允许同时处理更多的交易,这对区块链网络总是更有利的。然而,这可能需要处理争论和许多其他方面的问题。

不能明确地说,并行化总是可能的最佳解决方案。在一些特定的情况下,并发性可能有其优势。特别是当需要某种形式的同步来避免争用问题时。没有所谓的最佳通用设计。相反,我们可以谈论一个更适合于特定问题的解决方案。

让我们来解释一下确定性这个词。确定性算法是一种算法,给定一个特定的输入,将总是产生相同的输出,而底层机器总是经过相同的状态序列。

从用户的角度来看,这意味着他们可以估计甚至提前知道在插入特定的输入后可以期待什么结果。例如,如果你在计算器中输入一个5+5的操作,你会事先预期结果是10。任何其他的结果都会是一个错误。开发人员试图建立尽可能确定的系统,因为这保证了高水平的可靠性,从而保证了高用户体验。

在区块链的背景下,用户希望能够提前预测交易的提交结果。确定性意味着,当用户创建交易时,他希望带有设定费用的交易能尽快进入区块,并有预期的结果。用户对脚本验证和智能合约的执行有同样的期望。当一个交易被提交时,它不应该失败,用户也不应该为失败的交易付费。

在会计模型的设计过程中,随着智能合约的处理方式,预测可能发生不确定性的条件是很重要的。重要的是要了解导致不确定性的原因,并尝试设计一个系统,在其中可以避免或将发生最小化。去中心化应用程序的开发者应该被提供一些工具,帮助他们创建行为可预测和安全的程序。

应用程序的一个风险是访问易变的分类帐数据,即可能不断变化的数据。如果交易或智能合约的结果取决于可变数据的状态,那么在执行过程中可能会出现不确定性。当操作的处理尽可能与它的环境隔离(避免使用外部易变数据),并且只依赖于本地数据时,这总是有利的。

每个操作总是在某种程度上依赖于其环境。问题是环境能在多大程度上影响交易的结果以及如何影响环境。如果攻击者能够改变易变的分类账数据,他就可以影响交易的结果和智能合约的执行,从而获得个人利益。系统的设计应尽量减少攻击的可能性。

会计模型演变简史
首先让我们从比特币开始 ,它首先提出了UTXO模型。UTXO的优势在于,交易验证时的计算是在链外进行的。交易既是计算的结果(本地验证)也是证明。在区块链中存储交易就足够了,不需要进一步处理状态和它们的最终存储。

交易输入总是现有的未使用的UTXO,节点很容易验证它。这意味着同一交易或相同的输入不能被使用两次。验证是容易的,因为它发生在一个区块内,这是一个有明确边界的空间。试图第二次使用相同的输入很容易被发现,并且不会被接受。交易可以被并行处理,因为它们不依赖于任何外部状态。

比特币的UTXO模型在可编程性方面非常弱。几乎不可能创建一个复杂的计算。试图在UTXO模型上创建一个有状态的合约,往往会导致高存储需求和低状态利用率。每个输入需要一个见证脚本,每个输出需要一个锁定脚本。因此,随着UTXO数量的增长,相关的见证脚本的数量也在增长。脚本验证所需的计算能力以及存储脚本和见证数据的需要增加了资源需求,从而增加了成本。

以太坊是第一个提出基于账户的模式的。以太坊使写一个具有复杂逻辑的小程序成为可能,它被称为智能合约。交易被解释为改变全球状态的事件。以太坊虚拟机(EVM)根据之前的区块链状态,计算这些事件的状态转换结果。

这是一个重要的观点,因为之前的状态成为当前计算新的全局状态的一个组成部分。换句话说,当前计算的正确性取决于过去。影响区块链状态的交易(计算的输入数据)与交易的结果(输出数据)在语法上是分开的。

全局状态在节点上本地存储,不以区块为单位传输。节点通过基于交易(事件)在本地进行自己的全局状态计算,然后将其结果与收到的结果(State-Root)进行比较,就新的全局状态达成多数共识。换句话说,所有诚实的节点都应该在本地计算后得到与提议的状态根相同的结果。这是整个网络中转换到新的全局状态的唯一途径。

1*NbiENjla48WNEG7dy95_iw

图片:节点处理了3个事务(事件),从全局状态N过渡到状态N+3。然后它创建了一个具有根状态的新块。网络中的所有节点在处理完交易后都应该计算出相同的状态-Root。

在基于账户的模型中,所有账户都是有状态的。这意味着在过渡到新状态(智能合约处理)的计算时间,全局状态被锁定,即不可改变。开发者有一定的抽象性,使其更容易开发智能合约。他们可以与所有余额进行合作和互动。根据计算的结果,将创建一个新的全局状态,在下一次计算之前将再次锁定,这将导致另一个新的状态。状态之间有一连串的转换。

其优点是,当全局状态被锁定时,开发人员可以对任何账户(余额)进行操作。这意味着有可能在一个区块内多次处理一个特定账户。这是可能的,因为交易和合约的顺序处理。换句话说,Ethereum擅长并发性。

这种设计对开发者是友好的,因为它很容易操作。另一方面,开发者不能控制交易和合约的处理顺序,因为这掌握在区块生产者和用户手中,他们设定了费用。因此,开发者必须考虑到许多可能的结果和攻击企图。这可能是一个挑战。

遵守顺序是很重要的,因为它是防御双重消费攻击的一部分。每个账户都有一个 "nonce "值,包含在每个交易中。随着来自一个给定账户的每一笔新交易,nonce被递增。这种机制可以防止交易的平行处理。如果一个特定账户的几笔交易中的第一笔交易失败,并且没有包括在一个区块中,那么随后的交易也会失败。

重要的是要明白,交易(事件)是相互依赖的,它们在区块中的顺序很重要。当一个节点收到一个新的区块时,只有当它计算出与区块中提议的相同的状态-根时,它才会接受它。只有当正在处理的事件的顺序,即相同的过渡序列被遵循时,这才会发生。

在基于账户的模型中,一个简单的交易可以被看作是一个改变两个用户余额的请求。一个交易是一个改变全局状态的事件,而不是一个具体的输入和输出。因此,一个交易必须在先前状态的背景下被评估为正确的。这也适用于建立在EVM之上的所有其他应用程序和协议。

用户在提交新的交易时,会对某种状态做出反应,如资产的价格。用户无法影响的是交易在区块中的过渡序列中的预期位置。这对于在预定条件下操作的更复杂的交易来说可能是一个问题,因为不能事先保证在尝试包含时,提议的状态转换仍然有效。用户永远无法确定,也无法提前在本地验证他的交易是否会被加入到区块中。因此,尽管支付了交易费,但交易可能会失败。交易的结果具有较高的不确定性,它不是确定性的。

失败的交易是全局状态(可变的共享数据)的结果。多方可能希望提交交易,以特定方式改变全局状态。然而,修改后的全局状态会阻止其他提交的事务的处理。换句话说,只有在特定时间或特定条件下提交的第一个事务可以被处理。其余的交易可能会失败。这使得智能合约的构建变得复杂,并可以被认为是攻击的一个表面区域。

让我们举一个具体的例子。用户Bob可以根据他在某一时刻看到的特定余额的状态来构建一个交易。然而,这些余额可能已经被爱丽丝的交易所改变,而爱丽丝的交易被意外地放在鲍勃的交易之前(爱丽丝可能使用了更高的费用,或者矿工决定将爱丽丝的交易放在鲍勃的交易之前,因为费用是一样的)。在Bob的交易被插入的那一刻,全局状态与Bob考虑到的状态不同。全局状态的这种变化可能会导致交易失败,或者在更糟糕的情况下,可能会导致一个不可预测的状态。

让我们来总结一下。以太坊实现的基于账户的模式,对于应用开发者来说,它的优势在于不必担心并发性问题。开发人员可以自由地处理用户账户并改变余额。可以确保余额根据事件的需要被单独访问,所以两个代理同时访问同一余额的风险较小。因此,设计一个应用程序是相对容易的。基于账户的模式允许用户在一个区块内多次访问一个账户。这意味着爱丽丝可以在一次交易中从她的账户向鲍勃发送ETH,也可以在另一次交易中向卡罗尔发送ETH。这两笔交易可以在同一个区块中进行。

其缺点是上述并行化的复杂性,经常失败的交易,以及即使是失败的交易也要支付一定的费用。此外,由于交易的排序,有一个被称为矿工可提取价值(MEV)的问题。

E-UTXO的优势
Cardano使用扩展UTXO模型,缩写为EUTXO。EUTXO模型的目的是支持更高的可编程性,同时保持比特币的UTXO模型的所有优点。扩展的UTXO模型对Cardano很重要,因为它想成为不仅仅是一个交易性网络。Cardano是一个平台,所以允许开发者建立更复杂的功能是很重要的。这是通过智能合约实现的。在Cardano的情况下,谈论验证器脚本更为准确。在文本中,我们可能会交替使用这些术语,但它们是相同的。

与基于账户的模式相比,EUTXO提供了一些优势。特别是,在执行智能合约时更安全,费用可预测性 ,本地验证确保交易在提交后会被接受,以及固有的碎片化区块链状态。这允许交易处理的并行化,这对链上的可扩展性有积极影响。并行化对于智能合约的执行也很重要。像交易一样,智能合约也可以独立执行,即并行执行。

在处理智能合约时,区块中的顺序并不重要,不需要考虑区块中其他合约的执行结果,所以执行本身可以说是比较安全的。换句话说,由于各个智能合约的执行结果是相互独立的,而且没有共享的可变(全局)状态,所以攻击的面更小。

值得注意的是,去中心化应用的可扩展性是基于会计模型的能力。一般来说,智能合约及其执行可以被看作是一个取决于区块链能力的层。

并行化选项是基于原始的UTXO设计,每个现有的未使用的UTXO是由以前的交易序列组成的。每个EUTXO都可以独立处理。在处理和验证EUTXO的过程中,不存在需要考虑的全局状态这回事。只有本地状态是重要的。这意味着交易的结果只取决于UTXO的使用,UTXO是不可改变的,一次性使用的对象,作为交易的输入,将产生输出。

1*0oYEmFQ13mqSNriIwG2cqQ

图片:Cardano节点处理了3个常规交易和3个脚本交易。然后它产生了一个新的区块。这些交易是相互独立的,可以并行处理和验证。

每个交易可以消耗一个或多个EUTXO,这将创建新的EUTXO,其总价值相同。一个交易能够影响另一个应用于账本的交易的效果的唯一方法是,在后来的交易试图花费相同的EUTXO,从而导致节点拒绝它。

如果一个交易通过了本地验证,用户几乎可以确定该交易将进入新区块。EUTXO模型中的交易是相互独立的,是确定性的 ,这意味着交易很可能不会失败。这对于Plutus脚本的验证也是如此。用户可以在本地检查一个Plutus脚本是否可以在链上提交和运行。这可以确保费用永远不会丢失。然而,有一条规则必须遵守,即每个EUTXO只能在一个区块内花费一次,并且是一个整体。

UTXO的支出必须被整个网络接受,作为增加一个新区块的一部分。这意味着UTXO的接收者只能在下一个区块中花费。而不是在接收UTXO的同一区块中。增加一个新区块可以被认为是Cardano区块链的一个状态转换。然而,在区块本身,各个交易和EUTXO是相互独立的。

EUTXO模型比基于账户的模型更具确定性,但交易仍然可以被拒绝。拒绝意味着,尽管交易被正确构建,但它不能被应用到区块链上。如果发生这种情况,该交易对区块链的状态没有影响,所以不需要支付任何费用。交易拒绝发生在争夺的情况下。这意味着区块链的状态在用户在本地构建交易的大约同一时间发生了变化。本地验证已经通过,但区块链状态在提交的时刻已经不同。确定性确保,每当一个交易被接受时 ,它只会对账本状态产生可预测的影响。换句话说,它对账本状态的影响与它在构建和本地验证期间的影响相同。

对于开发者来说,创建一个验证器脚本可能更困难,因为他们必须自己处理并发问题。如果交易在同一时间依赖同一个EUTXO,就会遇到争用。例如,如果几个EUTXO被智能合约锁定,那么在一个区块内只有一个代理可以与它们互动。注意,这个限制只适用于EUTXO。不同的代理可以与其他智能合约互动,而不会出现任何并发失败。一个智能合约可以处理许多不同的UTXO,这些UTXO构成了它的当前状态和链外元数据,允许解释这些UTXO。

图片

图:并发和并行处理。代理人可以同时消费多个EUTXO。当他们想消费同一个EUTXO时,他们会遇到争夺。

并行化,或同时执行多个独立操作的能力,是整个网络性能和可扩展性方面的一个重要特征。基于账户的模型的全局状态限制了可扩展性的选择,因为在交易处理以及智能合约执行中实现并行化是非常困难的。通过EUTXO模型,可以实现更高层次的并发,这为提高可扩展性打开了大门。

让我们来看看与使用比特币的UTXO模型相比,EUTXO模型有什么新的地方。在Cardano网络中处理一个交易涉及验证所请求的行动。节点验证它是否能够执行请求的行动,以及交易的作者是否提供了相关的数据/输入。

常见的行动是普通的交易,打算花费用公钥锁定的EUTXO . 节点验证交易的作者已经提供了一个数字签名与相应的私钥 . 如果验证成功,将执行该操作,即消费EUTXO。与比特币相比,这里还没有什么新东西。

下一个动作是验证那些打算花费被脚本地址锁定的EUTXO的交易。

脚本是一个程序(一段代码),决定花费EUTXO的交易是否被授权这样做。一个脚本包含纯函数,其结果是真或假。为了验证一个交易,节点会调用脚本解释器,这是一个可以翻译和执行Plutus脚本代码的程序。解释器执行的脚本,其哈希值已经由UTXO被锁定的地址形成。换句话说,当一个EUTXO被Plutus脚本锁定时,该EUTXO的脚本代码就与它的地址相关。

1*rnl0ROUu3aL2GgbcI6mWYw

图片:节点收到一个交易,有一个花掉EUTXO的动作,该交易被脚本地址锁定。

让我们来看看,除了Plutus实现的更高的可编程性的表现力之外,与比特币相比,EUTXO真正的创新之处。

扩展UTXO允许用户选择性地在UTXO中添加类似JSON格式的任意用户数据。这种数据被称为Datum 。Datum将允许开发者赋予脚本类似状态的功能。用户数据可以被看作是一个本地的脚本状态。这种状态只具有本地的有效性,因为它与特定的UTXO相关联。使用Datum的全部潜力取决于开发者。

交易可以携带用户特定的参数,称为救赎者。Redeemer可以被看作是交易的作者对如何使用UTXO的意图。Redeemer可以被去中心化应用程序的开发者用于各种目的。

在Datum和Redeemer之间通常有一个约束力,这取决于特定应用程序的具体功能。当一个交易被验证时,一个验证脚本与Datum、Redeemer和包括交易数据的上下文一起操作。该脚本包含条件,当这些条件被满足时,允许消耗UTXO。Datum, Redeemer, 和交易背景是输入到脚本的数据。

图片:根据输入数据,脚本决定是否可以消耗EUTXO。

为了花费被脚本锁定的EUTXO,首先需要让脚本进入区块链。解除UTXO的锁定将取决于脚本,所以交易将包含脚本,也包含要锁定的UTXO。

开发者(或他们的应用程序)编写Plutus的链上代码,并以特殊格式打包。然后,必须创建一个交易,将Plutus脚本嵌入其中。一旦交易被存储在区块链上,就可以发送另一个交易来启动脚本的执行。该交易可以被看作是给脚本的一个消息。

开发人员将应用程序分为链上代码和链下代码。链外代码可以是钱包的一部分,也可以是一个去中心化的应用程序(DEX)。应用程序的链外部分可以创建一个交易,包含链上脚本和要锁定的EUTXO。对于每一个EUTXO,都需要指定Datum的哈希值。用户必须签署该交易。在交易被提交并被网络接受后,EUTXO将被脚本锁定。

图片:Plutus交易包含一个验证器脚本,并在EUTXO中添加一个Datum。一旦交易被包含在区块中,EUTXO将被脚本锁定。

验证一个脚本要比验证一个普通的事务需要更多的资源。不确定性的一个来源可能是智能合约/脚本执行费用的大小。在Cardano的情况下,执行脚本的预算是交易的一部分,有可能提前在本地计算出确切的费用。脚本解释器在预算范围内跟踪脚本执行期间的资源消耗。如果执行预算用完了,脚本评估就会停止,结果是False 。一个假值意味着EUTXO不会被消耗。

请注意,Plutus脚本只在与EUTXO相关的状态下工作,并进一步与它在事务中收到的数据相关。脚本的执行不依赖于其他任何东西 . 从账本的角度看,唯一会在全球范围内发生变化的是,随着每个新增加的区块,EUTXO从地址移动到其他地址。

同样的合约可以用来锁定Alice和Bob的币。执行Alice的币的脚本对执行Bob的币的脚本没有影响,因为它们是对不同的EUTXO的两个独立执行。这两个独立执行的结果取决于本地状态。

为了与脚本交互,构建了一个支出事务(消息事务)。事务的输入可以是被脚本锁定的EUTXO。花费事务调用脚本解释器,以验证脚本,并在满足条件的情况下解锁EUTXO。因此,解锁的EUTXO被转移到一个新的地址。

1*crDIhOEqx7MFcdKWYLSDcQ

图片:为了从应用平衡中消耗EUTXO,Plutus解释器必须执行与EUTXO相关的Plutus脚本。该脚本使用Datum、Redeemer和交易背景作为输入。执行的结果是True,所以EUTXO可以被消费。12 ADA被发送至Bob的地址。

一些应用程序可能需要在多个EUTXO上处理全局状态,可以使用Datum来实现。在特定的协议设计中,一种全局状态是可以实现的。协议的设计者必须意识到,如果EUTXO被脚本锁定,在一个区块内只有一个代理可以与之交互。这可能需要代理之间进行某种同步。

让我们用一个例子来说明这一点。AMM DEX使用的流动性池是共享资源,因为用户想在同一时间(在同一区块内)使用它们。每个流动资金池都包含一组EUTXO。因此,可用的EUTXO也是共享资源,因为除非一个代理以某种约定的方式为自己保留一个特定的EUTXO,否则它们对其他人都是可用的。

应用算法必须确保当事务被构建时,单个代理不会争夺池中的EUTXO。从验证的角度来看,想要消费特定EUTXO的事务是相互独立的。然而,由于多个代理可能想在同一时间消费同一资源(同一EUTXO)来构建一个事务,因此存在依赖性。换句话说,代理想要同时工作。目前使用的一个解决方案是批量交易。代理人搜索合适的请求UTXO,这些请求UTXO想与特定的流动性池互动,以实现请求的互换。代理人在这样做的时候会考虑到所有其他可用的互换请求,并将选定的互换插入一个大的批量交易中。当创建一个批量交易时,代理知道哪些EUTXO已经被使用。他们可以确保一个特定的EUTXO在一个批处理中不被使用两次。

总结
Cardano最好的一点是,团队正在不断地升级它,这将逐渐增加它的能力。在写这篇文章的时候,Vasil硬分叉即将到来,这将给Cardano带来许多脚本改进。具体来说,这些是参考输入(CIP-31),内联基准(CIP-32),参考脚本(CIP-33),和抵押输出(CIP-40)。所有这些改进将为开发人员在设计他们的应用程序时提供更多的选择。

1 Like

要花点时间才能理解 :+1: