EOF Implementers Call #18

EOF Implementers Call · 12 Jul 2023 · 54:31

EOF Implementers Call #18, held on 12 July 2023. The EVM Object Format, or EOF, is a proposed overhaul of how contract code is packaged and validated in the EVM. These calls bring client teams, compiler authors and spec writers together on implementation, testing and specs.

Topics

From EOF Implementers Call, hosted by Ethereum Foundation.

Transcript

hey good morning everybody Welcome to the eof implementers call number 18. let's just go ahead and get started and and hear what client teams have been up to the last few weeks does anybody want to start us off I'll go for bases um mostly we've been focusing on for the evm stuff on the Cancun release which involves some some drill down on some of the specifics of self-destruct to make it sure that the test consistently across platforms great

[Music] Ivan uh from nethermind side we were just minor bug fixes because we were focused on Cancun erps like pre-compile and like four seven eight eights and other stuff makes sense here that there's an important Fork um yeah anyone want to give an update for Epsilon you know then one with some non-returance functions that required all those changes in the

unit tests because of data section coins change from three to four so basically only that's the change and yeah besides this work model implemented below the store codes and I think that song has nice it's good to hear any other client teams I missed cool any compiler updates uh I don't have compiler updates but

maybe some stuff I want to talk about this spec again this time yeah okay uh I assume probably if not updates from you then no compiler updates so let's just jump into spec discussion what's on your mind Charles yeah um so last time we touched on a few topics and I followed up in the Discord um so I think for a create three so we were talking about X data copyright and one use case is um like fat free contracts that are using init code stored in another contract to to perform a create

operation um and a couple things I noticed were one is that the init code is validated at init time and sorry that create time which I think uh first of all the process can be simplified on the cost can be brought down if the init code is validated instead uh when the container is deployed um I think you can remove the if especially if you have a new um section kind which is uh init code instead of as arbitrary data um and then the other thing is I think that

there are different strategies for storyline code engine uh and I think it'll be more purpose it create three um has an address argument so you can take the unit code from the executing contract or from an arbitrary contract or if that's not feasible then I would want to propose create five which um does have an address argument and allows you to deploy code from init code stored in another contract so my concern with validating init code container creation is and then we have

to validate the subcontainers and those sub containers not have sub containers and there's no limit unless we put one in and say you can only have like five layers of subcontainers which seems somewhat arbitrary because you could have I think potentially like a thousand sub containers that you then have to validate and which would basically be possibly an attack Vector validation slow enough but isn't it an attack Vector at deploy time too you only validate one layer of container so if they do that thousand container deep they would have to do a thousand calls which would consume a thousand gas so unless we also charge per subcontainer validation and increase the gas and limit it there we would need to

do something Beyond simply allowing sub-contained validations we'd have to charge more for each subcontainer and Sub sub container I mean I think that's kind of similar to the the call limit right the call recursion limit so that was put in when the cost of call was not aligned with the efficiency of the EVMS um and also you could go I mean there's talk of removing it but you could still with 15 million gas go absurdly deep I think there's like a fixed bound now with the 6364th rule I think it's like around 550.

calls Powell I forgot to check the mic uh uh can you see me well yeah we hear you okay um so I think in the one of the previous version we've had this this validation happening yeah I mean mostly were we were validating the the subcontainance when the like the the master container was uh deployed whatever so I think the the issue I mean it actually looks very beautiful um so like when when you write or execute create distractions you already know like they need could uh container

is is valid so you don't have to revive that and uh in terms of dos vectors I mean all of that is bound by the the the outer container uh code size limit anyway and validation is linear to the code size so like like on on the paper it doesn't really make so much difference uh but yeah that's that was something we concerned a bit but I think it looks okay and the first first look and so yeah that's mostly that and uh I will I will let you download to respond to that but why this has been changed is

that uh we realized we also want to manipulate the the data section and the create create time right so when you have a create instruction uh it's it takes like fixed init code um well it takes the the init code container but the unit code container contains like the the to be deployed container and it also has ability to modify the data section and if I understand correctly like currently we allow to append some data to it and this app like data append means that we also need to update the header

of that and in in specifically the this container to be deployed it's not valid when it's stored in init code container so there's the two levels of of this containers and and like one of them is not valid when it's there it will be valid when it's kind of modified or something like that um if I understand correctly it's it's like we will kind of will modify it anyways and the validation happens happens before in practice for the current spec it's not so big deal if we kind of trust this update function which is also under the consensus regime will do the proper job

right but um like for the future proofing kind of it's it's a bit weird but you validate something and then later you modify and you kind of expect the modifying function to be produced something that is also valid I think that was the main reason we kind of uh dropped that and also maybe to anticipating uh further questions um it's not it's not it's not possible to distinct between init containers and they like to be deployed containers so like you can use the same container in like both contexts in some cases if I

remember correctly so that was the main reason we dropped that maybe there was some additional information but yeah we considered maybe this way to to make it work yeah that's mostly the background for the current for the current decision uh yeah what do you mean you can't tell the difference between init containers and to be deployed containers I have to remember what the example was but you can kind of use the same container I mean when you validate to start with uh what was the reason for that out in any code our end code

in in its code context when you're it is a convenient code I mean you can you can think about it like like it's kind of two levels like the first one is like runtime the next one will be the the init code and the end code will contain runtime right and this is the way to figure it out but in end code container you can have additional unit code container because in its code can also create execute create instruction with like sub container as a unit code so like in this level of when you go deeper in this different call call instructions you can have like two levels of imit code use it on this

this way I'm not sure I can explain it very well but when you validate mostly you can't tell if this init codes oh when you validate and you and you and you see a sub container the validator cannot say if this this container will be used as a init code or as as a runtime code because it can be buff depending which instruction will use that because in the same code you can have additional creative structures and also return container instructions right so you can point the same one you can even use this yeah yeah what if

you like don't recursively validate the init code what if you only validate like that it's a top level in encode and then leave a validation of any like child containers for when that thing gets created called on it because I mean I think that seems to solve first of all the recursion problem and then also like this issue of needing to validate subcontainers all at once you mean when you like haven't fully get it uh because I'm really smooth oh no

it's like uh when you for example when you spot when you validate the construction and you support create instruction you can go to this containary points too and then like validate it as well this way right so when create three is called let's see from the spec it says the deck gas reading and container index pop some stuff in the stock blah blah validate init code eof container and then execute the reference container in in code mode right so what I'm saying is we can run that validate initcode eof container one time when the parent contract is deployed and then not have to validate it in the future but what about nested containers

just we deploy the container has a container in it and that one has a container in it as well so yeah anyway yeah for me it also this nested uh validation doesn't seem to be a big problem and the main reason we gave up this idea was this data appending to the data section and in case code contains data load and instruction which can access

the appended data it will be invalid if you validated at uh earlier than grade 2 instruction maybe I'm not following fast enough because it's like there's two validations in create three right you validate the init code and then you validate the deployed code right all right yeah so I understand we still need to validate the deployed code which has the you know maybe the data section or whatever but can you skip I mean can you move the init code validation to a single time or one time step

foreign which one is deployed code maybe that is how how could the net code in the container be um deployed code so deployed code is referenced by return contract instruction but the same code that has returned contract can have earlier create three

instruction which references also some subcontainment so one container has can have for example two subcontainers one reference to by return contract another one referenced to by grade 3 and then one of them is unit code another one of them is deployed code contract better I think what Charles means that uh when you when you are about to deploy a container and you do a validation then it's kind of implied that every sample container in this container will be in

it called containers in the end because there's no other use for it and then you can validate these that's that's what the meaning was yeah I I'm

pretty confused by the difference between a deployed code container in an initial container um maybe I can talk about that with you offline then yeah I I think so um so like in the UF there's not There's no distinction just yeah there's no distinction between these two so they're not Mark anyway and like yeah they are all comes from which

instruction referenced them right so and that kind of two instructions want to create instruction one return container instruction and like that's the main thing and hotels and there are some cases like a bit more convoluted and basic examples the same container can be referenced by both instructions and they more or less should be valid as well um yeah and up to until we and yeah and um and this return container instruction it also modifies the container and that's

why it's really difficult means doesn't the validation before this instruction doesn't really work because something that is invalid before modification can become valid after as small as the case here this way rather the other way but anyway it's like doesn't make sense to validate before it's modified because it will be different container on like keeping the high level overview and that's why we dropped the the pre-validation of all subcontainers that we've had before and maybe there are some cases when this can be work but it will be kind of the

specific case and we can figure out offline uh what are the cases for that yeah all right thanks uh did we want to go on to your second question Charles yeah which was about uh invoking a netcode and an external contract oh I can I can say only this that we we also had considered that this kind of different addressing mode of like reference mode that the reference to the container is like a pair of address and maybe some index of

whatever the address has and so on and uh yeah and I think that was even like the first first draft of the of this pack because I think that was uh influenced by the this is some some sketch or like proposal by by vitalik with this thing different creation modes and the creation mostly means you copy existing code and do some specific modification to it which is restricted and and so on and so it was doing kind of replacing some other code that is already deployed and yeah so once that was it so you can I

think originally it was the idea was just copy whatever is deployed and then run the Constructor on top of that to allow modify Right storage and stuff yeah so there was number of iterations and I don't know it's I think we pick something that is simpler of like above the the like more generic uh more generic case I think that's that's the main reason yeah I think it can be a visit I I don't know like

don't create I have like much more to say about it right now yeah I mean the other option is that like you could just call this external contract and hope that it calls create for you correctly which isn't necessarily the end of the world but there's some like the salt is different than stuff like that yeah I mean I agree with this like kind of you can have the same systems work in both cases it's like probably like different way of

thinking about the deployment and all of that so yeah we kind of agree yeah I mean it's the same as having like a template contract which just loads the the init code index from call data and then runs create online but that that has like call Overhead and we don't we don't like transferring execution context um I mean so is it like

yeah maybe maybe I'll think about that some more I mean I'd like my I think we are a bit a bit more a bit better position to like yeah to discuss that I think like some months ago we were just like there was so many options to choose from we just pick if there's like alternative designs we just pick uh probably the simple simplest one like by our our assessment right um and I think it's it's worth it that like

there are some comments coming now about the design because this means like people are getting familiar with the concept says and then we can I mean it's it should be easier to discuss the like details right now than like dropped the draft with like multiple Alternatives so wow so we can collect comments about it but uh I don't really I don't like I don't have like good understanding how people like how contract developers might use that so yeah I mean there's different strategies for for fact for having these Factory contracts right and I think

um like Viper pretty much exclusively has Factory contracts call other use init code that's stored on other contracts on chain or a facility I think uh stores the init codes all in one contract right um so yeah any other comments about it just that I think that it would be useful but I think we all agree that there's you know

you can also get the same result with a little bit of more work right I do have another question which is about this uh EIP 2315 and I'm wondering if there are some very good Arguments for having code sections instead of like one Global code section allows for some other optimizations be done

so subroutines is the biggest argument for code sections they have a built-in return stack you can treat them without having to do stacking conventions and um if you don't want to use code sections you want to use one giant code um feel free to use it if your conventions work but the biggest Advantage I see of code sections is a is a NVM subroutine facility which is something almost every other VM system out there has uh I think the ip2315 has a way to have subroutines but without different code sections explicit code sections was that the one that was in Berlin and

was backed out uh I'm not sure what its history was yeah it was originally scheduled for Berlin and kind of in the last month before it started going to test Nets it was removed and I think the original reason was the solidity team had run some analysis on it and it didn't show a lot of improvement for their um yeah their test Bank so I don't know what the status of that is at this point um I don't know if anyone else knows well I I think like my understanding is like on the functional level

the the main difference I want Charles is pointing to is that um in this subroutine EAP from some years ago you could yeah your specified kind of for the subroutine starts and but that wasn't restricting uh like starting jumps to cross these boundaries so uh yeah so anyway that's that's mostly that's the functional difference in this although there were some routines you could jump between like from the middle of one subroutine to the middle of some other subroutine or like something like

that and that's like explicitly uh restricted in uof right and that's I guess that's the main the main point here yeah exactly and uh there's that's the functional difference and then there's also you know slightly less overhead because you don't need uh code section headers for every subroutine like that that's kind of the reason why this is done this way um so we kind of want to restrict this and also what that's why we we have this

metadata about subroutines so we know like how stack behaves yeah and this like job app that kind of like is the middle of the ground a bit so I can guess you can like design control flow using only jump half of something like that um I don't I don't think I have anything specific to propose at this point to train that um but there's one there's one big item still on me and just didn't have time between these two meetings uh touch it finally which is this stuck height like height restriction which I just

want to read like yeah make it a bit less annoying and I will need to help with this but uh at least I need to start this kind of discussion separately so yeah I don't know how much that will help and we'll come to any conclusion about it I'm in the stack height but uh maybe there'll be some outcomes and maybe that will solve this problem about singles single like supporting space I don't know um yeah I mean as we're discussing in Discord I think

jump fi and call if I will more or less do the trick but I think that it would be more elegant if we can get rid of the stack height restriction yeah I I'm not sure I can we can we can do like full full eliminate that I mean that was also proposal to do so so I think there's still possibility to do that uh but there are some voices on the other other side that really wants this but I think we can kind of forgot the English words right but like

make it less restrictive um so I guess it should work in some cases and not like on every case uh but that's my hope for now I can't really say anything about feasibility of that one thing code sections is kind of related but off the stack it allows for multiple entry points per contract I was just before we got to that section I was recording up an idea I had that what if we did create init code with code section you know a create F instead of having a nested container I'll get a draft out for that later this week but there is you know there's still utility to the code sections Beyond just subroutines you know it's multiple entry points I think is one rich uh thing in the mind

oh yeah uh I think that was also our original idea about using Code section as the init code kind of entry points and I can't remember why we dropped that but yeah definitely we can forget about it yeah so it sounds like we have some stuff to talk about offline um in and not have any other stack issues to bring up at the moment you briefly mentioned jump fi and um

callify yeah what are people's thoughts on that is that a good bad negative positive from the compiler side it would solve some issues I don't love it but it works um yeah I've from like instruction set perspective it doesn't look really uh astonishing but I think that this is kind of uh recurring

recurring proposal I think we already touched that with solidity discussions as well and yeah I don't know I mean other than the op code size below is there any downside to it well it's not so much in terms of implementation it's just like obviously like the mode of two instructions right or something like that so but they would save like five bytes to down to three save two a piece possibly

maybe more I need to I need to like think about it's like is it like purely the merge of of some instructions I was like this like some semantic difference or like I don't know um I need to like make sure I fully understand it but uh I mean it's like if it's yeah it's kind of question like how much do you want to do stuff like that right because probably there's like a lot of patterns that appear like very frequently and and client contracts and anything like this

so like the the common pair of instructions whatever right so you can always argue that we should merge this pair of instructions because they happen so so often right I mean the one argument is like it's something that you were able to do before which is like conditionally jump to some piece of code which you can't do now because it's in another separate team or and because of the stack height validation rule I I mean it's not like I think like arbitrary I think it would be weird if we started

having arbit like conditional execution for all instructions which I saw in some older arm specs which is like I don't know conditionally execute mall or something which I think looks pretty weird and that's probably a lot of complexity to the client and also to code generators and also it doesn't really have a excuse me uh precedent in the current evm but this call I find Jump if I do have an analogy in current evm uh because we had to jump and a jump if

sorry because we already have a for anything that changes the PC other than straight Advance we have a conditional variant you know with with uh jump and jump if so we bring that into our jump and our jump if and since then if we consider call F and jump f to be the same as a jump instruction um then yeah it would be consistent to say that they've always anything that changes the piece that the PC within a frame always has a conditional variance so it would be consistent my concern is are we bloating the instruction table can we afford two more

instructions maybe we can maybe we can't right well uh it might be doable with just call Fi uh I'm not sure if jump if I I mean it would be nice it saves two gas or something but I don't think it's uh yeah I have to think about it a little I mean but I mean also right where where would we stop doing do we add like call FV and jump FV uh because there's also changed the PC uh kind of conditionally because it would I think I'm running through it it would change six byte sequence in a three byte sequence we

would have you come in with your conditional on a stack you would jump conditionally jump forward um pass the call and you so you might have to invert it so there might be another knot there so it's seven or six down to four down to four or three I mean just from code space there's an argument for it in case there's no decision on that something to think about I think that um once we investigate the feasibility of

the loosening the stack height validation rules uh then we can see if it's still needed okay that might be uh another way okay sounds like a handful of things to continue discussing offline any other spec questions discussions that we wanted to have here erpat posted something about the XT data

copy uh her path you want to go and then Zane other folks haven't seen it yet I think there generally is a sentiment uh across application developers at least that are working with like unchain art stuff that it's uh a nicer way to expose things if there is

a standard way to read data in a data section from a post eof contract uh in a different execution context and yeah it's like I don't think it's a solvable in different ways via the like you know created in the pseudo standard where the contract as a method you can call into or it reads its data and returns it via call data but it seems maybe uh just funky and so I don't know wanted to give that as an additional two cents on the topic as it's being discussed so I think I would say I'm weekly in

favor of EXT data copy other Solutions do exist but I do acknowledge they're clunky and considering the needs of the data Community it's something I would support but it's you know depending upon how the other people feel about the spec I'm not gonna you know compel its inclusion but I would I would weekly support it guys exd data copy exists uh like anywhere like specked out I was having a hard time like tracking that down it doesn't exist um it's a logical hole in the data copy because we had code copy and there was the XT code copy but we didn't spec out an EXT data copy that corresponded to the XD code copy so it's functionality

we'd kind of lose um but there's patterns where you could just say well make contract expose some methods which means etxd code copy um in addition to the cold storage um which you're going you know the the 29 29 2930 cold account uh penalty you're going to have the first time you access it there would also be a hundred by call penalty plus evm overhead to go into the call um so there is a way to do it without it it just feels clunky um and unnecessary if we could do it um but I you know the other people writing the spec may have stronger reasons not to but it may go against the the code separation uh desire

um so that's that's why I'm not you know I'm merely just weekly in favor of it I'm willing to hear what the other people the engineers think about it how should we uh go about um like I guess putting forth a plan of action for EXT data copy or proposal for that what would you suggest would be the best way we don't even have a data copy EIP written yet that's in process because we're all you know trying to make sure we get the Cancun devnets out

when the data copy one comes up propose the Edition um I mean it should be simple it's just you add an extra argument that as a contractor's rest of the stack um costing is going to be the issue yeah I'm not I think uh not sure who's got the action item to write the data copy spec okay and that's going to be before or after again can you say eof is shipping after Cancun um that's probably another meta discussion you need to have when do we want to try and get Stacks finalized um and I think while we're still in the process of working with the compilers

and the end users I don't think we should push too hard to freeze specs but I think we should get a handle on what the issues are so we can start closing doors and get ready to batten down the hatches when it's ready to go cool cool um and then I kind of had another just like question what floated through through the own chainers which is just so if we have like uh an eof uh if we have a legacy contract that deploys hover Legacy contracts um do those Legacy contracts need to be in the proper eof format

um or or not um what's the behavior in that does that make sense can you reset it I think I got it but can you run it by me again one more time sure uh you deploy a legacy contract that deploys other Legacy contracts um when the eof change happens um what will happen to the uh sort of this Factory contract that deploys uh future like uh now invalid uh Legacy contracts so I don't think we want to get to the point where stuff used to work suddenly

breaks especially Factory contracts my understanding is that Legacy will continue to always work as as a layer and eof will be a second layer and what will be restricted is how you would deploy contracts into that new layer um you probably need to nail down can Legacy contracts deploy eof contracts but I think we've pretty much shut the door on eof contracts deploying Legacy contracts um and that's a question of how do we bootstrap the eof contracts do we require them to come in as eof from the create transaction um Can Legacy Factory contracts back to create eofs I think those are some of

the corner cases when we really start we really start getting some of this great stuff um probably after we we start up Cancun test Nets as I think when everyone will be able to fully focus on it and I think just today Charles pointed out some issues that factory contracts would require three layers deep so I think there's needs to be some more work done on Korea as well um but I I think if we broke Legacy deploying Legacy going forward I think we've done a disservice and I think that brings to the point as well that we need to make sure that EXT data copy um behaves well then pointed to a legacy um as well as the current contracts that's one other complication of an EXT data copy

is does it just become an EXT code copy when pointed at a legacy contract that's the easiest way to solve it which would also align with some of the s store 2 specs to see nothing I think that's what it's called sr2 um where you have the the EF header and the way that would work in yet in an eof contract is the data segment would just start with that EF header even though it would be nested deep into the eof contract part um I mean that's where some design can be made to try and extend it but I think that's a reasonable to set the first two bytes of the viewable data copy to those biases say treat this as data I think is a reasonable place to start whether it winds up in a legacy contract or in the

data section of an eof contract yep okay yeah all that like makes sense that makes sense there is one kind of follow-up question I have on that topic where like I think it's in uh is it the 35 40. I don't know if I'm just remembering sorry I haven't had enough coffee this morning uh I think it's in that you have here one of the uh like the eofv1 EIP there's kind of this mention of like the sentiment you're describing Legacy contracts will be able to continue to deploy Legacy contracts um but like to allow for some period of

before this Behavior may be deprecated or something like that and was curious if there's more concreteness as to what that might mean like I think our read of that has been you know you should update our on-chain storage libraries to use the UF format once it's kind of finalized and available there's maybe a different interpretation that says like oh it's never going to be deprecated so like before before this you know before the hard Fork make sure you deploy a generic Factory deployer or something which seems probably sub-optimal from my understanding of like what the intentions of uh the UF work are so just trying to understand like what is that

actually look like in practice is it like we can't backwards compatibly break Factory contracts ever but we can make them you know prohibitively expensive to use which is kind of my interpretation is like you there's economic forcing functions to get people to upgrade or something like that or is it something else just trying to understand like how yeah so for a theory I mean that I don't think we'll ever reasonably have a path to fully deprecate legacies unless we happen to find an EO to find an eof where they can be brought in not just brought in but brought in with them uh gas equivalents um recompiling it to a new format that is not gas equivalent it may be

compatible but I don't think that would be a viable path the more interesting paths I think are to look at layer twos um I see a world where there are layer twos that start out eof only and only allow you to have contracts um that's that's where I think the more interesting parts of this is um Powell's got some comments I'm sure he's got better opinions on this so let's have them talk no actually I don't have much to add but like yeah I kind of I agree with Daniel it's like it doesn't we don't see any any puff to like duplicate creating Legacy contracts um except one one thing which we can consider but later is to deprecate create transactions so it

won't be very easy to create Legacy contracts using a transaction but you can always have and pay with your exist like generic contract deployers that will do it for you so we can just like yeah forbid create transactions at some point later in the future but not to break the create instructions right and um and yeah so we can only kind of encourage people to migrate to eof and like current encouragement is hopefully this is the feature set is is good enough so people will consider this um the second thing you mentioned and maybe that will be used but I don't know

really is to kind of make eof cheaper than the Legacy right so but that's not something we already try to do uh but it's relatively easy to do later because you can't even see the gas from the your website so for example you can I don't know like make every instruction cheaper than one four different arguments but yeah we can we can use gas pricing as an encouragement for uof and there's lots of places we could add the gas charge and the charge to the accounts that wouldn't necessarily break the evm flow but I think those are at

least a year down the line before we even discuss the possibility or need of them yeah that makes a lot of sense thank you okay we've got about five minutes left I kind of want to time box the spec discussion so we can take a second to hear anything going on with testing is there any updates that people want to share with respect to that hey Eric can you hear me I hear you okay yeah so I made a small progress on the python tests so now um let me share it USD VR or you guys to

take a look so um this is the EOS test update to the latest uh python specs and we support now ebm1 and we support prep uh the fork um it doesn't currently work because the create three logic is basically not working yet but it now lists all the tests for Eos and python um so yeah it's not really working yet but I I will I wanted to share this because if you wanted guys to take a look you can get an idea of how the python tests are written and the amount of parameterization that can be done um there are some examples that for

example we have um lists of op codes and with those we can parameterized tests and how to generate tests for example to generate a contract as to try to generate an UF contract with all invalid outcomes and so on and so forth so yeah I I just wanted to invite you guys to take a look into the python source code and just any feedback just let me know if you if you want to share or if you need help um running this code or anything just let me know awesome any other testing stuff

three minutes left any last comments cool thanks a lot everybody um we'll pick back up again in two weeks in the meantime we'll see on the evm channel cheers thank you thanks thank you thank you bye thanks