leanVM-01: leanVM Crash Course and Sumcheck Optimization

leanVM Workshop 2025 · 3 Oct 2025 · 58:00

A workshop from lean week in Cambridge, UK, held on 3 October 2025 and hosted by the Ethereum Foundation. leanVM is a minimal zkVM designed for post-quantum signature aggregation and recursive proving. This session is a crash course on leanVM and covers sumcheck optimization.

Speakers

Topics

From leanVM Workshop 2025, hosted by Ethereum Foundation.

Transcript

[Music] movie FP sorry FP something else this is like one instruction one instruction will tell you this >> okay >> this is like >> so how does this relate to the fact that the memory you say is read only >> uh because for instance if you have a if you want to compute the difference of two things I don't know if you want to comput x - y and store the result. What you will say that you you will have one dedicated cell that will store the result. Uh and uh you transform a difference into an addition and then you

you put then this is this will become one instruction that will accept that this cell correspond to the differences of the these two cells. >> Okay. But once once the memory is represented as a big vector and once you write something inside a cell of this vector this is forbidden to rewrite something again on this set. >> So it's like write once and not only >> but it can still use that cell for assets. Yeah, you can see it as the right ones or you can see that it's because from the point of view of the

verifier there is one memory which has been previously filled by the prover and he's you simply accept that some relations between the sets are valid but you can see it as right once and if you rewrite you must get the same value it's a bit better >> but I mean if one then does you know like an assertion by saying add of element plus zero equals to something >> uh to some thing that was written to that uh memory location before then that wouldn't be valid. No, because the add instruction would still technically write to >> to the Z.

>> I think is the I I think we have we just have an execution trace and these are we're just checking constraints against the controller. >> Yeah, we only verify slides. >> I think I think we should think about this memory is like an execution trace that's been committed to. >> Okay, so we're already already there. You're not talking. >> Yeah, sorry. I think I was getting >> um so this is it clear those add and becomes relation between me. Okay. And as I repeat myself but it's relative to FP.

So you cannot do memory index three not possible. It's always relative to FP. Okay. So there's two first op codes. Third op code. Um the reference um the reference of code basically you basically let you do this memory index memory FP I will take as a constant like And it could it could also be a constant

like 500. So it let you access memory but instead of indexing indexing relative to FP plus constants it's indexed with a cell in memory. So it's like a referencing a pointer and this is useful because previously we were able to manipulate memory only relative like inside our current frame in memory. The decision is frame is abstract. But when you want to program using this ISI, you need to have to conceptually think in term of of a stack

or frame of memory. And using this instruction, you can write somewhere else which is not in your frame of memory. And for instance, um how will we implement function calls? Because you can see that each frame each fun each function has its dedicated frame and if you want to jump or on another fun another function you will need to allocate another frame. So for instance this is the memory.

This is like the current value FP and this is your current frame and you want to call a function with some arguments. And so what you will do is that you will allocate some chunk of memory. You must know in advance at compile time that this function will consume 20 F elements. You you must know the the the the memory footprint of each function. And um the idea is that you will be able to so this is the memory but there's also the the the B code this code and let's say currently we are here and your

function is here. So you have to jump into the B code to the location of your function but at the same time you want to jump in memory so that you want in what because if I take some events there will be a jump. This is the last op code. There will be a jump code that enables you to modify the proton pointer to go at the location of your function in the B code, but at the same time you want to modify your frame pointer because you want to access fresh memory. And so the key idea is that in KO for those who

are familiar with Kro you have one register uh the allocation pointer that points in memory to the last used um like in memory the allocation pointer points to the free uh to the part of memory which is still free to use but here we don't have the allocation pointer. So the idea is that when you want to jump to uh a function you will receive as hint the pointer to a new location to a new frame. And for instance, if you say 20, you will

receive as a hint this value which points to a new frame that the prover has allocated to execute this new function. And um the key idea is that because it's read only from the point of view of the verifier, you don't care where this new chunk of memory will be allocated. The prover could allocate it here or here here. You don't care because from the point of view of the verifier everything that will happen then will be the same because the the the relations between the cell will be the same and you do not risk

important to overwrite previously written chunk of memory because it's written and so that's why you can give the prover the liberty to allocate this chunk wherever he wants. And for the when you want to call a function, the prover will allocate the new chunk and we'll store the location of this new chunk in the current frame. And then there will be in the incription to jump to the B code of your new function and to update FP with this new value.

Yeah. And okay, >> one question. Why cannot like the hint be malicious? Like I say, >> yeah, I'm going to the right person. Sure. And then you move it to another place. Uh because actually you can um if you put 2011 it would still work because all the computation that you will do it's read only. So you you will accept the same things between the cell and when you will come back um because actually you will store the arguments and the result that you call your function like if you want to call your functions with an argument like your function f has let's say two arguments

you will store the argument at the beginning of this frame using the derence instruction because using the reference instruction you can before jumping you are still in this frame you can access the value here using this reference instruction. So before you jump you store the the arguments you want to call your function with you jump you do bunch of computations and also before you jump you also need to store the current frame pointer and the current you will also store the

current program pointer because after you you jump you execute your function in the end what will happen is that your function will jump back here and here. >> So, so Emil, so jump is used for calling a function, returning from a function as well as local flow control within a function. >> Correct. >> Okay. >> Correct. >> Um I I guess I'm a little unclear on what the spec for jump is like. What are what are brands?

>> Um, do you have your computer? >> Yeah. >> Yeah. Uh it's I think if Yeah. [Music] and and okay. So jump is a conditional jump.

It doesn't. Mhm. Uhhuh. Is your keyboard done? It's not my laptop, but it doesn't work quite well. Okay. >> Would you like to use mine? >> No, let me use mine. >> Oh, I see. That's the university's laptop.

Tragedy of the commas. [Music] You're familiar with Cairo, right? >> Yeah, kind of. >> Why didn't Cairo do this? Why do they have the extra um uh register >> the the other one?

>> Yeah, they have. >> Yeah, >> I think in the it was like kind of whole thing because in the new one they don't have >> the new one they don't have it. >> Yeah, I think they have replaces >> cuz Kairo M doesn't have it either. >> But the new one from Starware also doesn't have it. >> I think the new one from Starware is a Kairo M. >> Oh, I thought Kairo M was from Ky. >> Yeah. Yeah. When we asked to Maya, she told us that they're kind of collaborating. >> Okay. >> Okay. >> Sounds like a case of convergent evolution, >> right?

>> Nice. [Music] Can everyone see the screen clearly? See, but um does every frame always have a program counter and frame pointer cell uh in it?

>> Sorry. >> Does every frame have um a cell for program counter and a cell from frame pointer? >> Does basically every frame has FP >> FP and PC? >> Yes. uh because um this is like two register values that at any moment you have one FP and one PC. Okay. So, um, if someone has a better computer than I don't know why it crashed. Okay.

>> What's Wi-Fi, by the way? >> I don't have an HDMI port. They keep stealing our course. I mean, I still do, but in my laptop, it's a pain in the ass to get anything working. Like, I have to activate my Nvidia GPU that's in there in the BIOS because otherwise, you know, like internally, it's probably so that the HDMI port cannot be used and then only the HDMI port works and the display port also has never works.

At least >> I suppose I'm traveled for work in the last couple years. I discovered both my laptops would no longer move. >> So I was like, "Okay, let me fix this. Open it up. Look at the battery. Can I find a replacement for this battery? >> No. >> So, I have to laptop. >> Oh, >> that's why it's windows, huh? >> Planned obsolescence.

Intentional non-repairability. >> Mhm. >> Okay. There you go. I don't know what you're here. Okay.

Okay, perfect. Okay, [Music] perfect. So the question was the details of the joint infection. Okay. And um as you said it's a when you want to call your function before you jump you write at the beginning the frame pointer the current frame pointer and so then you can jump and in the end after your execution you can jump back using the same instruction but in in this case the value

the updated value of FP will correspond to the previous value of FP Because you have stored it here. [Music] >> Okay. And as you said also um we can use this jump for control flow. So if else in which case you will not update the frame pointer. You will simply jump into different location of your by code but you will stay in memory in the same frame. But typically in your B code you could have some kind of uh this is the

start of of your function. You execute some instruction and then you have an if f in your by code. And how will this be implemented? Using two blocks of by code and you have a conditional jump that will either go here or go here. and in hand both blocks will jump in an unconditional way to a common continuation of the weight cut.

So if you do a function call, you need a return address to go back, right? >> Yeah. >> So because we don't have a return or a stack to put the address in this, the compiler needs to pre-ompile the return address itself. Um there are two things uh when you return you need to know the the PC you want to return to and the FP you want to return to >> and both values will be stored in memory at the beginning like >> the frame.

>> Yeah. Um this is so you were here you want to jump here before you jump you store here frame pointer here pointer and here first argument second argument result >> okay so it's passed as a input to the function >> exactly exactly >> but but so the the program counter and the frame pointer like as as a register essentially they are really stored you know uh like the the current values you're actually they are stored independently outside of memory >> exactly there there are two values independent of memory um FP and PC and this is like really independent of

memory the current NPC and the current FP and here what you store is that at the beginning you store your current FP and PC then you jump and when you jump these values correspond to your previous PC and your previous FP that will be useful to come back to your previous context So it's a stack but with only two slots. >> Yes. >> But and so when you jump back do you then increment the program counter relative to the value that you had stored so that you actually jump to the instruction after? >> Correct.

>> Correct. Actually when you stop the PC what you do is that you you don't store the current PC you start current PC plus one. Yes. Correct. And um with these four oper codes muff and jump you can do uh so you can call functions return from functions if else um what you cannot really do is loops because in ko uh you could for loops and I'm not a expert but I guess it's done like that you could have your loop to stay in your in your frame. Yeah, you

could I think and you're not sure but I guess that in Kro when you had a loop you you could keep the same value of FP and just at each iteration of your loop you consume more memory and because you keep the AP register you can know um you keep track of how much the memory has expanded but in this context there is no AP so we must know at compile time the exact um size of the the exact footprint of each function. And so you cannot have a loop of unknown number of iterations in your uh in your frame because it because

each each iteration would consume some some more memory. So you would run out of memory inside your frame. So what you do is that you use a compiler to transform loops into recursive function and it's it's it's doable like for instance if you have a loop that for instance Fibonacci you can implement it using the loop but you you can also implement it using recursive and it's possible to tell a compiler to convert all the loops into recursive function and using recursive function when you have a new iteration of a loop it will allocate new memory there is

some overhead because it will have to store the PC to FP jump do the computation jump back so it's there is some over some overhead but the benefit is that you don't have to store you you don't you you can remove the AP register at the cost of having to store some values in the beginning of each new frame >> yeah but if you transform loop uh into uh what's called compiler technology continuation passing style. >> Okay, >> you actually don't need to return back. You can use state code optimization. So you just continue and you never jump back. So you can actually not store those um uh frame pointer and instruction pointer.

>> I think I see what you mean. And this is I think this is a >> this this is called TCO optimization. And um well it's unfortunate but the technique is called continuation passing time but it's not continuation and okay. >> Um so here's a here's a thought experiment for you. So so you say that we can't have a loop with an unknown number of iterations. Um and that's because uh well we're assuming that the loop is going to write some values to memory on each iteration. So if you don't know in advance how many iterations then you don't know um the uh memory consumption of the function. Um

but there there's this malic function right? Um so uh I I guess in principle you could allocate say an amount of memory that you know would be sufficient for however many iterations the loop has. Um and uh you may allocate more memory than needed but that would work right. Um this um uh the malot indeed there are two because um in the this high level language that compiles this ISA you can indeed use maloc

but are you speaking of of a maloc with compile time known size or a maloc where the the the number of the size you want to allocate is unknown common at compile time. >> Well, either way because if if you want to allocate some compile time known um memory, you can include it in your so it's easy because it will be included in the overall footprint of the function. So it's it's easy when you write maloc with an a value which is not compiled the time known what will happen is that uh the memory will will be allocated somewhere else not in the frame and then

you will hint this value as the the location of this allocated frame. But if you want so for instance you are in you are in this frame you want to mlock X uh with X an unknown value. What will happen is that for instance the allocated frame will be here of size X but then each time you want to modify one value here you need to dreference because it's not in your frame. So you need for instance if you want to access this value you need to reference to

store it and then if you want to addition with this value you need first to to the reference to store it addition and then the reference back here so you need to use the ref a lot and it can be expensive and that that's why I would suggest in this case to jump like to to define a new function to jump in this context next do the computation you want to do in which you don't have to use d and then jump back at at your function.

>> Mhm. Okay. So in essence uh you could have a loop with unknown number of iterations if you can put upper bound on the memory consumption. It just wouldn't be a good idea. >> I think yes. >> Okay. I think you could indeed you're right using df but um it would be costly but it could work. >> Understood. Okay. Thank you. >> Yeah. Actually, maybe if if your footprint is like really slow, your ID may be more optimal. Yeah, >> maybe sometimes. >> Yeah. Yeah. Yeah. >> And yeah, I remember you saying that um you kind of you allocate memory and sometimes part of it is unused.

>> Yeah. Um, is it fair to say that if you were to do kind of two passes where the first pass kind of determines how much memory is actually used and then the second pass kind of compresses everything, you should be able to remove all the zeros. >> Um, this is already done. >> Yeah. Yes. Actually, there are two things. There are the um um Okay. Because this is due to the thing that the two passes are due to the poss but I can talk this is like a little bit another subject but we can enter if we are done with this I can talk about poss but

first >> I don't want to derail the conversation. >> Yeah yeah yeah but I will I will answer the question but is there any more questions related to G etc etc. I'm good. Okay. Okay. So, okay. Um, there are already two passes and I think that we could do more things into the first pass. The the thing is uh we need a pre compile because we we will not do by hand using the it would be much more way too slow. So there is an exception let's call it poson 16 um

that's perform a permutation permutation over 16 actually there is also a 24 which is useful when you want to hash long slices slices um and so So there is one instruction on 16 that will read and write in memory but uh by chunks actually how is it currently implemented 16 takes in uh three arguments um let's say a b and c and for instance an example will be easier let's say a = 2 b = 5 and

c = 10 b = 2 meaning I will read uh 2 * 8 3 * 8 here we have eight field elements = 5 5 * 8 this is like okay start and six * 8. You also have eight elements and 10 here 10 * 8 12 * 8 you have 16 field elements

and what this means is that you concatenate this a are the inputs you concatenate them you obtain 16 feeding elements you can imitate and you write the results here. So then effectively this Poseidon 16 would have an internal state size of eight instead of not 16. >> So the pose here would have an internal state size of eight and not of 16. So it's like like a proper hash function and it's not just >> the it's not you can see it as a permutation like no no hash function

it's actually can be used to build a hash function indeed using like a spawn construction with internal state 8 correct but uh from point of view of the VM it's simply a permutation so no notion of internal state capacity okay but I mean just because if you compress 16 elements into eight and Um but it's compressed into 16 but this is >> eight 16. >> Ah the output is 16. Sorry I understood the output to be eight. That's why okay >> and um okay um but one key thing here is that um everything

is aligned. So our inputs uh have length at least eight and are aligned by eight. Like you cannot hash for instance the memory at index the three to 11 not possible because um for the proof system it helps a lot to have everything aligned by eight because you will have I didn't talked about it for now but if you guys that you have this memory which is committed and you have some f tables to prove the pre-ompile so pro and you will have a lookup from your procedon table into the memory. And due to the

fact that it's aligned by eight, you can um you you can and because we are in multilinear sitting, you can uh use random challenges random challenges to compress everything and to reduce everything like everything will be squeezed by eight. And so these eight feed elements will be transformed into one extension feed element. And you will compress everything and you will obtain like a memory eight times um smaller but in the extension field and you will prove the lookup in this compressed form. And it turns out that in particular using

lookup star it's much more efficient. So the lookups are almost free compared to the the the costly part in terms of lookup is in this memory uh where you have a granular access to each field element. This is more costly. Yes. Basically one question I have is um presumably every time you call 16ation it's in the context of the hash function of the sponge. So why not just have a pre-ompile for the whole hash function >> like only one output like 16 input and you mean eight input and eight output

>> for example. Yeah. Um because for instance in some cases for instance the the it's a it's a good point. For instance the XMSS chain we only need um so when you sign XMSS the chains there are v= 64 chains you need you only need eight inputs eight outputs. So you we could have a procedor that only like to be more efficient in it. We could have like a dedicated preo compile to do only eight and eight. But for instance in the fiat >> for recursion you need you need the full state the 16 field elements. Uh is it true? Yes, I think uh because

do we need 16 limits uh and also for instance in the mer tree in the compression. So in the XMss you have your inter one time signature and then you have your mer tree when you want to compress you need at least 16 inputs to compress. So you so the a are required >> and then catch me is it like first would you be using potato 24 to absorb like more >> um I think it's in plank 3 I think it's

currently we we do like we >> I think we do 24 per >> okay I think >> I filled around at some point. I don't think that is true. >> Yeah. Uh I believe in in WP3 it's it's the implementation is 16. >> Yeah. >> Um and that's for instance one reason we need these 16 outputs. So >> we can we can switch. No, this is just a setting that we can switch to.

>> Yes. Yes. Yes. But to answer in in some cases we only need eight inputs, eight outputs. In some cases 16 inputs and uh if we switch to Firer 24 maybe we can always have one like always have eight outputs. Yes, that's possible. Yeah. Okay. I should write things >> I'm writing some breaks down. We already have three >> because there was also the idea of the >> the thing.

>> Yeah. >> Yeah. >> Yeah. >> And also the the idea with the the loops that sometimes if the loops are small don't create new function but simply okay but I think I will >> and there was the bus ride as well. The bus ride from yesterday when you on the bus >> I will come back to it later. Okay. Uh okay. Anyway, so um okay and to summarize there is approximately the same thing with pos 24. Okay, because we need 24 when you want to hash for instance in XMSS you have your your chains 64 chains you obtain the 64

digest and you want to hash the whole thing to get the leaf of your mer tree and it would be two times faster using 24 over 16. Anyway, um the key thing is that all those memory accesses are by eight and are aligned also by eight and um actually uh currently uh in the uh in the implementation of the compiler there is this notion of vectorized memory and non vectorized

memory. Vectorized memory it's when it's aligned by eight and everything is a multiple of eight and currently it's it's um there's memory currently all the vectorzed stuff is at the right of your memory vector. Um this is at the right answer currently. Uh what there is like two passes when you want to execute the program.

uh maybe we we can do better I don't know but like what happens is like uh initially I the problem is is the problem is executed with a huge memory and vectorized memory is set at half and the goal is that the non vectorized memory will not clash with the vector memory. So the non vectorzed memory will end up here and the vectorzed memory will end up here and then we can run again the program. Then but now the vectorzed memory starts here and so in and and so in the end at the second

execution we get a compressed memory without these zeros that are that are here. I know director but should I repeat? >> Uh yes. >> Okay. Sorry. Um so the memory is in the current implementation there is like the vectorzed where everything is a multiple of eight and so on memory which is at the rate of memory >> and there are the non vectorized like normal accesses in memory and uh the issue is that when you start the execution of a program you don't know where your normal memory will end up and so you don't know

where to start your vectorzed memory. And so how it's done jointly is that there is two executions, two passes. In the first passes, we use a huge memory to be sure that if I start the vectorzed stuff in the middle, the normal stuff will not uh interfere. It will be smaller. It will stay below. And so the normal memory accesses will end up here. The vector the vectorized memory accesses will end up here. And there is some security room because we have taken a big memory. And then we reexecute everything. But instead of making the

vectorzed axis start here, we make them start here because we know that the normal memory accesses will end up here. So we start the twice just after. >> So you you take the first pass to remove your security room. Correct. >> Yeah. Yes. Yes. It's almost the same. Everything is the same as in the first place, but there is no more this security this. >> So during the first pass, you analyze everything and you you know what the security room is, so you remove it.

>> Yeah. Yeah. >> Yeah. What's the cost of this initial pass? Actually it's um it's it's the witness generations currently is like uh I would say between five or 10% of the whole thing and this increase the two passes but this could be probably can at least 10x I think performance of the generation could be reduced by at least 10 >> and you can remove the security buffer within the internal function calls on the left side as [Music] So my understanding is that when you were when you called Maloc internally on the left

>> you kind of allocate the worst case. >> Ah okay. >> And then you can remove the safety buffer. Same idea. >> Okay. Um when I when is called internally like with normal pointers um there is not distion of worst case. So it's but >> okay >> you're right. That's because the thing you were speaking um uh like some time ago is there is indeed in the end some zeros in the end it's not perfect because the issue is with the if else if you have I think Morgan always talk about this I think um if if you have if something you have a program

else you have a different program but imagine the the if condition uh is much more complex than the if else and and when you compile it you need to uh it could be both case you you don't want advance so you you need to allocate quite a lot of memory in in case it's the if that we enter the if but if we enter the s there will be some empty memory like unused memory and this this This is where why when you currently in the benchmarks you you run you will see like memory usage 95%. There are 5% remaining because of of this. But you

could easily prune that in the second run right? >> You could prune let's say you >> uh the thing is that at compile time there is an issue with because it must be some somehow known at compile time. Um when you have if else uh I don't know. Yes. Yes. Yes. Yes. Yes. Maybe. Yes. Indeed. But it So it's not compile time, it's kind of run time.

>> Yes. Uh then >> yes I think there is yes we could make it work but not in particular it needs to be I think we need to put it in the end of the current frame. Okay, it's complet but yes maybe for sure we can explore but it's it's like an optimization not but yes >> um so regarding that uh if we follow up on the continuation passing style uh those if and else are transformed into continuation of the current computation and so it's a separate chunk of the function okay and so um if you do this pass where you verify what's being used

you can just check that those uh branches of event else are in use and then delete them and prove them >> actually. >> I see. >> So uh yeah, I think it would be worth it uh if you look into uh continuation passing by compilers. Uh I can give you some references of books um because it may be uniquely suited to what you want to do. >> I see indeed we can And eventually we can go up to 100% of memory usage. Yes.

Removing all the zeros. >> These two passes are on compilation time or when to generate the >> the two passes are at generation time >> and like we have only two programs with some limited uh inputs. So can can we not like make a mix of the lookup and maybe some calculations um >> to do only one pass? >> Yeah, because mostly because we run two programs if not >> like to instead of doing two passes to one pass and to modify the thing a bit to to make it work.

>> Uh yeah kind of try to guess the right amount given that the parame is always the same. Uh >> I see. Ah uh good point. Good point. We we could uh try to for instance depending of the number of XMs being signed we could probably No. Yes. >> I think it works. >> Can you repeat? Um uh uh we could knowing uh like we could have a program that takes as input the the public memory and will tell you exactly without having to execute everything.

>> Uh this will use this amount of memory and this amount of memory because in practice XMSS it's like something really predictive. So we can ms to take this amount and we can yes I think >> we can turn well if you know maybe if we make the language weaker like if if the if the use case we care about is really deterministic and all of this uncertainty that we're discussing does not apply then maybe we can just build uh sufficient conditions into the language to uh you know ensure that determinism that could make easier.

>> Yeah. Uh even we can also restrict the number of symmetries that we uh I believe to power of two. Um and we know what we take for 5 12. >> Yes. Yes. Yes. Yes. Yes. Like even if it's not have to we can we could pre compute like between 1 to 2,000 to 10,000 MSS premputee everything and have a table. Yeah. Yes. Yes. It work because this is not something entwined in the data. This something that only the program. So if it's a Yes, definitely. It works.

[Music] >> Um Okay. >> There's a coffee break in 10 minutes. >> Yeah. I don't know if >> just just to kind of >> when you when you write there with 16 you said like a is two and b is five right like technically of course that should be like a multiple of eight given that it should be line right that's what you said >> uh and so like two and five here would be kind of like in this space of extension field elements right to some extent like in if you want to have five to be a valid or even two to be a valid that kind of a line value, right?

>> So, so like you said explicitly like for example you couldn't have the you know values from 3 to 11. >> Yes. Great. >> Yeah. So like in that point of view like two and five are also not you know sensible values. They're only sensible because we are treating them as being multiples of eight in >> Yes. Yes. >> Yeah. >> So then uh with Poseidon 24 um what do the inputs look like? Is it like eight and 16 or >> Yeah. currently with poson 24 um uh I think so we have a same ABC this is to make the theation simpler obviously

let me say so two five and 10 same example and so you take If I look at correctly, yes. Uh, yes. 2 * 8 to 4 * 8. So here you take 16. So for A you take 16. For B next 6 * 8 you take 8. And here 10 * 8 11 * 8 you only take eight. And what you do you concatenate

the 16 with the eight. You obtain 24 feed elements. You permutate and you keep the last eight. And the last eight this change here you write it here. >> Okay. Because it turns out we only use the like the the last eight elements of the permutation. >> So the pose 24 actually has a smaller output than the Pyon 16.

>> Correct. Correct. >> Is there a reason you don't give just three inputs like three inputs of size eight? Like is the reason you force the first two to be concatenated all times? >> Uh like could we do like eight eight and eight? >> Yeah. um not currently but we could imagine doing it but uh uh this has some advantage because uh the advantage is that there is only three um three values and so your um because there is if you look back at the add and null there is always often three memory access per cycle and

So every instruction can access at maximum three memory cells. And if you want to add like a fourth parameter uh A, B, C, and D, you would need a force memory access per cycle. And so this would likely slow down a bit, but it could be doable. But actually um >> so so there's there's some there's some requirements previously coded where you only want to do three memory accesses for each like like you want each instruction to have at the most three memory accesses.

>> Yes, this is to make it simpler but nothing for this we could design a system with four access but actually the pro 24 is not used very much. So uh for instance I think it's only used currently in XMss to hash the the what's the internet publicly and in this case actually we uh yes uh you need this eight to take into account the the state like you have your states and

you want to incorporate new information. So your eight will take will be your state and this 16 will be the the additional part that you want to ingest and that's why using only two arguments it's it's sufficient I believe in the current situation. So if all we're using it for is to hash the winter's pub key, why not have an op code that's just hash the winter's pub key? >> Uh we could do it. Yes. Yes.

>> But uh for recursion it canify things. I believe um we also use um present 24 to hash the leaves of the weird market trees because like weird market in weird the you have at each step you commit to but the the leaves the leaves in practice are 64 to 12 um uh eight feed elements that you need to hash and to speed up this hashing you need poson 24.

So actually you also need 24 in in like this. The other thing worth mentioning is that we have a stretch goal for lean VM which is to be a VM for general purpose hashbased with crypto cryptography with all sorts of other use cases beyond Ethereum. Maybe the application layer maybe other blockchains maybe for privacy wormholes which is the same thing as as Zcash but only on L1.

And if we have this virtual machine be adopted by the whole industry then you know more eyes on it more performance more security but actually uh in in both case wheing the leaves of the weird m tree in both case is you have a bunch of like 100 F elements or a thousand and you want to hash it. So we could imagine a pre-ompile that takes the start of of of like a sheet of set and you hash the

working. So it could be an idea >> a variatic pose sorry >> a variatic pose. >> Yes. Yes. So we like you hash a long chunk of data. Yes. Wait. >> Yeah. Maybe the answer. Why not? It would be hard to make a circuit for that. >> I think I like silly question here. But what are we trying to compile down to these op codes? Are we is like we take say were we trying to compile like the set of verifier checks of like how the verifier checks the prover is trace is

that what's getting compiled to this or >> so so so like so you take so you word that you've written so you could you could try and compile like what the proof is doing in word but that seems like that's not what we need here right like >> so it's just trying to ver like compile down the set of checks that the verify does approvers. >> Yes. >> This is what you have written in DSL. >> Okay. Correct. >> So basically receive the market commitment sample some random indexes open verify the market for some check etc. basically like you have like the verifier file but is rewritten in >> okay okay

>> break >> no