FOCIL Breakout #10
FOCIL Breakout · 6 May 2025 · 40:08
FOCIL Breakout #10, held on 6 May 2025. FOCIL, or fork-choice enforced inclusion lists under EIP-7805, is a proposal to make it harder for block builders to censor transactions. These breakout calls cover the spec, client work and testing.
Topics
From FOCIL Breakout, hosted by Ethereum Foundation.
Transcript
[Music] Hi everyone. Thanks a lot for joining the Fossil breakout number 10. Um, and I'm excited because today we have two good presentations that were prompted in the in the Discord uh I think by Mark. Um and we end up having like exactly the two presenters to that are like the most experts are present at pres for presenting these things. So it's pretty cool. Um but just right before we dive in, I wanted to make a small announcement that there is going to be a lot of things happening in Berlin uh in
June uh including a session that's like dedicated to Fossil. Um, for now it's it's very tentative tentative and it can change a lot but it's scheduled on Wednesday Wednesday the 11th in the afternoon. So if any of you guys that have been attending the calls are around um if you're core dev or dev or researcher just um that is like really working on on fossil just you're always welcome to join and uh if you want to join just like send me a message or something and we'll make it happen. Uh but yeah, more more generally I think a lot of things are going to happen around like Etherum related things uh in Berlin
in June. Uh so yeah, if you're around um let me interested uh know. Um and yeah, I think the for session will basically focus be focused on like present everything that's um been done on the implementation and research side around Fossil and maybe since we are like all together in person uh just try to get some consensus about like the future directions where we can take fossil uh and uh and yeah both in the research and in the implementation side. I think
at some point we need to sort of like be explicit or like make an actual push about like what fork we would want for soul to land on. Uh we haven't really done that yet. Uh, and I think it it shouldn't always be top of mind, but it maybe, yeah, I've been thinking some maybe more more intentionality would be nice at some point when we feel like full is like close to the end and we have done a bit more tests. Um, I think at some point it makes sense to also like say it. Uh, that we've been doing that. So because I feel like some people I don't know I was just asked recently um by someone that's like still in that
core dev and everything like is how yeah how is fossil doing on the research side of things. I was like, "Oh, uh, yeah, it's been done on the research side basically for like a long time now and we have like devets and intro working." So, it's much further than than what people at least some people think. Uh, so yeah, I think we should uh maybe talk about this a bit more. And then on the research side you have like you know GK fossil uh uh stateless for um and then everything that's going to be talked about today which is also extremely interesting is like how fossil interacts with other upgrades or forks or yeah I
mean not not forks but upgrades or proposals or EIPs. Um and uh so we have Tony and PUS. Tony will talk about uh Fossil and Delayed Execution. Um and yeah, uh then Pus I I don't think he's there yet. He told me he was going to be a bit late maybe, but once he but once he joins he's going to talk about for and EPBS. And it's kind of interesting because I feel like delayed execution and EPBS are like somewhat um in competition. So we can also like um see talk about like the advantages and pros and cons for both approaches. And I
think that's also like an interesting uh angle to to like look at both presentations. Um, so yeah, if you want to go Tony, I I think I saw you. Um, we'll start with you if that's okay. Yes, sounds good. One second. Okay, I created some slides here. Perfect. Yeah. Um the late execution and fossil,
right? So initially it started a little more complex because the late execution and fossil initially if you remember the the initial design they were not really compatible and we kind of worked a lot with Tomar to in order to to kind of get to a solution on that and today I kind of think we can present a solution that works that makes Fossil very well compatible with the lead execution and this is basically what I'm going to talk about in the following presentation.
Just as a quick recap. So what is the late execution? Let's look at block validation today. Um at t0 the block proposer proposes the block um that the station headline is at 4 seconds into the slot and then at some point the next proposer needs to run fork choice in order to determine which headlock to build on top of. And I have now just split up the first part until the um attestation deadline between propagation and execution. And with execution I mean both so beacon block checks plus the EL payload checks.
And what delayed execution is now trying to achieve is the following. We just extend the execution time. So instead of um having to finish execution at the at at the at the station deadline, you can just um execute um during the whole slot, this gives you way more time and hopefully we can scale the gas limit or shorten the slot time or or something similar. Right? So this is the goal what um the late execution is trying to achieve and it works in the following. Today we we chain blocks together using the parent hashes and the execution outputs um commit to the to their own block. So we have post execution outputs the commit
to the execution of the same block and instead of doing that we get a picture like the following where instead of committing to the execution outbook out outputs of the same block we just commit to the execution outputs of the parent block. And this is kind of nice for CKVMs because it gives them more time for real-time proving and at the same time it gives us at the execution layer more scale. So just as a quick recap the initial design that some of you might still be familiar with was using the Coinbase for the inclusion cost and the inclusion cost was everything that um has to do with data. So call data blobs and the
access lists and the coinbase address had to pay for the inclusion cost before we even start execution. This means we check the block statically. Then we check has the Coinbase paid for the inclusion cost and if so attesters can attest to the block and can basically already delay the execution because they at that point have the certainty that the block they just attested to will become canonical or will be valid because um we did all the checks up front that could make the the block invalid.
If a transaction turns out to be invalid during execution, for example, because its balance was drained or the block is already full, we consumed all the gas available, then the transaction can simply be skipped. And this is not a problem because someone already paid for that transaction. So it lands on chain, it becomes canonical, but someone had um paid for that transaction. So we don't have to worry. And yeah, as already said at at the at the station time, the validator does know that the block is valid. So they can attest to that block and it's not like they would attest to a block that suddenly after the attestation turns invalid and this had some problems with fossil because of course as you can see here at T4 we want to know is the block
valid or is it invalid and fossil comes with this postexecution validity condition when a transaction is not in the execution payload but it's on an ex and I then you have to check could that transaction could it have been included into the block. So you you have to try to append that transaction to the end of the block and this moves kind of the validity check of the execution payload to the end of the block because we have to check if a transaction could have been included. we have to do that at the end and this makes then no sense because then we would have to move that destation deadline to the same point and
then the whole delayed execution would not work. Um so a nicer way how how we can do so is by charging the senders of transaction up front. So we take the maximum that the transaction specifies the full gas limit times the gas price and we charge that amount up front before we start executing any transaction. This would then look like the following. Today on the left hand side we have the block validation which includes uh of static validation and transaction execution and we would take the charging the senders out of the transaction execution bucket and do it separately
before starting executing any transaction which means that if you have the funds to for to to send a certain transactions at the beginning of the block you will already reserve that gas and And you will always be able to send the transaction which means transactions cannot be invalidated anymore because of balance um trains and the um sender doesn't not having the money anymore. Right? and what we need to do for fossil, how to make this fossil compatible because this doesn't really solve the problem of not knowing how much um gas the block um effectively consumes because now we only
know the block the transactions by the full gas limit they specify. So what we need to do here is we have to introduce a new header field where the builder has to specify how much gas um the builder is using. And by having that information what we can do is we can check could that transaction have been included into the block without actually um executing the whole block. And this would then look like the following. The builder declares the gas used in the header and then the fossil validators they can check the validity of the inclusion list by having the following the pre-state the set of transactions and the IL. So this is nothing new but then they also have a
new field in the header which says gas used and based on that they can determine um if a transaction could have fit into the block but it wasn't included because this would then again turn the block into an invalid block. And finally, if the gas used is then specified wrong by the builder, which would be some very strange 3DA attack, then the whole transaction payload would be would revert. So builders have a strong incentive to not do so because they would lose all the pre pries and yeah, basically everything in the block if every transaction reverts.
Yeah, this is all I have. Thanks a lot. Thanks a lot. Okay. Yeah, that was very clear at least to to me. Um yeah, there was a small question by Terrence. Um he said, "Do you want to run the fork choice also before you attest as well because you need to attest to to the head?" Uh yeah, that's that's of course true. I I meant um boxes of the next proposal basically.
Yeah. Okay, makes sense. Yeah, this could if you if you do a a weird 3DA attack on the builder side. Um, so you lose all the priority fees and for for the block. Uh, do you do you lose any CL reward or No, no, you would still get them. So, yeah, the block would still be valid and you could still attach to the block. It's basically an empty payload.
And things we can do is we could just skip the transactions of the payload but still have um deposits or withdrawal or other um requests being processed. Okay. Yeah, that makes sense. And then would penalties like additional penalties help like against this attack or is that do you think just like not getting the execution rewards is is enough for it not to happen? Yeah, I think it's enough. Of course, there is um I mean if if we want to talk about this worst case scenario, then this would be a block where the builder specifies a wrong gas used because if you specify a wrong gas used then the
block um the transaction payload will just revert which means all the transactions in that block will have paid nothing plus the builder would have not received anything. Those transaction would of course stay canonical, right? Because you cannot just drop them for reasons like you would need to check the validity of this state reversion. So you we would have to keep those transactions. You would also keep have to keep them for sync. But the thing is that it's just not really worth it to do so, right? Because you would just um you could just um let's let's assume there is some market that pushes you to do so. then this market would give you definitely less
than what you would get in prior fees otherwise the market um we would have some market inefficiencies. Yeah, that makes sense. Nice. Um cool. And then Lucash said the gas used in the block header means that the builder has to execute the block which can be viewed as sub suboptimal in a way. Yes. So the builder has to execute everything. The builder has to know exactly how much how much gas um the block is going to use and based on this knowledge. So validators in fossil they just trust that value. They they see okay the block consumed um 35 million
gas and 36 is available and there is a transaction in the inclusion list that consumes 2 million. So it doesn't fit. Then the fossil committee uh the fossil validators or the validators in general can just decide um they see okay this transaction um is too large and I will just trust um the specified gas used and not enforce the inclusion list which means I will attest to the block and not vote for the head block in order to reorg because of the um invalid inclusion list. And then after execution you verify was the specified guess used actually right and if it was right the block stays as it is
and if it wasn't it becomes a a no the state will just revert. Okay. Yeah that makes sense. Um cool. And then so yeah I think so I read your post just before the session. So I no I I think like with the presentation I understood it quite quite well. Uh but did the post was quite like about like listing all the options and then you finished with the one that was both compatible with withul and without like sort of like tons of additional fork choice complexity or like attestations
that will um that will vote for the right block but but like not actually get the rewards and stuff like this. Do you feel like in in your mind at least like is this the the solution that sounds like it makes the most sense or like have you sort of settled on on one that's that's best? Yeah, this is a good question. of course still um to be decided but to very quickly speedrun the whole um design space. We started with Coinbase sponsoring um where the problem was directly like we don't want to introduce new signatures on the E. probably this is a lot of work and users might need two keys withdrawal key and a signing
key on the EL because of course we don't want to have keys that handle funds being controlled by a hotkey. So this would create already a very complicated situation that requires some yeah that would change the UX for validators quite significantly. If you suddenly need to control a balance on the EL2, then of course we could say, okay, then we treat it as a penalty and instead of staking on the EL, you get a penalty for skip transactions on the CL. But then the problem is for meth boost users, you would sign a payload where you don't know what the payload is actually doing and the payload could actually skip many transactions and then you as the Coinbase, you would pay for or uh you as
the proposer, you would pay for that. So suddenly when you are using meth boost the worst case the the worst thing that could happen would not be getting nothing but actually even losing losing funds and yeah so the pre-charging some entity approaches were kind of um difficult for the just outlined reasons and then what we can do is pre-charging the senders because what what you avoid by pre-charging the sender is that one transaction sender drains ains the balance of another sender and they invalidate their transactions um within the block. Of course, one important point which is a big downside with this
approach is that um funding an account and sending from that account within one block becomes impossible. And this is also something that yeah is I I don't really like a lot. So maybe that's also not yet the final decision um design. Okay. Wait, can you can you just repeat? I lost you on the So if you if you if you um fund an account and you want to send from then account from that account in the same block, this is of course possible today.
But with the pre-charging all the senders and then starting execution, it wouldn't be possible anymore because at the time where we would pre-charge you, you would have a zero balance, right? Okay, that makes sense. Yeah. Yeah. Yeah. There are refunds after Yeah. Yeah. Okay. There are like refunds afterwards, but like since you actually charge like the full sort of like uh gas limit. Um, okay. Yeah, that makes sense. You could solve that by allowing the Coinbase to sponsor the base fee and stuff. But this just complicates the whole thing and is probably better to treat separately. So, this is definitely
an uh a thing that we might might need still need to solve. Yeah. one very vague comment before I let Mark speak, but uh I mean, yeah, I haven't looked into it. I always bring it up, but like I need to actually look at it way more. But what about like this sort of like idea of a reserve balance or something that would be used specifically from users to handle like um this problem? Would that help in in some way like sort of have like two balances?
Yeah, I think that wouldn't really help in this in this regard because here it's really about um an account that has no Eve but would be able to do a if he receives Eve beforehand, right? So there's no reserve balance if someone has no Eve. Yeah, but it's it's getting very close to this reserve balance idea already because what you do is you reserve the maximum possible fees for each sender before starting executing. Yeah. Yeah. Yeah, for sure. Okay, cool. That makes sense. Uh yeah, go ahead, Mark.
Uh yeah, I just wanted to clarify exactly how the inclusionless checks will look um with this change. I think you had the slide about like all the different kind of variables you have like the pre-execution state and all that kind of stuff. Um but so the checks now you're just looking at the gas used and the gas limit of the inclusionless transa transaction and just seeing if you have space. Uh so you don't need to execute anything. Right. Yeah. So you can see the slides now, right?
Okay. Yeah. So the the the four things are the pre-state. So you could basically check um is the transaction valid against the pre-state. So if you get a transaction on an inclusion list that it has a two low nons, then you can directly filter it out and not enforce it. Then you have the set of transactions that you receive in the block and you have the inclusion list that you saw um being propagated through the network. And then what you can do is you get the block you see the block has for example the sum of transactions that the the sum of the gas that trans that the transactions claim to use is
way above the gas limit. But the actual gas used can of course be lower. So what you would need to do is you look into the header into the gas used field in the header where the builder specified and commits to how much gas this block is going to use. And then if if the builder says the block is full, then you don't have to enforce the inclusion list because um Fossil allows you to yeah to keep the incl to don't enforce the inclusion list if the block is already full.
Right. Thank you. Great. Uh maybe a last one I think Luc you wrote in the chat may can you speak or do you want me to read it out loud? Uh not sure. So this so in general the the late execution could allow builders to um behave a bit more sequencer like uh so not to execute all uh blocks at all or maybe execute only some part of the block because for example me can
happen in the beginning of the block and they want to maybe validate that and then just add later transactions uh based on from from like the public mele without executing them and this would require for them to execute the whole block always uh which might be a valid trade-off uh so I'm not against it just just a a small tradeoff that uh builders can't because in general delayed execution allows builders to behave more sequencer-l like but with this they can't.
Yeah, this is interesting. I I think I if I if I got you right, I I agree with that. I'm just thinking what would be the problem here, right? Because what the builder would of course do, the builder would check the nons and the balance because then the builder can ensure that the whole payload will not revert. But as soon as the builder check the nons and the balance, he can throw that transaction basically into the block, if it's at the last index in the block, then nothing can really happen.
That's what you meant, right? So the builder could just Yeah. Even multiple transactions, right? With the late execution because if the transaction, you know, uh fails or whatever, it's the builder doesn't care too much. Uh especially for like low paying transactions, right? But the but the if the nons and the balance is is wrong then the block is still invalid. So that's what you would still check preestation. Preestation. Okay. But you're checking the nons and the balance compared to pre-state to the pre-state. Right.
So not like in between state of the block. Yeah. But that can be checked way before building the block. Right. As soon as the transaction is seen, right? So currently in the specs it's uh basic it's just a for loop over all transactions and the nons every time when we see a sender the nons of that sender is increased by one first check if it's correct and then increased by one and the balance is just are you talking about validating fossil or general general with the general okay okay mhm so it's it's just um the nons are track checked before we do any execution of transactions and the same with the balance. So the nonsesses in the balance would still invalidate a block. Atters
would not attest to a block where a transaction with an invalid nons or uh a non-funite account is in there. But the only thing that can really revert the block is specifying the wrong gas. So it should be a very very rare occasion. And then of course some data got onchain or basically free. So if you have a transaction and the builder puts it on chain but specifies a wrong guess limit then your transaction lands on chain it won't execute the call data will be there and you will not pay for it.
Okay but are we talking about this gas used in the header? I'm sorry I'm confused. And the gas used in the header is really just used for fossil. We could we could move we could um remove it if we don't do fossil at the same time. Okay. Right. Okay. Yeah. So I'm talking just basically if you push guest use in the header then you then the builder has to execute the block. If you don't have guest use in the header the builder could build a block or part of the block without executing those transactions. Mhm. This is interesting. This is actually an interesting point especially maybe thinking of distributed block building or something.
Yeah. So, this is that's a tradeoff. That's I wanted to just I'm not saying which one we should pick, which one is better, which was I'm just I'm just pointing out a trade-off that is being done here. Yeah, it's a good point. I think if we if fossil wouldn't ship at the same time then we can just move the remove the gas used field in the header and then we just need it for fossil in order to kind of move this post execution um check to the pre-execution. Okay. But like if you ship the late execution without gas used and some people start using it as a sequencer like or part sequencer like right. So
they build part of the block but because this you know the timing is they want to wait till the end for their me transactions then they can easily fill up the rest of the block with uh not executing them right and then if you want to reintroduce gas then you can have friction right so right but those transaction they would still be good transactions right because if if they fill them without executing and the block will still not revert or yeah they should have correct nonsense etc. Right. Yeah.
Yeah. Yeah. Because in this case you could even sell it as a feature that builders can just stream their transactions into the block without executing them. Yes. Yes. To some extent. Yes. Mhm. Yeah. I agree with Lucasf it would be like sort of like a friction point if if builders like got used to do it and then like would have to go back for zone. But in general like I don't know my general take is like that we should be okay with imposing some constraints to builders and that's basically what is about. So if it also means like having to execute to put that guess used in the header like yeah maybe it's a tiny bit of a loss of an efficiency for builders but
like it's probably worth it considering like other approaches are like probably worse for them if you consider some social resistance. But if I can add something, my point is uh as from the point I'm starting giving feedback about delayed execution, it's more complicated than it seems. Uh it actually uh has some delayed execution itself. You mean? Yeah. Yeah. Yeah. That it opens up different doors and it's more complicated than I think uh initially uh estimated. I'm just I just like a joke.
Okay. Okay. Yeah. I think Yeah. I I mean I feel like to me at least it's quite what I like about it is like the concept is very straightforward like you do every static check you can do but every but but you don't do execution and like you leave that for for for later and so you you gain there. So at least like the ideal to me is like quite appealing because like I don't know it just like I can it's very easy for me to make a mental model of it. Um and then some of the complexity comes related I mean with for I guess um I so feel like it's it's yeah like imposing
constraints on on builders for example like does come from and I think that that's fine. Uh but then yeah, I I was going to just ask the the question like that always troubles me and I I want to know if you guys thought of it for a delayed execution which is like is it going to be something that's uh fine and completely compatible with full and native account abstraction? Do you guys think about this or like are there like no no conflicts there? Yeah, it should be because for example for native account obstruction I mean most of the times when there are problems with native account obstruction
then it's because of addresses draining each other's balances right and yeah that's basically solved with this reserved gas yeah um yeah I wasn't talking about 772 I was talking about like the more general native like 7701 or something when you can like do arbit arbitrary things. Um but I guess yeah it always comes down to like emptying or like draw like emptying an addresses balance I guess at the end of the day. Um okay cool that makes sense. Um I see potus is not here yet.
So maybe we do an interlude of implementation things and then uh we we get to to put this presentations on APVS and for if that works. Um but maybe yeah first like does anyone have updates? Did anyone make progress? Uh anyone is welcome to to to speak about this. Um I don't have any update on uh like a client implementation side.
Uh, as you all may recall, I was working on a ref implementation, but uh um lately I've been working on the execution specs and then once that is done, I'll work on adding some execution spec test. Um, more specifically, some, uh, it looks like there's a way to add, uh, test for the engine API new payload. Um, so that will be the plan. Um, and should have something um, by the next call, if not sooner. Um, so we'll definitely be sharing that
um, in the Discord. um should have a PR up and execution specs at least in the next day or two and then um yeah the execution spec test will uh will follow. Um but yeah that's in it for me. Awesome. Thanks. And just to make sure are you working with with the steel team on this or have you worked on this by yourself for now? Uh for now it's just been myself but yeah I think I will be uh yeah have some questions for the steel team um with respect to spect.
All right yeah we have uh we have a yeah I will add you to a group anyone else is welcome to join by the way but there is a fossil and steel group already so that would be easy. Yeah that's great. Thanks a lot. Um, no update from prison store. Tony, your screen is still on the uh Zoom, just FYI. Uh, yeah, Tony, if you want to just maybe stop sharing your screen.
Um, no big update from Nethermind. And Mercy, you posted a screenshot. Do you have any thing to share? No, exactly. Um, this is I just posted my update for the two that I was working on. And currently we just have um I'm able to subscribe to the Bitcoin API event for inclusion list and then logging received inclusion is data per slot and also showing transaction counts in the logs. I'm hoping to work more on fetching the block data for each slot and then performing comparison between transaction proposed in the event and
then where it was actually included in the block. That's just what I have for now. Okay, nice. Great. Thanks for sharing. Uh, cool. No, never mind. Anything from the lighthouse team? I remember they were like very very close to interrupt, but I I'm not sure right now. No, doesn't seem so. Okay. And who is anyone is anyone going to be in Berlin
in in June? I mean, I know Tony, Jacob are probably going to be there. Um, is Jun and Anders too, Nixo probably. Is Jun joining? Anyone else wants to Justin? Nice. Okay. And Okay. like a lot of people. Great. Okay. So, okay, that's awesome. Uh, nice. So, yeah, make sure you check the fossil session out because um I think it will be nice to have like at least a quick um yeah, presentation on where we are at in terms of implementations and where
what we've done so far. It would be like a good way to showcase it and then talk about it a bit more. Uh, cool. Okay. Um, I I don't I still don't see this. So, does anyone have anything else to to share? Otherwise, uh, we can also like close it and and leave the the presentation for for the next session. Okay. Uh then looks like we will have
the EPVS and full presentation on the on the next session. Uh thanks a lot everyone for for joining and um and see you around. Bye bye.