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

Loading player…

EVM Object Format (EOF), Layer 1 R&D - Day 1

Ethereum DEV NLSun, Oct 9, 2022, 12:00 AM

Adding new functionality to the EVM Speaker(s): Alex Beregszaszi Hosted at Devconnect Amsterdam, 2022 Visit the website: https://devconnect.org/ Or follow @EFDevconnect on Twitter

Transcript

foreign [Music] okay yeah sorry for the delay there um yeah I'm gonna talk about the evm object format and I wasn't sure you know who's the audience and so I kind of like left a mix of of you know different level of depth um but first I wanted to I was really happy yesterday when I found this um because this was the first time I found the in the original Wiki what is the design goal of the evm yet I worked on it for like I don't know six years at this point or seven um and it's quite funny that the original design goals were kind of on spot we actually did achieve most of these goals and I want to highlight one the first one here is um simplicity we definitely achieved that but maybe we have overdone it a tiny bit and it's it's biding back now and I would have if I would have been there's writing this Wiki I would have added two more design goals I would have added a design goal to be extensible uh so that we can add and remove features without disturbing existing stuff and I would also have added validation so that there's no code which looks invalid enters the state but we didn't have these goals we didn't add any of this so here we are now and um I just want to introduce like four different issues um we've identified and we are kind of like solving these issues with the UF so the first issue is um we have all all kinds of instructions basically any kind of byte can exist in the state and it can map to any kind of instruction we have all these bytes which do not map to an instruction today and if we introduce a new new OP code which tries to take up that bite then suddenly we have contracts which change Behavior so it's kind of really messy to introduce features because Anything Could Happen the second big issue is is basically data bytes and how they interact with jumps so we have for one example we have uh the single instruction called push which takes an immediate no other instruction takes an immediate today and we don't do not want to execute any data which is part of this immediate because that would mean that we can have like self-modifying code and code which does weird things how do we prevent this we prevent this by not being able to jump into the push data and that's the reason we have this jump test byte as well and validating this at runtime is kind of kind of sketchy and we don't do that therefore we have this process called jump test analysis which is done before execution and this cannot be done from any point of the code it has to be done from the beginning and it's done at every single time the code is executed now some clients do some kind of caching but you know it's not generally part of the uh the the specification we also have data sections uh think about init code when we deploy a contract there's an innate code which then has the actual runtime code at the very end which is returned and then stored in the state but of course besides that practically 99 of the deployed code is compiled from solidity and solidity has this metadata at the end which is just some random data um and the main issue with this this data is we don't want to to jump into it we want to have separation between the two and technically if there's like a jump test and then metadat like this data section is properly properly formatted we could actually jump there and we definitely break the separation of code and data um and in many cases especially the case of init code the innate code would be small but the data the runtime code would be big and we run this jump test analysis on this entire blob which is unneeded and of course the the last threaded issue is removing instructions or like deprecating them not allowing new code to use that that is just not possible at all today uh as you can tell UF is a solution to all of these and many other things um the main goals we have is to separate code and data have some kind of a validation process and to be also extensible now I mentioned versioning here but it may not need versioning to be extensible eof itself is a set of different eips and the first two eips here are the core of it and those are kind of accepted or I don't know considered for Shanghai we're gonna see when Shanghai gonna come first of all and whether he's going to make it um but the first two look like that they're going to be in Shanghai um I kind of hope that this third one static relative jumps would also make it I'm not hopeful that the function stuff gonna make it that's too complex um but the static relative jumps is really interesting um now the first dip itself just defines the structure and some basic validation um this is um how the the eof bytecode is going to look like we have a header at the top which starts with like a magic version and then you have the actual sections and which is just the section headers you don't have the content there so you have the section headers you have a terminator and then you have the actual content now to visualize this um here's like a legacy code of course the space here it doesn't matter it's just the space you can put spaces into hexadecimals don't be you know concerned by that but if you concerned that like compare the Legacy code against the UF you can notice that there's like this header that's the header I described before now to dig into what the setter looks like of course you have the magic we have the version it is the first section which describes the code it sets the length of the code the second section is the data which also just describes the length of the data and there can be eof byte code which doesn't have data it can be only code only code or code only a byte code that there can be bytecode which has code and data and lastly we terminate the header and then we have the actual code now this example is is like an init coding sample a contract creation code um it is pretty standard it just Returns what is the runtime code which in our case is this one at the end it doesn't do anything um now apart from having like this structure we also have to change evium semantics a tiny bit and the only things we change is re basically around control flow control flow instructions like jumps PC Etc they have to be uh they have to be limited to the code section they they cannot go outside of the code section but we still need to keep code copy and all these things intact because we want to be able to to copy the data here so if you look at the this code example code copy basically reads the entire container and just Returns the data section um now since we have this headers we also want to validate that these headers are kind of uh are correct and we are not just taking anything which looks like an UF header so we have some kind of a validation procedure at the Times time of deploying code um and this process is kind of flexible as well because we can have Legacy code Legacy code obviously is is an affected it can continue deploying Legacy code but it could also deploy UF code and the same happens with the UF code this is actually one of the topics we could discuss at the workshop you know whether we should have this case of eof deploying Legacy code um you know these things are flexible um it's really important to mention that you know if we have this validation that we make sure that you have code in the state is valid the question arises okay what happens with code which has been deployed prior to Shanghai uh can there be code which looks like UF but never has been validated and that is a really valid question and the answer to that is no and the way we solve that is true this magic which is Magic of course um now in London we have deployed a previous EIP which just rejected this UF byte to be the starting byte of a bytecode Envy we're kind of hopeful that nobody gonna deploy before uh activating the tip nobody's going to deploy any code which starts with ef but of course three people did and uh so we cannot go with the EF single EF magic byte but this is by design that was the reason for the CIP right it just kind of said that these people did it um but anyway we can still go with ef-00 two bytes for magic and the reason we choose zero because that's cheaper and uh you know call data gas um so basically this magic prevents that in the state currently there's no code starting with the ef-00 byte so whenever we deploy an UF validated code we can be sure that that is validated and this magic actually we compared not only on mainnet but we looked at most of the useful or you know it's a most of the useful ltus and test Nets and none of them really have um any code starting with ef00 um now moving on to the the next CIP the code validation which is an extension on top of this and it is pretty simple the reason we separated these two because we weren't sure you know that um even UF would be accepted and then code validation so we just separated it but it seems like you guys like it uh code validation is is an extensible system the first three steps we do in it that we don't allow like all of these random instructions to be deployed so when you deploy a newf contract it won't have up codes which are not assigned to anything we also want to prevent like having truncated bytecode so they won't be push data at the very end which is truncated and this actually helps some optimizations in in interpreters and we also want to to make byte code properly terminated with you know stuff like stop return revert Etc this also helps interpreters and lastly we could also use this system to deprecate up codes we could say that new bytecode cannot choose call data uh the the call code opcode or can we choose self-destruct um and now lastly my I guess most favorite dip out of all of these is the static relative jumps um there has been like a long discussion you know all of these Dynamic jumps analyzing a byte code you know what is the control flow of it um and it turns out that actually solidity like most of the over 95 of the jumps in solidity code is not Dynamic it is fully static it just jumps at no locations the only thing which is dynamic in solidity is return to color now with static relative jumps we can actually make these static we can remove both the jump test we can remove the push instructions we can save space and we can also save gas because we don't need to do any any analysis around it this is validated at deploy time so it's pretty awesome but it also is a building block for a few for other changes like having functions or having subroutines um or even having like this return to color on top of this um and the UF itself you know we kind of hope that it is a building block and it will enable other features as well I listed a bunch of features here subroutines I mentioned um but one issue with like 3074 and I'm sure Matt gonna talk a lot about all of these one concern people had with 3074 is okay how can I once I give authorization how can I revoke it and you could have like a revocation system a vtuf it's like a special section and eof um and lastly there's also like this um uh really interesting VIP to introduce complete control flow validation at deploy time that it also depends on on all of these VIPs I've explained so I guess that's that's in short you can find all of the eips all of these talks Etc on our website and I hope that we can discuss all these details on the workshops thank you [Applause] [Music]

Automatic transcript — names and jargon may be misspelled.