Progress on Ethereum 2.0, Phase 2 continues to move forward. The following is an update on progress to date. Most of the work around phase 2 has been a collaboration between the Ethereum Foundation Ewasm team and Quilt.
Many of the sections are generally orthogonal to each other, so feel free to only read the sections you’re most interested in. Before diving into this writeup, I highly suggest you follow these resources for an intro or background on phase 2 and execution environments (EEs):
Protocol Changes Affecting Phase 2
Vitalik Buterin has released a number of proposals or pseudo-proposals since April of this year. After iterating on these ideas, the current direction remains fairly stable. The original proposal first introduced the concept of Eth 2.0 Execution Environments (EEs) which have now been discussed at length within the ecosystem.
Vitalik’s second proposal is a refinement of the first and solidified Ethereum 2.0 as a stateless protocol (for an introductory explanation of statelessness, this blog post has a section titled, “Shard Chains Don’t Need State”).
The current phase 2 design space has not diverged significantly from this second proposal. To give a bit of history, a partial proposal did circulate after that introduced the concept of load balancing on the beacon chain. It suggested treating each shard as a pure computing process, allowing for EEs to dynamically run on pre-determined shards. In essence, it load balanced computation to the shards through a load balancing contract defined on the beacon chain. It is worth mentioning that this general design space is quite interesting and can accomplish various models of synchronous transactions across shards via coordinated relayers. It deserves more exploration and the tooling could be added to the beacon chain at some point in the future (after launch?) if promising.
Finally, Vitalik shared a proposal during Devcon 5 to simplify Phase 0 & Phase 1. This proposal does not change the root of Phase 2 but instead intends to strengthen the developer experience around Phase 2. One of the circulating complaints during Devcon 5 focused around a lack of cross-shard composability (which lead to a response from Vitalik). The new proposal enables cross-shard communication in one block. Previously, it required waiting for crosslink approval (6 minutes). As a result, if your funds or state is fragmented between different shards, it’s fairly trivial to bring those to a shard you need (you only wait 6 seconds). Furthermore, the proposal makes ETH more enshrined. It provides an “operating system” which gives the protocol the ability for shards, execution environments, validator accounts, and block producers to pass ETH between each other across shards with a one block latency. This results in a simpler fee market or gas market and removes some of the centralization concerns around the older fee market proposals (more on this in another section).
We’ve made significant progress on prototyping and building early Execution Environments. First, we needed to validate whether an Execution Environment would even work in a stateless model. Would the required proofs/witnesses be too large? Would the time to execute using a proof be too expensive? To answer these questions, we built a number of Execution Environments and used those to explore these questions further, but first, we needed an execution prototyping engine: Scout.
Scout is an Ethereum 2.0 Phase 2 execution prototyping engine (originally developed by Alex Beregszaszi). It builds a wrapper on the Ewasm API to allow for prototyping and benchmarking of Execution Environments. There is also an assembly script and C++ port.
EEs — Eth1 Related
In order to support the eth1 switchover into eth2, we’ll need to build eth1 as an EE in eth2. Main challenges in the switchover include converting eth1 to a stateless model and bringing the EVM and transaction/account model into an execution environment. The EEs described below are precursors to the eth1 EE. A recent working group has formed to ramp up efforts around building the eth1 EE. They have put together an initial plan to guide efforts and have kindly introduced themselves on eth research.
The first prototype of a stateless token EE aimed at mimicking Eth 1.0’s model. It used parity’s libraries for the eth1 trie (Hexary Merkle-Patricia) and RLP. It also included a basic relayer implementation to generate multiproofs for a transaction set.
Benchmark: 70 Transactions and 5,000 accounts/leaf nodes
Time: 5 seconds
Proof Size: 235 kb
Both execution time and proof size needed significant improvement but progress was shown through early results. One of the issues revolved around compiling Parity’s rust-based libraries to wasm. It resulted in far too many memcopy operations and other inefficiencies. In general, compiling rust to web assembly has shown to have a number of gotchas and difficulties. Additionally, signature verification made up 4 seconds of the total 5 second time period.
Turbo token utilizes turboproofs, which Alexey Akhunov originally investigated for eth1 stateless light clients. It provides a performant way of generating, merging and serializing multiproofs for the eth1 trie and supports efficient single pass updates on the trie. Casey Detrio and Sina built an initial single-branch prototype in assembly script and rust to verify decent performance could be accomplished. After initially accomplishing positive results on a single branch, Casey produced a simple, minimal turbo proof token EE in assembly script. Sina Mahmoodi forked this implementation then ported Guillaume’s comprehensive rust turbo proof library and generator into typescript.
Benchmark: 70 Transactions and 5,000 accounts/leaf nodes
Time: 140 ms
Proof Size: 50 kb
Execution time and proof size improved significantly from the SMPT prototype. Additionally, signature verification dominated 105 ms of the total benchmark time. Benchmarks from Casey Detrio, suggest the 105ms can be reduced to ~1/3 the time through further optimizations of signature verification. As can be seen, 5,000 accounts does not represent a real world value like the current # of accounts in the eth1 trie. Sina is now working on expanding the benchmark for this EE to run on a real life workload.
We need to build an EVM interpreter (web assembly) in an execution environment to support the eth1 EE. Hugo produced an initial prototype with tests around an add and mul256 contract. To advance the current prototype further, more contracts and benchmarking will be introduced.
All the experimentation above is intended to lead to an implementation of the eth1 execution environment. We can already begin prototyping it, but a number of performance concerns still need to be reviewed. As mentioned above, a recent working group has been established to hyperfocus on building the eth1 EE and making eth1 stateless.
Execution Environments — Eth2 Centric
In general, this section describes execution environments which are not necessarily focused on the eth1-> eth2 switchover. Eth1’s account and transaction model should be iterated on for a new account based execution environment in eth2 since the transaction, account and accumulator models eth1 uses is not optimal. Additionally, other EE models should be explored such as optimistic rollups, ZK rollups and more. The design space for eth2 EEs is wide open, and the following are early ideas and prototypes.
Paul Dworzanski’s implementation in C for a stateless merkle token uses a binary trie (not sparse). It uses a unique multiproof format for optimal memory layout on both the verification and the update of the trie. The update and verification is all done in a single pass (avoids memcopy and duplication) and can most likely be adapted to the eth1 hexary trie if needed. It is unknown, however, whether the update algorithm could be applied to the eth1 trie (since eth1 based models typically utilize multiple passes).
Benchmark: 2²² accounts and 40 accounts in the proof
Time: 20 ms (no signature verification)
Proof Size: 25kB
At this time, this implementation is the most performant. The benchmarks did not include signature verification, but we may only expect a ~30ms increase. There are a number of ways to optimize further. We may decrease the time and size by caching hashes and proofs. Adaptive hash length (the hash length would increase as the network grows) could also decrease the proof size further. Finally, the time could be decreased by using a better hashing implementation.
ZK rollups is a layer 2 scaling mechanism which does not require complex exit games or lockup periods (UX issues that plague existing L2 solutions). As compared to other token-transfer techniques we have explored, ZK Rollup requires significantly reduced data-availability requirements. The implementation utilizes web snark— a wasm generator for needed snark verifications and other pairing functions. In order to build the EE, Jared adapted from websnark to create a standalone wasm library for verifying Groth16 proofs. It’s an early prototype and work continues on this EE.
Sheth is a precursor to the eth2 contract EE (eth1 but iterated model which is more wasm/eth2 centric). Sheth is based on the simple serialize (SSZ) spec used for eth2. It uses a sparse merkle tree and an alternative format from turboproof’s opcode approach to manage in place read, writes and updates. Devised by Diederik Loerakker, it operates by storing a list of offsets which determine how to traverse the tree appropriately. The advantage of a proof being sparse is that you can statically define at compile time the general index of data you’re referencing. It also drastically simplifies the logic needed to update the state since nodes are never deleted or inserted but comes with its own set of tradeoffs (higher degree of hashing). Sheth also includes a command line client which acts in the capacity of a relayer or state provider.
Benchmark: 50 accounts and 50 transactions
Proof Size: 517 kb
The current implementation takes up too much space (517 kb is quite a bit!) and is slower than we would like to see . The size can be drastically reduced by removing zero padding or de-duping the amount of zero hashes. The speed should be improved by introducing host functions to manage 256 bit operations (as described in a subsequent section) as well as needed code optimizations. Diederik Loerakker has opened a new issue on how to make this design more performant. In general, using a sparse tree is going to be heavier on hashing and its effects can be seen from the initial benchmark.
SimpleUmbrella — Eth2 Smart Contract EE
The eth2 EE is a stateless smart contract execution environment. It runs smart contracts similarly to the eth1 EE, but the contracts are Wasm centric (not EVM). Additionally, it will likely support alternative accumulators vs. the hexary patricia merkle tree used in eth1. Sparse Merkle trees show promise, but further benchmarking is needed in order to make a concrete decision. Matt Garnett put together an early specification of how an eth2 EE would spawn runtimes and share callee/caller data in its child contracts. An early implementation of this EE gave ideas on a general API or set of host functions. More recently, we built a prototype of host functions, in response to a recent discussion, needed to spawn or execute child contracts within the eth2 EE. A new repository has been opened and we’ll be running basic smart contracts soon!
Ewasm — Interpreters, Compilers and Metering
This topic encompasses a significant amount of work from the Ewasm team over the last few years. During Devcon 5, the team gave a clear, data-driven explanation on the current and future state of Ewasm related work. I highly recommend watching the entire video if this topic sparks your interest. Below, I include a very brief summary. Additionally, Maksym also included a strong overview of what the Ewasm team shared at the Wasm in the Blockchain conference.
If we are aiming to launch eth2 as soon as possible, moving forward on compilers could be a risky decision. One of the difficulties or unknowns centers around managing JIT bombs (which have been found through fuzzing). Single pass compilers may help avoid JIT bombs, but there is general concern around the stability and safety of current single pass compiler implementations. Introducing compilers in the future as part of eth2 will likely make sense, but if we are looking to launch quickly, interpreters appear to be a safer choice.
Casey Detrio and Alex Beregszaszi’s portion of the Devcon 5 presentation gives a really comprehensive analysis on interpreter performance. Interestingly enough, near-native performance has shown to be achieved with optimized interpreters and well written code. As an exercise, Casey evaluated the performance of various pairing and hashing functions (websnark) using a wasm interpreter mixed with host functions for 256 bit math operations (Bignum library). Results were impressive and came close to native and optimized compiler speeds. In a number of his benchmarking operations, he also found the fastest interpreter was wabt.
Paul Dworzanski covers this topic at depth in his Devcon 5 presentation. In order to accomplish metering,
use_gas calls would be injected into wasm bytecode as the wasm contract is deployed and validated (whether it is an EE or part of an umbrella EE described in the EE section). The complexity of this injection and verification would of course have an impact on the cost of deployment for the contract. Current benchmarks show a range of a 1.04–2.4x slowdown on wasm code after the metering has been injected. Better pattern matching for the injection process and register assembly are suggested ways to optimize further.
Phase 1 and 2 Prototype in Lighthouse or Phase 2 Simulation
We wanted to simulate how a phase 1 and 2 client would actually end up being built and how we could support the implementing teams. We also wanted to use this work to simulate and benchmark execution environments in a more real world scenario across multiple shards. During Devcon 5, I shared a presentation on a simulation we constructed. We built/added a very simple phase 1 prototype into Lighthouse (without networking) and plugged in a phase 2 Ewasm runtime in the client. We interfaced with Sheth (which acted as a relayer and state provider) and were able to simulate basic EE or token transfer calls in Lighthouse.
Since the Lighthouse client is under active development, we realized maintaining and building further on a fork of lighthouse would likely be a bigger effort than we originally foresaw. In turn, we decided to take the learnings of the initial prototype and build an abstracted, stubbed version into Scout. We will still simulate the beacon chain and shard chains, but we will be able to drastically simplify the logic while focusing more attention on execution environment research and benchmarking across shards. This work is being managed by two new members of the Quilt team.
Relayers, State Providers and Fee Markets
John Adler wrote an extremely comprehensive review on this topic. His article also gives an interesting history and evolution of eth2 proposals. To summarize, the newest phase 0 & 1 proposal from Vitalik actually remedies a lot of the issues we originally saw in the relay model. However, we still have a number of questions around how state providers will send transactions to block producers and how block producers will merge transaction packages into a proper multiproof. One suggestion is to have a proof merging script deployed with new execution environments.
Furthermore, incentive schemes around state providers need to be defined. Zsolt shared his research around incentives during the first light client task force call (recording here). The eth1 EE working group is also evaluating a state provider network and has looked at prior work on Beam Sync as a model.
Finally, relayers or state providers would inherit the RPC endpoints web3.js or ethers.js connect to. Building a set of standards on how these operate across multiple EEs will be important.
Cross Shard Transactions
Asynchronous Cross Shard Transactions
Vitalik’s latest phase 0 & 1 proposal actually brings good news regarding cross shard transactions and composability. In the new proposal, a cross shard call has a latency of 1 slot (6 seconds), while in the past it required waiting for finality (12–18 minutes latency). As a result, moving your state or eth between shards should now be quick. Before the new proposal, we evaluated optimistic roots as a method to speed up calls, but found these schemes to be fairly complex.
From the perspective of a dapp developer, cross shard calls simply follow asynchronous paradigms and model methods of programming across threads. When writing a smart contract, the HLLs (Solidity) and DSLs (Vyper) will need to provide the necessary tooling to abstract cross shard behaviors to asynchronous models. The models will most likely follow:
- Simple Asynchronous Calls (async await, callback, etc.)
- Message Driven Approach (Actor model)
- Two Phase Commit (Atomicity)
- Locking — Read/Write (Contract Yanking)
Building support for these models into the EEs or at the lower level of contracts needs further investigation. The simulation described above (or orchestration tools below) should give us the foundation to begin experimenting with these models, however, we would definitely state that this is an important area of research and would be excited if people got involved. At the lower level, providing pre-process and post-process behavior as described here may provide the proper framework for pausing execution within a contract and continuing it later.
Synchronous Cross Shard Transactions
Previously, Vitalik presented a post on state schemes. These are essentially on-chain layer 2 models where the shards are used as a data availability layer. These models (previously known as delayed state execution, lazy execution or shadow chains) served as the precursor to what is now known as optimistic rollups. Using multiple shards as a data availability layer for an optimistic rollup scheme gives synchronous cross shard calls. We should be building a prototype around this concept in the near future.
Additionally, if load balancing is introduced to the beacon chain, we can accomplish synchronous cross shard calls via coordinated relay markets. See “Protocol Changes Affecting Phase 2” section above for a more detailed explanation.
Do we even need cross shard calls?
Another perspective worthy of further research suggests the majority of eth2 should really skew towards state channels, optimistic rollups and zk rollups (when ready). In this approach, most of eth2 presents itself as a data availability layer and cross shard calls would only be necessary in the case of bridging between these schemes or exiting/fraud proofs. The rollups would still be defined within the boundaries of the eth1 or eth2 EE, however, the execution would only occur on-chain when a fraud proof needs to be submitted.
Phase 2 Toolchain or Orchestration Tools
To further our research, we suggest a toolchain which needs to be developed. As explained in the “Phase 1 and 2 Prototype in Lighthouse or Phase 2 Simulation” section, we are actively building a simulation to benchmark and run execution environments across shards. However, there are a number of additional orchestration or client tools we need to develop further in order to run smart contracts in an optimal way. This discussion specs out this tooling in more depth.
- Phase 1 & 2 simulation
- Truffle like test tool to run wasm contracts within an EE (eth1 EE or eth2 EE)
- Runtime environment to plug into phase 1 clients
- Authenticated multi-proof backend (clients to generate, merge and manage multiproofs)
- Wasm centric smart contract languages with cross shard tooling
- Relayer, state provider tooling which interfaces with web3.js (described in “Relayers, State Providers and Fee Markets” section)
Other Vitalik Phase 2 Contributions
These are other recent research posts by Vitalik that discuss phase 2 related topics that I did not link to directly in the rest of this writeup:
The eth1 -> eth2 transition
Yes, they could, but it wouldn't be the default and so far we've seen a strong norm in the community (and other…
Implementing cross-shard transactions
One of the requirements of phase 2 is the ability to move ETH quickly from one shard into another shard. Though…
De-risking Execution environments by adding value-holding EEs
TL;DR: I suggest creating a store of value Execution Environment that is only tasked with ensuring balances of ETH and…
Formalizing and improving eth2's approach toward finalization of invalid shard blocks
This post requires understanding the general approach of publishing a Merkle root of erasure-coded data and having…
On-beacon-chain saved contracts
This is NOT a new idea; it has existed in discussions for a long time. However, it seems useful to have a post…
Call to Action
If you are interested in helping out, please do get in contact with us or get involved. Join this telegram channel for updates or questions. We’ve made progress, but there is a significant amount of work left to do.
Finally, we’ll be kicking off a monthly call. The first call will be scheduled Tuesday, December 3, at 10 am Eastern Time.
We’ve made a lot of progress on phase 2, but there is definitely more work needed. Early numbers show significant promise and the recent expanded efforts (especially on stateless clients) is extremely helpful. We need benchmarks and prototypes around cross shard activity and also need to begin thinking about how smart contracts will be written in eth2 EEs. More concentration and focus around accumulators in a stateless system are crucial and will help bring current EE prototypes to be more production ready and performant. We also need to put more effort into better tooling for EE development. Finally, work around relayers, state providers and the incentives that drive them need attention.