交易的生命周期
Sui网络上的交易在其生命周期内经历了许多不同的步骤。
生命周期概述
在高层次上,以下图表概述了Sui区块链上交易的生命周期。
以下步骤与上图中的步骤相对应。
过程的第一步是创建交易。具有私钥的用户创建并签署用户交易,以改变其拥有的对象,或改变其拥有的对象和共享对象的混合。
Sui将交易发送给每个验证器(通常通过全节点)。验证器执行一系列有效性和安全性检查,对其进行签名,并将已签名的交易返回给客户端。
然后客户端从至少占Sui总股份的2/3的验证器集合中收集响应,形成一个交易证书。因此,与基于共识的区块链不同,Sui验证器无需传播签名(八卦签名)或聚合证书,这个工作现在是客户端或网关的责任。
在组装证书之后,客户端将其发送回所有验证器,验证器检查其有效性并向客户端确认其收到。如果交易仅涉及拥有的对象,则Sui可以立即处理交易证书并执行它,而无需等待共识引擎(直接快速路径)。所有证书都将转发到Sui基于DAG的共识协议(也由Sui验证器操作)。
共识最终输出证书的总排序;验证器检查并执行其中包含共享对象的证书。
客户端可以收集大多数验证器的响应,将其组装成一个效应证书,并将其用作交易结算的证明。
随后,Sui为每个共识提交形成检查点,还用它来驱动重新配置协议。
完整的Sui Lutris文件提供了有关安全性和活跃性协议如何运作以及它们在具有拜占庭参与者的部分同步标准分布式系统模型中的安全性证明的详细信息。以下各节详细介绍了交易生命周期的各个阶段。
提交
在Sui上的所有交易都是在提交到网络时开始的。例如,假设你想将你在钱包中拥有的NFT转移到你朋友的地址。首先,你将使用钱包或其他应用程序创建一个交易。交易包括你的燃气支付对象和一个命令,将NFT对象转移到你朋友的地址。在钱包或应用程序将交易提交到网络之前,它还必须对其进行签名。
交易签名后,钱包或应用程序代表用户将交易提交给Sui全节点。
认证
认证发生在交易提交到全节点之后。提交后,全节点开始认证交易的过程。全节点无法单独认证交易,因为它无法完全了解网络上的所有交易。因此,全节点必须将交易发送给验证器。验证器对交易进行有效性检查,并在通过时对其进行签名。为了被视为有效,交易必须通过以下检查:
- 交易具有有效的用户签名。
- 交易的发起者必须可以访问交易使用的所有拥有的输入对象。在前述NFT示例中,有效性检查确保你拥有要发送给朋友的NFT。
- 交易使用的所有共享输入对象存在。
- 燃气币是一个
Coin<SUI>
对象,并且它包含至少与交易的燃气预算指定的一样多的燃气。
如果所有有效性检查都通过,则验证器尝试锁定所有拥有的输入对象到给定的交易摘要。这确保每个拥有的输入对象一次只能被一个交易使用,这是Sui防止双重花费的方式。换句话说,这确保你只将你的NFT发送给一个朋友,而不是试图将同样的NFT发送给所有朋友。
如果锁定成功,验证器使用其BLS私钥对交易进行签名,并将签名返回给全节点。然而,单个验证器的签名是不够的。全节点必须从足够多的验证器收集签名,以形成超过半数的超过半数。
全节点并行从验证器收集签名,以最小化延迟。
在全节点收集到超过半数或法定人数的验证器签名后,交易被视为已认证。确切地说,全节点已经形成了一个交易证书。
由于先前描述的锁定步骤,不可能同时为两个尝试使用相同拥有对象的不同交易形成证书。即使有一些不诚实的验证器非法签署了两笔交易,这也是由于分布式计算中的“法定人数交集”原则。
如果不到1/3的验证器是不诚实的(拜占庭式),则任何两个证书的签署者集合必须有一个包含至少一个诚实的验证器
执行
全节点将具有证书的交易发送给验证器以执行。每个验证器验证证书上的签名。 如果证书上的签名有效,则验证器可以确信交易是有效的,且不会尝试双倍花费任何对象。
然后,每个验证器根据交易是否:
- 不访问任何共享输入对象,此时立即执行。
- 访问共享输入对象,在这种情况下,将对象提交到Sui的共识层,该层使用相同共享对象的其他交易对其进行排序,然后执行它。
认证效果
在交易执行后,验证器对交易效果进行签名并将其返回给全节点。 交易效果基本上是交易所采取的所有操作的列表,主要包括:
- 所有被改变、创建、包装、解包或删除的对象。
- 花费的燃气。
- 交易的执行状态(成功或错误代码)。
最终,全节点从验证器中收集效果签名。这些签名与效果本身一起被称为 效果证书。
效果证书是交易最终性的保证。
在你或全节点观察到效果证书之后,你可以确信交易将被包含在检查点中,这意味着交易无法被撤销。
如果愿意,你可以向朋友展示效果证书,以证明你已向其发送NFT。验证器签名的存在意味着效果证书无法伪造。
检查点
包含在检查点中是交易生命周期的最终阶段。当验证器执行交易时,它们将其提交给共识。
虽然使用共享输入对象的交易必须在执行之前发送到共识,但仅涉及拥有的输入的交易也会发送到共识。区别在于,仅涉及拥有的输入的交易会首先执行。
共识层生成一个普遍同意的交易排序。这个排序是创建检查点的起点。
验证器从共识层获取排序的交易块,并使用它们来形成检查点。每个交易块首先被因果完成和因果排序 - 这意味着验证器将任何丢失的依赖项添加到交易列表中,并对它们进行排序,以便在检查点中始终在依赖项之前出现。
然后,验证器构建检查点,其中(除其他数据外)包含交易摘要的列表以及每个交易的交易效果的摘要。由于检查点必须完整,网络有时必须等待所有交易可用以形成检查点,这可能需要几个提交的时间。这个过程通常在几秒钟内完成。
在这一点上,交易已经达到了其生命周期的末端,并包含在Sui网络上交易活动的永久记录中。
交易最终性
交易最终性是交易执行变得不可逆转且其细节无法更改的点。
发送交易并接收验证器签名的网络往返时间不到半秒钟。在这一点上,发送方知道交易是不可撤销的,将在纪元内被处理,无论如何。交易已达到最终性;在同一纪元内,诚实的验证器视任何后续使用相同拥有输入对象的交易为无效。
结算最终性
在验证器执行交易后,它将来自该交易的已签名效果返回到网络。
在超过半数的验证器执行了交易,并存在效果证书的情况下,交易的效果(转账、新铸造的对象等)已经被实施。在这一点上,网络可以处理依赖于这些效果的交易。
对于仅涉及拥有的对象的交易,这在共识之前的半秒内发生。如果交易涉及共享对象,则在共识后的短时间内发生,这可能需要几秒钟。在这一点上,交易达到了结算最终性,因为现在可以在相同的输入对象上处理更多的交易。有关更多信息,请参见对象所有权。
达到效果证书的示例路径
作为一个现实世界的例子,假设你想支付当地咖啡店10 SUI购买早晨的咖啡。咖啡店如何确保支付已完成并允许你拿取咖啡呢?
第1步:交易创建
你打开手机上的钱包应用,扫描包含收款人链上地址的咖啡店二维码。钱包应用构建一个交易,从你的Sui地址向咖啡店地址转移10 Sui。你审核交易详情并批准。然后,钱包应用使用你的私钥对交易进行签名。现在你有一个已签名的交易。
第2步:交易广播
你的钱包应用将已签名的交易提交给一个全节点。全节点将交易广播到网络中的所有验证器。
第3步:交易认证
验证器从全节点接收交易。在检查其有效性后,验证器锁定了引用的拥有对象,并将其交易签名返回给全节点。
在全节点收集到法定人数的签名之后,它形成了一个交易证书。交易证书包含交易和来自大多数验证器的签名。
第4步:交易完成
全节点将交易证书广播到所有验证器。验证器接收交易证书,验证其有效性(例如,是否确实有足够的签名),执行交易,并解锁先前锁定的拥有对象。交易效果是执行的交易的输出。验证器对交易效果进行签名并将其与其签名一起返回给全节点。
全节点验证从验证器返回的效果与其相同。在收集到法定人数的签名之后,它形成了一个 EffectsCertificate
对象。效果证书包含交易效果和来自法定人数验证器的签名。
在这一点上,当你的钱包应用从全节点获取回效果证书时,你可以与咖啡店分享这个效果认证的交易。咖啡店随后可以确信交易已执行且不可逆转。
检查点处理
前一节中的过程演示了通过效果证书的交易最终化。正如过程所示,全节点扮演着法定人数驱动的角色。
如果全节点在收集到法定人数的验证器签名之前离线会发生什么?你的钱包应用可能会尝试使用其他全节点重试该过程。不幸的是,在将签名的交易发送到新的全节点之前,你的手机电池可能会耗尽。
别担心。咖啡店很快就会注意到你的支付已经到达其终端,该终端连接到另一个全节点。该全节点通过检查点了解你的交易。
正如前面提到的,检查点包含交易的列表。如果交易出现在已认证的检查点中(由法定人数的验证器签名的检查点),则它被视为已最终化。
咖啡店终端连接的全节点通过状态同步了解你的交易。在这种情况下,只要一个验证器从原始全节点接收到交易证书,即使没有效果证书,交易也很有可能最终化。咖啡店确保付款并给你咖啡。
全节点上的本地执行
在全节点将效果证书发送回你的钱包应用之前,如果请求要求,它可能会尝试在本地执行交易。
这个额外步骤的目的是在可能的情况下尽量使全节点保持最新,特别是当钱包应用经常连接到同一个全节点时。在这个咖啡店的例子中,这可能是微不足道的,但对于高频应用,比如游戏,这可能很重要。
当应用构建一个交易时,通常会要求全节点为其选择一个燃气对象。燃气对象是拥有的对象,这意味着如果全节点陈旧且不了解对象的正确版本,可能会导致无效的交易,或者更糟糕,如果客户端软件未正确处理它,则可能会发生客户端矛盾。在返回 EffectsCertificate
之前在全节点上执行是避免这种情况的一种方式。通过使用 WaitForLocalExecution
参数,请求可以要求进行此类行为。有关客户端矛盾的更多信息,请参见Sponsored Transactions。
然而,使用 WaitForLocalExecution
不始终是最佳选择。例如,在这个咖啡支付中,它增加了一层端到端的延迟,而没有带来显著的好处。在这种情况下,使用 WaitForEffects
参数可能更好,以获得略短的用户感知延迟。
纪元更改
定期(~24小时),Sui网络进入纪元更改的过程。在纪元更改期间,网络计算并分发质押奖励,验证器元数据生效,以及执行其他网络过程。所有用户交易都延迟到新纪元开始。
如果你的交易在纪元边界提交,以极少数的完美时机,可能法定人数的验证器已经决定在当前纪元中不接受任何新的交易证书。当然,这意味着你的咖啡购买也不会被检查点化。对于已认证但未最终化的任何交易,如果执行了,它们将被撤销,或者其拥有的对象将被解锁但尚未执行。在这种情况下,交易证书不能保证最终性。在新纪元中,该交易证书将变为无效,因为验证器签名是对纪元ID的签名。要继续进行此交易,需要具有新纪元ID的新交易证书。标准的全节点实现会自动处理这个问题。
验证最终性
假设你的钱包应用在原始交易期间崩溃。如果应用在将交易签名后将其存储在本地,然后再发送到全节点,这是最佳实践,那么当应用重新启动时,它将首先尝试验证交易是否已经最终。如果是,那么不需要采取其他步骤。如果没有,那么应用需要重新提交交易。
钱包应用可以使用getTransactionBlock
方法查询全节点。假设全节点是诚实的:
- 如果响应包含交易详细信息,则交易必须已经最终。它可能是使用
WaitForLocalExecution
执行的,也可能是作为一个经过检查点的交易执行的。 - 如果响应为
None
,可能意味着交易在某个步骤中被丢弃,或者已经最终但此全节点尚不知晓。在这种情况下,更安全的选择是重新提交交易。
在交易本地执行之前,其效果不会在全节点上反映。相同的想法也适用于咖啡店的全节点。你的交易未通过此全节点提交,因此在包含在检查点之前,它没有机会在本地执行。该全节点必须等待交易被检查点和状态同步,这通常需要几秒钟。在全节点在检查点中收到此交易后,它将被执行,并在本地更新效果,例如增加咖啡店的余额。
总结
希望你现在对交易如何获得认证和最终性有了更好的理解。
交易证书并不总是保证最终性,尽管这是非常有可能的。具体来说,交易证书在时代更改后可能会失效。
效应证书保证最终性 - 需要超过半数的验证器执行交易并承诺效果。
包含在经过认证的检查点中保证最终性 - 需要超过半数的验证器对检查点进行认证,在其中每笔交易都被执行并承诺效果。