diff --git a/doc/SUMMARY.md b/doc/SUMMARY.md new file mode 100644 index 0000000000000..bccf62a5157be --- /dev/null +++ b/doc/SUMMARY.md @@ -0,0 +1,58 @@ +# Sui Developer Portal + +Welcome to Sui, a next generation smart contract platform with high throughput, low latency, and an asset-oriented programming model powered by Move! Here are some suggested starting points: +* To jump right into building smart contract applications on top of Sui, go to [Dev Quick Start](TODO) +* To experiment with a toy Sui wallet, check out [Wallet Quick Start](TODO) +* To understand what's possible by browsing examples of full-fledged applications and games built on top of Sui, have a look at [Demos](TODO) +* To go deep on how Sui works, start at [Key Concepts](TODO) +* To learn what distinguishes Sui from other blockchain systems, see [What Makes Sui Different?](TODO) +* To experience Sui's speed and scalability for yourself, try [Benchmarking](TODO) +* To see the current status of the Sui software/network and preview what's coming next, read through [Roadmap](TODO) + +## Dev Quick Start +TODO: installation, defining custom objects, object operations (create/destroy/update/transfer/freeze), publishing, invoking your published code. Then deeper: Sui standard library, design patterns, examples. + +## Wallet Quick Start +TODO: installation, querying the chain, client setup, getting test coins, sending transfer transactions, viewing the effects in a block explorer. Then deeper: wallet CLI vs client service vs forwarder architecture, how to integrate your code (wallet, indexer, ...) with the client service or forwarder components. + +## Demos + +## Key Concepts +- [Overview](overview.md) +- [Authorities](authorities.md) +- [Objects](objects.md) +- [Programmability](programmability.md) +- [Transactions](transactions.md) +- TODO: clients +- TODO: state sync +- TODO: reconfiguration +- TODO governance, incentives, and rewards + +## What Makes Sui Different? + +EDITORIAL COMMENT: I think this section should lead with high-level selling points, then go into some more nuanced technical comparisons with existing systems, then conclude with honest descriptions limitations + pointers into the roadmap items that show we're already thinking about addressing them + +- High throughput and low latency (enables low cost w/ fixed hardware) +- Horizontal scalability +- Causal order vs total order (enables massively parallel execution) +- Move and object-centric data model (enables composable objects/NFT's) +TODO: more + +EDITORIAL COMMENT: feel free to take a hatchet to what follows + +### Authorities vs Validators/Miners +An authority plays a role similar to "validators" or "miners" in other blockchain systems. The key distinction between these roles (and the reason we insist on using a separate term) is that validators/miners are *active*, whereas authorities are *passive*. Broadly speaking: +* Miners/validators continuously participate in a global consensus protocol that requires multiple rounds of all-to-all communication between the participants. The goal is typically to agree on a *totally ordered* block of transactions and the result of their execution. +* Authorities do nothing until they recieve a transaction or certificate from a user. Upon receiving a transaction or certificate, an authority need not communicate with other authorities in order to take action and advance its internal state machine. It may wish to communicate with other authorities to share certificates, but need not do so. + +## Causal Order vs Total Order +Unlike most existing blockchain systems (and as the reader may have guessed from the description of write requests above), Sui does not impose a total order on the transactions submitted by clients. Instead, transactions are *causally* ordered--if a transaction `T1` produces output objects `O1` that are used as input objects in a transaction `T2`, an authority must execute `T1` before it executes `T2`. Note that `T2` need not use these objects directly for a causal relationship to exist--e.g., `T1` might produce output objects which are then used by `T3`, and `T2` might use `T3`'s output objects. However, transactions with no causal relationship can be processed by Sui authorities in any order. + +EDITORIAL NOTE: Feels like this last bit could/should be part of a different + +## Benchmarking +TODO: installation, running throughput and latency benchmarks, demonstrating that throughput goes up when you add more cores, adding more authorities leads to linear-ish decrease of latency/throughput. + +## Roadmap + +TODO diff --git a/doc/authorities.md b/doc/authorities.md new file mode 100644 index 0000000000000..a5fac583ed859 --- /dev/null +++ b/doc/authorities.md @@ -0,0 +1,41 @@ +# Authorities + +The Sui network is operated by a set of independent *authorities*, each running its own instance of the Sui software on a separate machine (or a [sharded](TODO) cluster of machines operated by the same entity). An authority participates in the network by handling [read](TODO) and write requests sent by [clients](TODO). This section focuses on the latter. + +Sui uses proof of stake (PoS) to determine which authorities operate the network and their voting power. Authorities are incentivized to participate in good faith via a share of transaction fees, staking rewards, and slashing to punish misbehavior. See [Governance, Incentives, and Rewards](TODO) for more detail. + +## Epochs +Operation of the Sui network is temporally partitioned into non-overlapping, fixed duration (e.g. 24 hours) *epochs*. During a particular epoch, the set of authorities participating in the network is fixed. At an epoch boundary, [reconfiguration](TODO) occurs and can change the set of authorities participating in the networ and their voting power. Conceptually, reconfiguration starts a new instance of the Sui protocol with the previous epoch's final state as genesis and the new set of authorities as the operators. + +EDITORIAL NOTE: not sure if the fixed duration part matches our plans--let me know + +## Committees +A *committee* is a set of authorities whose combined voting power is >2/3 of the total during a particular epoch. For example, in a Sui instance operated by four authorities that all have the same voting power, any group containing 3 authorities is a committee. + +The committee size of >2/3 is chosen to ensure *Byzantine fault tolerance*. As we will see, an authority will only commit a transaction (i.e., durably store the transaction and update its internal state with the effects of the transaction) if it is accompanied by cryptographic signatures from a committee. We call the combination of the transaction and the committee signatures on its bytes a *certificate*. The policy of only committing certificates ensures Byzantine fault tolerance: if <2/3 of the authorities faithfully follow the protocol, they are guaranteed to eventually agree on both the set of committed certificates and their effects. + +EDITORIAL NOTE: someone with BFT chops please correct/expand on this + +## Write Requests +An authority can handle two types of write requests: transactions and certificates. At a high level, a client: +* communicates a transaction to a quorum of authorities to collect the signatures required to form a certificate +* submits a certificate to an authority to commit state changes on that authority. + +EDITORIAL NOTE: A diagram would be useful here + +### Transactions +When a authority receives a transaction from a client, it will first perform [transaction validity checks](TODO) (e.g., validity of the sender's signature). If the checks pass, the authority will sign the transaction bytes and return the signature to the client. The client repeats this process with multiple authorities until it has collected signatures on its transaction from a committee, thereby forming a certificate. + +Note that the process of collecting authority signatures on a transaction into a certificate and the process of submitting certifcates can be performed in parallel. The client can simultaneously broadcast transactions/certificates to an arbitrary number of authorities. Alternatively, a client can outsource either or both of these tasks to a third-party service provider. This provider must be trusted for liveness (e.g., it can refuse to form a certificate), but not for safety (e.g., it cannot change the effects of the transaction). + +### Certificates +Once the client forms a certificate, it submits the certificate to an authority, which will perform [certificate validity checks](TODO) (e.g., the signers are authorities in the current epoch and the signatures are cryptographically valid). If the checks pass, the auhority will execute the transaction inside the certificate. Execution of a transaction will either succeed and commit all of its effects to the ledger, or [abort]() (e.g., due to an explicit `abort` instruction, a runtime error like divison by zero, or exceeding the maximum gas budget) and have no effects other than debiting the transaction's gas input. In either case, the transaction will durably store the certificate indexed by the hash of its inner transaction. + +As with transactions, we note that the process of sharing a certificate with authorities can be parallelized and (if desired) outsourced to a third-party service provider. A client should broadcast its certificate to >1/3 of the authorities to ensure that (up to BFT assumptions) at least one honest authority has executed and committed the certificate. Other authorities may learn about the certificate via [inter-authority state sync](TODO) or via [client-assisted state sync](TODO). + +EDITORIAL NOTE: please check that my advice about how many authorities a client should broadcast certs to looks good + +## Further Reading + +* Transactions take objects as input and produced objects as output--check out the [objects](objects.md) section to learn more about the structure and attributes of objects. +* Sui supports several different transaction types--see the [transactions](transactions.md) section for full details. diff --git a/doc/objects.md b/doc/objects.md new file mode 100644 index 0000000000000..1ec2915b97f19 --- /dev/null +++ b/doc/objects.md @@ -0,0 +1,43 @@ +# Objects + +Sui has programmable objects created and managed by [Move](https://github.com/diem/move) packages (aka "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 distinct name. A package can depend on other pacakge objects that were previously published to the Sui ledger. + +## 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 a counter encoding the number of ID's 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 immutable objects can be read. Once an object becomes immutable, it remains immutable forever. + +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 BCS-encoded payload. For a package value, this contains the bytecode modules in the package. + +## 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. +* 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 that 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 + +Transactions (and thus, certificates) take objects as input, read/write/mutate these inputs, and produce mutated or freshly created objects as output. And as we discussed above, each object knows the (hash of the) last transaction that produced it as an output. Thus, a natural way to represent the relationship between objects and transactions is a DAG where: +* nodes are transactions +* directed edges connect transaction output objects to transaction input objects and are labeled with object references. + +To construct this graph, we add a node for each committed transaction and draw a directed edge labeled with object reference `O` from transaction `A` to transaction `B if `A` produced object `O` (i.e., created or mutated `O`) and transaction `B` takes object `O` as an input. + +The root of this DAG is a "genesis" transaction that takes no inputs and produces the objects that exist in the initial state of the system. The DAG can be extended by identifying mutable transaction outputs that have not yet been consumed by any committed transaction and sending a new transaction that takes these outputs (and optionally, immutable transaction outputs) as inputs. + +The set of objects that are available to be taken as input by a transaction are the *live objects*, and the global state maintained by Sui consists of the totality of such objects. The live objects for a particular Sui address `A` are all objects owned by `A`, along with all immutable objects in the system. + +When this DAG contains all committed transactions in the system, it forms a complete (and crytographically auditable) view of the system's state and history. In addition, we can use the scheme above to construct a DAG of the relevant history for a subset of transactions or objects (e.g., the objects owned by a single address). + +EDITORIAL NOTE: A diagram would be useful here +EDITORIAL NOTE: Should we describe how to audit this here? In a separate section? + +## Further Reading +* Objects are modified and created by transactions--read more about the [transaction types](transactions.md) supported by Sui +* Objects are stored by [authorities](authorities.md) diff --git a/doc/overview.md b/doc/overview.md new file mode 100644 index 0000000000000..26c93f830cc46 --- /dev/null +++ b/doc/overview.md @@ -0,0 +1,9 @@ +# Overview + +FastX is a distributed ledger that stores a collection of programmable *objects*, each with a globally unique ID. Every object is owned by a single *address*, and each address can own an arbitrary number of objects. + +The ledger is updated via a *transaction* sent by a particular address. A transaction can create, destroy, and write objects, as well as transfer them to other addresses. + +Structurally, a transaction contains a set of input object ID's and a pointer to a Move code object that already exists in the ledger. Executing a transaction produces updates to the input objects and (if applicable) a set of freshly created objects along with their owners. + +A transaction whose sender is address *A* can only accept objects owned by *A*, with one exception: a transaction can read from immutable objects regardless of their owner. diff --git a/doc/transactions.md b/doc/transactions.md new file mode 100644 index 0000000000000..2d2161d9ccc7e --- /dev/null +++ b/doc/transactions.md @@ -0,0 +1,63 @@ +# Transactions + +All updates to the Sui ledger happen via a transaction. This section describes the transaction types supported by Sui and explains how their execution changes the ledger. + +## Transaction Metadata + +All Sui transactions have the following common metadata: +* Sender address: The address of the user sending this transaction. +* Gas Input: An object reference pointing to the object that will be used to pay for this transaction's execution and storage. This object must be owned by the user and must be of type `Sui::Coin::Coin` (i.e., the Sui native currency). +* Gas Price: An unsigned integer specifying the number of native tokens per gas unit this transaction will pay. The gas price must always be nonzero. +* Maximum Gas Budget: The maximum number of gas units that can be expended by executing this transaction. If this budget is exceeded, transaction execution will [abort](TODO) and have no effects other than debiting the gas input. The gas input object must have a value higher than the gas price multipled by the max gas, and this product is the maximum amount that the gas input object will be debited for the transaction. +* Epoch: The Sui epoch this transaction is intended for--see [Epochs](TODO). +* Type: A call, publish, or native transaction and its type-specific-data (see below). +* Authenticator: A cryptographic signature on the BCS-encoded bytes of the data above, and a public key that both verifies against the signature and is cryptographically committed to by the sender address--(see [Addresses and Authenticators](TODO) for more details). + +EDITORIAL NOTE: things are organized slighltly differently today. Gas input and max gas live in types, but I think they should be moved up here since all transactions need them. Gas price does not exist yet, but eventually should. Epoch does not exist yet, but eventually should. Authenticator does not yet exist in the current form, but will eventually. + +## Move Call Transaction + +This transaction type is a "smart contract call" that invokes a function in a published Move package with objects owned by the sender and pure values (e.g., integers) as inputs. Executing a function may read, write, mutate, and transfer these input objects, as well as other objects created during execution. + +In addition to the common metadata above, a call transaction includes the following fields: +* Package: An object reference pointing to a previously published Move package object. +* Module: A UTF8 string specifying the name of a Move module in the package. +* Function: A UTF8 string specifying the name of a function inside the module. The function must be a valid [entrypoint](TODO). +* Type Inputs: A list of Move types that will be bound to the type parameters of the function. +* Object Inputs: A list of unique object references pointing to objects that will be passed to this function. Each object must either be owned by the sender or immutable. The gas input object from above cannot also appear as an object input. +* Pure Inputs: A list of BCS-encoded values that will be bound to the parameters of the function. Pure inputs must be primitive types (i.e. addresses, object ID's, strings, bytes, integers, or booleans)--they cannot be objects. + +## Move Publish Transaction + +This transaction type publishes a new Move package as an immutable object. Once the package has been published, its public functions and types can be used by future packages, and its entrypoint functions can be called by future transactions. + +In addition to the common metadata above, a publish transaction includes the following: +* Package Bytes: A list of Move bytecode modules topologically sorted by their dependency relationship (i.e., leaves in the dependency graph must appear earlier in the list). These modules will be deserialized, [verified](), and [linked]() against their dependencies. In addition, each module's [initializer function]() will be invoked in the order specified by the list. + +## Native Transaction + +Native transactions are optimized versions of common Sui operations. Each native transaction is semantically equivalent to a specific Move call, but has a lower gas cost. + +### Transfer + +This transaction type transfers coins from the sender to the specified recipients. + +In addition to the common metadata above, a publish transfer includes the following fields: +* Input: An object reference pointing a mutable object owned by the sender. The object must be of type `Sui::Coin::Coin` with arbitrary `T`--that is, any fungible token. The gas input object from above cannot also appear as an object input. +* Recipients: The addresses of that will receive payments from this transfer. This list must be non-empty. +* Amounts: A list of unsigned integers encoding the amount that each recipient will receive. This list must be the same length as the recipients. Each amount will be debited from the input object, wrapped in a freshly created coin object, and sent to the corresponding recipient address. The value of the input object must be greater than or equal to the sum of the amounts. + +EDITORIAL NOTE: today's transfer sends the input object instead of debiting it + creating/transferring a new object. But that seems inconvenient because a user will not typically have an object with exactly the intended value. This means the typical "send money" flow will be two txes: (1) split an existing coin object to get a fresh one with the desired value, then (2) send the fresh coin. I think we should change transfer to work in the way described here, which combines this into a single transaction. I think we will still want a transfer that works like the current one as well, but I think it should operate on (e.g.) nonfungible token types instead once we have a standard for those, and should support sending multiple tokens to multiple recipients in a single transaction. + +### Join + +This transaction type combines several coin objects into one. It includes the following fields: + +* Inputs: A list of unique object references pointing to mutable objects owned by the sender. The objects must all have the same type: `Sui::Coin::Coin` with arbitrary `T`--that is, any fungible token. The list must contain at least two objects. All objects except the first one will be destroyed, and the new value of the first object will be its old value plus the sum of the value of all destroyed objects. The gas input object from above cannot also appear as an object input. + +EDITORIAL NOTE: this does not exist yet, but I think it should + +## Further Reading +* TODO: something about Move or smart contracts +* Transactions take objects as input and produced objects as output--check out the [objects](objects.md) section to learn more about the structure and attributes of objects. +* Transactions are executed by Sui [authorities](authorities.md)