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

Loading player…

Decoding... Tornado Cash

Ethereum MalaysiaSun, Oct 9, 2022, 12:00 AM

"Decoding..." is a series exploring on-chain protocols in-depth, including a walk through their source code. In our second episode, we dive into Tornado Cash, a mixer that allows tokens to be transferred anonymously. We go through the core contracts and go through how anonymity is achieved. On top of the usual Solidity, we also look into the Circom code used by Tornado Cash to generate proofs.

Transcript

okay um so let's make a start uh and uh uh like a couple of people down the line so uh we need your help yeah let us do that yeah just letting everyone in so um hi everyone my name is chitran and welcome to uh the second episode of the decoding series um the first one was unisoc v2 for those who would like to um would like to review the first session which is tolerant has stolen no relation to this they can do so in our youtube channel but today we are going to talk about tornado cache uh it has been a while and i apologize but now i think we are back so um just a very quick um one two minutes high level intro uh of toronto cash for those for the benefit of those who do not know uh what tonight cash is so um tonic is commonly known as a mixer why do i say a mixer well we have a bunch of inputs these are basically deposits so we are actually depositing some some amount of tokens or some erg 20 tokens into a pool and then um any some someone is able to um withdraw from the pool anonymously and what's actually going on is that um you you are we are not able to track between the inputs and outputs because there's this little the pull in the in between that attempts to mix the uh the inputs in a rather uh around so what can i say is that let's say alice has deposited one if one deposit one if and um now there are like five four inputs in the pool and let's say someone x withdraw one if we are not able to know whose one if belong uh that's it comes from because all four individuals um deposit has already been mixed around in a two so yeah therefore it's known as mixer so with that in mind um you therefore need uh to let your deposit uh stay in the pool for only a bit of time so that it can be properly mixed before depositing so that people will not be able to trace um between the output and the input yeah so um let's jump straight into the call concepts so um there are three things which i would like to highlight which are used in total cache number one is the it's a hash the concept of hashing functions um number two it's uh merkel trees and number three it's uh commitments uh oh yeah i forgot to mention uh for those who want to ask questions uh just leave them down in the checkbox or you can just admit yourself and ask questions okay so what are hash functions um hashtags are basically like like a like a function that takes some input and returns an output well this basically it's uh like the function that we normally learn in a given school but a good hashing function has some certain nice properties such as the input can be anything and the outputs are deterministic so um the same input will always predict sorry we'll always put uh return the same output but the output is not predictable and there's a fixed length so in the case of a track 256 the output will always be two five six bits chart two five six also be sharp two five two two five six speeds and regardless of the length of the input the output will always be uh at the same like bit length so that is one of the criteria's uh for a good hashing function and um it is not not predictable so let's say i'm trying to hash the word apple and before putting in um the input apple into the hash function it is certainly almost impossible for me to like know the output without actually performing the calculation and um this is a bit out of scope but some people do use like hash functions to uh as a sort of like a random oracle uh you see that a lot in uh in zka security gta related protocols and a good hex function ideally is a one-way function now what do i mean by that is that given the output and you know the hash function that you use it is um very very very difficult to figure out uh what the input is so um you can if people already always use the word one way function or trackball function it basically means that uh given the output and the type of hashing function it is very hard for you to know what the input is without actually uh doing the input already um before before you put in function and one very important thing for a good hashing function is that the output has to is a sort of collision resistant so uh when i say that i do mean that it is very hard for two inputs to produce the same output yeah we will be uh relying this on this a lot later so um what are the general uh hash functions that you may have you may have heard of so sha-256 for example is very commonly used contract 256 is being used in a lot of in a in solidity and a lot of smart contract related stuff you've probably seen this a lot um these two are actually different so do not the way they are calculator is different but we don't go do that and patterson hash mincy and poseidon so um we'll be looking a lot where we look uh tunnel change uses pat patterson and mincy but there is also a group of hash functions called sided which i will not go into um the reason why they are like the reason between the difference between mc and poseidon and the traditional ones like this is that they are known to be uh snug friendly so it's um so when you try to uh use that in a in a in a circuit that you'll be building these two will generate like less constraints so just to let you know and uh why there are so many types and yeah so the next excuse me so the next um thing that um we will be talking about would be merkel tree um so merkel trees are basically an efficient way of storing data so um over here i have two illustrations one is a simple four block linked list and one is like a tree structure so let's say uh when we try to query uh the data and our target happens to be at the end of the uh the fourth block so in a linked list we will need to uh uh we don't need to iterate through the four blocks this one is one this one this one and um basically uh in terms of time complexity this is known as a linear time complexity of n and uh for three so basically uh when you come here you just need to make the decisions whether to go left or right and when you're here you just make an addition to go left or right so you can see that we're only making like two steps and um the time capacity is uh it's a logarithmic logarithmic uh time so big o of log n so uh you can see that uh in terms of query um merkle tree is that sorry a tree structure normal between the tree structure is definitely more efficient so now let's look into the specifics of a merkle tree so um what um how does a mercury look like so um the base layer which is the top bottom most layer is uh what we call what we normally call as the leaf node because they are like the end of the tree like there's nothing uh branching out from over here and the rest of rest are branches these are these two are branch nodes and this is what we call the root node so um how do we uh what are these like this weird like h type thing um that is on in the node they are like the hash that like the header hash of the of each of the node so um let a b c d be the content that we want to store let's say i'm storing um some information like my my account balance is a i will hash a using the hash function that i one of the estrogen that i mentioned before and then it will return the result of w and uh likewise i do it for all the leaf nodes and then with the with the header of w and x i will combine these two and hashing pass them together to form another um another header hash and this will be the uh the header hash for this branch node and the same goes to the to the other side of the tree and finally i will just combine the two branch nodes together and have them and this will be the group of the uh the merkle tree so um why do we want to do that you may ask so um say that i want to prove that um a exists in a tree i do not need to look through all the leaf nodes all i need to do is that i produce this thing called the merkle path i wish you already know the route because it's publicly available to everyone and what i will need to do is that i will need to provide you with this one the hash here and the hash here and knowing that this thing exists you are able to reconstruct the roots from uh from the sibling so when i have this and i have this hash i'm able to combine these two to form the hash of this one and i'm able to combine this one and this one to form the root and all i need to do is i can compare the roots that i calculated and the roots that is publicly available and if they match um then we are very quite very we are quite certain that a uh indeed does exist in a tree so that's why the uh collision resistance property of hashing function is important because if any of this uh thing changes the route will be entirely different and we we we can say that hey it doesn't exist in the tree or you give me like the the incorrect path cool so uh so far any questions no okay cool um next up um will be commitment so commitments are basically um what we use coming a lot in what we call the commit review scheme so um yeah these are too worthy but let me explain in a very elemental so let's say um i'm trying to i'm telling you that i know what's going to happen in uh tomorrow at 2 p.m but i don't tell you exactly because i don't want you to know what's going on but i i i want you to trust me that i know so how do i how do i do it i write right on paper and i fold the paper i like kind of like frame it somewhere publicly so that everyone knows that i have i will not touch the paper until tomorrow two p.m and this is what what we call the commit phase and when the event happens at tomorrow 2 p.m i'm able to like show you the result of paper and say hey look uh what whatever happens has been described by me like yesterday or something and this is what we call the review scheme so um in our international cache we use a lot of hash functions uh as a kind of like a commit commenter review scheme uh thing so uh yeah so these three are like uh basically what i can see that what we need to know in order to understand how the protocol works so um sorry where was i yeah here so putting them all together um we will have the commitment to be one of the notes one of the leaf nodes and the commitment is made out of the nullifier and the secret so the secret is um is something that the user the depositor will need to generate and keep it so that they so that no one knows and uh the withdrawal will need the secret to withdraw uh from the pool so the nullifier is something that used to prevent double spending but uh we'll talk about it more in the code but what gonna happen is that i'm combining my nullifier and secret and i'm gonna hash them together sorry i'm gonna this will be the commitment i'm gonna hash them together and i'm gonna like insert them into the merkle tree and of course we know that if something in the root needs node changes the root changes according so um this is how tornado cache is going to look like later so um to withdraw the user will need to provide the merkle path so they need to provide here here this this this hash of this and half of this and of course they need to provide the leaf node that they are they they want to withdraw from and for that they need the secret and and then uh this is something that will not be done in the smart contract but uh they will generate a proof locally and they will just need to submit the proof to a smart contract and that's particularly verified the proof is correct and then um the referring process can take place so um these three steps uh sorry uh to control the merkle path they definitely have to read from the from the on chain data but to calculate to prove that the merkle path is correct um all they need to do is that they need to um generate the proof locally using a a circuit like a snug like by using a slug sorry by generating a snap proof locally using some circuit that has been constructed previously and then yeah okay and uh okay cool microchip is binary two leaves um this is a good question well um there are like a lot of types of mercury's like binary merkle trees that we are seeing now and uh if you use the one i forgot like 16 neri i i don't remember how i don't know how it's being like called correctly but 16 mercury so there can there can be a lot of branches but um but yeah tonality uses like binary mercury and there are reasons why they do that uh the reasons is because whenever you want to prove want to prove the path you don't have to provide 15 other siblings you need to provide one sibling so the proof size can be like x smaller so this is actually a huge problem faced by the ethereum right now that you need to provide a lot of siblings so it's a large large overhead yeah good question um so how the tornado cache pools will look like so um over here you can see that there are like multiple trees and h3 represents a type of token and the denomination of the token for example 0.1 if has its own tool that has its hand and that has own like a merkle tree and one if has also had has his own pool a 10 effects on pool and of course it supports other esc 20 tokens and each different type of token plus uh the value has its own pool so uh in reality we are like many many trees out there and we can pick and choose which tree that we want to uh to to participate in of course the value has to be the same cool so that's a very high level uh walkthrough of uh what how how when tornado cache like works so let's look into the code so um there are actually two parts of the code one is the contract part and another one is the cli part uh we will go through both but we won't go through that everything in the cr part because this is used to generate like the proof and stuff so we are going to treat that later but let's go through the the contract part because uh because why not so over here there are at the twelve-core people there are two folders one is the circuits folder and one is the contrast folder which is uh which has a bunch of solidly files the circuit folders are basically some circumfiles uh which we'll see later and this will allow us to generate um will be used to generate proofs and uh stuff and yeah and then we can use this to prove that our combination is done correctly locally so uh so for now contract um um right away you can see that there are like erc20 and uh if if tornado oh this is blocking my view so um [Music] before that i mentioned that there can be like various types of tokens like erc20s and each of them do need their own pool but we know that if it's like a native token in in the blockchain so it deserves its own [Music] its own implementation because uh because uh one thing is because the things are being handled a bit differently you know in the case of if so we have message stop value which we definitely do not see in uh we definitely do not need in the c20 over here is just to ensure that we don't uh we don't get get if by accident and then there's the fees also being paid if so we need to take into account in the in this in this thing so these two are basically uh ciao contracts of the of the base contract the tornado.

soul so uh we they are like internal override function so right away we know that uh most of the logics uh for these two pools are very very similar so we are only they're only overwriting the process deposit and the process withdrawal function yeah and uh the logic is basically very straightforward i won't go into that oh yeah before that i need to mention that that is a layer um just keep that in mind that really exists and uh i will i will go through the importance of relay later so yeah let's look into the uh the um the main implementation of the contract so over here um we can see that uh there are two um parent contracts one is mercury history and one is be electricity guy uh really interesting guys it's just a simple uh protection against uh reentrancy attacks so it's a very standard opens appear library which i will not going through we'll go into so the way you use it is to put this modifier not in the entrance but yeah i won't go into it in detail and mercury history is where we are able to insert and to compute the uh the merkle root which we'll also go into later let me check different questions no so um so now um there are two main functions in uh in this base uh in this base implementation one is a deposit function and one is the withdrawal function let's me check if they're not yeah all these are are just uh they're not essential so let's go into the deposit one first um so what's going to happen is that can we remember our commitment that is made up by the number five secret so we are going to pass on our following here and then the first thing the contract will check is check if the nullifier has been submitted comment is submitted before if it has of course it doesn't allow it to happen and then it will insert the commitment into uh this is uh into the tree and then it will store the commitment into um into one of the mappings so that we know that it has been used before and then we process deposit so what is interest what is the most interesting part will be the insert internet function over here uh it's it's very messy so to make things much easier let me jump back to the slides so um so um just let me have a single waterfall so uh we remember that each pool has its own merkle tree and in toronto cash the amount of leaves in the merkur tree has been fixed to um i can't remember exactly how much how many i think it's 2.32 so it means that it can only have up to 2 to power 32 commitments or deposits so once you hit the limit uh it won't be able to um accept any more deposits and that a new tree has to be deployed so that's the limitation it has and but it's a very large number so um it won't be hitting that limit uh soon so so yeah and and by default when the tree is empty um there has to be some sort of like a hash associated to each note so um in this case we can see that um the hashes are like this one for the for the base layer this one for the second second lowest layer so and so forth and the root layer would be this hash so um how do we know uh sorry how do we know that uh this thing exists so this thing is actually the zero values uh when it when this the the node is empty so because in a new in the new tree everything is empty so we but we uh by default assign like this value to be the default value so these two i mean all these leaves will have two c seven a blah blah blah whatever as the hash and then we know the same hash has together will form this one and then um this one has this one will form uh some other layers and finally it will have this layer so when you see that the the tree has this root it means that basically it's empty tree so the reason why they want to do that is that they don't want to look through everything to initiate the the the hash form all uh for all the uh notes because they are like 2 to power of 32 so it's very very not efficient to do so so what they do is that whenever they see it's an empty note they just assign the value uh that is uh according to the layer so let's jump back to the code to see uh what do we mean by that so yeah there you go so um there's this uh zero function that uh that that defines the the value when is when the node is empty at a specific level so uh at the lowest level is two c seventy blah blah blah and the highest level is the 2ft 2f blah blah blah so i basically copied these three values and put it into my slides but yeah and uh what's going to happen next okay so now so now the current index is zero because because everything is empty so you'll be inserting into the zero leaf node so what happened if i were to add something to the tree so let's say our complement is a and we were to add a into the poison zero so so um we will add to the left most note so everything that means everything on the right remains to be zero and we know that zero stands for 2 c7a blah blah blah 9 cc so we we kind of already know the hash for this one so all we need to do is that we get the hash of this one and then combine with these two c7 to form the hash of the branch node and then we get the branch node that we just calculated and then we have the zero value again for that level one f three blah blah and then we form the hash of the of the parent of this two branch node and then afterwards the current x will update to one so that now um we know that the next complement will be inserted into the one position which is this one so and what's going to happen next if we were to add another uh commitment to the tree so notice that just now it was the left left most note and now it's the right note of this this little branch so now the index is one so we put b into the ones position and we update it to two so that we know that a bit over here and and then we we know a already because we we have um we have calculated before here and then we can use this one and this one to form a b prime and then we use this one and the zeroth node on the saving because these two are all empty so this one will will be zero as well so we combine these two to form a b double prime and so and so forth and um a note that you you'll see later is that the left sibling they only store like they'll need to store the left sibling of the tree because you basically do not need to know like what comes before because we don't need we don't need it again you need to know like this one so they actually store this uh here a conical level so um at level 32 this one will be a at level 31 it will be a b and uh so and so forth yeah we will see that later in action but i just want to highlight that they are using this uh mapping to store the uh left hash left saving hedge so so um so notice that um this one uses zero value but this one uses the left siding so uh how do how does the code determine which one to use they actually uh rely on the index so if the index is an even number uh it's ring zero we hash it with a zero value because that's a let's give me the right saving if it's an odd number like in this case the index one is an odd number which hashes against the left sibling and and the index is uh specific for the current level as it moves up the level the index needs to be changed how is it going to be changed it's basically the index of the current level divided by 2 and we floor it so um in this case this one was 1 and then if we divide by 2 it's going to be 0.5 but we flow it to make it 0. so now this one is the zero index and we know from our example zero index will be hash against a zero value at the current level so as you can see this is a very efficient way to reconstruct the merkle root without having to uh do a lot of queries and uh and um yeah and a lot of like very uh heavy process because they only need they only they already know the zero value and they have already stored the left sibling and they only need to do some some small operations to recalculate the local route so it's it's rather efficient i would say and by playing around with index they know which saving to choose either it's left or right so that also means that the index of the commitment is important that you need to store that as well uh when it comes to storing roots so we know that each complement has the has the will definitely modify modify the routes in some way so when i have a commitment i will change the route another command i'll change the word so what if we have like a lot of um [Music] a lot of transactions uh and that and then uh sorry and to withdraw we need to know the current route because we need to match our path against the root and what happens if when we are trying to withdraw the route changes so in tornado cache they actually saw this thing called the root history whereby they will store the 30 30 last uh route that that the contract has seen so for example right now um so right now the uh yes until like it has stopped 28 goods previously and the root index is over here so the next time someone deposits it will start at the 29th position and then someone deposits again it will just you just replace the um the zeroth position and with the latest route and of course the current decks can reflect your point towards the latest one so that also means that when you withdraw you will check against all the histories to see if the route that you are trying to match match against uh exists in the in this um how can i say like a finite uh finite map because you cannot go past 30 elements so if it exists then we know that hey uh yeah we will compare the path against this tree it's a ring buffer okay i didn't know yeah good to know so so yeah that's how you um how you store the roots okay i explain it over here so so now we have looked into the high level uh explanation of how the code works let's dive into the actual code so um oh sorry insert yeah so just now we are trying to insert a leaf into the tree and uh over here it's we are checking if the the tree is full remember that um toner merkle tree is it can only support like a certain amount of uh it's only fixed size it can it cannot like have too many deposits but it's big enough so that like it can uh sustain itself for like a very long period of time and then this is where the index comes into play it uh it gets it this one checks if it's an even number so if even number the left the left part of the tree will be the commitment that uh we the recommend that we submit and then the right will be always be zero and likewise uh conversely on other end if it is odd uh this left part will be from our field subtree which is the left part of the sibling that we stopped previously and then the right will be our commitment and then this one starts from the base layer and because it's a for loop it just um it just moves up uh moves up the tree so at the base layer and then it will be the second lowest layer the lowest and so on and so forth until finally when you reach the top most layer um we we are able to know that uh the current level hash is now our route and then we store it into our root ring buffer and yeah this is the root history size that i was talking about it supports only like 30. and yeah so uh okay i forgot to mention this hash left and right so this is uh the hashing function that we uh that we mentioned before is they hash the left sibling and right thing together so that you can form the uh the hash of the parent uh parent node so uh under the vote it uses this bimc hash function and uh you don't have to like know how bimc works just know that it's uh that this function is basically trying to hash the left siding and right ceiling okay so um that basically uh describes how we insert and deposit that insert into the tree of tornado cache any questions cool no questions and once that is done you will emit an event called deposit and this one will uh will show the the instant index and the compliment uh and later on you'll see that this one will be used to uh to help us generate our motor path so yeah we'll see that in the inner circle let me just have the same water while i see if there are any questions oh no questions um so moving on uh when after you deposit we definitely will want to withdraw so uh victoria is much simpler because all you do is that you need to provide a proof this proof is generated off-chain like i mentioned before and we'll see how it's generated later but know that we just need to provide a proof and then it checks if the proof is is valid so uh all these things are what we call the public input they're allowed to be shared and if this is valid we will check if the nullifier hash has been spent oh sorry actually check the nice five knife hash first so if the nullifier hash exists in the record we know that the node has already been spent and we are not allowed to um to process because uh this is basically what what what what what's going to happen if you allow the process why we call the double spending attack um because we are always able to generate um the same the correct motor path for a root and uh but but we need to have some some way to know that the one of the nodes have been spent so what they do is that they store it as a variable in the smart contract and they use that to check and over here it's it's called uh it requires its node route basically it's known is um it's checking against the the ring buffer that we uh that we have looked into just now so uh you look through the ring buffer to see that if our route exists if it it exists if then true if not it will just return false and if it's false we just revert and we say cannot find your rule afterwards we verify the proof if it's correct then uh we reset the nullifier hash to be true because we the node has been spent and then we proceed uh process very strong so um i'm going to talk about the relay now and why is it important um so let me let me just come back to the first page so um when we deposit we are basically calling calling us making a transaction and we need to pay a guess so same goes withdrawal we are calling a transaction and we need to pay guests but for the withdrawal to have if to pay guests basically there has to be you have to somehow transfer a certain amount if uh through the account and if you're able to already transfer the if anonymously to the account that you want to withdraw there's really no need for you to use tornado cache so the relayer access like the service like over here so what you can do is that you can publish your proof to the relay and the relay will withdraw the funds on your behalf and send it to you so that maintains the uh anonymity between the input the depositor and the withdrawal because um if you need to get some e-film here you you someone had to transfer it to you and for sure there's something to track so so yeah you you rely on a very very layer network to do that for you and in return they will require a small amount of fee like like a commission and of course they need to pay gas so they need to cover that cost as well how is the nullifier generated right after the span function is called we will go into that later in the uh the cri part so yeah but good question so um so yeah once it's done we will withdraw we are able to defraud our nodes and then we will emit an event if this is a pre-standard okay so aside from the verifier hash questions are there any questions regarding these two functions because if not i'll do a move on to this circuit it's the missile correlate no mixer is basically um the row of tornado cash it mixes the deposits so that uh you're not able to track like the the depositor and withdrawal because everything every of the deposits have been jumbled up there's no way there's no way for you to tell which deposits uh belongs to who a relayer is yeah yeah furnace that we explained the relay is the one that will pay for guests and send opens to you in return for a small amount of commission or fee yes tonal cash is the mixer okay no questions okay cool okay so that was the solidity length so we will not look into solid code anymore um instead we look into a circumcode um for those who are not familiar with silicon code it is a pretty weird the logic is also pretty weird you're saying this like double arrows and like double equals and one little arrow triangle thing uh these are basically what we call the uh we are assigning and we are constraining the thing but you don't have to know that for now um so the main the main uh core function will be this withdrawal because it's declared as the main component so um we are going to use this circuit to generate a proof for us so what do we need to do is that we need to provide all the inputs to the circuit we will see how later but just know that we need to provide all the inputs and all the private inputs as well uh okay uh let me get that one the result address is another form of contract address for ua it can be any uh address you just have to let the relayer know where you want to withdraw to yeah but if you set a contract address without the the fallback or the receive function then i think the transition will fail so if you want to like refer to a contract rest make sure that you're able to pay that contract yes cool uh okay so um the difference between okay this is like the older version of circle um but the difference between the private input and the public input is that your the primary inputs are are not known to the public so whenever you generate the proof using all these inputs no one is able to know what the what private inputs you use to generate the computation the publics are are the ones that everyone is able to see and you definitely need people to see some public input such as the route because we want to compare it against uh the history and we want to compare the nullifier hash to see if you have already spent another hash before so that's the reason why sometimes things are public and sometimes things are private because we don't want people to see the secret we don't want people to see the denali fire before we hash it and we don't want people to see the tough because if people see the path they're able to know which index are we trying to withdraw and then they are able to map the index to whoever that is the depositor so the path and the indices are definitely secret uh okay this one circle is a normal it's very long i'll let you read that uh yes uh i think this one use spasm uh you can also use c plus plus uh oh yes mentioned but normally if you want to use in some like uh like a javascript environment people use swaziland because there's a web assembly thing it's kind of convenient so yeah what is what is happening in the circuit is that um it will this merkel tree checker it will try to record proof that the route i mean prove that the path that you provide provide uh will will match with the route so we don't have to do that now on in the solidity side because we have to do it in the circumcised and and it basically saves a lot of communication because you're pregnant of chain plus you're able to get the privacy that you want because when people are not able to know the element and the indices that you use to prove that the rule is so this is basically the meat of the logic yeah these are just uh as you can see the comments are probably not required but it's there so yeah so any questions so far uh when it comes to the uh circumcision and why is it needed don't be shy to admit yourself to ask questions because sometimes that may be more efficient cool i think it's a no so okay so now finally we will see the uh cli part and this is where we are able to see how the um how we generate uh the commitment and how do we generate the proofs using uh this circuit so okay oh yeah before i move on once it compiles uh it will spit out like a wasm kind of like binary and then you use that one in your in your uh cli to generate proofs and it also spits out like a very fire solid contract and uh you've seen uh sorry i'm going back going back to this again you'll see that this one calls uh the verifier 35 proof contract specifically this one so the circom will also split up this contract and all you need to do is that to provide the proof into this function hang on where's it uh sorry wrong one this contract yeah sorry and all you need to do is to um throw your proof into this function and return a boolean true or false to say that hey your proof is fairly or not and under the hood it does a lot of like a lot of uh math uh to prove that your your your proof is correct uh okay all right question it's kind of nice um let's start from the top uh let me read this still a baby it's far contract why do we use the what's it for um we use circle because we want that kind of privacy right and um because if you were to submit the the root and the index to the um to the smart contract directly they're able to reconstruct we are able to trace back uh who the uh depositor is so by using a circum circuit and the private input we are not able to do that because it's all like nicely hidden because it's zk yeah no questions probably because it's a lot next to one goal oh yeah sorry about that for a question on the referral since there's only more slots how does the victoria free up the stuff no it doesn't free up it if it just keep it it will just keep appending until the end and finally if it's filled up that's it you have to deploy your new um a new mojo tree circum circuit values passes to the 20.

sole functions uh circumcision values i i assume you mean the uh let's see what is it the proof so um the output of the uh of the wasm will have this proof and then you pass it to the um to the soldier function and then it will check that the proof is valid against the verifier here i said some i searched some google just like it's a compiler for circuits what's the role for circuits here um well the role of this circuit is to uh to in this case is to give you the zero knowledge list so everything that is done in this circuit you you're not able to know what the private input is and you're able to prove that the inputs that you provided are correct did i just uh repeat oh okay yeah does guess yes price deposit increases as much score or is the same regardless of which level um it's roughly the same because we all start at the base layer so it's all going to be at a 32 layer so it's going to be roughly the same there can be a bit difference such as like when you hash against the left or heavier right but i was i would assume that it's going to be like roughly the same uh circuits only involved when we want to generate proof strokely uh now that's a good question um for this yes but um basically okay uh for this yes uh the only involvement they want to generate proof locally and the proofs can it can be in the case that we want gk we have zero knowledge we want to hide the private inputs and in the case where we want we want like to to not execute a heavy process in the smart contract so we can say that we've done that exclusion correctly locally and then we just gave the proof to the smart contract saying that we have done it correctly so the smart coffee doesn't have to execute everything so they are like the scalability part and the zero knowledge this part as to why circle need it uh i think i i love these questions keep them coming guys so we got i think that's enough time to go through the cra part i know it's a bit fast because we only have one hour and a lot of things cover but uh there's always the youtube um recordings who you can refer to and you can always ask me in a telegram uh so what we want to look in this here is a deposit sorry generate i can't remember the name just let me know uh create this great deposit actually not create invoice so to to create like the commitment and the um the secret we will call the grid device we throw in the 390 the amount and the currency and then it will call this create deposit function which you've seen over here so it will what is it oh yeah it uh the fire and the secret will be randomized by you so these two are actually generated by you but in a randomized manner but you can also you can also put in your values that you want but make sure that it doesn't it's not the same so and this one will i mean if you have used another cache before after you have like generic you have like try to deposit they'll also download like a doc file that contains your secret information so you need you you'll need the secret and nullifier to withdraw so that's why they asked you to keep the little text text file so yeah that's about it so uh deposit is just to it's just to create a commitment which is another fireplace secret and then it it just helps you to back up your your stuff so that you you so you don't lose them in case you want to withdraw yeah that's that's really straightforward and now how do we withdraw so to withdraw we will call this generateproof function now remember that all these are done locally so uh the first thing it really does is that we will pass in like the currency the amount whatever information that we need and um we will need to generate the microproof so recall the mercury proof is the merkle path which is the siblings that we need um to reconstruct the root and then we will compare the root against um the root that is saw in history so the first thing we do is that we need to generate the merkle path so what essentially is going on is that it's calling the blockchain to fetch the deposit event so um it will try to get all the events that is deposited into the pool and then it will reconstruct the the tree locally and then from the tree we are able to get our puff according to our leaf index so what uh this is just to validate we just don't care what's going on is that we are actually reconstructing the merkle tree locally by reading from the event logs we remember the event the deposit event that has our index the commitment and uh so and so forth so we are actually using that to um to reconstruct our path so yeah we definitely need uh we definitely need uh we need to read from the blockchain and uh this is reason why when the deposit it takes like a few minutes because it's trying to grab everything and read everything from the blockchain and to recalculate that's why it's very slow yeah and over here it uh it will try to search for your your commitment so that uh whenever say hey this is your compliment that you that you want to withdraw from you will know that this is the the index of the leaf and then from there you will know um how to create a path so yeah this is a very um very troublesome a very lengthy search but you have to do it so once you have created your let's see where was i yeah once you have created your sorry sorry sorry about that once you have created your i've said three times once you've created your path uh this is the interesting part so this is where a circums comes into play so you will call the you'll construct the inputs remember this is the inputs that we need to input in the circuit this is a private input and this is the public in private sorry this is a public input and this is a private input uh it has nicely been corrected out to to let us know what is private and what is not and then we will call this generated weakness and proof and this circuit is basically oh there you go oh this one oh sorry about that for now oh that's not going to go let's switch that uh you will need um to have a circuit and then with the input basically what happens behind the cd is there's some awesome thing going on so and with your proving key proving key it's it's like a trusted setup kind of thing i will not go into that and just unless someone asks and then by doing this computation with a circuit you're able to get your your proof data and then this is just formatting and after you have formatted the proof data you're able to get this proof and send the proof to uh to the function that we have seen so uh so the meat of this function comes from this thing which is to generate the path and then this thing which is there in the proof and and yeah once you have done that you are able to withdraw your uh you're able to deposit and withdraw from to look to another cash and let's see what i have and yeah okay cool that's the end of the presentation i put it here to remind myself that it's a feedback form that i need to share so please feel free to drop your feedbacks and um and yeah hope to uh hope you enjoy the session and uh we got we've got some time left so uh if you have any questions uh just feel free to to voice out thanks for sharing you're welcome oh are they processed uh are there process flow chart available to illustrate the execution flow uh i don't know because i made this on my own right so if i i don't know if they're good enough for you to understand but this is all i have if if there's a better one i definitely have to do that in slides but i i did not see any probably because i didn't find hard enough but i don't know you have to uh you have to do the hard work i'm so sorry gonna rewatch the session uh sorry sorry that is a bit confusing okay um cool uh there's no question so um i am going to stop recording okay how do i start recording and we'll call it a day

Automatic transcript — names and jargon may be misspelled.