Opinion: Eth2 as a Data Availability Engine
Editor's Note: This article comes fromEthereum enthusiasts (ID: ethfans)Editor's Note: This article comes from
Ethereum enthusiasts (ID: ethfans)
Ethereum enthusiasts (ID: ethfans)
, Author: Casey Detrio, Translator & Proofreader: Min Min & A Jian, reproduced by Odaily with authorization.
Editor's Note: The original title of this article was "Phase One and Done: eth2 as a data availability engine". At the time of publication (April 2019), the author intended to propose a roadmap for Eth2.0 to replace Phase 2 , that is, if only sharding is used to ensure data availability, is such a system useful, and what parts need to be added to make it useful. Surprisingly, a year and a half ago, the author realized that for a system like zk-rollup, the bottom layer must guarantee that "the execution of state transitions and data availability must be atomically bound Together", so the underlying layer must have the ability to execute, even if it is a very simple stateless execution; moreover, (the author also pointed out through layers of reasoning) to ensure the user experience, the main part that is still missing is the procedure of how to shard the data Fee payment agreement (these two points of understanding, even today, can still be called cutting-edge, even advanced). The fee protocol is still missing in the Phase 2 specification.
By the way, the author of this article is Casey Detrio, who is a member of the Ewasm team and has provided many ideas for Phase 2 before; he also believes that Eth2 should be designed with the core of "guaranteeing that Eth1 contracts can be executed as usual when Eth2 arrives" .0. He is an underrated developer.
Currently, the bottleneck limiting Eth1 throughput is state growth. So, if we want to scale Ethereum, logically, 1000 shards with independent state can increase throughput by 1000 times.
However, from the Eth1.x route, Eth1.x wants to make major adjustments to the cost of two types of resources: storage (storage) and transaction data (tx data). Currently, storage is underpriced and transactional data is overpriced. This will incentivize dApp developers to use more storage than transaction data when writing contracts, causing storage to become a throughput bottleneck. The proposed solution to this problem is to increase the pricing of storage and decrease the pricing of transactional data. With these cost adjustments, developers will be incentivized to use transaction data more than storage (i.e., they will write more stateless contracts instead of stateful ones). Therefore, in the near future (if the Eth1.x roadmap achieves widespread adoption), we expect Eth1 throughput to be limited by transaction data rather than storage.
If we assume that throughput is bounded by transaction data, then shards on Serenity do not need to be stateful in order to scale Ethereum. If throughput is limited by transaction data from stateless contracts, then 1000 stateless shards will increase throughput by a factor of 1000.
This sounds good, but it needs to be implemented through sharding, which is planned to wait until Phase 2. At the same time, we can use Phase 1 as the data availability engine. The term data availability engine seems to be gaining popularity. Let's think about how it works.
Taking zk-rollup as an example, zk-rollup is limited by data availability. Can a zk-rollup contract on Eth1 effectively use Eth2 as a bridging availability guarantee provider? If data availability cannot be guaranteed during execution (ie, verifying the SNARK proof and updating the state root), you end up with a plasma-like zk-rollback system. Although this system can greatly improve TPS, it will introduce complex trade-offs and need to deal with operator challenges and exit mechanisms like plasma. In an availability challenge, anyone can contribute data to prove availability, so it's not clear that putting data into a bridged Eth2 shard would make things easier.
Now with another version of zk-rollup, 500 TPS zk-rollup, everything is much easier. There is no longer a need for a designated operator, anyone can act as a relay at any time and generate SNARK proofs to update the state. In fact, data availability guarantees are always accompanied by state updates, which means that there is no need to deal with operator challenges and exit mechanisms like plasma. But this requires both execution and data availability to happen in the same transaction, which unfortunately we cannot do with a bridged availability engine. In other words, bridging is sufficient for a fraud proof system like zk-rollback, but not enough for a validity proof system like zk-rollup. The conclusion is that in order to simplify the validity proof on Layer 2, an important function that the availability engine on Layer 1 needs to have is to ensure that the availability of data and the execution of state transitions happen together atomically.
Perhaps we shouldn't be surprised by this realization. If data availability alone (without execution) was useful, no one would argue that Phase 1 started just to ensure the availability of a bunch of non-zero blobs (binary large objects), and no one would complain about having to wait for Eth2 to come in The next stage will really come into play (besides PoS). We're working on Phase 1 as the data availability engine, but it still doesn't do anything, so it's disappointing. (Wow, we can build Mastercoin 2.0!)
So why does Phase 1 conflict with execution? Well, assuming stateful execution, each shard maintains some local state. Validator shuffle is much more complicated if validators need to maintain a lot of local state. Conversely, if there is no implementation, don't worry about local state. Validator shuffle would be much simpler, we could focus on building shards with data blobs, and start shards faster.
However, let's not assume that the execution is stateful. What if we try to do it with a very simple stateless virtual machine?
Suppose there are 3 new validator fields in the beacon chain state: code, stateRoot, and deployedShardId. There is also a function process_deploy (just below process_transfer). Once the code is deployed, the verifier must ensure that the account balance does not fall below a certain threshold [at least 1 ETH is locked. If there is no self-destruct program (SELFDESTRUCT) in the code, then this part of ETH is equivalent to being destroyed, and the code will be permanently deployed].
Now, let's assume that there are already some accounts with codes in the global state.
Next, we try to pack specific data blobs onto shards, but how? As far as I know, it is still an open question for phase 1 shard validators to decide which data blobs to pack into shard blocks. Assume this is not detailed in the phase 1 specification. Then, for users, if they want to pack their own data blobs into shards, there are only two ways: (1) contact the verifier, and send to Its payment; (2) Become a verifier yourself, and you can (when they are randomly selected as the block proposer of the shard) pack the data blob onto the shard. Both of these methods are bad ideas.
A better approach is to bring things to the table and allow validators to pay the current block proposer through a transaction agreement. In exchange, the block proposer packages the validator's data blob onto the shard chain. However, this approach does not work if beacon chain block operations (such as validator transfers) have minimum capacity requirements. The "phase 1 as data availability engine" use case would not be possible without a transactional protocol that would allow validators to prioritize data blob packing (whether it's an eth1 contract connected via a bridge to the beacon chain, or a Truebit , Mastercoin 2.0, or other data availability use cases I’ve heard of before). Anyway, let's assume that no matter how the shard proposer packs data blobs in the "Data Availability Engine without Execution" mode, it can also be in the "Data Availability Engine with Simple Stateless Execution" mode. do it.
Alright, so let's say that certain data blobs can be packed into blocks. Each block restricts execution to one transaction (eg, the entire data blob must be included as one transaction). We have not yet clarified whether the transaction will be signed with a key (there is a transaction agreement), or it will not need to be signed (there is no transaction agreement). Assume the latter, and the code implements its own signature checking (similar to an account abstraction; there is a block gas limit, but no fee transfer mechanism, so no gas price and no GASPAY opcode). If the blob can be successfully decoded as a transaction, the target account code is executed with the data and the current state root as input. If the execution is successful, the return data is the new state root.
How do we update the stateRoot of the validator account? We cannot update the state root in the BeaconState (beacon chain state) of each shard block (because the number of beacon chain operations is strictly limited). However, the fragmentation field in the state of the beacon chain will be updated with the crosslink. Take the updated state roots of all accounts on the same shard, assuming that they are hashed to get shard_state_root (shard state root). shard_state_root seems similar to the crosslink_data_root already in the phase 1 design (both depend on the hash of the previous shard block content).
Admittedly, not all shard state roots are updated every time a beacon chain block is mined, so there is some local state. However, if the account is global, the state root data is minimized. This is similar to the need to transfer some shard block data between validators during a shuffle.
Of course, many details are omitted here. What I'm trying to convey is that most of the requirements for stateless execution seem to be met in phase 1. In my opinion, the biggest problem is that it is not yet clear how users can package their blobs on the chain (if this problem is not solved, phase 1 cannot be a bridge usability engine). Perhaps this is just the first problem, and there are other serious problems that I have overlooked. What am I missing? What is the hardest part about allowing users to somehow package blobs on-chain in phase 1 (or phase 1.1, if you like)?


