eth_multicall Meeting, Apr 8, 2024
eth_multicall and eth_simulate Meetings · 8 Apr 2024 · 1:08:01
A meeting of the developers working on eth_multicall and its successor eth_simulate, held on 8 April 2024. Client and tooling teams compare implementations and work on the specification for simulating transactions.
Topics
From eth_multicall and eth_simulate Meetings, hosted by Ethereum Foundation.
Transcript
hello hello what is different between get logs and E call get logs doesn't have to actually run anything because the logs were already run and most clients saved them whereas eth call Will execute some code on top of some block and then give you the results and in fact very annoyingly to most people eth call doesn't actually return any logs and so um simulate does that was one of the big wins of the
simulate over e call is that you actually get logs back it's super annoying when you're writing applications and you don't get logs but you do get a return value if execute a contract offchain like you eth call and you do get a return value but you don't get logs if you execute if you look at a past execution that happened on chain because it makes building your applications just so much harder when the results set is different between on versus offchain so in this feature that Aragon was trying to develop they actually allow execution of additional code code on top so yeah so what I we've been
talking to B a little bit in our server and I think I better understanding of what they're doing now it appears what they're doing is they want to be able to say okay over the last you know 10 million blocks pick out the set that expressed this log this log line and they use that as like an indicator like a a flag to say this transaction touched this contract and then from that subset of transactions in all the last 8 million blocks whatever they're looking at U now rerun those transactions so run those transactions again that subset but with this code at address X instead of the normal code address X and where their
replacement code maybe has um some new events or new logs and then return me all the logs from those executions so they rerun only the ones that are related to this particular contract yeah and the and unfortunately the way they identify that because the only information that's stored about what contracts are called are logs that were fired and so if you call a particular contract but the log is never emitted for some reason let like say the log is in a conditional statement right um if that condition is not met and therefore the log was not emitted their technique will skip over that contract even though maybe it would have still fired the log and this is necessary to make it so they
can do their thing in reasonable time frame because you can't just reexecute 8 million blocks worth of transactions in in a reasonable time right so they need to narrow that set set down the way the technique they use to do that is say anything that had you know this log in it rerun but rerun it with this code instead but using the same state and so you do need an archive no for this because you need to be able to accute with the same state again MH so so I do think their thing is different enough from ours like it's serving a different goal um you could in theory and we talked to them a little bit about this in our chat I think you
could reproduce their results with e simulate but it would be much more heavy weight and involve a lot more round trips so with their thing you just tell the server look for any transaction that fired these events and then rerun those transactions with this code replaced and all that can be executed then on the server side you don't need to have round trip between back and forth between client whereas if you want to do the same thing with each simulate you would need to basically go to the server ask it please tell me all the um places where this log showed up in the last n blocks and then the client would get that build out a set of each simulate calls and then call an each simulate for every single block that showed up in that set of event with those set of
events and so there's a huge amount of round trips if you were to use our e simulate to solve the same problem versus if you use their stuff to solve that the problem it's a single round trip and the node does everything and it can have optimizations that make it fast whereas if they simulate no optimizations it would reexecute everything um it's going to return results that are much bigger and so I think the they serve different enough purposes that I can see value and having both separately so do I understand it correctly that if like compared one to another filtering of certain trans actions in history running through like block ranges and rerunning transactions
that are only filtered out based on some criteria would be the like essential difference between what is simulated currently does and what they thing is doing yeah I'd say that's the biggest difference um just fact that you can kind of you tell it I want you to rerun some subset of things here's the filter that will tell you what that subset of things is and here's the code I want you to replace when you do the re-execution and you're giving all that up front and you're telling it and do this over a very large range of blocks whereas e simulate we're basically saying each of these calls is we're just saying I want you to run this set of transactions in its entirety and give me all the results that's the other thing is they will only give you back the results that are the
the events they're not going to give like if you do each simulate you get back the whole blocks right you get blocks all the receipts and every transaction that occurred like it pretty bulky and so um so I think what you described as the biggest and the second one the second biggest thing is just the volume of results that get returned it's going to be much smaller for theirs because it's very narrowly targeted what they're looking for it will be smaller because it only returns logs or what would be the difference uh yes it only returns logs and it only returns logs for the specific subset of transactions you care about and so you still need in both cases you still need to execute all the transactions in the block prior to the transaction you of interest to right so
if your transaction showed up at transaction number 53 in the block you still have to in both cases you still have to execute transactions 1 through 52 um in their case they execute transaction 1 for 52 and then they execute transaction 53 return the results and they stop whereas in our case we execute all the transactions 1 through 52 plus all the transactions 53 plus 54 through 100 and then return all the results for every single transaction and so it's just a lot more bulky of a um just protocol and is it's serving very different purposes mhm so basically in terms of collaboration with them we probably potentially want to align the rpcs
somewhat a little bit closer to make them or what do we think yeah I could see some use in just having the shape of the data structures be similar um it's always nice you know when you're as an app developer it's nice when you the same data structures are used over and over rather than having completely different data structures or even worse two data structures that are very similar but like they're different they're different in how they do casing or how they do um naming just in a subtle way because then it makes it really easy to get mixed up and get it wrong um canonical example of this right is uh depending on what client you're using for a long time it was input versus data as the um the field the data field for transactions was sometimes
input sometimes data depending on what context you're in and this is super confusing for app developers because everything else is the same except for that one field was named differently and so I think with each simulate and um and their thing they get logs thing I think just having similar data structures where it makes sense may be valuable just in term synchronization again just for ease of use by app developers I guess the use case for that is the shadow logs or is that going different The Shadow things you're talking about the overlay get logs the use case yeah I mean the use case makes sense to me so some app some contract developer write some contracts and
you're using those contracts or maybe you're building some sort of analytic software that cares about what's happening in those contracts but the app develop or the contract developer didn't think to put in the logs you need right and so you now want to do some you you want to do some big analytics or on on what's going on internally but the logs are simply not present and so you're saying I want things to execute exactly as they did I don't want to change execution I just want um to change I just want different set of outputs I want you to give me different details about what's happening and you can do this with Trace tracing right so tracing tells you literally everything that happened every single operation op code but that's really heavyweight to do a full trace on you know eight million blocks is insane that would take you
weeks and so instead the idea here is is we can do a much more narrowed sort of tracing that gives you very kind of the inner details that you want without needing to do um a bunch of you know really heavy weight stuff on the Node I guess e scan and explorers are doing that tracing everything uh I believe so they have the advantage though is that uh well so sort of so they have their own internal indexes that they maintain and those indexes I think do require them to do tracing on every single call but if they want to add some new index they need to retrace the entire blockchain right because they need to go re re do everything and build a whole new index
um whereas if you're trying to do some data analytics you just kind of want a one-time answer or you want to go back and get some data but you know where to find that data you don't necessarily want to retrace the entire blockchain you want to spend two weeks on a big beefy server just running your your trace retracing the whole blockchain just so you can pick out one new piece of information and so I think the idea with this overlay git logs is you can get that exactly what you want at a fairly low cost and it does come with a disadvantage and I think this is sounds like from I talk with vant that this is okay with them uh it does come with a minor disadvantage that if the contract of interest to you doesn't always fire a log in the executions where you need the
data you don't have a good way of figuring out which transactions to reexecute and so they're using this this concept that we're assuming starting from the assumption that some some log was fired to let us know this contract was executed um so that we know to reexecute it with this new code in place that will fire new logs if you don't have that like let's say you had some contract was deployed and didn't and is always called internally and doesn't fire any logs ever then you wouldn't be able to use this to redo it because you wouldn't know which transactions you need to rerun again disadvantage but I think the trade-off there I can see definitely why that's worth it because um yeah that's almost impossible problem to solve without in a reasonable amount of time unless you just literally index the
entire blockchain with some you know petabyte index set of indexes that indexes like every op code and every contract that was called then maybe you could do something like that what is Trace filter but I wonder what this would mean to us that this doesn't sound something that we can Implement in each symbolite and it should be a different method yes I don't think we should merge this in my personal opinion is um so as for I mean honestly well Aron went ahead and merg this so but
just just thinking for just thinking about this method it seems like um yes you will have to do a lot of re executions especially when coming from East get logs you might think that large block ranges are okay um but that's because we fetch stuff from database but here you would have to actually reexecute all those transactions and bugs which is uh quite a lot more overhead and my second concern is that it's easy to shoot yourself in the foot because when you're doing the state override let's say if you add a view function that's fine but if you add another function that kind of
changes the state in different ways like it also calls another contract that modify something then I don't know like what are the implications of that exactly I think you definitely get weird results out but from my understanding of their use case is the use case is primarily around um basically just more getting more extracting more data out of the executions not about changing the behavior at all in fact I think they explicitly don't want to change Behavior they just want more data out of what happens when those transactions were executed so I think this is all about uh leveraging new arigon archive index that is now per transaction this so they can
not execute anything beyond what they have to so probably but what is this new index from Aron so before they were indexing divs per block and now they want to I'm not sure if this released or not but they will want to index them by transaction right so they can execute one transaction from the middle of the block without uh uh without executing any prior transactions just to make sure I understand you're saying that basically they're storing a pre-state for every single transaction rather than just the pre-state for a block yeah yeah exactly exactly that's what they are trying to
do more more more archival version of an archival node yeah yeah yeah yeah that's Aron what three or four whatever I don't know what number there on um and yeah so that's probably leveraging that a lot yeah so unless you have similar database design you might not be completely like for you yeah I think if you want to do this in a datab in a client that did not have such a database um at best you'd have to use an archive note and you'd have to reexecute all the transactions up until the one that was interested to you at the very [Music] least I am kind of curious just um I
don't know I'm guessing no one here knows the answer off top of their head I'm curious how big the archival database would be if the index included every contract that was touched as part of transactions execution so for any given transaction you you would index okay these these transactions were touched within that trans or sorry these addresses were touched within that transaction touched meaning either called or had um I guess just called yeah called or had like a non-server count change or code change uh so less than 420 gigabytes it's got more than 4 Dev
okay thinking about it a little bit uh well hard to say well it should be few gigabyte few terabytes sorry I would think it would be measured in ones or tens of terabytes because an archive node which just stores the state and D duplicated State at that for all of history is measured terabytes if you then wanted to take every single transaction oh I guess okay maybe that's the wrong way to look at it so I guess we want to look at the total number of transactions in all of history and then kind of average out okay how many addresses were touched on average in each one and that would be your number ballpark when you say that like to keep
all the utilized addresses do you mean index it it would mean not only index the addresses that were directly called by also indirectly for example yes mhm and ideally do it uh have the index both go transaction to address and address to transaction so that way you can say for this address tell me all the transaction show me all the transactions and all of history that ever touch this address in some way um and that way in a single small query you do a single index look up and you would get a list and um in terms of performance you get a very high performance in terms so basically trading storage performance that right so your index gives you a really fast
return result on all the hits of touches of this contract all of history but you pay a lot in terms of this space yeah true blocks has an interesting solution to this um I looked into it a while back they don't track calls though I think I think they only track when an account was referenced but not when it was called I think it's slightly different but yes um maybe that's a good kind of proxy for sizewise because there's I think their thing is on the order of single digit gigabytes their indexes should we discuss about it
simulate forward probably should do you have updates yeah yeah currently basically cleaning up the code for the future uh last review to for it to be merged haven't yet looked into the hash difference between nethermind and gu but we'll do this soon on the local hyp Cas not uh yeah so last week I looked into some reports from
killer um and did some fixes basically our base fee was um computed incorrectly when there were Phantom blocks in the middle um I also added um withdrawals to the to the block result as well as exess exess block gas and block gas used now it is kind of interesting question um what to return for excess blob guas um when there are Phantom blocks in
the middle and this is because the excess blog gas calculation is a function of Prior blocks right the parent basically yes is it just parent it's I mean I guess the parent then depends on the parent so it's like moving average yeah yeah so very similar to um 1559 B Fe yeah exactly so can we just do the same thing that's what I did so basically I what I did was ignore the fact that there were Phantom blocks and I just assumed that the last block was the last real
block we just have to make sure we do same thing on on other mind as well yeah yep we do the same thing okay that sounds good then there was the other issue when the gas price is zero then the base fees is set to zero on the evm but it still return something else for the base fee that was something that was difference between get and N mind yes yes so we have this um we have this logic that if the gas price is zero doing like basically doing a simulate uh by default we set the Bas fee to zero for the purpose of um exposing it to the evm so when the
a contract holds the base fee up code then it returns zero and we did this because um it seems to be a common pattern to do uh TX gas price minus block Bas Fe and it would have returned a negative number in this case which is like kind of undefined yeah didn't think about the negative number part it's unfortunate though because um hypothetically one could design a contract that is dependent on base fee never being zero because it is technically impossible to reach zero it can never go below seven just due to the
way the formula works and so one could imagine a hypothetical contract that you know broke very badly if it was ever zero um I think though that the issue you were worried about about return negative numbers is worse and so I think I'd rather have the problem of some obscure random contract C breaking and because you can always fix that by just specifying a base fee right MH yeah if you specify gas price then it's going to and you can also specify base fee well yeah you you'd have to have a gas price as well that does it always set that base fee uh yeah we are looking for so
there's a comparison between uh between the gas spand and gas owned uh and gas available in a block uh if you would post me this issue once more on trailer I probably would be able to look at it again and fix it soonish and also I had a question uh which Hive test currently would provide us with the like as complete pre-built block and transactions as possible like in which ones do we have in which test do we have as much defined as possible in terms of
like block data and transaction data so basically I want to check a case when say we had every field in the block possible fied up every field in transaction if possible filled up and if there would be difference in hash between us and guess then uh I'll know that there is something fundamentally different and if there will be no difference I'll be able to like eliminate field by field one second third three four Etc uh and uh find out the field the specific field that is uh subject to to to change of the hash so if we could could have such a
test where we have a like field as much as possible block and fill as much as possible transaction uh that would be perfect I think the easiest one is just doesn't need to be contract calls or can it just be a bunch of eth transfers I think very easy to fill a block with just like you know thousand eth transfers two would be enough two think said you won the block full oh yeah yeah yeah so the each is transfer is I guess there's two way to do this one you write a little contract uh even then still the um each the gas cost is going to be 21,000 each
right and so if you have a 30 million I guess you set the block size really low so if you just set your block limit to 42 thou 42,000 and you can have two two transactions or E transfers he's cing exactly 21,000 they don't do anything it's a very simple version of this test would that be sufficient for you yep yep okay you don't need anything fancy the contracts don't need or the transaction don't need to do anything special or be fancy or anything they just need to have transactions and fill the block guess yeah that would be perfect basic start okay is that something that you can do Kor you think yeah I can do that I Just sh the test that that's a code that just Returns the base fee and at the moment
get net mind is disagreeing on the output on this and get is returning zero and then NE mind is returning something else returning non zero basically and this is that what we're discussing right and here I would like to point out another Quirk um I'm I'm kind of open to changing this but basically the basy up code in this case in gas return zero however when we return the base Fe as part of the block result then it's the it's a real Bas Fe value it's not zero so there is this kind of inconsistency that I noticed when killer pointed out
issue but I guess I'm open to changing this um based on the results of the discussion here like seeing what we want to do in general so so how many better understand this negative number issue then uh if you were to have the op code of Base fee that was the same matched whatever you would have returned or whatever you returned as part the base fee for the block why would that yield a negative number exactly um that's when you would do like TX gas price minus Block Base fee because gas price would be zero in a simulation I see you're allowing zero gas price even when the base fee is
greater than zero which in reality can never actually occur yeah exactly gas price should always be higher so I guess this is not a problem where in G or nethermind you have to deal with this negative number this is just someone solidity contract that was designed to under the assumption that number can Nega never be negative would break and so the solution could be solved by the purely by the user by just if they have such a contract they could then set the gas price to larger than the base fee and that would fix it right uh yes they would if they specifi the gas price then that would fix it okay I think I think I changed my position then
I think having the the off code return the same thing that the block will return is more important because in both Cas in both cases whichever route we go the user can ultimately solve their problem by just specifying the gas price in the Bas spe explicitly and so I don't care much about you know if someone's random contract does something weird like this break in an e simulate and they have a workaround that allows them to make it not break um I'm totally fine with that but I feel like it's it's worse it's better to have a user some users have to do that than to have inconsistent results such as your ebml code doesn't match your Json RPC result I think my position is now those two should
match yeah I think Al it's also very weird when I'm getting different base feed and it's block is returning but we do also have the option of returning zero in the BL result yeah that's one option yeah yeah but I mean we we already have the code for correctly calculating the base fee for some definition of correct and I I think I'd prefer personally to keep that I'm not super strong on that on that AR the Mantic of gas price being larger than base fee is kind of I mean it is part of the yellow paper
let's say or the protocol could we just is this one of those things is like validation mode on versus off if you have if we had a validation mode that we all agreed on and it was on then this would not be a problem would that be an accurate assessment yeah so this is purely a problem of we're trying to make things easy for the user by setting things to zero that normally cannot be zero and allowing and ignoring not doing validation of things that don't make sense and so we don't want to just return an error if the user ends up situation where the base fre is higher than the gas price because we want things to just work and be simple but that then leads to weird results that don't make sense like should it
work this is this is the whole debate of validation mode versus non-v validation mode right in validation mode we definitely this should not work like you should just get an error and it should just tell you you're doing something dumb don't do that um in non-v validation mode we we're trying to make it it's the difference like typescript versus statically typed versus dynamically typed language right statically typed language stops you early and fast and says no you made a mistake don't do that whereas Dynamic Lish is like yeah sure go ahead and you know add your number in your string we'll figure out we'll make that make sense sort of and then sometimes the dynamic language you're going to get a weird result out at the end because the language let you do something that doesn't make sense um and I think it's the same general line of argumentation
here where the validation mode is the statically typed equivalent stop you early from doing things that don't make sense to the the system so my question would be then can we have some formulation that would like create default values that are like that could could potentially work with validation mode on and won't like in in in most scenarios and keep and place them into validation mode off also so I think the problem we run into is that we're going to have in validation mode off we're going to have to violate something if we have the goal of making
it so user transactions just just work the reason primary reason for this is is we want to make it so people can execute things without needing money to cover gas fees and since base fee can never actually go to Z technically um it means either we need to allow Bas fee to go to zero which again is against consensus protocol rules or we need to allow the gas price to be lower than the base fee and the transaction still execute which is again against consensus rules um or we need to I think those are those are two options right in either case we're violating a consensus rule we have to choose which cons rule we violate or I guess the third option is we don't allow people to have gasless transactions but I'm pretty sure we want people to have
gas transactions in nonv validating mode can we insert like saying defaults for like transaction that is given to us as gutless but to like feel the gas values for it automatically um I guess one option is is we could you say the defaults are transactions are not gasless but we automatically fund every account with some gas money so you just give everybody E I think the problem there is you're going to run into weird things where people aren't expecting accounts to suddenly um mint eth out of nowhere right and so you could then be a little smarter about it and say only give eth to transaction only give eth to accounts that are
executing where where the account is the two address of a transaction and that address doesn't have any eth at all like it's balance is exactly zero and only give it enough e such that gas limit times Max fee per gas is the amount you're giving it so that that would be a way um I believe it's the client developers it sounds like it's adding quite a bit of complexity to our implementation to do something like that but that would solve the problem as well so that way it's you know you can send submit transactions from any address doesn't need to have eth in it but the transactions are fully valid by default and the reason they're valid is because we're basically covering your gas fee by just minting you some e beforehand unless you explicitly tell us not to Mint you e in which case we will then
not do so so you could if you explicitly say you know set this accounts balance to zero as part of the override then we would not do that thing and instead you would get bizarre weird results that last part made it all a bit more complicated right yeah I agree with B it is definitely useful to sometimes call from addresses that have no eth in fact you know one of the we went to quite a bit of length to make it so that's that's possible like we're overwriting the rule that you can't initiate transactions from a contract specially so you can do exactly that so I guess it's
complexity versus violating rule a versus violate rule B those are our three choices or take away useful feature would you elaborate which rules are rule a and Rule B sure we'll say rule a is rule a is the base feed cannot go below seven that's a consensus rule it's like the spec doesn't allow it to go below seven ever rule B is that the gas price can never be less than the base fee of B I think the first one where we allow
it to be less than seven may be a bit easier because then all other stuff would still work regarding the like always positive stuff like that yeah like I mean I can imagine a contract that breaks in either case I think both cases are unlikely to be broken I think it's just we just have to make a call I'm okay with either really you can imagine a a contract that you know some math doesn't work if the denominator is zero like you could divide by zero error and they assume that the base fee can never be zero and that's the denominator of some function but if that's one you guys want to go
with I'm fine with it ca what would you well I mean we already have this implemented as basically we took um route B but I think regardless of which one of these rules we choose um we do have to also specify what to return in the block result the if base Fe is not defined by the block should be set it to zero I
guess that's the y like at the moment it's assumed that it's going according to normal rules but now in my example the user is not defining it so it becomes that that transaction would normally fail if just answer C's question uh my preference is that we should always return the same thing in the evm and the Json RPC result so if the within the evm the base be is seen as zero then we should return zero as the Bas Fe for that transaction block whatever
and that one I do feel a little bit strongly about I'd argue a little for a little bit to support that one I I I have very little care whether we go with option one or two here for the other but should we set the base default base feed to be zero if the user is not setting it uh yeah so if we went with one then I I would say yes the way to solve this is just to set the base feed to zero that would mean that if you set the validation mode true then it would always fail unless you set calculate the base fee yourself and at the moment we have the multi simulate to calculate the base fee for yourself so you don't need
to calculate but then it's we can make validation yeah we can make a a validation true um sets the B base fee accurately but you don't have this other problem um or rather yeah this other problem doesn't exist because we would also default the gas price to be greater than zero in validation mode so both of them would be valid and and higher and then in non-v validating mode we would allow we default to get base Fe to zero and the gas price to zero I think there is one more approach potentially we could take we can uh replace the sender of the transaction with something like system
system address or this is not a good idea um I think we still have the same problem in the end because uh I think the same bug will show up if the user specifies a source address from um but they don't specify the base fee or the gas price so we still have to solve this either way what what is the default from address that we're using right now is it zero yes I think that depends on the client oh we should we should make sure those are the same we have a test for that I mean e call I think it depends on the there but I don't think we have test
for that no we should we should get a test that just uh leaves the from out and has some you know contract that outputs different results based on what the from address was yeah maybe just something as simple as just return the from address do anyone have strong opinions on whether we go with one or two here for non-v validating mode do we allow base fee to be zero or do we allow gas price to be less than Bas fee not really I can go with whatever is
comfortable for guess I would go with Gus price being lower than b base fee you prefer that one okay um it sounds like Cena has a mild preference for that just because you already have the code written you wouldn't have to change anything so we've got two people that have a very mild preference for two let's go with two well actually uh I have a mild preference for one because that's what we have to okay so so gu has two written NE mind would like to write two but has one written and gu would like to write two but has one written got it anyone want to
AR when those are different if that we don't get any negative numbers anywhere if we allow that so in the evm you would have um a negative number which is basically is likely to overflow in someone contract somewhere so someone's contract does gas price minus base fee they're expecting that number to be positive it's going to overflow and and solidity checks may even say this is a checked math that will always give you a positive number but in simulate that number could actually become negative and therefore you're going to overflow and it's you know zerox f f f f f FF I'm really really really really really big number and then something's going to break this all hypothetical I can't
imagine why someone uh that's not true I I can imagine people writing contracts to do gas price minus base fee but what my call return should it return the zero or should it return the normal base fee uh if we went with one it would return zero if the user did not set the base fee yeah so they would return zero in your little call there if we went with two then it's going to return whatever the calculated base be is I think that's what NE is doing because that's why it's
returning but I guess with with the Cho the problems that if you set the validation mod true then I think that would fail even if you add the you have to override the block Bas feore fail with defaults anyway because gas price should be set explicitly oh yeah that's true but yeah when you set that then is the base or then the base feere I guess get calculate it's validating the Bas feere I guess the validation mode so the one argument I have for one
which I'm not going to defend this but the argument I can think of is that two is much more likely to happen in the wild I think one is much less likely to happen in the wild I think there are probably zero to one contracts in the wild today and possibly in the foreseeable future that um that have like something divided by base fee where they're going to get a divide by zero error whereas the the number two scenario I think actually exists in the wild today and is not uncommon it's any any contract that's to trying to calculate gas premium for the transaction being executed which is frequently used in things like meta transactions and stuff like that I think this corner case was found
by Peter because he has this um Chad nft project that basically you can um you can take ownership of an NFD when the base fee goes higher than the latest claim so he certainly faced this issue and that's why he fixed it I say and he faced the issue because you guys had number two implemented right yeah number two is the default number two is if you don't do anything then you have number two and Lucas you said you preferred two
or you preferred one sorry I forgot uh I prefer two okay and and why don't you like uh why don't you like one we can do one but uh I don't know um base fee was calculation was pretty well defined I'm not sure if what what would it need to change it maybe it's not a big deal I don't I don't know yeah I think I think all of us agree it's not a big deal either way we just need to pick one yeah just one uh two are like more in line what we're doing on other potential
places right like what like f feels more more natural to me what why I'm used to um yeah let's um to postpone this decision to next week sure someone come up with a good argument either way by next week if not we'll flip a coin and choose one nice and could you Kari please update the trailer with the issues that we are currently having so that I could brush up on them also if there are any yeah I had some issues with the test RPC and I guess CA fixed it and then I
can run it again then I can see what other differences now perfect or did you push the pr to the test RPC but I guess need to be merged or I need to refer that you can uh you can make those change just like two lines you can make it in your local repo and already do the testing until that gets merged up Upstream okay do girls well there there was a topic that kind of was discussed shortly last week about um removing Phantom
bucks now M was pretty set against it um but we said we would discuss it this week as well so just bringing it up in case could you elaborate on what did we mean by removing Phantom blocks basically what I mean is we would require the user to provide every subsequent block as in the number has to be strictly increasing by oh why so my um my reasoning was that
Phantom blocks are kind of weird um especially in places where we have where we have moving averages for example in the case of Base fee and excess blob gas these are things that move with each like these are values that get adjusted with each block and the approach that we we took now is kind unintuitive um to the user I think because um when you have 100 empty blocks that means the gas
used is zero that means like for 100 blocks the base fee should go down but we're not actually doing this yeah I think I see where you and I our mental models differ uh for Phantom blocks I've always imagined them as not empty blocks but just like you know average blocks like here's between block n and Block M where you've got like a 100 block space i i in my head my mental model I'm like okay there's some blocks there they're normal average whatever meaning the Bas fee doesn't change because they're you know Middle of the Road full middle of the road not interesting you know just a bunch of e transfers or whatever again just the
mental model my head sounds like maybe it's different which is perhaps part of why we're disagreeing on this exactly I think it's a like they are confusing and we've had to kind of add a whole section to the documentation because of these Phantom blocks and um basically it came up for me when uh implementing Beacon Roots um so the thing with and we have the that whole complicated thing with block hashes so very unintuitive we had to invent a scheme to calculate the block hases for Phantom blocks which is kind of
just really hacky it feels to me and we have the same thing now with Phantom block so we would have to invent another scheme for that because uh Beacon Roots can be so we basically contracts can access the beacon R for the last 8,000 block what do you mean the beacon rout can access last thousand block mean the beacon Roots contract so basically users can request the beacon routs for the last 8,000 blocks and that means that when we have Phantom blocks we kind of have to yeah
somehow we have to return something there and we would have to add them to this system contract is that a new thing that's coming or that that's uh that's already shipped it was part of the last Fork oh okay yeah I only realized recently that we actually we need to add support for this in simulate and E call yeah because this is the first time that um we've had a basically contract update from the system right previously contract updates always occur due to transactions that execute I think it's the first time in ethereum's history
where the system itself you know wrote to some addresses storage exactly so at the beginning of block we would have to do this extra processing to add the the beacon route for that block to actual to the actual try right so I agree with Cena wholeheartedly that Phantom blocks add a lot of complexity so I'm not disagreeing on that at all I think for me the I just see it as complexity that is worth it for the benefit of being able to um have very large gaps of time that are accurately
represented now I think the thing that would convince me otherwise like if I was going to argue against myself here if I double out any well-written contract should use time stamps for large spans of time they should not be saying you know after a million blocks have passed do X or have X as a some function of number of blocks pasted like that is not the way you should be writing your contracts you should always be using a time stamp on ethereum like you should if if thing you care about is time pass you should be using time stamp you should not assume that blocks are 12 seconds you should not make any assumption about stuff like that and there are essentially no use case that I could think of where you
actually care about how many blocks have passed um but it would cost more wouldn't it to look at the time comparison in comparison with looking into the in both cases it's just two numbers minus each other so I think the cost should be identical in one case you're just doing block. time stamp minus your save time stamp other one you're doing block. number minus your save number so I think the execution costs are identical in both I believe the one place I could see you maybe counting blocks is if you've got some system where the number of blocks that have been produced um since a previous thing occurred lets you calculate like the security parameter
some security parameter right so you've got some some so your security your system is a function of number of blocks passed between two points in in time and it's not a function of how much time has passed so if you know a thousand blocks happen in 4 seconds then you're just as secure as if a th blocks happened in a month um and so I can imagine that but that's a pretty far-fetched kind of construction and I don't think anyone's doing that and so the argument against my position in favor of cen's position is just that no one should be writing contracts that do you know block number minus prior block number and so um we don't need the ability to simulate you know large spans of block numbers we just need this ability to simulate large SP of time and
we can do that by just allowing you know block n to have a time stamp of X and block n plus one to have a time stamp of X plus a million and we currently allow that and so I think that's that's my argument against myself I don't know if wins uh clari yes on ethereum Main net today blocks happen every 12 second oh no slots happen every 12 seconds blocks do not necessarily happen every 12 seconds blocks blocks happen on mod 12 second intervals um that being said it is not set in stone that that will never change and in networks that are ethereum like but not exactly ethereum those numbers can change and one could easily imagine and and there are Dev Nets that have
that number different that are ethereum Dev Nets not public test that's but the internal Dev ones often change that number as well and even like I think you can spin up Nether mindes and gu both with like their out of the box Dev test net and I think it's got one second block times and so it's just generally a bad practice to use assume blocks for 12 seconds which is so no one should be no one should be doing that especially when you have a literal clock how does the beacon routs work is is every block or every slot need to have a beacon rout and if you're doing each sybol like this we creating new blocks then we also need to calculate some kind of block route for every block as well I would love to know the answer to
that question what happens when you have a missed block does it be get two updates in one block uh no only the the B the Bon block that is corresponding to the E block we'll have the update okay so if you have uh a Miss slot you would basically you'd update the beacon roots with a hole is that or sorry you'd update the beacon roots and that would result in a hole in the list no because you can have same height El blocks on different CL blocks oh I see so it's a um this is Beacon roots
are a function of BL e block number not slot number I think IND I'm not entirely sure I would have to double check C you know I think so too I I think they are related to E blocks not C I see okay so if you Sate 10 blocks forward do we also need to calculate those roots for those 10 blocks if we were doing these shadow shadow blocks then yeah we need to back fill this is I agree Cena this does add some complexity that I hadn't considered I'm meaning just when you normally create new blocks that are one after another and no Phantom blocks do we need to calculate some bigger Ro for those as well yeah we need to update the beacon R state for each one of those and we should have test for that basically
then the question would be that if I'm a user that wants to simulate block number one and block number million I would need to stick in uh like 999999 empty blocks with gas price zero for this same thing to work for me yeah uh yes and you would almost certainly get throttled or if you're running your own node You' crash your own node no no no you don't really need to no no no you don't really need to put blocks anywhere it's just you need to update the state correctly with 19 999 uh hashes in the state so we don't really need to put any
blocks it's just a simple State update to be honest for we' have to adjust our Json RPC API to support something like that or you saying we would use the same AP we've got right now but instead of doing these Phantom blocks we would actually you know generate some blocks get some hashes update the beacon Roots etc etc for each one of these along the way oh okay that's what you mean so um why would you generate a block to get a hash like I don't get it if we got rid of this if we just got rid of the whole concept of phantom blocks then uh the client like there's no virtual blocks at all like every single block actually was a thing that was executed may have zero transactions
and execute execution may have been short but it was treated exactly like you if you specified every single block along the way it may have all defaults that's fine but you've got we don't have okay this is about beon Roots right we don't have beon roots in eth simula in any way I think we're we're saying we should update Beacon route yeah so we should add Beacon roots to the block overrides okay okay and we should calculate it properly if you're not overwriting it what do you mean calculate properly meaning as you iterate over blocks we actually do fill in the beacon rot Merkel tree or we you know have some sort of virtual function
thaton root Miracle tree how would you feel beon root mirle whatever whatever the data structure is the storing all these uh Beacon Roots right so in cont contract we just fill in default Beacon Roots uh and that would maybe be the has yeah what data would you put as a beon root of a block where you don't have a explicit see that's you're saying so you're saying for each simulate we literally would just be making something up yes to put in here yes exactly and so it's either a random number like some sort of deterministic round number or it's just a fixed value each time like the zero hash or whatever
yes it's either a fix value we can have like a consecutive counter because it's basically you know uwing 256 in some other way yes so we can have just a counter put block number there as a counter right whatever right we can do multiple things yeah okay I think I'm I'm very slowly I'm slowly coming around to Cena's point of view just in that this is one of those things where there's like lots of little tiny bits of complexity that are just starting to add up and Beacon Roots is just simply the latest one where our Phantom blocks are adding lots of little tiny bits of complexity no individual one is bad we
can solve all of them but there's a lot of them in my opinion Phantom blocks don't have complexity here too much because you have the same complexity if you just don't override uh this you still have to put something there and in my opinion users would just fill in with nearly empty damy data and I think there won't be any issue for the node to process block that is extremely empty it won't consume any any real gas so yeah so let's say let's say we simulate block n and block n+ 1 million yes
um so if we don't have Phantom blocks then you are going to have to do some amount of execution for each of those no no keep Phantom blocks if you didn't override uh block yeah I'm sorry I'm um Roots then you just just returns empty hash for it and that's be done with it right regardless if you have Phantom or non Phantom blocks so so the point here is that you would need to um go ahead and do this state update for all of these one million blocks or you would have to write some specialized code that does does this lazy evaluation
yes and I will do lazy one to be honest all right I agree I think that's like from a performance standpoint lazy one's definitely the way to go here but that's now again more complexity in the clients to support Phantom blocks one more small piece of complexity but it's additive to all the other complexity we're getting just for support for Phantom blocks and so I think the question that Cena is the broad question Cena is trying to propose and I'm slowly coming around to is that we just keep adding little the Phantom blocks are adding lots of little pieces of complexity and it's not clear that they provide the commensurate value to users especially since users should be doing timestamp based stuff anyways and and my question here is that like given that we want to support those
features is it possible somehow to like override something in those contracts to make their time span a bit shorter so that they do fit in 200 blocks that I can actually do simulate on automatic not automatically like the the things people do with timestamps are often you know complex defi Lego things where you're like okay I need to calculate um continuously or per second compounding interest and so they have some function that comp calculates compounding interest over some span of time and that's going to be very wrong if you don't have the proper amount of
time that being said anyone doing that should be using time stamps and so removing Phantom block support would not break them if they correctly use time stamps it would only break them if they had compounding interest as a function of blck number where it's like each block compounds the interest a little bit and if you're doing that which again is very bad idea you shouldn't do that uh but if you did that and we don't allow Phantom blocks then you can't simulate into the future the block has some R then that's also breaks I think why block break uh because if you want to change a transaction that refers a block has and then you want the block has to match something then you might need Phantom
blocks to do that okay I have a uh very uh very cool idea okay uh so if someone supplies you uh the overrides then you override right that's simply simple thing but if someone doesn't Supply you overr right you just do nothing and because this if I remember corle correctly this is like a round dropin list that you go through it in in the in the actual uh implementation then you would just
return uh some data that is some from some other uh block but it would be consistent uh in different implementations you just do nothing and you just return it so you're saying that we we have some kind of placeholder pre-built blocks that we just all agree on no no no I I'm not saying it because you're starting from some state right from the uh from the main blockchain and it has some values there right y so uh what if the the chain is less than 8,000 blocks old then that would be zeros
H if you read them right yeah yeah so no problem yeah I think also to counter m point one thing is that if you allow users to override time stamp and at the same time you limit the ability to override block number it would feel like a pain because you want to override them both together you want your Phantom blocks to exist if you can have Phantom time um so yeah I mean that's that's the the that is the broad General argument
um Phantom blocks is allowing users to overwrite anything that includes down to the block number uh I'm I struggle to think of legitimate cases where a user actually cares to over the block number vant if you know of some situations where overing block number would useful that' be super helpful I'm struggling to think of cases where you know you want to do that and you know it makes sense not just you're doing something stupid or you should have been using time stamp we can continue discussing this and it is late sorry I didn't realize it was past our normal stopping time um perhaps we can continue discussing this in Telegram and like I said I'm starting to come around so
maybe I can re-engage with you there CA more on this y sure I guess we need to discuss the bigger roots and how we are going to implement those if we want to add those as well we can continue that in telegram well yeah let's do a sync and continue next week thank you all guys for coming you thank you bye thanks