Skip to content

Commit a8eefee

Browse files
latest changes
1 parent 2299046 commit a8eefee

File tree

4 files changed

+45
-41
lines changed

4 files changed

+45
-41
lines changed
Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
# Transactions
21
Asset transfers between accounts are done by executing transactions. Miden aims for parallel and private transaction execution. Therefore, a transaction is always performed against a single account which provides asynchronicity. And, every transaction causes a provable state-change and a STARK proof thereof. Thus, when executed locally, it provides privacy.
32

43
## Transaction design
4+
55
Transactions can be described as state-transition function T that takes an account and `0 to n` notes to map it to another version of that account and produces `0 to n` notes
66

7-
$
7+
$$
88
T(A, \sum_{\substack{
99
0 \leq i < 1024
1010
}}
1111
N(i))) \to (A', \sum_{\substack{
1212
0 \leq j < 4096
1313
}}
1414
N(j))
15-
$
16-
, where $ A \in { Accounts }$, $N \in { Notes }, 0 < i + j $
15+
, where $ A \in { Accounts }$, $N \in { Notes }, 0 < i + j $$
1716

1817
A transaction must include an executable program in addition to inputs and outputs. The transaction program has a well-defined structure and must perform the following functions:
1918

@@ -23,29 +22,33 @@ A transaction must include an executable program in addition to inputs and outpu
2322
4. Create a uniform vault for all outputs.
2423
5. Ensure that the assets in the unified input and output vaults are the same.
2524

26-
### Transaction inputs and outputs
25+
### Inputs and outputs
26+
2727
As inputs, a transaction accepts the state of one single account and up to `1023` notes for consumption. Optionally, it also takes a user defined script which is executed after all input notes have been consumed. The transaction's output will consist of that single account and up to `4096` newly created notes.
2828

29-
### Transaction program
29+
### Program
30+
3031
In addition to specifying inputs and outputs, a transaction must also include an executable program. The transaction program has a well-defined structure which must do the following:
3132

3233
A user-defined transaction script can also be included in a transaction.
3334

34-
The last point ensures that a transaction does not create or destroy any assets. A transaction can also include a user-defined transaction script. A transaction script is different to the [note scripts](https://0xpolygonmiden.github.io/miden-base/architecture/notes.html#script) that are executed during a transaction.
35+
The last point ensures that a transaction does not create or destroy any assets. A transaction can also include a user-defined transaction script. A transaction script is different to the [note scripts](notes.md#script) that are executed during a transaction.
36+
37+
## Execution steps
3538

36-
## Execution steps of a transaction
3739
Transaction execution consists of several steps. These steps are described below:
3840

3941
1. **Prologue**: during this step we build a single unified vault all all transaction inputs (account + notes).
4042
2. **Execution**: during this step we first execute scripts of all input notes (one after another), and then execute an optional user-defined script (called tx script).
4143
3. **Epilogue**: during this step we build a single unified vault of all transaction outputs (account + notes), and make sure it contains the same assets as the input vault.
4244

4345
## Asset transfer using two transactions
46+
4447
Under this model transferring assets between accounts requires two transactions as shown in the diagram below.
4548

46-
<p align="center">
47-
<img src="../diagrams/architecture/transaction/Transaction_Flow.png">
48-
</p>
49+
<center>
50+
![Transaction flows](../../img/miden/architecture/transaction/transaction_flow.png){ width="80%" }
51+
</center>
4952

5053
The first transaction invokes a function on `account_a` (e.g., "send" function) which creates a new note and also updates the internal state of `account_a`. The second transaction consumes the note which invokes a function on `account_b` (e.g., "receive" function), which also updates the internal state of `account_b`.
5154

@@ -57,19 +60,24 @@ It is important to note that both transactions can be executed asynchronously: f
5760
* Both transactions can be executed "locally". For example, we could generate a ZKP proving that `transaction1` was executed and submit it to the network. The network can verify the proof without the need for executing the transaction itself. Same can be done for `transaction2`. Moreover, we can mix and match. For example, `transaction1` can be executed locally, but `transaction2` can be executed on the network, or vice-versa.
5861

5962
## Local vs. network transactions
63+
6064
There are two types of transactions in Miden: local transactions and network transactions.
6165

62-
<p align="center">
63-
<img src="../diagrams/architecture/transaction/Local_vs_Network_Transaction.png">
64-
</p>
66+
<center>
67+
![Local vs network transactions](../../img/miden/architecture/transaction/local_vs_network_transaction.png){ width="80%" }
68+
</center>
6569

66-
For **local transactions**, clients executing the transactions also generate the proofs of their correct execution. So, no additional work needs to be performed by the network. Local transactions are useful for several reasons:
70+
### Local
71+
72+
Clients executing the transactions also generate the proofs of their correct execution. So, no additional work needs to be performed by the network. Local transactions are useful for several reasons:
6773

6874
1. They are cheaper (i.e., lower fees) as ZKPs are already generated by the clients.
6975
2. They allow fairly complex computations because the proof size doesn't grow linearly with the complexity of the computation.
7076
3. They enable privacy as neither the account state nor account code are needed to verify the ZKP.
7177

72-
For **network transactions**, the operator will execute the transaction and generate the proofs. Network transactions are useful for two reasons:
78+
### Network
79+
80+
The operator will execute the transaction and generate the proofs. Network transactions are useful for two reasons:
7381

7482
1. Clients may not have sufficient resources to generate ZK proofs.
7583
2. Executing many transactions against the same public account by different clients would be challenging as the account state would change after every transaction. In this case, the Miden Node / Operator acts as a "synchronizer" as they can execute transactions sequentially and feed the output of the previous transaction into the subsequent one.

docs/miden/crypto-primitives/crypto-primitives.md

Whitespace-only changes.

docs/miden/crypto-primitives/tsmt.md

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,49 @@
1-
# Tiered Sparse Merkle Tree (TSMT)
2-
A sparse Merkle tree (SMT) is a cryptographic data structure that allows authenticated manipulations of a key-value store, i.e. a dictionary. It is a Merkle tree because it is
3-
a binary tree in which each leaf node represents a key-value pair, and each non-leaf node represents the hash of the concatenation of its two child nodes. The index of the
4-
leaf node in the tree corresponds to the key and the data stored in this node corresponds to the value. This implies that the depth of such a tree is logarithmic in the size of the key space, which implies that, for most key spaces used in practice, such a tree is impractical if done naively. However, the tree is sparse, i.e. it is going to be made up of mostly empty leaves, which in turn implies that most sub-trees are empty with roots that can be pre-computed.
5-
A major issue with SMTs is the fact that operations scale with the size of the key space, meaning, for example, that if our key space has size $~ 2^{256}$, then performing any operation on the key-value store, for example, an update, will require performing $256$ hashing operations. This is undesirable both inside as well as outside the STARK.
1+
A sparse Merkle tree (SMT) is a cryptographic data structure that allows authenticated manipulations of a key-value store, i.e. a dictionary. It is a Merkle tree because it is a binary tree in which each leaf node represents a key-value pair, and each non-leaf node represents the hash of the concatenation of its two child nodes.
62

3+
The index of the leaf node in the tree corresponds to the key and the data stored in this node corresponds to the value. This implies that the depth of such a tree is logarithmic in the size of the key space, which implies that, for most key spaces used in practice, such a tree is impractical if done naively. However, the tree is sparse, i.e. it is going to be made up of mostly empty leaves, which in turn implies that most sub-trees are empty with roots that can be pre-computed.
74

8-
A common solution to this issue is to keep only non-empty leaves in the tree, which in practice means that sub-trees with only one non-empty child are replaced with the sub-tree rooted at that non-empty child. Here's an example of this:
5+
A major issue with SMTs is the fact that operations scale with the size of the key space, meaning, for example, that if our key space has size $~ 2^{256}$, then performing any operation on the key-value store, for example, an update, will require performing $256$ hashing operations. This is undesirable both inside as well as outside the STARK.
96

10-
<p align="center">
11-
<img src="./diagram/../../diagrams/crypto-primitives/tsmt/tsmt_compaction_example.svg">
12-
</p>
7+
A common solution to this issue is to keep only non-empty leaves in the tree, which in practice means that sub-trees with only one non-empty child are replaced with the sub-tree rooted at that non-empty child. Here's an example of this:
138

9+
<center>
10+
![tsmt compaction example](../../img/miden/crypto-primitives/tsmt/tsmt_compaction_example.svg){ width="80%" }
11+
</center>
1412

1513
Compaction implies then that the tree depth is logarithmic in the size of the dictionary entries as opposed to the size of the key space. This, in turn, means that the number of hashing required for executing operations on the key-value map scales logarithmically in the size of the map.
1614

17-
The first documented implementation of a compact SMT was described [here](https://github.com/proofchains/python-proofmarshal/blob/master/proofmarshal/merbinnertree.py). This implementation relies on augmenting nodes with
18-
a field called `prefix` which is the longest common prefix of all childs of a given node. This means that internal nodes are hashes of a left and right child together with `prefix`, i.e. `(LEFT || RIGHT || PREFIX)`. Leaf nodes are hashes of just the key-value pair. In addition, domain separation is used to distinguish
19-
between an internal and a leaf node by appending a `0` or `1` before hashing.
15+
The first documented implementation of a compact SMT was described [here](https://github.com/proofchains/python-proofmarshal/blob/master/proofmarshal/merbinnertree.py). This implementation relies on augmenting nodes with a field called `prefix` which is the longest common prefix of all childs of a given node. This means that internal nodes are hashes of a left and right child together with `prefix`, i.e. `(LEFT || RIGHT || PREFIX)`. Leaf nodes are hashes of just the key-value pair. In addition, domain separation is used to distinguish between an internal and a leaf node by appending a `0` or `1` before hashing.
16+
2017
A disadvantage of this implementation, as well as all known implementations of compact SMTs, is the reliance of their operations on bit-wise manipulations. This makes them very expensive to implement inside Miden VM.
2118

2219
Tiered sparse Merkle trees (TSMT) are a result of the idea that one can trade hashing for more efficient bit-wise operations. More precisely, in TSMT, compaction happens only at certain pre-specified tiers and this leads to simpler bit-wise manipulations. In the case of Miden VM, compaction happens at depths `16`, `32`, `48` and `64`. To illustrate this, consider the following example where the keys have length 4, i.e. the SMT has depth 4.
2320

24-
<p align="center">
25-
<img src="./diagram/../../diagrams/crypto-primitives/tsmt/tsmt_non_compact.svg">
26-
</p>
21+
<center>
22+
![tsmt non compact](../../img/miden/crypto-primitives/tsmt/tsmt_non_compact.svg){ width="80%" }
23+
</center>
2724

2825
If we choose the tiers to be at depths 2 and 4 then the compact version of the above tree will look like
2926

30-
<p align="center">
31-
<img src="./diagram/../../diagrams/crypto-primitives/tsmt/tsmt_compact_2.svg">
32-
</p>
27+
<center>
28+
![tsmt compact 2](../../img/miden/crypto-primitives/tsmt/tsmt_compact_2.svg){ width="80%" }
29+
</center>
3330

3431
If, however, we choose compaction at all possible depths we get a compact SMT that is similar to the [Jellyfish SMT](https://developers.diem.com/papers/jellyfish-merkle-tree/2021-01-14.pdf)
3532

36-
<p align="center">
37-
<img src="./diagram/../../diagrams/crypto-primitives/tsmt/tsmt_compact_1.svg">
38-
</p>
33+
<center>
34+
![tsmt compact 2](../../img/miden/crypto-primitives/tsmt/tsmt_compact_1.svg){ width="80%" }
35+
</center>
3936

4037
We can see that a TSMT is a parametrized SMT, where the parameter is the number of tiers, that interpolates between a plain SMT with no compaction and a (fully) compact SMT with compaction allowed at evey depth.
4138

42-
4339
The Miden VM TSMT is a map from a key-space of size approximately `256`-bit to a value-space of the same size and are represented by four $64$-bit field elements in the Miden VM native field, i.e. a `Word`. Athough keys are `256`-bit long the maximal tree depth that is allowed is `64`. This has several consequences:
4440

4541
1. Limiting the tree depth to `64` means that we can use one of the four field elements making up the (full) key as the (compact) key in the TSMT. We choose the 4th field element to act as the (compact) key since when loading the (full) key on the operand stack, the 4th field element will be at the tip of the operand stack and thus will be easier to access. Using a single field element to act as the (compact) key implies that we can levarage the native instructions of the Miden VM to manipulate it during the course of operations on the TSMT inside the VM.
4642
2. In order to deal with keys sharing a common prefix of length greater than `64`, we introduce a special type of leaf nodes at depth `64`. These leaf nodes are a sorted list of `(key, value)` pairs where sorting is done using `key`. Notice that all pairs in the sorted list have the same first part of the key, namely they share a common `64`-bit prefix , and that all pairs with the same first part of the key belong in the same sorted list. The decision to go with a sorted list of pairs instead of a standard sub-tree node with multiple childs at depth `80` sharing the same `64`-bit prefix is partially motivated by the fact that, for most scenarios related to Miden VM, the probability that two distinct keys will end up sharing a common prefix of length greater than or equal to `64` is very low, and even feasible grinding attacks can only make the sorted list on slightly longer than a dozen of elements and with very little clear benefits. Thus putting all pairs with the same first part of the key in a sorted list is a good tradeoff for dealing with prefixes of length greater than `64`.
4743

4844
The Miden VM TSMT has three types of nodes:
49-
1. Internal nodes with a left and right child, and value computed as: `Hash(left || right)`
45+
46+
1. Internal nodes with a left and right child, and value computed as: `Hash(left || right)`.
5047
2. Leaf nodes at depths `16`, `32` and `48` with value computed as: `Hash(rem_key || value; domain=depth)` where:
5148
1. `depth` is the depth of the node, i.e. either `16`, `32` or `48`.
5249
2. `rem_key` is the the remaining key after either the `16`, `32` or `48`-bit prefix is removed depending on the depth of the node.

mkdocs.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,8 @@ nav:
289289
- State: miden/architecture/state.md
290290
- Transactions: miden/architecture/transactions.md
291291
- Crypto primitives:
292-
- Crypto primitives: miden/crypto-primitives/crypto-primitives.md
293292
- Tiered sparce Merkle tree (TSMT): miden/crypto-primitives/tsmt.md
294-
- Miden VM docs: https://0xpolygonmiden.github.io/miden-vm/
293+
# - Miden VM docs: https://0xpolygonmiden.github.io/miden-vm/
295294
- Developer tools:
296295
- Developer tools: tools/index.md
297296
- Smart contract development:

0 commit comments

Comments
 (0)