DAPPCON 2025: Scaling Ethereum's L1 - Toni Wahrstätter

DappCon 2025 · June 2025 · 24:39

Toni Wahrstätter discusses scaling Ethereum's Layer 1, the base blockchain that rollups and other Layer 2 networks build on top of. The talk is framed, per its own title, specifically around the base layer's own scaling path rather than the Layer 2 ecosystem built on top of it.

Speakers

Topics

From DappCon 2025, hosted by Dappcon Berlin.

Transcript

Wonderful. Perfect. Hello everyone. My name is Tony. I'm with the Ethereum Foundation and today I want to use the opportunity to talk a little bit about scaling the L1. Scaling one has been a big topic in the recent months and I want to look particularly into the midterm future and especially into like a future some future hard forks and introduce two scaling EIPs based execution and block access lists both giving us um some more scale on the L1.

Before we get into the topic, let's first um set the stage for what this talk is going to be about. Today we can scale Ethereum using two levers. We have the gas limit and we have blobs. But today I want to only focus on the gas limit. So focusing on blobs um will be done in the next hard. we will ship puras and I want to focus more on the hard fork after puras namely on glamsterdam and what we could do to in glamsterdam to then significantly increase the gas limit on Ethereum um from 36 million to something like maybe 5x 10x that in general how to scale Ethereum there are different things we

can do um first of course some short-term things and this is basically involving client optimizations clients client teams are constantly working on their clients, optimizing things and we already saw um a um a gas increase from 30 million to 36 million and this was done without even um shipping some um core protocol feature. So clients are constantly improving their software and this then allows us to scale the L1. Midterm it's protocol changes. So, do we actually need to change the protocol in order to allow the gas limit to be raised even higher? And long-term, I just put CKVMs there. This is often like the the holy grail solution for um scaling Ethereum and more on the long

term. But again, my talk will now focus on the mid-term solutions. What can we do in the next in the next next hard fork and beyond in order to um allow validators to increase the gas limit? Just to put that into a timeline, we ship Fusaka by the end of the year. Then there will be the Glamsterdam hard fork next year and then the hard fork after that doesn't have a name yet. It will be something with Bogotaa, but the age is not um decided yet. So I want to focus particularly on what we can do by next year.

Perfect. So this is enough to kind of enough high level context to now get into the topic. I split it up in two parts. We have slot restructuring and we have parallelization. And the slot restructuring there are many different ideas what we can do in order to allow for more scale in the end. For example, we can do six second slots and then keep the gas limit as it is. there is this idea of um enshrined payload block separation that also kind of moves things around in the slot to allow for more time and relieve the critical path and then the late execution which I'm going to talk about and also um on the right hand side we can see

parallelization and the main idea behind parallelization is the introduction of block level access lists. Perfect. So let's get into the first part which is the late execution. If you look it up today, there is an EIP for it. It's 7886. Um I would say it's still a very early stage, but it feels like client teams have some consensus that we might want to do some restructuring of what we use the slot for and the late execution is one of those proposals. Um besides EPBS and the late execution, the concept is actually quite simple. So this is how the slot um looks like today. We have the proposer proposing the block at the

very early of the slot. So basically at second zero because of timing games we might see them proposing a little later. But in general they have to propose the block until second four because at second four here um uh at T4 um validators attest to that block. So if you propose your block after the after second four, you might not receive enough at the stations and the next proposal would just reorg your block out. And the late execution now basically just extends this red line here. What we want to do is we want to allow validators to attach to a block without this block um kind of risking of turning invalid because why do we need execution

before the at the station deadline today? The reason is very simple because blocks could turn invalid because of transactions they um contain. So for example, if I include a transaction that cannot pay the gas the gas fee or if I include a transaction that has a wrong nons, then the transaction is invalid and as a consequence the whole block would turn invalid. And this brings me to the challenging part here. So what how can we make sure that if validators attest to a block that the block will never become invalid anymore.

The rational behind this um behind this change is not only scaling um the gas limit but also giving CK provers more time to generate the proofs. Today uh CK EVM prover would need to generate the proof very early. So there's only time between the block propagation and the attestation deadline to generate the proof. Now by delaying at uh by delaying um execution so that we still attest but we can um use the full slot for um execution CK provers just have more time and today CK provers get quite close to real-time proving. So I think 90 90% of the blocks are already below the 12

second mark but they are far away from proving within like 1 to 3 seconds and this is kind of the challenging thing here and the idea behind the late execution is give provers more time to generate the proof right so we essentially go from um like 1 second two sec seconds that we have today for the whole execution to something around 8 seconds. So this allows you to not only kind of squeeze all the execution into the critical path um right before the attestation deadline but instead you can use the full block to execute the transactions and as already said we just um make more time

for CK provers to create the proofs. Right? So the question is how can we make sure that if a validator attests to a block that he has the certainty that this block will stay valid right because what we want to avoid is that validators attest to a block and suddenly the block becomes invalid which would mean the attestation is now facing or voting for invalid block and we would have to throw it away. This is how an Ethereum block looks today. It's actually very simple. It's the blockchain 101. You have a block that links to the previous block by containing the hash of the previous block. And inside the block, you also

have execution outputs. So I put for example the state route of my block into the block header. Execution happens and then in the end I compare that the execution output for example the output that I get from my stage matches to what I was referring to in my header. And now we need some um some form of um validation where the block doesn't commit to those execution outputs because if we commit to those execution outputs then this also means we need to execute in order to check that the execution was correct.

And the idea here is actually quite simple because we can just defer execution output fields. So instead of um a block committing to its own state route for example, the block can just commit to the state route of the previous block. So instead of checking state roots at the end of a block, so after executing all transactions, we can check that up front but for the previous block. And this is a very simple trick how to make um how to already introduce this delayed execution paradigm.

There's still one problem because um transactions can still turn invalid and what to do if a transaction turns invalid or becomes invalid and then the whole block would basically turn invalid too. And the trick here there are different ways how to solve this problem. But one of them is essentially we just ignore it. So we allow transactions to turn invalid which would mean a wrong nons for example no balance on a on the senders account and then the trick here is we just revert the entire blocks execution.

What does it mean? So a transaction is in a block it turns invalid and the proposer that built that block the execution output of the payload would would be completely reverted. This means you you as the proposer you would lose your math boost payment. You would lose all the money you got in that block through prior fees. So you have a very strong incentive to not ever generate uh create such a situation. If you still do then what happens is we have transactions on chain that are actually not paying. This is the this is the trade-off here. Um transactions could get on chain. They stay on the canonical chain. they become part of history and no one would have ever paid for those

transaction. And this is often referred to as the 3DA problem. And the argument here is um it might be fine, it might not be. But the argument is that if you revert the whole execution then the proposer has a big enough incentive to never create such a situation. Great. So the second part I want to talk about block level access lists. So block access they try to tackle the scaling pro the scaling um problem from a different angle by trying to um make block validation faster. Today it's super hard to parallelize transactions.

Um clients already do an amazing job in in on that front because they have some optimistic parallelization going on. So the average block on Ethereum today is quite well parallelizable. The problem is worst case blocks. A worst case block for paralization would look the following. You would have each transaction being dependent on the previous one. So transaction one writes to storage slot one in the rep E contract and the next transaction uses this updated value in its own transaction and so on. So transactions will basically create this long dependency chain.

And the goal for parallelization would be to allow transactions to be fully parallelizable. So this means if you have an infinite amount of cores, you could parallelize all of them, run all transactions at the same time, and you would end up with an execution time that is essentially the execution time of the worst transaction in your block. I put on the slide some 5 to 10x um speed um improvement. This is still to be analyzed if that's actually the case. Maybe it's more, maybe it's less, but this is somewhere where we um should land.

Furthermore, there is another argument to do something like block access lists because what we can do is we can basically include a full state into the block and this has other nice advantages. For example, for executionless nodes, imagine you're running a node that doesn't execute any transaction, but you still want to um stay a full node. So, you still want to have access to the full state. And then you can use the state divs that come within the block to update your state and then you get from the pre-state to the post state of the block without actually executing transaction. And this might be very nice in the future if we want to lower hardware requirements for certain types of nodes while still allowing them to act as a full um RPC

provider. There are other advantages like faster indexing. For example, if you have the balance changes directly inside the block, you don't rely on doing things like debug trace transaction to check what actually happened in the block. So you will have a way faster indexer. And there are other advantages like a speed up in the healing phase during sync or it helps having stative helps with aligning certain proposals like fossil. Fossil is an inclusionless design that is currently I would say the best um Ethereum has and fossil is kind of incompatible with some other with some other proposals like the late execution.

And if you want to make fossil compatible with the late execution for example, you might need something like a full state diff that comes in the block. So let's get into the topic of how transaction parallel parallelization would look like. So today this is a very naive picture of how transaction execution would look like today. You would start with some IO stuff basically loading information from disk that you need for all the transactions and then you would start executing.

The block would then look like the following. So this is a a gun chart of multiple transactions being executed. All of them need to first um do IO and then execution. Of course, we can already parallelize a lot today um through clients optimistic parallelization strategies, but essentially you can think of a block execution like the following. If every transaction relies on the previous one, you would end up with a picture like here. And now what we would love to see is essentially parallelizing them all. So executing transactions in parallel and saving time in execution.

Even cooler, we could also think of parallelizing between IO and execution. So allowing you to get a block, start executing executing without actually having to go to disk beforehand and then checking that the execution inputs you got are correct afterwards. And this brings me to the to this EAP 27928 block access list. Um in short buls are basically nothing else than an additional field that we would add to the header uh to the block. There is a bal hash in the header and in the block body we would put the block level access list in there which is essentially an

indicator what storage you are going to be t what storage is going to be touched in your block and also the values you need to parallelize the transactions if we have to include them in a block or not maybe it's better to do it in a sidecar this is still to be figured out but this picture already gives you a yeah a sense of how this could look back right in short um the block builder needs to include those files and we enforce that simply through consensus. So the block builder has to while building the block build also the block level access list and then put the block level access list into the block. So for the block builder this is not that much work actually but

for the validators it's it's very very helpful. So some work offloaded to the block builder to make the work of validators significantly easier. And then there are still many design choices. You might think, okay, what do I actually need in order to parallelize transactions? What you need is basically the values that you would find on disk, right? For example, in order to parallelize a transaction, you might want to know what is the balance of a certain wrapped Eve pool when my transaction will be executed. And then there are different ways to do so. I could give you the value the a transaction h um the value of the state after a certain transaction or the value

of a certain um state storage slot before a certain transaction. And this is already quite an interesting design trade-off because on the left hand side you can see if I give you the post transaction values which are nothing else than the pre-transaction values of another transaction then you can get to an execution time of parallel IO plus parallel EVM. On the right hand side, if I give you all the values you would find on disk for all the transactions in the block, then you wouldn't even need to go to disk before starting execution, which would allow you to execute and do IO at the same time and then just validate that everything was correct um async

during execution or something. The problem here is the worst case sizes. So if I have to give you all the values you would find um on disk then this means the worst case is basically a block doing a lot of S loads then um imagine a block with many S loads I would have to give you all the storage values on disk um that those S loads are going to read. So the worst case size of such a block would be 1.51 megabyte with the current gas limit right with 36 million. So if you scale that up by 3x, it scales quite linearly. You end up with a maximum possible block size of um yeah 4.5 megaby. And this is this is um this

sounds very bad. And it actually is very bad in my opinion because this is higher than the block size you get from a max call data block. So if you put as much call data into a block today, you end up at 1.4 1.5 maximal um call data. And here we are beyond that. So we would actually create a new worst case block by block level access list and this is why I prefer the left hand side and this is also the design that is currently in the EIP in 7928 um providing the post transaction values because if you only care about the post transaction values then we can ignore um s loads um entirely. You only need values that are actually changing disk.

And this is why the worst case size is reduced so massively. The worst case basically becomes a block that does a lot of sors and not s loads anymore. on this table you can see um many different designs being compared and I think especially the maximum block um the maximum size of that object is a very important metric to look at because of course um if we add like another let's say 50 kilobytes to a block this is um of course adds another more bandwidth um requirements and this is then bandwidth validators could also use for including more transactions. So the question is the average B size would be

around 40 kilobyte and is that 40 kilobyte worth it the parallelization we get the efficiency improvements or should we actually just scale the gas limit without that and um have those 40 kilobytes of bandwidth that are a very limiting factor today just being consumed by more transactions in the block. And this brings me to the end of this presentation. I put some QR codes with um the most important links here onto this last slide. Um you'll find the EAPs um they are all updated so everything is up to date there and also to research posts um going a little bit more in depth into the into those topic because the design space um that we can actually um um we are working here is very big.

So there are many different design possibilities and yeah would love to receive feedback. So if everyone wants to contribute to those earpiece just reach out. I'm super happy for any collaboration there. Thank you very much. Yeah, thanks. We have time for questions. Okay, thanks for the talk. Very interesting. I have a question for the block level access lists. um the graphs that you displayed where like the optimal case that there are no shared access between the transactions. What would happen if I

have two transactions that access the same state? Would they then still be SQLized or would you just say it's not allowed that two transaction access the same state or Yeah. Um so it would be allowed and you can still parallelize them because for example let's let's do a simple example. Um my transaction touches the unis swap pool and your transaction reads the unis swap pool and based on the balance of that pool it can either go on this track or that track. Right? So you would actually rely on a value on state right before your transaction. So what the block level access list would contain here is the value of this pool after my transaction.

So for you when when it comes to executing your transactions, you have all the information um needed to execute your your transaction without relying on my transactions to be executed up front. So the cool thing is we you could take a block and execute it from the bottom to the top um knowing you will have perfect parallelization which means no transaction is actually dependent on another and you would still have um the guarantee that um all transactions are executed um yeah in a in a correct way. Uh so one of the things that solo

stakers are worried about is um high bandwidth requirements right now and um one of the ways that uh EPBS is being sold to solo stakers and they're like really buying into it is increased time for execution which um spreads the bandwidth over u that time a little bit lower uh and lowers the peak bandwidth requirement. Um is delayed execution uh compatible with that an alternative with that? What where does that fit into EPBS? Yeah, it's a good question because EPBS has many advantages when it comes to broadcasting the block. So you get way more time um for propagation. The late execution would give you something very similar because today the at the station deadline is at second six. So what we can then do with the late

execution, we could just move it to uh at second four is that at the station deadline and we could just move it to second six for example. If we want to make blocks bigger, we might need more time um to for propagation because bandwidth requirements would increase for bigger blocks and then you might just move the attestation deadline a little later into the slot which would mean the critical path here would just grow and then you could still keep the aggregation and everything as is today. But yeah, it's a good question because bandwidth seems like bandwidth is a very big constraint for many solo stakers today and then it's we we have to be really careful especially for block exist for example introducing some

additional size. We have to really um yeah look very careful at this trade-off of size versus parallelization. And for delayed execution you would not really need um additional objects in the block. you would just have the p this payload reversion mechanism that I that I described and then the propagation shouldn't be a problem. Sorry. Sorry. We don't. Yeah. Thank you, Tony. Thank you.