Skip to content

Commit

Permalink
Update docs for consolidation (#998)
Browse files Browse the repository at this point in the history
* Update readme + remove tutorials from base

* Change version to 6

* Cargo update

* Update mkdocs.yml + remove images from tutorials

* Fix broken link

* Reverted cargo.lock update
  • Loading branch information
phklive authored Dec 2, 2024
1 parent 2b8d3db commit a8d038c
Show file tree
Hide file tree
Showing 32 changed files with 357 additions and 914 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ Miden is a zero-knowledge rollup for high-throughput and private applications. M

If you want to join the technical discussion or learn more about the project, please check out

* the [Documentation](https://docs.polygon.technology/miden/).
* the [Documentation](https://0xpolygonmiden.github.io/miden-docs).
* the [Discord](https://discord.gg/0xpolygonrnd)
* the [Repo](https://github.com/0xPolygonMiden)
* the [Roadmap](roadmap.md)
* the [Roadmap](docs/roadmap.md)

## Status and features

Expand Down
109 changes: 50 additions & 59 deletions docs/architecture/accounts.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
---
comments: true
---

Accounts are basic building blocks representing a user or an autonomous smart contract.

For smart contracts the go-to solution is account-based state. Miden supports expressive smart contracts via a Turing-complete language and the use of accounts.
For smart contracts, the go-to solution is account-based state. Miden supports expressive smart contracts via a Turing-complete language and the use of accounts.

In Miden, an account is an entity which holds assets and defines rules about how to transfer these assets.
In Miden, an account is an entity that holds assets and defines rules about how to transfer these assets.

## Account design

In Miden every account is a smart contract. The diagram below illustrates the basic components of an account.
In Miden, every account is a smart contract. The diagram below illustrates the basic components of an account.

<center>
![Architecture core concepts](../img/architecture/account/account-definition.png){ width="25%" }
</center>
<p style="text-align: center;">
<img src="../img/architecture/account/account-definition.png" style="width:30%;" alt="Account diagram"/>
</p>

!!! tip "Key to diagram"
* **Account ID**: A unique identifier for an account. This does not change throughout its lifetime.
* **Storage**: User-defined data which can be stored in an account.
* **Nonce**: A counter which increments whenever the account state changes.
* **Vault**: A collection of assets stored in an account.
* **Code**: A collection of functions which define the external interface for an account.
> **Tip: Key to diagram**
> - **Account ID**: A unique identifier for an account. This does not change throughout its lifetime.
> - **Storage**: User-defined data which can be stored in an account.
> - **Nonce**: A counter which increments whenever the account state changes.
> - **Vault**: A collection of assets stored in an account.
> - **Code**: A collection of functions which define the external interface for an account.
### Account ID

Expand All @@ -33,14 +29,12 @@ The four most significant bits specify the [account type](#account-types) - regu

The [storage of an account](../../objects/src/accounts/storage/mod.rs) is composed of a variable number of index-addressable [storage slots](../../objects/src/accounts/storage/slot/mod.rs), up to 255 slots in total.

Each slot has a type which defines its size and structure. Currently, the following types are supported:
Each slot has a type that defines its size and structure. Currently, the following types are supported:

* `StorageSlot::Value`: contains a single `Word` of data (i.e., 32 bytes).
* `StorageSlot::Map`: contains a [StorageMap](../../objects/src/accounts/storage/map.rs) which is a key-value map where both keys and
values are `Word`s. The value of a storage slot containing a map is the commitment to the
underlying map.
* `StorageSlot::Value`: contains a single `Word` of data (i.e., 32 bytes).
* `StorageSlot::Map`: contains a [StorageMap](../../objects/src/accounts/storage/map.rs) which is a key-value map where both keys and values are `Word`s. The value of a storage slot containing a map is the commitment to the underlying map.

As described below, accounts can be stored off-chain (private) and on-chain (public). Accounts that store huge amounts of data, as it is possible using storage maps, are better designed as off-chain accounts.
As described below, accounts can be stored off-chain (private) and on-chain (public). Accounts that store large amounts of data, as is possible using storage maps, are better designed as off-chain accounts.

### Nonce

Expand All @@ -54,26 +48,23 @@ An asset container for an account.

An account vault can contain an unlimited number of [assets](assets.md). The assets are stored in a sparse Merkle tree as follows:

* For fungible assets, the index of a node is defined by the issuing faucet ID, and the value
of the node is the asset itself. Thus, for any fungible asset there will be only one node
in the tree.
* For non-fungible assets, the index is defined by the asset itself, and the asset is also
the value of the node.
* For fungible assets, the index of a node is defined by the issuing faucet ID, and the value of the node is the asset itself. Thus, for any fungible asset, there will be only one node in the tree.
* For non-fungible assets, the index is defined by the asset itself, and the asset is also the value of the node.

An account vault can be reduced to a single hash which is the root of the sparse Merkle tree.

### Code

The interface for accounts. In Miden every account is a smart contract. It has an interface that exposes functions that can be called by [note scripts](notes.md#the-note-script) and transaction scripts. Users cannot call those functions directly.
The interface for accounts. In Miden, every account is a smart contract. It has an interface that exposes functions that can be called by [note scripts](notes.md#the-note-script) and transaction scripts. Users cannot call those functions directly.

Functions exposed by the account have the following properties:

* Functions are actually roots of [Miden program MASTs](https://0xpolygonmiden.github.io/miden-vm/user_docs/assembly/main.html) (i.e., a `32`-byte hash). Thus, the function identifier is a commitment to the code which is executed when a function is invoked.
* Only account functions have [mutable access](transactions/contexts.md) to an account's storage and vault. Therefore, the only way to modify an account's internal state is through one of the account's functions.
* Account functions can take parameters and can create new notes.

!!! note
Since code in Miden is expressed as MAST, every function is a commitment to the underlying code. The code cannot change unnoticed to the user because its hash would change. Behind any MAST root there can only be `256` functions.
> **Note**
> Since code in Miden is expressed as MAST, every function is a commitment to the underlying code. The code cannot change unnoticed to the user because its hash would change. Behind any MAST root there can only be `256` functions.
#### Example account code

Expand All @@ -97,12 +88,12 @@ There is a standard for a basic user account. It exposes three functions via its
```
</details>

[Note scripts](notes.md#the-note-script) or transaction scripts can call `receive_asset`, `create_note` and `move_asset_to_note` procedures.
[Note scripts](notes.md#the-note-script) or transaction scripts can call `receive_asset`, `create_note`, and `move_asset_to_note` procedures.

Transaction scripts can also call `auth_tx_rpo_falcon512` and authenticate the transaction.
Transaction scripts can also call `auth_tx_rpo_falcon512` to authenticate the transaction.

!!! warning
Without correct authentication, i.e. knowing the correct private key, a note cannot successfully invoke `receive_asset`, `create_note` or `move_asset_to_note`.
> **Warning**
> Without correct authentication, i.e., knowing the correct private key, a note cannot successfully invoke `receive_asset`, `create_note`, or `move_asset_to_note`.
##### Basic fungible faucet (faucet for fungible assets)

Expand All @@ -128,7 +119,7 @@ There is also a standard for a [basic fungible faucet](https://github.com/0xPoly
sub
# => [max_supply - total_issuance, amount, tag, note_type, RECIPIENT, ...]
# check that amount =< max_supply - total_issuance, fails if otherwise
# check that amount <= max_supply - total_issuance, fails if otherwise
dup.1 gte assert.err=ERR_BASIC_FUNGIBLE_MAX_SUPPLY_OVERFLOW
# => [asset, tag, note_type, RECIPIENT, ...]
Expand Down Expand Up @@ -173,48 +164,48 @@ There is also a standard for a [basic fungible faucet](https://github.com/0xPoly

The contract exposes two functions `distribute` and `burn`.

The first function `distribute` can only be called by the faucet owner, otherwise it fails. As inputs, the function expects everything that is needed to create a note containing the freshly minted asset, i.e., amount, metadata, and recipient.
The first function, `distribute`, can only be called by the faucet owner; otherwise, it fails. As inputs, the function expects everything that is needed to create a note containing the freshly minted asset, i.e., amount, metadata, and recipient.

The second function `burn` burns the tokens that are contained in a note and can be called by anyone.
The second function, `burn`, burns the tokens that are contained in a note and can be called by anyone.

!!! info "Difference between `burn` and `distribute`"
The `burn` procedure exposes `exec.account::incr_nonce`, so by calling `burn` the nonce of the executing account gets increased by `1` and the transaction will pass the epilogue check. The `distribute` procedure does not expose that. That means the executing user needs to call `basic::auth_tx_rpo_falcon512` which requires the private key.*
> **Info: Difference between `burn` and `distribute`**
> The `burn` procedure exposes `exec.account::incr_nonce`, so by calling `burn`, the nonce of the executing account gets increased by `1`, and the transaction will pass the epilogue check. The `distribute` procedure does not expose that. That means the executing user needs to call `basic::auth_tx_rpo_falcon512`, which requires the private key.
## Account creation

For an account to exist it must be present in the [account database](state.md#account-database) kept on the Miden node(s).
For an account to exist, it must be present in the [account database](state.md#account-database) kept on the Miden node(s).

However, new accounts can be created locally by users using the Miden client. The process is as follows:

* Alice creates a new account ID (according to the account types) using the Miden client.
* Alice's Miden client asks the Miden node to check if the new ID already exists.
* Alice shares the ID with Bob (eg. when Alice wants to receive funds).
* Bob executes a transaction and creates a note that contains an asset for Alice.
* Alice consumes Bob's note to receive the asset in a transaction.
* Depending on the account storage mode (private vs. public) and transaction type (local vs. network) the operator eventually receives the new account ID and - if the transaction is correct - adds the ID to the account database.
1. Alice creates a new account ID (according to the account types) using the Miden client.
2. Alice's Miden client asks the Miden node to check if the new ID already exists.
3. Alice shares the ID with Bob (e.g., when Alice wants to receive funds).
4. Bob executes a transaction and creates a note that contains an asset for Alice.
5. Alice consumes Bob's note to receive the asset in a transaction.
6. Depending on the account storage mode (private vs. public) and transaction type (local vs. network), the operator eventually receives the new account ID and - if the transaction is

correct - adds the ID to the account database.

A user can create an account in one of the following manners:

1. Use the [Miden client](https://docs.polygon.technology/miden/miden-client/) as a wallet.
2. Use the Miden base builtin functions for wallet creation: [basic wallet](https://github.com/0xPolygonMiden/miden-base/blob/4e6909bbaf65e77d7fa0333e4664be81a2f65eda/miden-lib/src/accounts/wallets/mod.rs#L15), [fungible faucet](https://github.com/0xPolygonMiden/miden-base/blob/4e6909bbaf65e77d7fa0333e4664be81a2f65eda/miden-lib/src/accounts/faucets/mod.rs#L11)
1. Use the [Miden client](https://0xpolygonmiden.github.io/miden-docs/miden-client/index.html) as a wallet.
2. Use the Miden base built-in functions for wallet creation: [basic wallet](https://github.com/0xPolygonMiden/miden-base/blob/4e6909bbaf65e77d7fa0333e4664be81a2f65eda/miden-lib/src/accounts/wallets/mod.rs#L15), [fungible faucet](https://github.com/0xPolygonMiden/miden-base/blob/4e6909bbaf65e77d7fa0333e4664be81a2f65eda/miden-lib/src/accounts/faucets/mod.rs#L11)

## Account types

There are two basic account types in Miden: Regular accounts and faucets. Only faucets can mint new assets. Regular accounts can be mutable or immutable, which simply means that it is possible to change the account code after creation.

Type and mutability is encoded in the most significant bits of the account's ID.
Type and mutability are encoded in the most significant bits of the account's ID.

| | Basic mutable | Basic immutable | Fungible faucet | Non-fungible faucet |
|---|---|---|---|---|
| **Description** | For most users, e.g. a wallet. Code changes allowed, including public API. | For most smart contracts. Once deployed code is immutable. | Users can issue fungible assets and customize them. | Users can issue non-fungible assets and customize them. |
| **Code updatability** | yes | no | no | no |
| **Most significant bits** | `00` | `01` | `10` | `11` |
| | Basic mutable | Basic immutable | Fungible faucet | Non-fungible faucet |
|------------------------|---------------|------------------|------------------|----------------------|
| **Description** | For most users, e.g., a wallet. Code changes allowed, including public API. | For most smart contracts. Once deployed, code is immutable. | Users can issue fungible assets and customize them. | Users can issue non-fungible assets and customize them. |
| **Code updatability** | Yes | No | No | No |
| **Most significant bits** | `00` | `01` | `10` | `11` |

## Public and private accounts

Users can decide whether to keep their accounts private or public at account creation. The account ID encodes this preference on the third and fourth most significant bit.

* Accounts with public state: The actual state is stored on-chain. This is similar to how accounts work in public blockchains, like Ethereum. Smart contracts that depend on public shared state should be stored public on Miden, e.g., DEX contract.
* Accounts with private state: Only the hash of the account is stored on-chain. Users who want to stay private, and manage their own data, should choose this option. Users who want to interact with private accounts need to know the account's interface.
Users can decide whether to keep their accounts private or public at account creation. The account ID encodes this preference in the third and fourth most significant bits.

</br>
* **Accounts with public state**: The actual state is stored on-chain. This is similar to how accounts work in public blockchains, like Ethereum. Smart contracts that depend on public shared state should be stored publicly on Miden, e.g., a DEX contract.
* **Accounts with private state**: Only the hash of the account is stored on-chain. Users who want to stay private and manage their own data should choose this option. Users who want to interact with private accounts need to know the account's interface.
12 changes: 2 additions & 10 deletions docs/architecture/assets.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
comments: true
---

In Miden, users can create and trade arbitrary fungible and non-fungible assets.

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.
Expand Down Expand Up @@ -29,13 +25,11 @@ The `faucet_id` identifies the faucet and starts with a different sequence depen

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.

<center>
![Architecture core concepts](../img/architecture/asset/asset-issuance.png)
</center>

### Fungible assets

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.
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.

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.

Expand All @@ -49,9 +43,7 @@ Examples of non-fungible assets are all NFTs, e.g., a DevCon ticket. The ticket'

[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.

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

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.

Expand All @@ -63,4 +55,4 @@ For example, developers can replicate the Ethereum ERC20 model, where ownership

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.

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.
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.
Loading

0 comments on commit a8d038c

Please sign in to comment.