Sui 中经常提到的 Objects 到底是什么?

ω
发布于 阅读 720

Sui 中的基本存储单位是 object,中文可以翻译为对象。与许多其他区块链的存储以账户为中心并且每个账户都包含一个 Key Value 存储相比,Sui 的存储以对象为中心。智能合约是一个对象(称为 Move Package),这些智能合约操纵 Move 对象:

  • Move Package:一组 Move 字节码模块。每个模块在 package 中都有一个唯一的名称。package ID 和模块名称的组合是模块的唯一标识。当我们向 Sui 发布智能合约时,一个 package 是发布的单位。一旦发布了 package object,它就是不可变的,永远不能更改或删除。一个 package object 可以依赖于之前发布到 Sui 账本的其他 package objects。

  • Move Object:由 Move Package 中的特定 Move 模块管理的类型化数据。每个对象值都是一个结构体,其字段可以包含原始类型(例如整数、地址)、其他对象和非对象结构体。每个对象值都是可变的,并且在创建时由一个地址拥有,但随后可以被冻结并永久不可变,或者被共享并因此可以被其他地址访问。

Object 元数据

所有 Sui objects 都有以下元数据:

  • 一个 20 字节的全局唯一 ID。object ID 源自创建对象的交易摘要和编码交易生成的 ID 数量的计数器。

  • 一个 8 字节无符号整数版本,表示包含此对象作为输出的交易数。因此,交易新创建的所有对象都将具有版本 1。

  • 一个 32 字节的交易摘要,指示包含此对象作为输出的最后一个交易。

  • 一个 21 字节的所有者字段,指示如何访问此对象。对象所有权将在下一节中详细解释。

除了通用元数据之外,对象还有一个特定于类别、大小可变的内容字段。对于数据值,它包含对象的 Move 类型及其二进制规范序列化 (BCS) 编码的有效负载。对于 package 值,它包含 package 中的字节码模块。

Object 所有权

每个对象都有一个所有者字段,表示该对象是如何被拥有的。所有权决定了如何在交易中使用对象。有 4 种不同类型的所有权:

由地址拥有

这是 Move 对象最常见的情况。在 Move 代码中创建 Move 对象时,可以将其转移到一个地址。转移后,该对象将归该地址所有。一个地址拥有的对象只能由该所有者地址签名的交易使用(即作为移动调用参数传递)。拥有的对象可以以 3 种形式中的任何一种作为 Move 调用参数传递:只读引用 (&T)、可变引用 (&mut T) 和按值 (T)。请务必注意,即使在 Move 调用中通过只读引用 (&T) 传递对象,仍然要求只有对象的所有者才能进行此类调用。也就是说,在验证对象是否可以在交易中使用时,Move 调用的意图无关紧要,重要的是所有权。

由其他对象拥有

一个对象可以由另一个对象拥有。将这种直接所有权与对象包装(object wrapping)区分开来很重要。当你将一个对象的结构定义的字段作为另一种对象类型时,可以将一个对象包装/嵌入到另一个对象中。例如:

图片

定义一个对象类型 A,它包含一个类型是另一个对象类型 B 的字段。在这种情况下,我们说 B 类型的对象被包装到 A 类型的对象中。通过对象包装,被包装的对象(在这个例子中是对象 B) 不作为顶级对象存储在 Sui 存储中,并且不能通过对象 ID 访问。相反,它只是类型 A 对象的序列化字节内容的一部分。你可以考虑一个对象被包装类似于被删除的情况,只是它的内容仍然存在于另一个对象的某个位置。现在回到另一个对象拥有的对象的主题。当一个对象由另一个对象拥有时,它不会被包装。这意味着子对象仍然作为顶级对象独立存在,可以直接在 Sui 存储中访问。所有权关系仅通过子对象的 owner 字段进行跟踪。如果你仍想观察子对象或能够在其他交易中使用它,这将很有用。我们提供库 API 以使一个对象归另一个对象所有。有关如何执行此操作的更多详细信息,请参阅 Sui Move 库。https://docs.sui.io/build/move/sui-move-library

不可变

这意味着一个对象是不可变的,任何人都不能改变。因此,这样的对象没有独占所有者。任何人都可以在他们的 Move 调用中使用它。所有 Move packages 都是不可变的对象:一旦发布,就无法更改。可以通过 freeze_object 库 API 将 Move 对象转换为不可变对象。不可变对象只能在 Move 调用中作为只读引用 (&T) 传递。

共享

对象可以共享,这意味着任何人都可以读取或写入该对象。与可变拥有的对象(单一写入者)相比,共享对象需要共识来排序读取和写入。有关创建和访问共享对象的示例,请参阅 https://examples.sui.io/ 上的共享对象。

在其他区块链中,每个对象都是共享的。然而,Sui 编程者通常可以选择使用共享对象、拥有对象或组合来实现特定用例。这种选择可能会对性能、安全性和实现复杂性产生影响。理解这些权衡的最佳方法是查看一些以这两种方式实现的用例示例:

Escrow: 

Auction: 

Tic Tac Toe:

引用 objects

有几种不同的方法可以简明地引用对象而不指定其完整内容和元数据,每种方法的用例略有不同:

  • ID:上述对象的全局唯一 ID。这是对象在时间上的稳定标识符,可用于查询对象的当前状态或描述在两个地址之间传输的对象。

  • 版本 ID:一个 ID,版本对。这描述了对象历史中特定点的对象状态,并且对于询问对象在过去某个时间点的值是多少或确定对象的某些视图现在有多新上很有用。

  • 对象引用:(ID、版本、对象摘要)三元组。对象摘要是对象内容和元数据的散列。对象引用在对象历史中的特定点提供对象的经过验证的视图。交易需要通过对象引用指定对象输入,以确保交易的发送者和处理交易的验证者就对象的内容和元数据达成一致。

交易对象 DAG:关联对象和交易

交易(和证书)将对象作为输入,读/写/改变这些输入,并产生变异或新创建的对象作为输出。如上所述,每个对象都知道将其作为输出产生的最后一个交易的(散列)。因此,表示对象和交易之间关系的一种自然方式是有向无环图(DAG),其中:

  • 节点是交易。

  • 有向边将交易输出对象连接到交易输入对象,并用对象引用进行标记。

为了构造这个图,我们为每个提交的交易添加一个节点,如果 A 产生对象 O(即创建或变异 O)并且交易 B 将对象 O 作为输入。

这个 DAG 的根是一个创世交易,它不接受任何输入并产生存在于系统初始状态的对象。DAG 可以通过识别尚未被任何已提交交易消耗的可变交易输出来扩展,也可以通过发送将这些输出(以及可选的不可变交易输出)作为输入的新交易来扩展。

可供交易作为输入的对象集是活跃的对象(live objects),而 Sui 维护的全局状态由这些对象的全部组成。特定 Sui 地址 A 的活动对象是 A 拥有的所有对象,以及系统中的所有不可变对象。

当此 DAG 包含系统中所有已提交的交易时,它形成了系统状态和历史的完整(且可加密审计)视图。此外,我们可以使用上述方案为交易或对象的子集(例如,单个地址拥有的对象)构建相关历史的 DAG。
原文:https://docs.sui.io/learn/objects

翻译:Suiverse 社区

标签: Sui
评论