Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs]: Update Asset and State sections #1030

Merged
merged 20 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 28 additions & 34 deletions docs/architecture/accounts.md
phklive marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Accounts
# Account

phklive marked this conversation as resolved.
Show resolved Hide resolved
phklive marked this conversation as resolved.
Show resolved Hide resolved
> The primary entities of the Miden protocol
> The primary entity of the Miden protocol

## What is the purpose of an account?

In Miden's hybrid UTXO and account-based model accounts enable the creation of expressive smart contracts via a Turing-complete language.
In Miden's hybrid UTXO and account-based model `Account`s enable the creation of expressive smart contracts via a Turing-complete language.

## What is an account?

Expand All @@ -30,72 +30,72 @@ These components are:

> An immutable and unique identifier for the `Account`.

A 63-bit long number represents the account ID. It's four most significant bits encode:
A 63-bit long number represents the `Account` ID. It's four most significant bits encode:
- [**Account type:**](#the-accounts-type) basic or faucet.
- [**Account storage mode:**](#the-accounts-storage-mode) public or private.

This encoding allows the ID to convey both the account’s unique identity and its operational settings.
This encoding allows the ID to convey both the `Account`’s unique identity and its operational settings.

### Code

> A collection of functions defining the `Account`’s programmable interface.

Every Miden account is essentially a smart contract. The `Code` component defines the account’s functions, which can be invoked through both [Note scripts](notes.md#the-note-script) and transaction scripts. Key characteristics include:
Every Miden `Account` is essentially a smart contract. The `Code` component defines the account’s functions, which can be invoked through both [Note scripts](notes.md#the-note-script) and transaction scripts. Key characteristics include:

- **Mutable access:** Only the account’s own functions can modify its storage and vault. All state changes—such as updating storage slots, incrementing the nonce, or transferring assets—must occur through these functions.
- **Mutable access:** Only the `Account`’s own functions can modify its storage and vault. All state changes—such as updating storage slots, incrementing the nonce, or transferring assets—must occur through these functions.
- **Function commitment:** Each function can be called by its [MAST](https://0xpolygonmiden.github.io/miden-vm/user_docs/assembly/main.html) root. The root represents the underlying code tree as a 32-byte hash. This ensures integrity, i.e., the caller calls what he expects.
- **Note creation:** Account functions can generate new notes.
- **Note creation:** `Account` functions can generate new notes.

### Storage

> A flexible, arbitrary data store within the `Account`.

The [storage](../../objects/src/accounts/storage/mod.rs) is divided into a maximum of 255 indexed [storage slots](../../objects/src/accounts/storage/slot/mod.rs). Each slot can either store an arbitrary 32-byte `Word` or serve as a pointer to a key-value store with large amounts capacity.
The [storage](../../objects/src/accounts/storage/mod.rs) is divided into a maximum of 255 indexed [storage slots](../../objects/src/accounts/storage/slot/mod.rs). Each slot can either store a 32-byte value or serve as a pointer to a key-value store with large amounts capacity.

- **`StorageSlot::Value`:** Contains 32 bytes of arbitrary data.
- **`StorageSlot::Map`:** Contains a [StorageMap](../../objects/src/accounts/storage/map.rs), a key-value store where both keys and values are `Word`s. The slot's value is a commitment (hash) to the entire map.
- **`StorageSlot::Map`:** Contains a [StorageMap](../../objects/src/accounts/storage/map.rs), a key-value store where both keys and values are 32 bytes. The slot's value is a commitment (hash) to the entire map.

### Vault

> A collection of [assets](assets.md) stored by the `Account`.

Large amounts of fungible and non-fungible assets can be stored in the accounts vault.
Large amounts of fungible and non-fungible assets can be stored in the `Account`s vault.

### Nonce

> A counter incremented with each state update to the `Account`.

The `nonce` enforces ordering and prevents replay attacks. It must strictly increase with every account state update. The increment must be less than `2^32` but always greater than the previous nonce, ensuring a well-defined sequence of state changes.
The nonce enforces ordering and prevents replay attacks. It must strictly increase with every `Account` state update. The increment must be less than `2^32` but always greater than the previous nonce, ensuring a well-defined sequence of state changes.

## Account lifecycle

Throughout its lifetime, an `Account` progresses through various phases:

- **Creation and Deployment:** Initialization of the account on the network.
- **Active Operation:** Continuous state updates via account functions that modify the storage, nonce, and vault.
- **Creation and Deployment:** Initialization of the `Account` on the network.
- **Active Operation:** Continuous state updates via `Account` functions that modify the storage, nonce, and vault.
- **Termination or Deactivation:** Optional, depending on the contract’s design and governance model.

### Account creation

For an account to be recognized by the network, it must exist in the [account database](state.md#account-database) maintained by Miden node(s).
For an `Account` to be recognized by the network, it must exist in the [account database](state.md#account-database) maintained by Miden node(s).

However, a user can locally create a new account ID before it’s recognized network-wide. The typical process might be:
However, a user can locally create a new `Account` ID before it’s recognized network-wide. The typical process might be:

1. Alice generates a new account ID locally (according to the desired account type) using the Miden client.
1. Alice generates a new `Account` ID locally (according to the desired `Account` type) using the Miden client.
2. The Miden client checks with a Miden node to ensure the ID does not already exist.
3. Alice shares the new ID with Bob (for example, to receive assets).
4. Bob executes a transaction, creating a note containing assets for Alice.
5. Alice consumes Bob’s note in her own transaction to claim the asset.
6. Depending on the account’s storage mode and transaction type, the operator receives the new account ID and, if all conditions are met, includes it in the account database.
6. Depending on the `Account`’s storage mode and transaction type, the operator receives the new `Account` ID and, if all conditions are met, includes it in the `Account` database.

## Additional information

### Account type

There are two main categories of accounts in Miden: **basic accounts** and **faucets**.
There are two main categories of `Account`s in Miden: **basic accounts** and **faucets**.

- **Basic Accounts:**
Basic accounts may be either mutable or immutable:
Basic Accounts may be either mutable or immutable:
- *Mutable:* Code can be changed after deployment.
- *Immutable:* Code cannot be changed once deployed.

Expand All @@ -104,26 +104,20 @@ There are two main categories of accounts in Miden: **basic accounts** and **fau
- *Fungible Faucet:* Can issue fungible [assets](assets.md).
- *Non-fungible Faucet:* Can issue non-fungible [assets](assets.md).

Type and mutability are encoded in the two most significant bits of the account's [ID](#id).
Type and mutability are encoded in the two most significant bits of the `Account`'s [ID](#id).

### Account storage mode

Users can choose whether their accounts are stored publicly or privately. The preference is encoded in the third and forth most significant bits of the accounts [ID](#id):
Users can choose whether their `Account`s are stored publicly or privately. The preference is encoded in the third and forth most significant bits of the `Account`s [ID](#id):

- **Public Accounts:**
The account’s state is stored on-chain, similar to how accounts are stored in public blockchains like Ethereum. Contracts that rely on a shared, publicly accessible state (e.g., a DEX) should be public.
- **Public `Account`s:**
The `Account`’s state is stored on-chain, similar to how `Account`s are stored in public blockchains like Ethereum. Contracts that rely on a shared, publicly accessible state (e.g., a DEX) should be public.

- **Private Accounts:**
Only a commitment (hash) to the account’s state is stored on-chain. This mode is suitable for users who prioritize privacy or plan to store a large amount of data in their account. To interact with a private account, a user must have knowledge of its interface.
- **Private `Account`s:**
Only a commitment (hash) to the `Account`’s state is stored on-chain. This mode is suitable for users who prioritize privacy or plan to store a large amount of data in their `Account`. To interact with a private `Account`, a user must have knowledge of its interface.

The storage mode is chosen during account creation, it cannot be changed later.
The storage mode is chosen during `Account` creation, it cannot be changed later.

## Conclusion

In this section, we covered:

- [What is an `Account`](#what-is-an-account)
- [Its constituent components](#the-accounts-core-components)
- [Its lifecycle](#the-accounts-lifecycle)

With this information, you are now better equipped to understand how Miden `Accounts` operate, how they manage data and assets, and how their programmable functions enable secure and flexible interactions within the Miden protocol.
You are now better equipped to understand how a Miden `Account` operates, how it manages data and assets, and how its programmable interface enables secure and flexible interactions within the Miden protocol.
68 changes: 39 additions & 29 deletions docs/architecture/assets.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,68 @@
In Miden, users can create and trade arbitrary fungible and non-fungible assets.
# Asset

We differentiate between native and non-native assets in Miden. Native assets follow the Miden asset model. Non-native assets are all other data structures of value that can be exchanged.
> Fungible and Non-fungible assets in the Miden protocol.

phklive marked this conversation as resolved.
Show resolved Hide resolved
Native assets in Polygon Miden have four goals:
## What is the purpose of an asset?

* Asset exchange should be parallelizable.
* Asset ownership should be self-sovereign.
* Asset usage should be censorship resistant.
* Fees can be paid using any asset.
In Miden, `Asset`s serve as the primary means of expressing and transferring value between [accounts](accounts.md) through [notes](notes.md). They are designed with four key principles in mind:

All native assets in Miden are stored directly in accounts, like Ether in Ethereum. Miden does not track asset ownership using global hashmaps, e.g., ERC20 contracts. Local asset storage in accounts provides privacy and the ability for client-side proofs. That is because ownership changes are reflected only on an account and not in an ERC20 account (global hashmap). Thus, these changes can happen in parallel. Additionally, asset exchange is censorship resistant at this level because there is no global contract the transfer must pass through. Finally, users can pay fees in any asset.
1. **Parallelizable exchange:**
By managing ownership and transfers directly at the account level instead of relying on global structures like ERC20 contracts, accounts can exchange `Asset`s concurrently, boosting scalability and efficiency.

## Native assets
2. **Self-sovereign ownership:**
`Asset`s are stored in the accounts directly. This ensures that users retain complete control over their `Asset`s.

Native assets are data structures that follow the Miden asset model (encoding, issuance, storing). All native assets are encoded using a single `word` (4 field elements). The asset encodes both the ID of the issuing account and the asset details.
3. **Censorship resistance:**
Users can transact freely and privately with no single contract or entity controlling `Asset` transfers. This reduces the risk of censored transactions, resulting in a more open and resilient system.

Having the issuer's ID encoded in the asset makes determining the type of an asset, inside and outside Miden VM, cost-efficient. And, representing the asset in a `word` means the representation is a commitment to the asset data itself. That is particularly interesting for non-fungible assets.
4. **Flexible fee payment:**
Unlike protocols that require a specific base `Asset` for fees, Miden allows users to pay fees in any supported `Asset`. This flexibility simplifies the user experience.

### Issuance
## What is an asset?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find having lots of small sections a bit distracting - though, maybe that's just in Github rendering and it it would look better in mdBook rendering.

Only specialized accounts called faucets can issue assets. As with regular accounts, anyone can create a faucet account. Faucets can issue either fungible or non-fungible assets - but not both.
An `Asset` in Miden is a unit of value that can be transferred from one [account](accounts.md) to another using [notes](notes.md).

The `faucet_id` identifies the faucet and starts with a different sequence depending on the asset type, see the [account id discussion](accounts.md#account-id). The faucet's code defines rules for how assets can be minted, who can mint them etc. Conceptually, faucet accounts on Miden are similar to ERC20 contracts on Ethereum. However, there is no ownership tracking in Miden faucets.
## Native asset

Faucets can create assets and immediately distribute them by producing notes. However, assets can also stay in the faucet after creation to be sent later, e.g., in a bundle. That way, one can mint a million NFTs locally in a single transaction and then send them out as needed in separate transactions in the future.
> All data structures following the Miden asset model that can be exchanged.

![Architecture core concepts](../img/architecture/asset/asset-issuance.png)
Native `Asset`s adhere to the Miden `Asset` model (encoding, issuance, storage). Every native `Asset` is encoded using 32 bytes, including both the [ID](accounts.md#id) of the issuing account and the `Asset` details.

### Issuance

### Fungible assets
> **Info**
> - Only [faucet](accounts.md#account-type) accounts can issue assets.
phklive marked this conversation as resolved.
Show resolved Hide resolved

A fungible asset is encoded using the amount and the `faucet_id` of the faucet which issued the asset. The amount is guaranteed to be `$2^{63} - 1$ or smaller, the maximum supply for any fungible asset. Examples of fungible assets are ETH and stablecoins, e.g., DAI, USDT, and USDC.
Faucets can issue either fungible or non-fungible `Asset`s as defined at account creation. The faucet's code specifies the `Asset` minting conditions: i.e., how, when, and by whom these `Asset`s can be minted. Once minted, they can be transferred to other accounts using notes.

If the `faucet_id` of MATIC is `2`, 100 MATIC are encoded as `[100, 0, 0, 2]`; the `0`s in the middle distinguish between fungible and non-fungible assets.
![Architecture core concepts](../img/architecture/asset/asset-issuance.png)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this picture could be improved:

  • It feels disproportionally big (I think we can reduce the size of text and shapes quite a bit).
  • I would probably not introduce new colors - e.g., in Miden VM docs arrows also use back color.
  • I would maybe add some simple comments to make it easier to understand what's what.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Perhaps the arrows from the faucet to the note should be labelled "issues", as in, "the faucet issues notes" and the arrows from the notes to the accounts should be labelled "transferred", as in, "the notes are transferred to the accounts"?

### Type

### Non-fungible assets
#### Fungible asset

A non-fungible asset is encoded by hashing the asset data into a `word` and then replacing the second element with the `faucet_id` of the issuing account: For example `[e0, faucet_id, e2, e3]`. Note that the second element is guaranteed to be non-zero. Together with the fungible asset encoding, this makes it easy to differentiate between both asset types by inspecting the second element.
Fungible `Asset`s are encoded with the amount and the `faucet_id` of the issuing faucet. The amount is always 2^{63} - 1 or smaller, representing the maximum supply for any fungible `Asset`. Examples include ETH and various stablecoins (e.g., DAI, USDT, USDC).

Examples of non-fungible assets are all NFTs, e.g., a DevCon ticket. The ticket's data might be represented in a JSON string representing which DevCon, the date, the initial price, etc. Now, users can create a faucet for non-fungible DevCon tickets. This DevCon faucet would hash the JSON string into a `word` to transform the ticket into an asset.
#### Non-fungible asset

Non-fungible `Asset`s are encoded by hashing the `Asset` data into 32 bytes and placing the `faucet_id` as the second element. Examples include NFTs like a DevCon ticket.

### Storage

[Accounts](accounts.md) and [notes](notes.md) contain asset vaults that are used to store assets. Accounts can keep unlimited assets in a sparse Merkle tree called `account vault`. Notes can store up to `255` distinct assets.
[Accounts](accounts.md) and [notes](notes.md) have vaults used to store `Asset`s. Accounts use a sparse Merkle tree as a vault while notes use a simple list. This enables an account to store a practically unlimited number of assets while a note can only store 255 assets.

![Architecture core concepts](../img/architecture/asset/asset-storage.png)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the above comment, I think this graphic can be improved.

The information on which and how many assets are owned can be private depending on the account's or note's storage mode. This is true for any native asset in Miden.
### Burning

`Asset`s in Miden can be burned through various methods, such as rendering them unspendable by storing them in an unconsumable note, or sending them back to their original faucet for burning using it's dedicated function.

## Non-native assets
## Alternative asset models

Miden is flexible enough to create other types of assets as well.
> All data structures not following the Miden asset model that can be exchanged.

For example, developers can replicate the Ethereum ERC20 model, where ownership of fungible assets is recorded in a single account. To transact, users must send a note to that account to change the global hashmap.
Miden is flexible enough to support other `Asset` models. For example, developers can replicate Ethereum’s ERC20 pattern, where fungible `Asset` ownership is recorded in a single account. To transact, users send a note to that account, triggering updates in the global hashmap state.

Furthermore, a complete account can be treated as a programmable asset because ownership of accounts is transferrable. An account could be a "crypto kitty" with specific attributes and rules, and people can trade these "crypto kitties" by transferring accounts between each other.
## Conclusion

We can also think of an account representing a car. The owner of the car can change so the car account - granting access to the physical car - can be treated as an asset. In this car account, there could be rules defining who is allowed to drive the car and when.
Miden’s `Asset` model provides a secure, flexible, scalable, and privacy-preserving framework for representing and transferring value. By embedding `Asset` information directly into accounts and supporting multiple `Asset` types, Miden fosters a decentralized ecosystem where users maintain their privacy, control, transactions can scale efficiently, and censorship is minimized.
Loading
Loading