在Cardano上进行无意外的交易验证

image

随着Alonzo硬分叉为Cardano带来了核心的Plutus智能合约能力,分类账也在不断发展,以满足日益增长的去中心化解决方案的部署需求。Cardano账本设计的重点是高保障、安全和经过验证的形式验证。为了与这一战略保持一致,确保交易处理的确定性也很重要,这意味着用户可以在实际执行之前预测其影响和结果。

随着智能合约支持的引入,保证交易执行成本的能力,以及交易在提交前在账本上的行为方式,变得更加突出。基于未消费交易输出(UTXO)的区块链,如Cardano,提供了这种能力。基于账户的区块链,如以太坊,是不确定的,这意味着它们不能保证交易在链上效果的可预测性。这就带来了金钱损失的风险,不可预测的高额费用,以及对抗性行为的额外机会。

在这篇博文中,我们仔细研究了Cardano的确定性设计的好处,它允许在执行之前进行安全的交易和脚本评估。在本周晚些时候的下一篇博文中,我们将讨论Cardano上交易验证的两个阶段。

什么是交易确定性,为什么它很重要?
确定性,在交易和脚本处理的背景下,是可预测性的同义词。这意味着用户可以在本地(链外)预测他们的交易将如何影响账本的链上状态,而不会有

  • 意外的脚本验证结果或失败
  • 意外的费用
  • 意外的账本或脚本状态更新

确定性系统中的交易可能还会被拒绝,即使构造正确。拒绝意味着该交易根本无法应用于分类账,因此对其状态没有影响,所以不需要支付任何费用。之所以会发生这种情况,是因为在初始交易构建和处理期间,其他交易的处理导致了分类账的变化。即使是简单的交易也会发生这种情况。例如,另一个交易可能花费了一个用户也打算花费的UTXO。确定性确保了无论何时交易被接受,它都只会对账本状态产生可预测的影响。

解决不确定性的问题
不确定性意味着我们无法在执行之前预测一个交易会对账本产生什么影响。在设计分类账以及智能合约解释器时,重要的是预见可能发生不确定性的条件,并做出设计决策来避免这些条件。在这种情况下,主要的危险之一是访问可变的分类账数据,也就是可以改变或更改的数据。当交易或智能合约对账本的改变取决于处理时的状态,而不仅仅是交易的内容时,不确定性可能成为一个问题。

以太坊特别容易受到这个问题的影响。例如,汽油价格或分散式交易所(DEX)的汇率在用户提交交易和交易被处理之间可能会有波动。这导致了意外的汽油费,或购买资产的价格变化。或者一个脚本可能只是失败,导致高额的执行费用(数百美元),而没有其他效果。例如,如果可用于支付汽油费的资金在执行过程中耗尽,就可能发生这种情况。确定性的账本设计消除了这些可能性。

其他可能的不确定性的来源包括允许脚本看到。

包含交易的区块中的数据,但不包括在任何交易中,例如,系统随机性、区块头或当前槽号
被对手改变或替换的数据,这可能会改变脚本验证的结果,而交易本身仍然可以处理。
在大多数系统中,有办法通过改进脚本编写方法或第二层解决方案来缓解这些问题。Cardano的设计是为了保证所有脚本和交易的可预测结果。

基本UTXO模型如何在确定性方面获益
Cardano账本建立在UTXO会计模型上,这意味着资产被存储在账本上的未花费的产出中,而不是账户中。每个输出都指定了存储在其中的资产数量,以及它的地址。未使用的产出是不可改变的,所以一个交易可能会消耗整个产出,但它不能改变它。

为了转移资产,一个交易会消耗一个或多个产出并创建新的产出,这些产出所包含的资产数量与被消耗的产出数量相同。这些数量–以及它们的UTXO地址–在交易的输出中被指定。一笔交易能够影响另一笔应用于账本的交易的效果的唯一方法是通过花费与后来的交易试图花费相同的UTXO,从而导致节点拒绝它。这是UTXO模型赖以维持确定性的关键特征。

与基于账户的模式相比,UTXO分类账既有好处也有坏处。例如,后者会遇到较少的交易相互阻塞的情况。与UTXO不同,账户是可变的分类账数据。因此,一个交易可能会看到,例如,一个账户中不同数量的资产,这取决于它是在另一个更新同一账户的交易之前还是之后处理的。这种情况可能不会导致交易被拒绝,但它可能导致不同的–和不可预测的–分类帐的变化。

花费UTXO只是交易行为的一个例子。接下来,我们将解释什么是交易行为,以及如何验证它们。Alonzo中引入的最重要的一组变化是对行动验证过程的改变。

用签名和脚本验证行动
处理一个交易的一个重要方面是验证它正在采取的行动。当一个交易在特定的字段中包含了该行动的数据时,该交易就是在采取一个行动。例如,当一个交易在其输入字段中包含对U的引用时,它就是在花费UTXO U,当它的mint字段包含X时,它就是在铸造一个代币X。

当节点处理一个交易时,它验证了它是否能执行它打算执行的行动。为此,交易的作者必须提供相关的数据,例如,脚本、赎回者或签名。一个需要验证的行动的常见例子是花费一个用公钥锁定的UTXO。交易必须提供来自相应私钥的签名来执行这个动作。

Cardano使用脚本来验证行动。这些脚本,是一段段的代码,实现了具有真或假输出的纯函数。脚本验证是调用脚本解释器在适当的参数上运行一个给定脚本的过程。

脚本验证可以针对以下行动进行。

Plutus 脚本
由于Plutus脚本的实施,Alonzo在Cardano上引入了一种新的交易验证方法。作为Alonzo的一部分部署的扩展未用交易输出(EUTXO)模型,提供了支持Plutus合约的分类账基础设施。下面,我们提供一个关于分类账和交易变化的高层次概述。关于使用分类账和Plutus脚本的更多细节,请查看Plutus先锋计划!

阿隆佐改变账本上的数据,如下。

Plutus脚本可以锁定UTXO。
一个新的组件,添加到UTXO的输出部分的内容中,可以实现类似脚本状态的功能。除了资产和地址之外,被Plutus脚本锁定的UTXO还包含一个基准点。数据点是一块数据,可以被认为是对脚本状态的一种解释。
有一些新的协议参数用于对交易施加额外的验证要求。这些参数包括对脚本所能消耗的计算资源的上限。
为了支持Plutus脚本,事务已被升级为如下内容。

对于它的每一个动作,交易现在携带一个用户指定的参数,称为赎回者。根据不同的脚本,赎回者可以有不同的用途。例如,它可以作为用户在拍卖中的出价,或者用户在猜谜游戏中的猜测,以及其他许多功能。
交易规定了每个脚本的计算执行预算。
为了确保交易能够支付其执行费用,Alonzo引入了额外的数据,我们将在后续博文中讨论这些数据。
交易包含一个完整性哈希值,需要确保它没有被破坏、过期等。
与Mary相比,Alonzo交易验证的具体内容也有一些变化。对于每个动作,节点会集合Plutus解释器所期望的脚本参数,包括:

  • 数据集
  • 赎回者
  • 执行预算
  • 交易的摘要
    该节点执行新的、针对Alonzo的检查,以确保交易被正确构建。例如,它不能超过最大的执行资源预算。它还调用Plutus脚本解释器来运行脚本。

Datum对象与脚本状态
和易变的账户一样,易变的脚本状态也完全属于 "易变的分类账数据 "这一类的不确定性来源。我们已经看到,UTXO模型避免了可变账户的不确定性问题。它还可以帮助我们以一种保持确定性的方式重新想象脚本状态的概念。如果一个UTXO被一个Plutus脚本锁定,那么这个UTXO的脚本代码就与它的地址相关。这个脚本的状态模拟是存储在该UTXO中的数据。当一个交易用完该UTXO后,它就会从账簿中被删除,包括数据。然而,Plutus脚本的内容可以强制要求携带它的交易也必须创建一个包含特定数据的UTXO,这个数据可以被视为更新的脚本状态。

脚本执行预算

非决定性的气体模型可以向用户收取不可预测的大额费用。在Cardano脚本中,这种不确定性的来源是通过要求资源预算本身以及支付该预算所需的费用包含在交易中来解决。在Alonzo中,用户可以在构建交易时在本地预测这两点。脚本的执行必然返回真或假,不会无限循环。原因是脚本执行的每一个操作都会占用非零的资源,而这些资源是由解释器跟踪的。如果超过了事务指定的预算,脚本的执行就会终止并返回False。

Alonzo中的事务验证
针对可能的不确定性来源,以下关键点使得脚本和事务验证的结果可以预测。

当应用于相同的参数时,脚本解释器将始终终止并返回相同的验证结果
事务必然会固定所有的参数,这些参数将在验证期间传递给脚本解释器
事务指定了所有需要脚本验证的操作
事务上的强制签名确保它不会被对手以导致脚本失败的方式改变。
在EUTXO分类账模型中应用交易是确定性的。
最后一点在很大程度上继承了UTXO模型,因为Alonzo分类账协议的更新在大多数情况下仍然与以前时代的更新一致(包括委托计划等)。在Alonzo升级后,脚本验证的失败或成功确实会影响到交易的处理方式(关于这一点,在第二部分有更多介绍!)。然而,"真 "或 "假 "的结果,以及与这两种结果相关的分类账变化,对于一个特定的交易来说是可以预测的。

Cardano的脚本和交易验证的确定性行为不是使用EUTXO模型的自然结果。为了确保这一属性,IOG团队不得不仔细跟踪脚本被允许看到的每一个数据的来源。