New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Scaling Ethereum's L1

DappconThu, Jun 19, 2025, 11:54 AM · 24:38

by Toni Wahrstätter

Transcript

Wonderful, perfect. Hello, everyone. My name is Tony. I am with the Affirm Foundation. And today, I want to use the opportunity to talk a little bit about scaling year one.

Scaling year 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 EAPs, namely the late execution and block live access lists, both giving us some more scale on the L1. Before we get into the topic, let's first set a 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 blocks. But today, I want to only focus on the gas limit.

So, focusing on blocks will be done in the next hard fork. We will shift PeerDos and I want to focus more on the hard fork after PeerDos, namely on Glamstadam and what we could do in Glamstadam to then significantly increase the gas limit on Ethereum from 36 million to something like maybe 5x, 10x. In general, how to scale Ethereum, there are different things we can do. First, of course, some short-term things and this is basically involving client optimizations. Client teams are constantly working on their clients, optimizing things and we already saw a gas increase from 30 million to 36 million and this was done without even shipping some core protocol feature.

So, clients are constantly improving their software and this then allows us to scale the R1. 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 CKBMs there. This is often like the holy grail solution for scaling Ethereum and more on the long-term.

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

Perfect. So, this is 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. At 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 enshrined payload block separation that also kind of moves things around in the slot to allow for more time and to relieve the critical path. And then the late execution, which I'm going to talk about. And also on the right-hand side, we can see parallelization. And the main idea behind parallelization is the introduction of block-level access lifts.

Perfect. So, let's get into the first part, which is the late execution. If you look it up today, there is an EAP for it. It's 7886. 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 besides EPVS. And the late execution, the concept is actually quite simple. So, this is how the slot 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 at T4, validators attest to the block. So, if you propose your block after the second four, you might not receive enough attestations and the next proposal will just reorder 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 attest to a block without this block kind of risking of turning invalid.

Because why do we need execution before the attestation deadline today? The reason is very simple, because blocks could turn invalid because of transactions they contain. So, for example, if I include a transaction that cannot pay the gas fee or if I include a transaction that has a wrong nonce, 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, how can we make sure that if validators attest to a block, that the block will never become invalid anymore?

The rationale behind this change is not only scaling the gas limit, but also giving CKProvers more time to generate the proofs. Today, CKEVM Prover would need to generate the proof very early. So, there is only time between the block propagation and the attestation deadline to generate the proof. Now, by delaying execution so that we still attest, but we can use the full slot for execution, CKProvers just have more time. And today, CKProvers get quite close to real-time proving.

So, I think 90% of the blocks are already below the 12-second mark, but they are far away from proving within like one to three seconds. And this is kind of the challenging thing here. And the idea behind the late execution is to give Provers more time to generate the proof. Right. So, we essentially go from like one second, two seconds that we have today for the whole execution to something around eight seconds.

So, this allows you to not only kind of squeeze all the execution into the critical path right before the attestation deadline, but instead, you can use the full block to execute the transactions. And as already said, we just make more time for CKProvers to create the proof. 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 an invalid block, and we would have to throw it away.

Right. 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 root of my block into the block header, execution happens, and then in the end, I compare that the output that I get from my state root matches to what I was referring to in my header. And now we need some form of 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 a block committing to its own state root, for example, the block can just commit to the state root 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 already introduce this delayed execution paradigm. There's still one problem, because 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 nonce, for example, no balance on the sender's account. And then the trick here is we just revert the entire block's 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 be completely reverted.

This means you as the proposer, you would lose your mass boost payment, you would lose all the money you got in that block through priorities, so you have a very strong incentive to not ever 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 trade-off here. 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 transactions. And this is often referred to as the 3D problem, and the argument here is 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-level access lists, they try to tackle the scaling problem from a different angle by trying to make block validation faster. Today, it's super hard to parallelize transactions. Clients already do an amazing job 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 parallelization 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 wrapped-if 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 speed 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 should land.

Furthermore, there is another argument to do something like block-level access lists, because what we can do is we can basically include a full status 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 stay a full node. So, you still want to have access to the full state, and then you can use the status that comes 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 transactions. 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 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 transactions to check what actually happened in the block. So, you will have a way faster indexer. And there are other advantages like speed up in the healing phase during things, or having status helps with aligning certain proposals like Fossil. Fossil is an inclusionless design that is currently, I would say, the best Ethereum has.

And Fossil is kind of incompatible 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 status that comes in the block. So, let's get into the topic of how transaction 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 disks 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 Gantt chart of multiple transactions being executed. All of them need to first do IO and then execution. Of course, we can already parallelize a lot today through 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 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 EAP-27928 block-level access list, in short, BALs.

BALs are basically nothing else than an additional field that we would add to the header, 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 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 sense of how this could look like. Right.

In short, the block builder needs to include those BALs and reinforce that simply through consensus. So, the block builder has to, while building the block, build also 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 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. For example, in order to parallelize a transaction, you might want to know what is the balance of a certain wrapped ETH pool when my transaction will be executed. And then, there are different ways to do so. I could give you the value of the state after a certain transaction, or the value of a certain 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 disk, 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, 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 on disk, then this means the worst case is a block doing a lot of S-loads. Then, imagine a block with many S-loads.

I would have to give you all the storage values on disk that those S-loads are going to read. So, the worst-case size of such a block would be 1.51 megabytes with the current gas limit, 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 4.

5 megabytes. 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 call data, and here we are beyond that.

So, we would actually create a new worst-case block by block-level access list. This is why I prefer the left-hand side, and this is also the design that is currently in the ERP, in 7.9.2.8, providing the post-transaction values.

Because if you only care about the post-transaction values, then we can ignore S-loads entirely. You only need values that are actually changing disk. This is why the worst-case size is reduced so massively. The worst-case basically becomes a block that does a lot of S-stores and not S-loads anymore. On this table, you can see many different designs being compared, and I think especially the maximum size of that object is a very important metric to look at, because, of course, if we add like another, let�s say, 50 kilobytes to a block, this is, of course, adds more bandwidth requirements, and this is then bandwidth value that this could also use for including more transactions.

So, the question is, the average file size would be around 40 kilobytes, and is that 40 kilobytes worth it, the parallelization we get, the efficiency improvements, or should we actually just scale the gas limit without that and have those 40 more transactions in the block? And this brings me to the end of this presentation. I put some QR codes with the most important links here onto this last slide. You find the EAPs. They are all updated, so everything is up-to-date there, and also three research posts going a little bit more in-depth into those topics, because the design space that we can actually � 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 EAPs, just reach out. I�m super happy for any collaboration there. Thank you very much. Thanks. We have time for questions.

Thanks for the talk. Very interesting. I have a question for the block-level access list. The graph 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 equalized, or would you just say it�s not allowed that two transactions access the same state, or?

Yeah, so it would be allowed, and you can still parallelize them, because, for example, let�s do a simple example. My transaction touches the Uniswap pool, and your transaction reads the Uniswap pool, and based on the balance of the 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 it comes to executing your transactions, you have all the information needed to execute your transaction without relying on my transactions to be executed up front.

So, the cool thing is, you could take a block and execute it from the bottom to the top, knowing you will have perfect parallelization, which means no transaction is actually dependent on another, and you would still have the guarantee that all transactions are executed, yeah, in a correct way. So, one of the things that solo-stakers are worried about is high bandwidth requirements right now, and one of the ways that ePBS is being sold to solo-stakers, and they�re, like, really buying into it, is increased time for execution, which spreads the bandwidth over that time a little bit and lowers the peak bandwidth requirement. Is delayed execution compatible with that, an alternative with that? Where does that fit into ePBS? Yeah, it�s a good question, because ePBS has many advantages when it comes to broadcasting the blocks, so you get way more time for propagation.

Delayed execution gives you something very similar, because today the attestation deadline is the second six, so what we can then do with delayed execution, we could just move it to a second four, if that�s the attestation deadline, and we could just move it to second six, for example. If we want to make blocks bigger, we might need more time 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 solar stakers today, and then we have to be really careful, especially for block-led accesses, for example, introducing some additional size. We have to really, yeah, look very careful at this tradeoff of size versus parallelization, and for delayed execution, you would not really need additional objects in the block. You would just have the payload reversion mechanism that I described, and then the propagation shouldn�t be a problem.

Sorry, we�re done. Yeah. Thank you, Tony. Thank you.

Automatic transcript — names and jargon may be misspelled.