Replies: 2 comments 3 replies
-
Thank you for this! This brings a lot of clarity to your vision of the execution model. I have one particular curiosity with this. I wonder if the requirement that all the transactions passed to the os kernel must already be proven could introduce undesirable latency properties for the system as a block can only be produced once all proofs have been produced. As we are aware proof generation is far more time consuming that just running a program, this makes it undesirable to wait for proving before a block can be produced. As you have alluded to in your description - transactions touching the same state must be processed sequentially to ensure that pre-transaction state is known. Proof generation can take place in parallel and via a decentralised set of network participants provided that the pre-transaction state is known. I wonder if you had considered a system that works as follows. The block producer selects a set of both local and network transactions from the transaction pool and executes the state transitions associated with the transactions. They produce a block which contains initial database state commitments, ordered network and local transactions and also final database state commitments. The block producer would only execute the state transitions and would not do any proving at this point. They would then publish this unproven block. This will allow the blockchain to proceed with block production without having to wait for proof generation to complete. Once a block has been publish the network provers now have an ordered set of transactions and initial + final database commitments. Under the model you described you could have prover_n generate proofs for transactions n to n+100. This may include both generating proofs for network transactions by running the tx kernel and also aggregating proofs using the ag kernel. These batch proofs would then be passed to the os kernel as you described. This system would allow new blocks to be produced and could give users fast guarantees of finality even before proofs have been generated. I believe this is a similar construct to the one that starkent have implemented. I also wonder if you had considered the implications of the note based model on MEV. Are there any potential mitigation strategies like ordering transactions based on the lowest note serial number they consume? |
Beta Was this translation helpful? Give feedback.
-
I wonder if there is a way to generalize the proposed execution model to enable more than one type of transaction and state model. This can act as a hedge against the possibility that the currently proposed models fail to satisfy the needs of all applications and users. It is easy to observe that different types of applications benefit from different state and transaction representations. For example, a payments-focused rollup would benefit greatly from the proposed actor-message architecture. In such a setting, transaction processing is highly parallelizable, and little to no coordination is needed with the sequencer, as notes containing assets can be produced and consumed asynchronously. However, a rollup hosting DeFi protocols requires a large degree of composibility. For example, an exchange aggregator may need to split a large trade across several DEXs in order to obtain the best execution price -- an interaction which is cumbersome in a note-based transaction model. Instead of enshrining one particular state model, it should be possible to allow multiple state models with completely different properties to coexist. Each state model would be associated with its own set of potentially unique block and transaction kernels that constrain the space of allowable state transitions. The basic implementation idea is to introduce an independent block producer for each environment (I'll use "environment" from now on to refer to both the state and transaction model), along with a block batcher role, which exists one level beneath the block producer. The block batcher is responsible for verifying single block proofs for each environment and batching them into a single superblock. The block batcher would also generate a new proof attesting that the set of state commitments was correctly reduced to a smaller set, which is then submitted to L1. Note that the block batcher does not need to know the full state of each environment, only their initial state commitments, and that different block producers can operate in parallel as they evolve the state for isolated environments. Bridging between environments can be solved by deploying smart contracts that validate the appropriate authenticated state representations of source and destination environments, as has been described elsewhere in the context of L3s. It can also be enshrined through the definition of block kernel functions that mediate creation/destruction/yanking of state across environments. For example, to bridge an asset from environment 1 to environment 2, either a block kernel function or account/smart contract would verify that a transaction locking an asset in environment 1 was executed before creating its equivalent representation in environment 2. Reading through the above, it might seem that I'm describing an L2/L3 architecture, but this approach differs in some key ways. In a typical L2/L3 design, the L2 is a general-purpose execution layer, where developers can deploy arbitrary smart contract logic, including verifiers for L3 rollups. In those designs, the L2 acts as a kind of intermediate settlement layer for deployed L3 rollups, and their liveness also depends on that of the L2 block producer. In the execution model described in this comment, there is no enshrined general-purpose L2 execution layer. Instead, the block batcher serves to efficiently aggregate and verify state transition proofs for multiple isolated enviroments, and can even facilitate their bridging. The currently proposed state and transaction models could exist as the first of these environments, and more can be added at a later time by upgrading the batcher kernel. This design places all environments on an equal footing, where each environment can use L1 as a direct settlement layer. This approach shares some similarities with Tezos' vision of enshrined rollups described here. Another interesting feature of this archiecture is that VMs other than the Miden VM could be used at the level of block production or transaction execution. The only requirements are that the batcher can efficiently verify the proof of VM execution, and a whitelisted kernel exists for that VM at the appropriate level. This could potentially allow for radically different environments to live alongside each other, such as a zkEVM, with kernel-based bridging that is settled on L1 (not IOU-based) and provided at a fraction of the cost as having to move assets from one rollup to another on L1. |
Beta Was this translation helpful? Give feedback.
-
This note is a followup on #192 and #222. One of the things that I didn't cover in these notes is the description of who are the network participants, what are their roles, and how their actions result in transaction execution.
In this note I will describe a simplified centralized model, primarily because I want to avoid talking about things like consensus, P2P network etc. As with previous notes, this is just a high-level description and a lot of details and specifics are missing, frequently because they are yet to be thought out.
In the centralized model, we have the following entities:
In the decentralized model we'd also have full nodes, validators etc. - but as mentioned above, I'm skipping them for now. Also, in this note, I will focus on clients and block producers, and will leave details on L1 contract to future notes.
Transaction aggregation
As mentioned above, a block producer collects transactions from the clients and aggregates them into a block. Since we are building a ZK rollup, this block needs to be accompanies by a ZK proof attesting that all transactions in the block have been executed correctly. Graphically, this could look something like this:
Where$a_0$ , $n_0$ , and $x_0$ are the commitments to the account, note, and nullifier databases before the transactions in the block have been executed, and $a_i$ , $n_i$ , and $x_i$ are the commitments to the same databases after the transactions have been executed.
One way to generate this ZK proof is to execute transactions one by one on the VM and output a single proof of their execution. This would look something like this:
This approach works and it is a very efficient way to generate a ZK proof. But it has a few drawbacks:
Another approach could look something like this:
In this approach, we assume that execution of each transaction has already been proven (which works well in our transition model). So, the program which gets executed on the VM to generate a block level proof would need to do the following:
We will call the program which performs the above steps os kernel.
In this model, resource accounting is greatly simplified for two reasons:
We can take this approach further: instead of aggregating individual transaction proofs, we can aggregate batches of already aggregated transactions like so:
Assuming batches are non-overlapping, the above would work just as well as the case with individual transaction proofs. Though, obviously, os kernel would need to be slightly different.
It would be very interesting to see if we can make this work for overlapping batches - i.e., the same transaction is included in multiple batches.
Transaction execution
In the section above we assumed that each transaction already comes with a ZK proof attesting to its correct execution. But how do these ZK proofs get generated, and who generates them?
As mentioned in the previous notes, there are two types of transactions: (1) local transactions and (2) network transactions.
For local transactions, clients initiating the transactions also generate the proofs of their execution. So, no additional work needs to be performed by the network. Local transactions may be useful for two reasons:
For network transactions, the block producer would generate the proofs. Network transactions may be useful for two reasons:
In both cases, the entity generating a transaction proof would need to execute the same program on the VM (i.e., the program which executes a prologue, note scripts, epilogue etc. - as described in tx model note). We will call this program a tx kernel.
Block producer could also "outsource" tx proof generation to others as all proofs could be generated independently in parallel. Though, in cases when many transactions are executed against the same account, the block producer would also need to provided additional info (i.e., before/after account states) to such helpers (or another option could be to give all transactions which touch a particular account to the same helper).
Block producers will probably need to be compensated for the proof generation for network transactions. Thus, clients submitting network transactions would need to include a higher fee. The amount of the extra fee may be determined by the market, but more thinking is needed on how it can be made easy to estimate.
Transaction batching
Verifying a STARK proof within the VM should be relatively efficient (though, this has not been implemented it) - but it is still a pretty costly operation. I don't know what the actual numbers will come out to be, but I don't think it will be desirable to verify more than 100 proofs inside a single larger proof (at least for the near future).
However, if we are able to batch transactions, each batch could contain 100 transactions (or w/e the number that makes sense), and the block-level proof would contain 100 batch proofs. This way, each block could fit 10K transactions, which will be processed in batches of 100 in parallel.
To generate transaction batches we will also need to have a separate program. We will call this program ag kernel.
We can also take the batching approach a step further and add more recursion layers (i.e., batches of batches) - but this will complicate both the ag kernel and the os kernel quite a bit. So, my thinking is that at least initially, we don't try to do that.
Another interesting benefit of batching is that we may be able to use it to support proof generation on resource-constraint devices. One of the reasons why proof generation for transactions will be expensive is that to do recursive proof aggregation we need to build lower-level proofs using arithmetization-friendly hash functions (i.e., Rescue Prime in our case). These hash functions are not very efficient (i.e., probably 30x less efficient than BLAKE3) and will dominate proof generation costs.
However, with batching, we can allow the following:
Recursively verifying proofs built using BLAKE3/SHA256 would be quite a bit more expensive - so, such transactions would need to include higher fee - but there could be use cases where this may be justified.
VM implications
To support the the above model, it seems like we may actually need 3 separate kernels:
Beta Was this translation helpful? Give feedback.
All reactions