Skip to content

Commit

Permalink
adding more clarity
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominik1999 committed Feb 5, 2025
1 parent da03534 commit 327ccad
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 14 deletions.
25 changes: 11 additions & 14 deletions docs/architecture/transaction.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Transaction

A `Transaction` in Miden is the state change of a single account. This is different to most other blockchains, where a transaction typically involves the sender and the receiver, e.g., Alice sends 5 ETH to Bob. In Miden, sending 5 ETH from Alice to Bob takes two transactions, one in which Alice creates a note containing 5 ETH and one in which Bob consumes that note and receives the ETH.
A `Transaction` in Miden is the state change of a single account. This is different to most other blockchains, where a transaction typically involves the sender and the receiver, e.g., Alice sends 5 ETH to Bob. In Miden, sending 5 ETH from Alice to Bob takes two transactions, one in which Alice creates a note containing 5 ETH and one in which Bob consumes that note and receives the ETH. This concept concept enables Miden to treat transactions (single state transitions) asynchronously and therefore allows accounts to prove their own state transitions independently from each other - no global lock is needed and transactions can happen in parallel.

Miden's transaction model aims for:

Expand All @@ -19,23 +19,20 @@ There will be two types of transactions in Miden: **local transactions** and in

In **local transactions**, clients apply the account's state transition locally and send a transaction proof to the network. The network only verifies the proof and changes the global parts of the state.

Local transactions are useful when:
Local transactions are useful, because

1. They are cheaper (i.e., lower fees) as zk-proofs are already generated by the clients.
2. They allow fairly complex computations because the proof size doesn't grow linearly with the complexity of the computation.
3. They enable privacy as neither the account state nor account code are needed to verify the zk-proof.
1. They are cheaper (i.e., lower fees) as zk-proofs are already generated by the clients. This means privacy is the cheaper option on Miden.
2. They allow fairly complex computations because the proof size doesn't grow linearly with the complexity of the computation. That means there is no gas limit for client-side proofs.
3. They enable privacy as neither the account state nor account code are needed to verify the zk-proof. Public inputs are only commitments and block information that are stored on-chain anyway.

In the near future, there will be **network transactions** as well. In network transactions, the Miden operator or the network executes the transaction and generates the proof. This type of transaction is more in line with a traditional understanding of how blockchains work.
In the near future, there will be **network transactions** as well. In network transactions, the Miden operator or the network executes the transaction and generates the proof. Miden needs network transactions for smart contracts with public shared state. This type of transaction is more in line with a traditional understanding of how blockchains work.

Network transactions are useful when:
Network transactions are useful, because

1. For autonomous execution of smart contracts. Local transactions require a client to execute and sometimes a smart contract should execute when a certain condition is met or simply when it is called by someone.
2. For public shared state of smart contracts. Network transactions allow orchestrated state changes of public smart contracts without race conditions.
1. Smart contracts should be executed autonomously. Local transactions require a client to execute and sometimes a smart contract should execute when a certain condition is met or simply when it is called by someone. Network transactions ensure liveness of smart contracts.
2. For public shared state of smart contracts. Network transactions allow orchestrated state changes of public smart contracts without race conditions. See <here> for an in-depth explanation of public share state on Miden.
3. Clients may not have sufficient resources to generate zk-proofs.

Handling of public shared state. This is an important thing to cover somewhat in depth because after reading about local transactions, savvy developers will immediately have questions about how how public shared state works.
Ensuring liveness for public accounts. This is something we haven't really covered previously, but is a pretty cool thing which would basically let the network update some accounts only during some blocks. For example, let's say for 59 minutes of every hour only some permissioned set of entities can update a given account, but every last minute of the hour, the network can do it. This way, as long as the permissioned set does what it is supposed to, the computational burden on the network is minimal. But if the permissioned set stops working, the network could still update the account (though at a much slower pace).

![Local vs network transactions](../img/architecture/transaction/local-vs-network-transaction.png)

In general, the ability to facilitate both, local and network transactions, is what differentiates Miden. Local transaction execution can happen in parallel and for most transactions there is no need for public state changes. This increases the network's throughput tremendously. Network transactions on the other hand is what constitutes a normal blockchain with autonomous smart contracts and public shared state.
Expand All @@ -55,15 +52,15 @@ In order to execute a transaction locally, the executor needs to know the full d
Transaction execution starts with a prologue where on-chain commitments are checked against the provided data. Then, all notes are being executed sequentially against the account. The executor can define the sequence of the `InputNotes` and notes must be consumed fully. That means all assets must be consumed into the account and the note script must be executed fully given the provided [note inputs](notes.md/inputs) and transaction arguments. Let's unfold what that means:

When a note is being consumed in a transaction, the note script is being executed against the executing account. That way, the note script can call exposed functions of the account interface. For example, a basic wallet account exposes `receive_asset`. When a note calls this function in its script, the assets that are contained in the note are being transferred to the account. In most cases, the note creator doesn't want a note and its assets to be consumable by all the accounts. That is why, the note creator can impose an additional checks. Since the executing account needs to execute the full note script in order to consume the note, it can not circumvent the checks set by the note creator. For example, the P2ID note script checks that the ID of the executing account matches the AccountID provided by the [note inputs](notes.md/inputs). But also the executor can inject arguments to the note script execution called `TransactionArguments`. For example, a basic SWAP note is defined as "Anyone can consume this note and take the X assets A on it if during execution another note is created to send Y of asset B back to the sender". Now, the executor might not want to "buy" X of asset A, but only X-m - a smaller portion. If the note creator is fine with also selling less of A for the same price, this can be encoded in the note script. The executor will then provide the amount willing to buy via the `TransactionArguments` and the note script forces the executor to create two new notes - one back to the sender containing Y-n of asset B and another one, a copy of the initial node containing X-m of asset A for other people to consume. Note creators can define any arbitrary logic into their note scripts which is executed during transaction execution. However, note scripts can only call functions of the account that are exposed via the account code.
When a note is being consumed in a transaction, the note script is being executed against the executing account. That way, the note script can call exposed functions of the account interface. For example, a basic wallet account exposes `receive_asset`. When a note calls this function in its script, the assets that are contained in the note are being transferred to the account. In most cases, the note creator doesn't want a note and its assets to be consumable by all the accounts. That is why, the note creator can impose an additional checks. Since the executing account needs to execute the full note script in order to consume the note, it can not circumvent the checks set by the note creator. For example, the P2ID note script checks that the ID of the executing account matches the AccountID provided by the [note inputs](notes.md/inputs). But also the executor can inject arguments to the note script execution called `TransactionArguments`. For example, a basic SWAP note is defined as "Anyone can consume this note and take the X assets A on it if during execution another note is created to send Y of asset B back to the sender". Now, the executor might not want to "buy" X of asset A, but only X-m - a smaller portion. If the note creator is fine with also selling less of A for the same price, this can be encoded in the note script. The executor will then provide the amount willing to buy via the `TransactionArguments` and the note script forces the executor to create two new notes - one back to the sender containing Y-((m*Y)/X) of asset B (assuming that X/Y = m/n) and another one, a copy of the initial node containing X-m of asset A for other accounts to consume. Note creators can define any arbitrary logic into their note scripts which is executed during transaction execution. However, note scripts can only call functions of the account that are exposed via the account code. Most internal account functions, manipulating the vault or storage, are shielded from note scripts.

After all notes are being consumed, the transaction script is next in line. The transaction script is an optional piece of code defined by the executor. Normally, it is used to sign the transaction, but it can also be used to interact with an account without using notes. For example, the owner of a faucet can `mint` new tokens using only a transaction script.

After all note scripts and the optional transaction script are being processed, the account is being updated in the transaction's epilogue. If the transaction also creates new notes, they are now being created and assets are moved from the account to the corresponding `OutputNotes`. Now, the transaction execution is complete resulting in an account with a new state and the corresponding `OutputNotes`.

![Transaction execution process](../img/architecture/transaction/transaction-program.png)

If the kernel doesn't throw an error and the transaction can be completed, a proof is being generated of the correct transaction execution. This proof together with the corresponding data needed for verification and updates on the global state can then be submitted and processed by the network.
If the kernel doesn't throw an error and the transaction can be completed, a proof is being generated of the correct transaction execution. This proof together with the corresponding data needed for verification and updates on the global state can then be submitted and processed by the network.


> **Info**
Expand Down
Binary file modified docs/img/architecture/transaction/transaction-diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 327ccad

Please sign in to comment.