Stateless Ethereum Meeting 15
Stateless Ethereum Meetings · 16 Jun 2021 · 1:00:10
Stateless Ethereum Meeting 15, held on 16 June 2021. Researchers and client developers discuss the road to stateless Ethereum, including Verkle trees and state expiry. This meeting covers a proto-EIP for state expiry, drawing on a proposal that combines Verkle trees with state expiry.
Topics
From Stateless Ethereum Meetings, hosted by Ethereum Foundation.
Transcript
okay thanks everybody um for uh coming on i appreciate this um so it's been a little while since we had our last some uh either group stateless call or kind of a topic call um i think uh um piper and co have been pretty busy working on the front on the state transaction network and client um and uh we may do a topic call that's a little more focused on that side um but the impetus for this call was one we realized it had been a little over a month um and then the second one um i don't know
if onscar is going to want to chat a little bit as well because i think he had a few conversations um but the the main impetus is um vitalik has been thinking about and putting forward a clearer set of thoughts around the state expert protocol and we thought it would be helpful for everybody if he would be able to get a chance to go through it and have a discussion and then see if uh that would spark a bit more of a game plan around that aspect of uh development so people are aware of it and think about who would be want to be working on that side as well so um
this call i think we'll have enough time to talk about that topic uh pretty well so it's going to be focused more on vitalik's memo so i'm going to hand it over to him for people who are just joining here is the kind of meta more recent agenda of the last couple of meetings that we've had and it's got links in there to uh some of the recent documents that uh italic has produced so please take a look uh through those and open that up i don't know if telecom wants to share as well but um in any case you can uh look through that too all right thanks vitalik you got the floor okay excellent thank you um so uh is everyone seeing my browser share by the way
okay uh so um picking up from the last uh stateless desk discussion and that we had which i think was around is it two and a half months ago or so or something close to that or is it may have been one in the middle as well um but the state where we were at then is basically that we were had agreed on a somewhat more concrete um approach for how we would approach uh statelessness and state expiring uh so um i had made a document where i made three proposals one was to do just sales does one was to do just state expiry and proposal three was to do statelessness and state expiry at the same time and
we had a call and option three um ended up being the favorite i think because enough people uh just in the core dev group and you know among other people just wanted state expiry to exist regardless of whether or not statelessness happened it didn't end there was enough demand for statelessness to exist regardless of whether or not state expiry happens and so it turns out that it's actually easier to do both at the same time and and i have a bit of a kind of one paragraph explanation here for why like basically if you want to do state expiry without changing the tree structure to make witness sizes smaller then you are going to need
witness sizes for proving old state anyway and those witnesses would be extremely large and if you do a statelessness uh without state expiry that you have to basically do this complicated in place swapping procedure to move from a hexagon to your viral tree so you actually end up with incurring a significant portion of the complexity of uh doing both anyway and if you do both then it turns out that you can avoid the inefficiencies or many of the deficiencies of each one right so some links here in this documents if anyone wants to kind of recap on uh kind of the history of uh statelessness and state expiry as
ideas but for for this call i'm gonna kind of mostly assume that people have at least at least some backgrounds on both of them um so for statelessness we've talked about the core idea enough right basically instead of clients having the state clients have the state route and blocks would come with witnesses that just prove what the individual pieces of state are that were accessed state expiry is a bit more complicated because there's a lot of different ways to do it but the core concept behind state expiry is that they're like basically a state that was not read or written too recently uh somehow gets kind of dropped out of the state right uh so and
what it means for state to be dropped out could be different uh so the older state um proposals were actually very unforgiving they basically said that if your state drops out then your state's dead and uh you know you're screwed like you're uh you know if you've got your ether you've got your dojo on mars or you've got your whatever you just i accidentally forgot about it for two years then you know well you're screwed right the recent proposals are more forgiving and i think there has been a kind of steady increase in the amount of uh forgiveness that these state expiry proposals have uh so the challenge that we were dealing with about six months ago was this concept of our resurrection conflicts
uh where basically if some piece of state dropped out and we wants to be friendly and he wants to have the possibility of reviving state that was dropped out then there was there's this problem that you have to somehow distinguish between a piece of state not being in the tree because it was dropped out and so if you want to bring it back to life you would have to provide a witness versus a piece of state not being in the tree because well there was never anything put into that position in the tree in the first place um so i came up with this concept of address spaces and and so that was in the pre in the previous documents that kind of solves the problem and address spaces the solution behind
address spaces is basically to say well we have these different regions where you can create contracts and every region has some minimum like a time during which you're allowed to modify it right and so like basically if he wants to fill a new storage slot you don't have to prove that there was nothing there before all the way back to t equals zero you just have to prove that there was nothing there before all the way back to t equals whatever was the mid the earliest allowed time during which you are allowed to put anything there at all and there is a new uh address space that opens up every period and so there's always some place you can put a contract where after you put a contract there then for at least one to two years
you can just like throw things into new storage slots wherever you want without needing to worry about witnesses um so the core design of us this particular state expiry proposal kind of in this diagram here right basically instead of doing a continuous approach right so some of the older approaches were continuous they said like every single account might have like a time to lift counter it has a balance and if it's time to deliver its balance drops to zero that account gets sort of kicked out individually instead we have a more discreet design right so we have the system of trees and where every tree there's a new tree every year and every tree stores the
information or state that was read or written to during that year right so here as this example we assume that we're in period three um so this would be like the fourth year during which this system is running or and period zero here this tree could say a state that was rather written to during period zero this is state writer written to during period one this is state rhetoric into during period two and then period three um every tree except for the most recent one is fixed right so only the most recent tree act can actually be modified any modifications go to the most recent tree um and if he wants to read state what you would do is you would first try to read it here
and if it is here then that's what it is if there is nothing here so not even a zero but just nothing like some particular key is empty then you go check the tree in period too if there's nothing there you check between period one and if there's nothing there you check the tree and period zero so the rule is that to read a piece of state like it it's always the value in the most recent tree that has something and if no tree has anything then uh you know you have zero uh so the idea would be is that a state that gets frequently accessed and frequently modified would just always stay within the most recent couple of trees but then older thing a state that gets spotified very infrequently or and even access very infrequently would fall behind
clients only have to store the most recent two trees right so if you as a transaction sender wants to provide anything that's in the older two older trees then you personally have to provide awareness right so if you want to provide some state that was last modified in period zero then you have to provide a witness for period zero let a witness said there was nothing there in period one a witness that there was nothing the er er and then if there's more periods um in between here you'd have to provide a witness that there was nothing there in any of them those and then you don't have to provide witnesses for the most recent two trees because the most recent sutures are the trees that regular clients store um so this was the idea right and this is what
we had two months ago but the main feedback that i got two months ago was that in order to move closer to implementation and even to move closer to kind of sophisticated critique um people wanted to have some a much more formally specified proposal um that actually felt like something that you know here's a a complete description of how everything works and you know it's even theoretically implementable um as opposed to you know something that just kind of looks like a set of principles and ideas so that's what i did right so um i came up with two proto eips so basically you know they're
they have most of the components of any ip again if mike kazoto was here and i tried to submit them as an eip he would probably yell at me a hundred times but uh you know they're still formally specified enough and they have uh you know a complete uh implementation and that you can feel like you can go and start implementing this as an implementer i'm sure there's mistakes of some um at some points but like it's still fleshed out enough that like there is something here that as a client's implementer like you can just like uh go and create right um so uh and so there's two eips and there's
also this road map right so i guess i'll talk a bit about the road map uh the idea is that this is a transition to verkle trees and state expiry that happens in multiple stages and we can implement it one stage at a time right so if we we could just implement the first stage theoretically before we even start like like specifying the the second stage any further uh so the first stage is uh basically this hard fork uh that just begins period one right so after this hard fork we go from having one tree to having two trees
so we have still the pitcher fishing tree but but then the maturation tree becomes frozen solid and then there is a new vertical tree right so the new vertical tree contains state that was edited or accessed after the fork and the patricia tree is just this old frozen solid thing that just is a record of what the state was um or right before when the fort happened right so basically and then the for the older trees the patricia tree the newer tree is a verbal tree so what this does is it's it sets up a convenience um environments to do some of the later stage things because first of all we already have a after phase period or after this hard fork we have a
virgo tree and then the patricia tree is frozen solid so it becomes much easier to kind of do other manipulations to the the patricia tree and the this period this eip of the theory had one hard fork it's actually forward compatible with two things it's forward compatible with finishing the road map and implementing full state expiry and it's also if we want forward compatible with just abandoning state expiry so what would basically do is we would just poke everything in the patricia tree move everything slowly over to the vertical tree and then once everything is moved over to the vertical tree clients can just go and forget that the retribution should be existed right so it's kind of forward compatible with an
sort of eip at 25 84 like uh just full transition to a vertical tree process but it's also forward compatible with uh the rest of this right now right um so after the period one hard fork or before the period one hard fork at any point we also have to do this address space expansion so we have to extend addresses from 20 to 32 bytes and this has two um objectives right one objective is that we just need to allow more address space uh more room for azure new addresses so that we can create this notion of address spaces that i talked about for the state expiry concept and also it's a needed security measure at some points
because four things that require collision resistance uh 20 byte addresses only have 80 bits of security and it's nice to have addresses that have more bits of security right so in the scheme that i propose we have 26 bytes that go into the hash so we have more than 100 bits of security if we wants we could go up to 27 as well um so i made a proposal for how to do this in a yeah a way that maximizes backwards compatibility so 32 byte addresses can still interact with 25 applications um so you know you can still like hold your shiva coins or whatever as a 32 byte address you can still participate in uniswap v3 um you can still you know to participate
in all your ethereum applications um but and then epsilon here made a counter proposal where he had just like took some of my ideas and then added some of his own thoughts his own critiques and kind of his own ideas for how to make this kind of transition even better right so i definitely recommend reading this document as well and then the third step is the period to hard fork uh so the period two hard fork uh basically just is a hard fork that begins uh period two um and it also kind of schedules all the future periods now because of the period after the period one hard fork the hexary patricia tree is frozen in place
and because after period two you only actually clients no longer need to store the period zero tree they need to store the period zero root uh we do this clever thing where at the transition boundary we replace the period zero hexley patricia tree with the root of a vertical tree that contains the same information right so this is um nice because you can just compute the new vertical tree off-chain and client clients and kind of users can check that it's correct off-chain and so the amount like clients themselves do not need to have any kind of built-in transition logic which is something that i think is really nice right and then the state expiry eip like basically it just
schedules all of these uh kind of periods and after a state expiry eip is implemented then we basically have the benefits of both verbal trees and state expiry and everything that we want has been turned on so i'll probably just briefly stop here in case anyone has a kind of quick questions before we start going through the vertical tree in particular ding dong [Music] okay again if no questions um oh oh
right or right sometimes uh people do this stuff in the in the zoom chat or mummy check the zoom chat um oh absolutely your name of the you allison team i didn't uh actually realize that so okay great the uh the no thank you very very much so i'm actually going to everyone for that for that lovely document um okay um let's see it's bad for offline clients how would i generate all the required block witnesses if i was offline for four periods okay well this is part of state expiry um but i think the answer um to that is if you were off the line
for so this the system is the state expiry approach right it's designed so that if you're offline for up to one period you're completely safe um if you're offline for more than one period then there's a risk that a state that you care about is going to be old state and or is going to become old state that you have to provide witnesses for um if you are running an archive node so you're just like grabbing historical blocks and processing all historical blocks then if you choose you have the ability to um like actually store either every state tree or potentially just the state the the portions of the state trees for the account that you care about
so that's one thing that you can do um the other approach that you have is that you can just uh ask the peer-to-peer network for blog witnesses i think realistically in the long term most users are just going to be relying on asking the peer-to-peer network um right so we definitely like right now that's willing for grabbing witnesses does not exist yet um but the good news is that like this whole state expiry here is the last of the three hard forks right and uh yes like the responsibility for storing old state does kind of go over and go over to the users and potentially piper's portal network can take over this responsibility potentially something like the graph or or some similar solution you can take
over this responsibility if worse comes to worst um like etherscan and etherchain i'm sure we'll have uh apis for witness provision like you only need to find one node willing to provide witnesses and then you and then you got it right so that's infrastructure that like the risk that old state will just literally not exist is uh like basically non-existent um but um there definitely is a challenge in actually building up this infrastructure but the good news is that we have a long time to do it um right and also yes i could point out the first period doesn't have to be one year the first period like basically well the length of the first period is not fixed right because the first period is literally the period between
or the time between the period one hard fork in the period two hard fork that could be three months that could be six months that could be 36 months that's all that all depends on our development time so okay going to uh for countries uh so verbal tree is basically they solve the key problem standing in the way of ethereum being stateless client friendly which is witness sizes right so a witness accessing an account in today's hexadecimal tree is in the average case about three kilobytes and then in the worst case it could be even larger because you can attack the tree by a kind of grinding keys that shove things into positions that are very close to each other uh vertical trees are much better so the witness size
um goes down to about 200 bytes per account and so stateless fly witnesses go down by a factor of something like 15 and so stateless fly witnesses with verbal trees actually are acceptably small um in addition to uh just vertical trees this eip also implements code verbalization right so this is using the 31 bytes junking scheme um i think one important point to keep in mind is that with vertical trees um witnesses other like especially for small pieces of data like the code the portion of the witness that's other than just the code itself is pretty negligible right and so it actually there actually aren't really significant gains that we
can make from like coming up with better chunking schemes right basically you're a witness just for a piece of code just is going to be like the specific portions of code that you accessed plus a maximum of four elliptic curve points uh it's uh uh kind of uh points to the the kind of different subsections of the code um so it's already close to optimal in my opinion there's not really much to be gained from like from optimizing further um but like you know there you have it right um so a witness i write is going to be very small we have a code vocalization um and there are challenges involved in like well one is creating an evm uh kind of modification that can keep
track of which chunks of code you access i intuitively think that this should not be hard because like basically all you have to do is like divide the pc by 31 and then poke a bit field and if if you poke the bit field and it's zero then you then you you uh like fill that midfielder you use some logic but if that if that position is already one then you just keep on going um so it's just like a couple of uh arithmetic operations um but you know it's still important to make sure that that gets uh kind of implemented efficiently and then also there is the work of like analyzing existing clients
um to uh make sure that existing clients are um and um oh there was another analysis by the the formerly known as ewasm team and now the epsilon team um showing some how existing contract gas usage will increase um they showed an average of 10 and 20 percent uh gas usage increase um if the gas cost per chunk was a 350 gas and so here the gas cost is set to 200 so it's a bit lower and but but at the same time like as i'll talk about a bit the scheme was designed so that there are some goodies that do kind of compensate for the extra cost of having to store chunks of
code um so getting into the spec so here there's just a vertical tree that's defined by uh essentially a function that gives you the tree bird um if you have the uh the data that you're storing um here it is right so and it assumes that both keys and values are bytes 32 objects so this is one other important piece of this circle should be designed like basically it's designed in this abstracted model where you the stage 3 just is a mapping from bytes32 to bytes32 uh and every piece of state that we currently have so a block headers uh headers code storage uh like
everything gets mapped to a particular bytes 32 keys uh in this state right so the reason why that gets done is basically it improves simplicity um there isn't any kind of two-layer structure there isn't special case code it improves uh things if you for from a database point of view it improves um it also improves efficiency it reduces the risk of like tree attacks that make branches really long uh so there's like oh and it also just there's a simplicity gain because it makes it easier to upgrade to different tree designs and or stage tree designs in the future right because all that we need to tell them is that
hey you're implementing a key value store uh so there's this vertical tree definition um in the m in the spec that just basically computes a main tree root uh given a piece of data um one important property of this design is that in the current hex patricia tweet we're pretty clear that storing zero in some position is the same thing as that position being empty the vertical tweet changes that right and the verbal tree being zero is different from being m2 um so that's the vertical tree design um guillaume and kev have been quietly doing some excellent work recently on actually implementing a verbal tree and
making sure that everything around the implementation is efficient um that it can actually generate proofs for uh ten thousand keys in a reasonable amount of time that it can update for 10 000 rights in a reasonable amount of time um i picked the number 10 000 because that's like roughly the number of uh like random accesses that you can have in a block if that block has 25 million gas so kind of assuming um you know people's kind of even demand some for some gas increases over and above what we have today i just me and we have like a dos attack on top of that just to make sure that clients can still handle it um
so right so here i define the tree embedding scheme so the tree embedding scheme is basically a scheme that says for any particular state object so it could be a piece of code could be a storage key it could be an account nonce uh we're going to map it to a particular 32 byte key um so this uh for convenience this all uses address 32 objects um but if we don't have the address extension yet then like basically we can just pretend existing addresses are azure 32 as they just have uh 12 zero bytes kind of attached to the front of them um so here's an example of how header positions get converted into a tree keys
so first of all the tree key right basically you take an address a tree index and a sub index and then you just hash together the address and the tree index and you add the sub index as an independent byte at the end right so a sub index has to be from 0 to 255 and the sub index just does get added as a byte to the end so the reason why this gets done is is that this allows us to have at least some pieces of information put kind of be adjacent to each other in the tree and this gives us the benefit that it allows us to reduce witness sizes for the account header it allows us to reduce witness sizes for adjacent chunks of code and it also allows us to reduce witness sizes for adjacent chunks of storage
which is a benefit that we actually don't have at all today right but so it's a sort of a nice convenience to have um but aside from that right the address and the tree keys just kind of get um hashed together and like some of this is what happens already today right today um to convert from an azure storage miki you have to hash it but here we're putting the address and the tree index and so what happens is actually that there is no longer this thing where all of the storage and all the code of an account is under one roof right um you can have like different portions of the storage and even different portions of the code of an account could be located at very different positions in the tree
and this is um like there are some some genuine disadvantages to this but there's also some big advantages right one big advantage is that it ensures that the tree is very uniform like basically it ensures that like the storage in the tree is very evenly distributed and you're not gonna have a situation where like there's one object in the tree where well actually that object is a really important trc20 contract and under that object there's like three percent of the state just like hiding there and it looks like a really tiny piece of the tree and so this is like uh useful for things like the portal network for example because it makes it easier to just say like hey you're responsible for location 0x135 in the tree
and then whoever gets location 0x135 is going to be pretty confident that they actually have something close to one over four thousand and ninety six of the entire state um right so everything gets mapped to tweekies and tweakies have this uh property that um if you have positions that have the same address and the same tree index but they have different sub indexes then they are going to be beside each other but at most 250 six things can be beside each other uh 256 is also the width of the vertical tree so that just makes it easier from an implementer's perspective right like you don't have one kind of commitment you don't have a tree inside a tree it's just like a tree that has this special case property where
you just always have this extra note at the end um right so we have a version field um that's the versions don't exist now but we're just going to add them here because while forward compatibility is nice why not uh we have a field for the balance um the the keys are 0 1 2 3 4. uh we have a field for the nonce uh and then over here a backwards compatibility field for storing the ext code hash um if if we are wants to screw backwards compatibility we could always not have that but like it's fairly low cost so like whatever um and then we also have a field for the code size right and field for the code size is also important because like that tells you uh for which code positions
do you actually look at a look at the code for and for which code positions you say well hey we already know it's outside the code and so we're just going to return zero um so now we also have two keys for chunks of code so chunk is uh just a continuous set of 30 of 30 31 bytes right so bytes 0 to 31 in uh the code uh go to uh chunk uh 0 uh bytes um or sorry byte 0 to write 0 to 30 in the code go to check 0 bites thirty one to sixty one in the code you go to chunk one bite 62 to 92 in the code to go to chunk two and so forth right and the reason why we do 31 bytes is because we needs to have
one byte that just stores like the number of leading bytes that's part of push data right so if you have a proof that just gives you like some random uh chunks in the middle of the code you have to know what part of that code is push data and so we have one byte that tells you um just for kind of for precision sake um i have a kind of quick implementation here of code chunkification uh so this just converts a piece of code to a sequence of these bytes 32 chunks um so basically a code gets split up into chunks chuck zero gets saved at up the posit the position that you get by uh putting chunk id zero into here um chunk one uh gets uh uh becomes uh it gets pointed to
position one check two gets put into position two and then for storage you also have a mapping right so if you have an address and you have a storage key that also generates a tree key um one really important kind of cool feature here is that we i basically set things up so that um we have the block headers fields they all take a tree key as zero um for the code the code offset is 128 and so if your chunk id oh right this should be uh thank you and this should be chunky instead of chunk um if the chunk id is less than 128 um then this expression like basically code offset plus chunk is less than 256.
so that divided by 256 is going to be zero and so the for any code up to chunk 128 so up to uh about three kilobytes the uh the tree key is also going to be zero and then for storage uh basically if your storage key is less than 64 then the position is gonna be set to a number from 0 to 63 and then the tree key is also going to be zero right so this has this nice property that the header and the first three kilobytes of code and the first 64 storage slots all live under the same subtree and so if and so accessing all of those things becomes really cheap right like so for example like i looked at the huda swap code
and they have about nine storage variables that are basically like just simple storage variables like they're just like single values and solidity compiles those into like position zero position one position two position three and so all of those are gonna live in basically the same place as the header and then if say you have a smart contract wallet that and you manage to fit everything under three kilobytes then that's also going to be in the same position as the um or all your code is going to be in the same position right so if you have a small smart contract wallet you basically like you act doing everything would just require accessing this one
kind of self-commitment in the state which is really efficient and if you have something like unit swap then like if you just need to access a small fixed number of variables then those are also going to be like within one object that's basically stored beside the header right so there's some opera there's like you still get a lot of opportunities for some nice efficiencies here um now one thing that we are going to do actually is we're also going to change the gas schedule to take advantage of these efficiencies right so the gas schedule basically says there's a cost of 1900 for accessing a new uh sub for accessing a new like branch um and then there's a cost of 200 for accessing a new chunk
so if you access a bunch of chunks that are beside each other in the same sub-commitment at the bottom of the tree you have to pay 1900 for the first one but then you only have to pay 200 for every subsequent one which is really nice because if you're a uniswap and you have to access like say three to five storage variables that are like right in your very close to the beginning today you would have to pay um you know like 2100 times five but here you would have to pay like 1900 plus 200 times five and so like that's just immediately a savings of seven thousand guests and that's something that can easily um compensate for the increased gas costs that you have to pay because you have to
pay for accessing uh chunks of code and then if you're a smart quadrant wallet and you have less than 64 slots and less than three kilobytes of code then you just have to pay 1900 once and you have to pay 200 a few times um if you're a delegate call forwarder then you also only have to pay 1900 once instead of uh paying uh uh paying a cost of that size twice which is what you have to do today um so some uh benefits here for uh users as well um right so we have mappings for from header values to tree keys from code chunks to three keys for storage values the tree keys um a quick description of the fork it's pretty simple
basically instead of having one state we have two states and the patricia tree becomes immobile um or immutable and the vocal tree stores all updates to state and it also stores state that was accessed after the fork right so if state gets accessed even without being modified after the fork then it also gets saved into the verbal tree and then it's a read state you first try to read the verbal tree and only if there's an empty uh like there's nothing at some particular position then you try to read the position uh so in order to strictly define uh when we copy state over and how we charge gas um
we have this concept of access events so when access events just formalizes when a particular uh position in the tree actually gets accessed so we say that if the address is the target of a call then you access its version you access its code size um only if the call is value bearing do you actually have to bother accessing the balance uh when a contract is created you access everything um if the balance op code is called um then you would access the balance um if the self-destruct top code is called um so as part of this eip also it includes like commutering self-destruct so it doesn't do anything except it's like
transferring all the value and so we access the balance of both accounts the ext code has shop code accesses the key the exec code hash key um access an slot in store and they make an access event for that storage position um and then for code um you have this access event for a code chunk and we have like an attempt at specifying when particular code chunks uh get access right um and then same thing for our for transactions right so we have this a kind of fairly precise specification of well it should be 100 precise specification of like at what particular times do we count um particular pieces of the state as being accessed and this is really important
also for state expiry because when a piece of state is accessed that's not just an act of reading right when state is accessed we also have to save it in the most recent tree which is something that we do here and so and then we also have as i mentioned witness gas costs so we as charged 1900 every time a new address and sub keeper or i guess address the tree key pair is accessed and then 200 for every new weave key uh and that kind of reflects how um accessing this a new address and sub key kind of takes you to a brand is basically your band of access imagery and you have to prove an entire branch but then for a leaf key you just have to
prove the 32 bytes and so the cost is much lower and will only charge 200 guests for it um also self-destruct opcode is renamed to send all it doesn't do any destructing and all refunds are removed right so basically this like so this eip as a whole it kind of implements all of the logic and transitioning to a verbal tree it also does uh some gas reforms and it also implements this concept of access events but it and it does it in a way that is minimally disruptive to the existing system right it's minimally disruptive because it does not require swapping any tree in place it just requires creating a new tree from scratch and just like slowly
growing that tree over time so that makes the code easier to write and what after you have this then we basically have this kind of for um well we have a very clear path toward implementing state expiry and if we want we also have a very clear path toward um just uh moving toward a single vertical tree if that's what we end up wanting backwards compatibility issues so this includes self-destruct tutoring um if we decide that we really really wants to keep self-destruct in its current functionality there is a way to do that um like basically we would just have to include a counter like number of times
self-destructed um in the state of an account and then we would have to like basically say like um store code and storage in different positions uh depending on like what the offset is uh but that's like uh i don't know like to me that's not very nice and i personally prefer just like saying you know screw it we're going to neuter self-destruct but the you know this is something that we can discuss as well but i think the vertical tree um implementation is a probably the best decision points we'll ever have for this for this question um gas cost for chunk code chunk access is going to make some applications less economically viable but as i mentioned at the same time like
there are also benefits from um the new gas cost schedule like costs for accessing adjacent storage slots decrease and costs for are accessing um early storage slots going down all the way to 200. um so there's advantages as well um so like that's basically the vertical tree eip um if feel free to kind of i guess to look at it and would definitely appreciate any comments um okay let's see if there's more um okay there's lots of vigorous discussion and this is uh excellent um okay
uh delegate call style smart contract decomposition becomes potentially viable while still being gas efficient yes a very important point from piper because uh another thing that happens here right is that well first of all as i mentioned uh delegate like why a delegate call forwarder would only have a single branch access of overhead instead of today where you have like an account access and the storage access of overhead and another thing nice thing is that with this uh model a big contract actually like contracts with big code actually do cost more than contracts with small code because if you want to access all the big code like basically storage is saved into
multiple trees right like every sub or sorry code is saved into multiple trees right every subtree is going to save a maximum of 256 code slots so it's going to save a maximum of 8 kilobytes and so if you have a maximum size to contract it's going to be split between four trees and so accessing all of the code is going to require four branch accesses whereas smaller contracts require uh like fewer branch accesses and so like today there is this problem where we have a de facto penalty for having uh for using libraries and using delegate calling and being modular because you have to like go and pay the fixed cost of a call multiple times
but here like basically you pay that cost anyway right like if you're accessing a lot of code then you have you're jumping around and like multiple uh subtrees that you're paying a lot anyway and so if you have a delegate call forwarder or even if you just call a library then like that it's you still have to pay but like it's more balanced right you have to like you would still have to pay if you just access your own code if your code is too big anyway um okay bad news is that current proxy contracts do not work with this um unfortunately no right so one important thing here right is that there are efficiencies like basically there's efficiencies that
contracts can gain by taking advantage of this design but like compilers will have to be modified right so it's possible that existing contracts will become slightly less efficient but new contracts will become more efficient um okay only best basic storage variables benefit from being in the main tree right so like owner well it's right so there's different contracts and there are some contracts that have a lot of basic storage variables right so like uh you know like unit swap for as i mentioned right it has somewhere between three and five basic storage variables that just get accessed with every trade and so uniswap is going to be able to save like more than 5 000 gas a transaction with something like this even as it is today um a raise
yes array is very important um okay so i'll okay i'll just take a tea break so my mouth doesn't break from my speaking for an hour straight right so this eip is the state expiry eip right so this actually implements the state expiry mechanism so it implements basically the thing that is in this diagram and is the thing that basically is option three in the documents uh that we talked about in the call that we had in march
um so prerequisites of a state expiry one is the verbal tree eip and two address extension so at this point we just assume addresses are 32 bytes and we can make a new address type that is 32 bytes um so the cip basically it assumes of the post vertical tree status quo where you have two trees and it goes from two trees to having entries where clients are only expected to store the last two trees older state can still be accessed but the transaction sender is required to provide witnesses to verify any older state um some parameters so one here is uh the period length so this assumes a period of length of like
slightly less than one here um but you know we can argue this parameter if we want fork block number and period zero vertical root right so well as i mentioned a bit before one of the nice properties of this design is that once the vertical tree eip has been implemented the patricia tree is frozen solid and so the period zero vertical vertical root can just be computed offline and it can just be hard coded as a parameter for the cip um after the uh virtual tree eip is already fit is uh on mainnet and so we know what the and we can just locally compute what the vertical root equivalent to the period zero patricia tree actually is
um so the transition right so at the fork block height uh we have a state structure that has a patricia tree and a verbal tree and we're going to change it to a list of verbal trees and we're going to start it off with three uh verbal trees where the first one is a verbal tree that's just the period zero vertical root uh then the first one is just the period one verbal tree and then or state and then the or i guess i guess the second one is the period one vertical tree and then the third one is a new empty verbal tree clients only store the last two states for all states except the previous they just have to store the route because transaction senders have to provide witnesses
um and so over here look we've heard we're gonna hard code the period zero vertical route and so clients are just gonna have this uh um and then over time this list is going to keep on growing um so actually i think i have the logic um here here's the logic for how it uh whoa what happened there um here's the logic for how it grows right basically um we have this function for get current state period and that just takes the the number of blocks since the fork and it divides it by the period length and then it adds one because well we start with period two um so oh actually i think this should be plus two instead of uh in instead of plus one um that's uh okay um important thing to remember um
so if the occur basically every time a new state period begins uh we would just add on a new virtual treat to the list and of course the state period but increment by one and so we have the property that the length basically the length of the states equals the current state period plus one right so the last state tree is the state tree belonging to the current state period um we have a concept of address spaces um so um address spaces um basically we introduce them by adding a new address type um so this address type would use the 0x01 tag but then it allows bytes 3 to 5 to be nonzero and
bytes 3 to 5 represent the address space number of an address in little endian form right so to get the address based number of an address um here we're going to assume the address version byte is either zero or one and then if it's zero um then the first 12 bytes are constrained to be zero and so this is gonna return zero anyway right old style addresses are just for period zero and then if the address is version one then you take the first three bytes you interpret them as a little idea number and that just is the address based number um we in order to be to create transactions that send whose origin is in the new ad in a new address space we're going to
add a new transaction site right and at the same time we're going to overload this new transaction type so that this new transaction type is the new transaction type that can actually like include proofs of old state and actually can properly interface with the state expiry mechanism so once this um eips starts like basically everything like all the previous transaction types sort of become de facto deprecated um which which is good right it's good to deprecate all transaction types uh so the sign the new transaction type has um it's i defined it as an ssd structure um so we have a payload and the payload just is a new transaction um signature an ecdsa signature and then old state proof uh so this is a
vertical a vertical proof that proves the old state that is being um that is being claimed in the claimed state structure of the transaction the old state proof is outside of the body that gets signed and this is an important user convenience feature the old state proof does not have to be signed because the old state group is authenticated and for being a valid proof against the claimed states anyway um and the old state and the benefit that you get from the old state proof not being signed is that it allows a third party to add an old state proof easily so if you as a transaction sender do not have old state and you just send a transaction then you would still have to know what the old states that you're
claiming are but someone else that has the branches can add the proof which is nice um so the transaction it's fairly simple um we have a nonce um a target address space so which address space your eoa the ela that you're sending from is in um gas priority fee max gas price we don't have these work uh the two value data and then the claim states is just a list of like what state you're claiming and so you have um it's this a container and then you have an address um so each one of these containers you have an address and a from period so the address is what addresses state you're claiming and then the from period is
which um period you're you're saying this the the status is going to be from so is it from period zero eventually if the current period is 12 then you know it could be claiming it from period 10 or period 7 or period 4. um one other thing that i did here is i kind of overloaded this mechanism so you can also claim that the front period is the current period and this basically means that the state claims also double as an access list right so state claims kind of they serve a dual purpose they can both be an access list into current state and they they are a mandatory access list into a historical state um and then i mentioned the the old state proof so here we have this new transaction type
um a vertical proof i actually haven't defined vertical proofs yet um it's not even in the virgo tree eip yet but this is something that can probably be kind of fully specced out and finalized very uh very soon by the virtual tree team and the claimed state structure serves as a function of access lists and then here we have a simple function to compute the origin uh so basically you take the signature you easily recover it to a public key and then we return a version one address um where the address space of the address um is uh based on the target address base of the transaction and then everything else here is just the last 26 bytes of the uh um oh um hold on this uh should actually be
instead of payload this uh should be a pub key um that's another mistake on my part so it's just the hash of the pub keys name as it is today um so when stage period is at least two all the transaction types that like uh uh before um the cfo was introduced become invalid right because like you just have to have this logic in order to be able to interface with the kind of old state system we also introduced a new op code i call it create three but if we introduce create three before we can call this create four and create three allows us to create contracts that are in new address spaces uh so create three takes stack arguments very similar to create two and you have assault except the memory size memory
start amounts of if you're sending but you also have an address space and then the contract address is created very similar to a create two address um you have creator salt init code and you just save it except you also have the address space um so once again recapping the concept of azure spaces basically an address space is just a number but there is a rule that says that um con accounts in address space n can only be created in state periods that equal and or that are greater than n and so a transaction if the current state period is n the transaction origin cannot be greater than n and create three indications cannot create um
address uh um contracts whose address spaces are uh uh are greater than n um so yes oh i'm sorry you were saying that's that sounded like a wrap up okay um that's right okay i'm happy i'm i'm happy to kind of be a quicker in kind of jumping through the rest of this stuff um i actually was i was i was jumping in because um you know even with uh sipping tea as you're going along um i think uh you know you wrote quite a bit of uh material here um and uh it's all quite valuable um we're about at the top of the hour
and i want to be conscious that we're probably going to have some people go off um i think it is really valuable for people to see the you know all of the kind of details that you're going through on the thinking i'm wondering if um rather than you kind of going to hyperspeed um if it might be helpful for people now having the first intro and seeing this if we schedule a pull-up call you know in a week or so to do the second portion and then we can have a more extended conversation um given that i think people see now how kind of concrete and real um and thorough the thinking is um across these i think a few people in the comments
also raised the point uh about um uh how you know users are holding state or the portal network or other things which i think is going to be a very big you know good discussion to have as well um so i'm i'm wondering if uh i don't see questions that you need to answer really on the chat side i think people have been mostly listening as you've been going through here um does that sound reasonable to do a follow-up that allows you to go through this more next week right that sounds a very reasonable yes um oh this is nice thing and it definitely looks like there's a lot of kind of good questions already and uh and a lot of a lot of the good good questions have been
answered but and i'm sure people will have more questions a week from now so yeah definitely a good idea to um have another call then okay okay very good um yeah joseph is saying same day and time next week um i think i think that's a reasonable starting point certainly i think the only people that uh well yeah it's a little hard for pacific and mountain time but other than that the time is a pretty good time for many others [Music] okay well um i think this is this is i mean you know
uh i'm sure you're excited every time you write something new uh i think this is really exciting to see that the thought kind of crystallizing around this and uh this is a very nice adjunct to all of the discussions we had earlier the piper was leading um and a few others have been joining in about the you know the part of the network that actually adds state and so forth this side is uh really useful to see how the protocol changes to make the state set reasonable and then how contract writers will have to start changing their thought process and compilers thank you everybody for um coming on for this this session i hope it's been very helpful um and i will
follow up quickly um with the video for this if anybody wants to go through because i know vitalik kind of went through a lot of this quickly reading these documents uh a time or two and then listening may be valuable as well um and then maybe when we have the discussion next time if people uh maybe want to have a little bit of mindset i think it's wonderful to see these things written it's absolutely essential to first have that but then it's really good and i'm hoping that when we have the call next week we can also have a discussion around maybe time frames um and people thinking about uh where and when this might prioritize compared to a lot of the other you know important work that's going on on for eth1x and um
for uh e2 and the merge and so forth um i'm just going to say here let me just pause for a sec if anybody else wants to jump in with officer questions before we adjourn i saw piper once or twice you went off mute but i don't know if that's relevant still all i was going to say is continue the conversation in the statex free channel happy to answer questions talk about it there right okay good all right thank you everybody and uh we'll be talking again soon later bye thanks thanks everyone this was really thanks
you