Skip to content

Commit

Permalink
Rewrite most of objects.md (#825)
Browse files Browse the repository at this point in the history
  • Loading branch information
lxfind authored Mar 15, 2022
1 parent 9971ce1 commit e7b4cfb
Showing 1 changed file with 28 additions and 5 deletions.
33 changes: 28 additions & 5 deletions doc/src/build/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,49 @@
title: Objects
---

Sui has programmable objects created and managed by [Move](move.md) packages (a.k.a. *smart contracts*). Move packages themselves are also objects. Thus, Sui objects can be partitioned into two categories:
* *Mutable data values*: typed data governed by a particular Move [*module*](https://github.com/diem/move/blob/main/language/documentation/book/src/modules-and-scripts.md). Each object value is a [struct](https://github.com/diem/move/blob/main/language/documentation/book/src/structs-and-resources.md) with fields that can contain primitive types (e.g. integers, addresses), other objects, and non-object structs. Each object value is mutable at the time of its creation but can subsequently be *frozen* and become permanently immutable.
* *Immutable packages*: a set of Move bytecode modules with a distinct name. A package can depend on other package objects that were previously published to the Sui ledger.
The basic unit of storage in Sui is **object**. In contrast to many other blockchains where storage is centered around accounts and each account contains a key-value store, Sui's storage is centered around objects. A smart contract is an object (called **Move Package**), and these smart contracts manipulate **Move objects**:
* *Move Package*: a set of Move bytecode modules. Each module has a name that's unique within the package. The combination of the package ID and the neam of a module uniquely identify the module. When we publish smart contracts to Sui, a package is the unit of publishing. Once a package object is published, it is immutable and can never be changed or removed. A package object can depend on other package objects that were previously published to the Sui ledger.
* *Move Object*: typed data governed by a particular Move [*module*](https://github.com/diem/move/blob/main/language/documentation/book/src/modules-and-scripts.md) from a Move package. Each object value is a [struct](https://github.com/diem/move/blob/main/language/documentation/book/src/structs-and-resources.md) with fields that can contain primitive types (e.g. integers, addresses), other objects, and non-object structs. Each object value is mutable and owned by an account address at the time of its creation, but can subsequently be *frozen* and become permanently immutable, or be *shared* and thus become accessible by other addresses.

## Object metadata

All Sui objects have the following metadata:
* A 20 byte globally unique ID. An object ID is derived from the digest of the transaction that created the object and from a counter encoding the number of IDs generated by the transaction.
* An 8 byte unsigned integer *version* representing the number of transactions that have included this object as an output. Thus, all objects freshly created by a transaction will have version 1.
* A 32 byte *transaction digest* indicating the last transaction that included this object as an output.
* An `is_mutable` flag indicating whether the object can be mutated, destroyed, or transferred in a transaction sent by its owner. Both immutable and mutable objects can be read. Once an object becomes immutable, it remains immutable forever.
* A 21 byte *owner* field that indicates how this object can be accessed. Object ownership will be explained in detail in the next section.

In addition to common metadata, objects have a category-specific, variable-sized *contents* field. For a data value, this contains the Move type of the object and its [Binary Canonical Serialization (BCS)](https://docs.rs/bcs/latest/bcs/)-encoded payload. For a package value, this contains the bytecode modules in the package.

## Object Ownership
Every object has a *owner* field that indicates how this object is being owned. The ownership dictates how an object can be used in transactions. There are 4 different types of ownership:

**Owned by an account address**
This is the most common case for Move objects. A Move object upon creation in the Move code, can be [transferred](move.md#sui-move-library) to an account address. After the transfer, this object will be owned by that account address. An object owned by an account address can only be used (i.e. passed as a Move call parameter) by transactions signed by that owner account. Owned object can be passed as Move call parameter in any of the 3 forms: read-only reference (`&T`), mutable reference (`&mut T`) and by-value (`T`). It's important to note that even if an object is passed by read-only reference (`&T`) in a Move call, it's still required that only the owner of the object can make such a call. That is, the intention of the Move call is irrelevant when it comes to authenticate whether an object can be used in a transaction, the ownership is what matters.

**Owned by another object**
An object can be owned by another object. It's important to distinguish this direct ownership from *object wrapping*. An object can be wrapped/embedded in another object when you have a field of one object's struct definition to be another object type. For example:
```
struct A {
id: VersionedID,
b: B,
}
```
defines a object type `A` that contains a field whose type is another object type `B`. In this case, we say an object of type `B` is wrapped into an object of type `A`. With object wrapping, the wrapped object (in this example, object `b`) is not stored as a top-level object in Sui storage, and it's not accessible by object ID. Instead, it's simply part of the serialized bytes content of an object of type `A`. You can think of the case of an object being wrapped similar to being deleted, except its content still exist somewhere in another object.
Now back to the topic of object owned by another object. When an object is owned by another object, it's not wrapped. This means the child object still exists independently as a top-level object and can be accessed directly in the Sui storage. The ownership relationship is only tracked through the owner field of the child object. This can be useful if you still want to observe the child object or be able to use it in other transactions. We provide library APIs to make an object owned by another object. More details on how to do this can be found in [the move library doc](move.md#sui-move-library)

**Shared Immutable**
This means an object is immutable and cannot be mutated by anyone. Becaose of this, such object doesn't have an exclusive owner and hence is considered as shared. Anyone can use it in their Move calls. All Move packages are immutable objects: once published, they cannot be changed. An Move object can be turned into an immutable object through the [*freeze_object*](move.md#sui-move-library) library API. An immutable object can only passed as a read-only reference (`&T`) in Move calls.

**Shared Mutable (WIP)**
An object can be shared and mutable, meaning that anyone can use and mutate this object. Proper support of this is still being developed in Sui. A more detailed explanation about shared mutable object support will come online soon. Here is a brief primer: for any other objects that's not shared mutable, no two transactions can be mutating the same object at the same time since a transaction is pinned on a specific (and must be the latest) version of each object, hence Sui doesn't need to worry about reaching a consensus or ordering (it's ordered by construction). However for shared mutable objects, in order to allow multiple transactions mutating the same object at the same time, we need a sequencer to properly order these transactions. Because of this, using a shared mutable object can be much more expensive in terms of latency, throughput and gas cost. On the other hand, shared mutable object is also a powerful primitive that allows for expressing richer behavior that doesn't require central trust. Examples of this difference can be found in the two different implementations of TicTacToe in our Move examples.

## Referring to objects

There are a few different ways to concisely refer to an object without specifying its full contents and metadata, each with slightly different use cases:
* ID: the globally unique ID of the object mentioned above. This is a stable identifier for the object across time, and is useful (e.g.) for querying the current state of an object or describing which object was transferred between two addresses.
* Versioned ID: an (ID, version) pair. This describes the state of the object at a particular point in the object's history, and is useful for (e.g.) asking what the value of the object was at some point in the past or determining how fresh some view of an object is now.
* Object Reference: an (ID, object digest) pair. The object digest is the hash of the object's contents and metadata. An object reference provides an authenticated view of the object at a particular point in the object's history. Transactions require object inputs to be specified via object references to ensure the transaction's sender and an authority processing the transaction agree on the contents and metadata of the object.
* Object Reference: an (ID, version, object digest) triple. The object digest is the hash of the object's contents and metadata. An object reference provides an authenticated view of the object at a particular point in the object's history. Transactions require object inputs to be specified via object references to ensure the transaction's sender and an authority processing the transaction agree on the contents and metadata of the object.

## The transaction-object DAG: Relating objects and transactions

Expand Down

0 comments on commit e7b4cfb

Please sign in to comment.