NoirHack: Ecosystem Workshop - Starknet

NoirHack 2025 · April 2025 · 59:12

StarkWare's Maya Dotan and Michael Zaikin guide NoirHack participants through building privacy-preserving applications on Starknet using Noir, Garaga and Cairo. The workshop goes from scaffolding a project to verifying zero-knowledge proofs and deploying to testnet.

Speakers

Topics

From NoirHack 2025, hosted by Aztec Network.

Transcript

Everyone, welcome. We'll wait for a couple minutes to let people in. GM GM. How are you guys doing this uh I guess evening? What what time is it for you

guys? Oh, it's uh 6 o'clock here. 6 p.m. It's uh 10:00 a.m. for me here in uh Dallas, Texas. And Michael, you're in London. Yeah, it's 400 p.m. Yeah, I mean it started for you like early in the morning, right? Today. Crazy. Yeah. Yeah. Not as early as in Hawaii when I uh I had met uh with you guys. So more doable now. Well, all right. Um I think you know this is being recorded so we'll just go ahead and and hop in. Um yeah, I want to introduce uh Maya and Michael from Starkware. Um they'll be going over

uh building with Noir. um they'll do some basic examples with uh Noir circuits and then verifying and then going into like deployment on their test net. So I'll let u Maya take over uh and share a bit more about uh uh Starknet and Starkware. All right, thanks and happy to be here. So I think I'm going to uh start off with a bit about Starknet and how this meets Noir and how we can work together and then I'll pass it on to Michael for the hands-on stuff and more in depth. So um I'm Maya. I'm uh the product manager

for anything proving and privacy related on starkware uh in starkware and starkware builds stark net. Um so starknet is a zk rollup over ethereum. It's stark based as opposed to snarks with noir. Um it's battle tested and performant. We had recently shown a peak of 850 TPS I think. Um and we are going to be fully decentralized. This is our road map both for sequencing and proving. So all stocknet blocks are proven and they will be proven in a decentralized manner. Um we will also be in L2 over both Bitcoin

and Ethereum simultaneously. This is hopefully by end of year. Um Cairo is the Starknet language. It's a language and virtual machine extremely performant for proving it's a general purpose language. So it's we'll talk about that and the prover for starknet is currently stone. It's moving to stew which was will be soon rebranded to a different name but it's the starket 2 prover. Um what about privacy? So even though startnet is a zk rollup it's not truly zk. So everything is proven but it's not zk. So uh we are aiming to enable as much privacy for users uh in

which fl whichever flavor they need and um that's what we will be talking about today. So, as you probably all know, noir is a DSL for writing zk programs. Truly zk very rustlike, very nice to to interact with a nice intermediary representation and uh supports multiple proving backends. erh all snarks uh which is very nice um very well documented and uh very easy to get started with which is I'm guessing why everyone is here today um Cairo is a generic language so it's

true incomplete um which means that you prove as opposed to noir in which you write your code and you get a proverifier pair in uh in Cairo you write your program in a rustlike language and you can verify all programs with the same verifier. Um, so it's kind kind of a different animal. Um, and this is how Starknet operates. And this is very nice for Starknet because uh you can deploy any contract and uh as long as it's written in Cairo, the state of the blockchain can be proven because of its gen a generic language. Um, and it's Stark based or circle stark for stew which is a different proving system.

Um, so where do the do these two meet? So, Noir is a great developer experience. Very very convenient for writing privacy apps. Super easy to follow. Um, fast for anything client side that you need to prove locally also because you can choose the one of the multiple proving systems. Um, small proof size. So really perfect for anything that you want to do uh client side for privacy. And where does this meet? So uh start has low fees and native account abstraction which is very nice for privacy privacy related stuff which Michael will be going into soon.

Uh it has no trusted setup which is really nice for a blockchain. So maybe it trusted setup doesn't matter for a client side application but for a blockchain it's really great not to have. Um and with the the bridge between these two things is Gavaga which is a basically an SDK for a super super cheap and efficient verification of snarks on startnet. So it's at least 100 times cheaper than Ethereum and this is basically what enables us to use noir as is uh for writing client side applications and verifying them on startnet. So, how does this work? Um, basically, Gara lets you take a Noir

program and autogenerate a verifier contract in Cairo for your noir program, which means that you are indifferent when writing uh to uh whether you're writing for Starknet or not. and you have a verifier in Cairo that's autogenerated and you can just deploy it on startet which uh Michael will show soon. Um, it's also nice because it doesn't only give you the verifier circuit, but also it uh lets you autogenerate um everything that you would need for on onchain transactions that you would use to uh interact with this verifier um without having to learn anything other than war basically and uh it's

super super efficient for elliptic curve operation. So, um, the basically I'm not going to go into all of the math right now, but I listed some things here today. Um, but and it does very efficient EC computation and it uses hints which is kind of the Cairo equivalent for unconstrained functions in Noir uh in the s in the sense that it uses some nondeterminism. So you can give as a as a hint the result of a computation that you don't want to do directly because it's expensive. So this allows for very

very efficient stuff doing snarks on starknet and this is a nice chart by Michael actually for showing the entire flow of noir and garagga on starknet. So noir you write your program in noir you autogenerate using using arga a startnet smart contract you deploy it and then you would write your noir program and autogenerate a call data to interact and invoke this smart contract. So as you can see it basically abstracts away any Cairo that you might need to use.

Um so some prices uh it's super super cheap to verify uh noir proofs on starknet we have a order of magnitude of 04 cents um much cheaper than ethereum 100x and um what Michael will show you as well is that um because the proof verification is below 1 million cyro steps which is I guess meaningless to anyone not interacting with Cairo but uh it's a not a huge amount of computation h which means that you can actually use account abstraction um to to get a lot of functionality out of noir proofs by using the the

verification in validation instead of well Michael will go into it. So where does this leave us? Uh it leaves us with a super easy integration between StartNet and Noir. Um it's very nice we believe because it both uh enables us to decentralize our technological stack, reach more people who love Noir for good reason. And um uh we believe that decentralizing technology will just enrich the ecosystem and bring and drive better results for everyone. Um I'll say a couple words about our stew prover, our new

generation prover. Um so it's kind of um state-of-the-art prover. It will prove all startnet blocks. Um we hope to make it also zk at sometimes in in the future but for now you can use noir and I'll just show some benchmarks about performance of stew. Uh so you can see that it's going to be a gamecher for proving stark net blocks. um it beats state-of-the-art competition uh even using pre-ompiles uh so plus skyro code beats uh dedicated heirs in computing systems um by a landslide typically and yeah so come build with no

garnet and Michael to you thank you Yeah. Hello everyone. Michael from Exploration. Yeah, super excited to be here. Thanks a lot Rafi and all the Noirans tech team. Thanks a lot Maya for the introduction. Uh if yeah this uh to continue with some hands-on session. So it's going to be uh okay.

Um, all right. Yeah. No, no, no worries. Maya, could you please share the QR code like just for for for a bit for for people to to Yes, sure. Yeah, I will do that. This is not okay. Yeah, thank you. And I and I didn't mention but indeed Feltroid is uh responsible for Garaga. So sorry for not mentioning that. And yeah, he's the genius behind it. He is.

Yes. Uh all right. So the uh Yeah. So the hands out session will be will be uh we'll use uh Gaga and Noir and Kairo to build a privacy bron application on stark net. Uh so it will be done in in steps. Um so I prepared some uh starter so it's like a simple application with a uh the circuit that does nothing from the noir quick start and some autogenerated verifier contracts and simple front end. We will

be creating proofs in the browser just to start from some something because it takes time to build things from scratch and then we will iterate on top. uh we will first introduce more involved noir logic in our circuit then we can do things in Cairo and lastly so we will uh deploy earth into the public test net so let's start I will share my screen a sec Okay. Okay. Great. So, uh the be like for your operating system uh

specifically uh okay sorry uh I will troubleshoot my my issue. this in a sec. So meanwhile, so please try to install the dependencies. Uh they are like listed in the repo and I will be back shortly. Okay, great.

Great. Okay, cool. Uh yes, thank you for suggestions. I have turned and turn on my router. Okay, guys. Yes, sorry for that. Uh all right, so if uh everyone like up to up to speed. So uh you can follow like the steps or just like bear with me. Uh I won't do like any live coding because I'm pretty bad at speaking and writing the code. So I have everything prepared in advance. Uh but we will like go through the code line by line by one just to for me like to explain you what every line means. But before so we need couple of

dependencies to install so that we can uh work with the project. So first of all for the front end I'm using uh like a simple uh react like a scaffolded project using re react and white uh and I'm using bun for dependencies. So if you don't have bun you can install it uh there is a nice alias in the make file for you uh if you'd like. Next for noir. So we will need uh noir tooling for compiling the ser circuits and generating the um witness and we also would need the proven back end the Barrenburg proven back end

uh so that we could generate the proof uh again. So there are like aliases in the make file for you for the convenience. So note that we need specific versions uh so that we don't so that we have all the components compatible with each other. If you have previous uh installation for like either noir and burner just please make sure that you have this specific versions or like otherwise you would need to to switch and uh then for the sorry for the starknet uh we need the also the compiler tool chain uh in order for us to compile the contracts. Uh it's all nicely packaged in a

single installer. uh it relies on a SDF package manager. So if you don't have it, so that comment will install it for you. If you have then then good. And finally, so for us to experiment with smart contracts, we will need local environment. So this is akin to uh ganache or like if you if you had a previous experience with with EVM or other networks. So this is kind of typical thing you would do. Uh so yeah just also please install this um right so a bit couple of words about the project so it's organized in in um in

layers so we have several g branches so in the master uh I have a kind of minimal apps scaffolded uh so it does nothing so it's a dummy circuit uh verifier config and some simple front end And then on top of that uh there's like a next branch that adds some logic to to the circuits. Another br another branch that uh adds state on top of that. And finally we need uh to do some changes to to be able to connect the wallet and you know like uh do everything uh on the public test net. All right. So the project itself consists of three things.

uh as I mentioned before so this is the the noir circuit written in noir uh we will have couple of contracts uh written in ko and finally the front end all right uh so pretty uh as I said before so the circuit is pretty straightforward so it just asserts that uh we have two two inputs one is private another one is public and we just check that they are not equal. That's it. So this is the example take uh taken from the noir quick start and uh right. So now I'm just will show you the flow like how we go from building the circuits to

uh running the app and proving in the browser. So everything is uh is available in the make file uh as commonly. So you can write you can find all the commands in the readme step by step. So you can try to do this on your own. I will just do like a quick walk through. So uh the first thing we do is we need to to build our circuit uh and uh we have a common for that. So uh once we've done that so we have uh the output right so

the the uh the circuit represented in it in its intermediate representation. So this is required for other components. So it's it's needed for generating the bitness and later for uh for the prover to produce the proof. Uh what we can do next is we can uh generate the witness or like in other words the um the solution for the set of constraint that that our circuit represents and uh yeah so here uh I have um a file that contains some values actual values assigned to the inputs for private one and for public

one and using those values we can generate uh the solution the weakness and we can also like check that uh the prover like works. Okay, so we're using the ultra honk flavor. So this is the one of the flavor of flunk that is uh targeted at more uh like a faster proven speed on the client at the cost of slightly larger proof size and uh slower verification. But since uh but yeah we can we can ver still verify honk proofs pretty cheaply on uh on circuits thanks to Gaga. And uh yeah so we can uh generate the proof everything is okay with the

circuit and the inputs. Uh and last thing is we need to generate the verification key. So this is something that uh we need to hand on to the verifier. It's specific to the circuit. It's not the trusted setup but it's just like a set of constants that are required to verify proofs for specific circuit. This is something that will uh leave onchain and this is something that gaga needs in order to automatically generate the verifier contract in KO and this is something we will do right now. So, uh, yep. Uh, yeah, I just have some issues with the scar version, but so the

formatter didn't work, but that's fine. That's that's not a problem. Uh, right. So, Gaga uh actually has created the entire project for us with uh all the modules uh all the uh configuration files. So like in KO we have something similar to cargo it's called scarp and it's basically the same it's the uh def definition of the of the package list of dependencies and some compiler specific flags and uh yeah so we here we have a bunch of uh car modules uh they look

quite scary but that's all right because uh we actually we don't need to change anything so So it's like ready to deploy smart contract that we can work with as is but I will like still quickly go through to just explain you uh what are what is it we're like looking at. So as Maya said before, KO is a generic language. So you can like in theory you can use it to write anything but there is uh specific framework for writing start for writing smart contracts and that we use in stark net. And uh all those special attributes that you see here, they are like part of this smart contract framework.

And typically if you wanted to describe smart contract in ko you would start with uh creating an interface. So this is how your contract would look like uh for the users and so it's like a set of methods public methods like either uh view only or the ones that can uh mutate the states. uh and uh second so this is denoted by the interface attributes and second part is where you actually implement that interface so we specify that the following module is our contract so it's the entry point of

the program uh so that um startnet OS would understand that and inside that module so we will have couple of uh essential section for the smart contract for instance the storage so in our case it's empty as I said before so uh proof fire contract is a stateless contract so it doesn't have any state uh and uh yeah so that's this is essentially the uh implementation of the interface that we declared previously okay and uh for the verify contract we just have uh single method to like verify by the proof uh and it accepts

just like a single variable which is a serialized proof uh that we obtained from the prover and uh it returns either none if the proof is incorrect or some or it returns a list of public inputs in case proof is valid. All right. Uh so yeah there's like a lot of code it's quite scary don't worry. So like Gaga handles everything for us. Uh now what we can do with this contract in order to use it we need to deploy it.

Uh so and uh for that we need to do two things. So first we need some environment so that we can deploy our contracts and uh the easiest way is to just spin up your uh local instance for stacknet chain. So we will like use uh start net and uh yeah so this like there is a nice alias for spawning a local network. You just run that in a separate terminal window and uh yeah it will do it for you. So this is local chain. It creates new blocks every time you submit a transaction. There is there are a couple of predeployed accounts

that we can use for uh interacting with the contracts, deploying contracts. So it's quite handy. Uh now I'm going to So we just need to do one more step to configure the uh the account that we will be using for deployment. So don't worry. So this private key has no real money. It's just some predeployed key in the uh local network. Don't try to yeah check out it on the mainet and uh yeah but please don't use it on the mainet with the real money. So uh we will be using foundry so it's

stark net foundry uh tool set for interacting with starknet for like deploying contracts and interacting with the contracts and we just need to do uh some configuration to tell foundary that this is our local RPC endpoint. This is the file with the accounts we're going to use. This is the name of the account. Uh yeah, just don't show explorer explorer links because we don't have explorer locally. And uh yeah, so that's uh enough for us to deploy the contract. So one important thing so in starknet the deployment actually consists of two steps. So first step is called declare and it's roughly uploading the code of

your contract to the network. Okay, once you do that and your code is uploaded uh uploaded then you can uh move to the next step which is actual deployment and you sort of instantiate your contract from the uh class hash. It's called class hash that you declared before. Okay. Uh sorry I will just stop a bit to address the issue. Okay. Should the Gaga be installed separately? Should be installed during make install. Okay. Yeah, that's a that's a good question and uh yes, thank you for

point for pointing that. I think I I missed one of the dependencies you need to install. So uh you need to install Gaga. Uh yes, you need to do that with Python. Uh yes, please note that you need uh this specific version. Yeah, sorry for that. Uh it's usual, you like it works on my machine thing. Yeah, please let me know if if that worked.

Cool. Okay. Um so so come back to deployment contract to start right. So first we declare then we deploy all right. So I'm declaring the verifier right now. So that uses cast. It's like one of the tool set in start foundry and uh it compiles the verifier contract for me in the release mode. Uh and once it's done so it will create like a special transaction type and submit to our local development

network. Okay, cool. So this is the class hash that we just declared, right? Uh so once we have the class hash we can deploy. So I have already hardcoded that just for the sake of speed and uh yeah so this is the contract address in our development network. So cool uh we're like almost there. So last step is we need to run our application. So but before that I will do one more step.

So I will copy some artifacts from uh our from Noir outputs and k uh scarpa outputs to the application because this is necessary later for uh generating proof on on the front end and later to interact with the contract. Okay. So final step the application as I said before it's like a really simple react app. So all the logic is bas is basically in the uh single file. Uh yep in this file uh it's pretty straightforward super

simple uh and uh what I have here is I have a state machine that has several stages. So we start from initial then we generate the witness then we create a proof then we reformat the proof so that we can uh put that into the transaction call data then we connect the wallet this is an optional stage and finally we submit transaction to the startnet and if everything is okay so like reach the proof verified stage right uh so essentially those are the same steps we did with make file locally but ju just now we are going to do that in

the browser. Uh so all these steps are written here. It's just one large try catch again for uh just for for better understand things. And I have the contract address hardcoded here. I will just update it. Okay. And uh yep I will run the app. Okay. Uh, it's Gaga with a at the end. Okay. So, this is the

app. Pretty simple. So, I have uh my private and public inputs. And uh here are the states of the machine that I mentioned before. And uh yeah, we'll just start the process. It will generate the witness, then the proof, then the call data wallet and send the transaction. Okay, so everything worked well. Uh yeah, just like show is that if you for instance provide some incorrect inputs that do not satisfy the constraints, it will result in an error.

Okay. So what just happened? We have generated the proof in the browser use with Gaga. We have um yeah sorry I will just like go show you here what what happened. So we generated the witness. Okay. So we loaded the bite code and the application binary interface from the circuit that the compiled circuit. Then we created the proof using the B and B back end uh using the results of the of the previous step the the bitness. Okay. Now uh next we we um reconstructed the proof and serialized to uh in a startnet

compatible format using Goraga. We skipped the wallet connection step right because we now we're just interacting with the local chain. And finally we called our contract. So remember I called you I I told you that the um verified proof is a view only method right. So we didn't mutate the state and there there was like no actual transaction. We just invoked the contract. All right. And therefore so there is no transaction but it's still we we we needed a a deployed contract so that we could interact with it. So this is the base the baseline. All right. So this is the uh fully functioning

application with noir arrow goraga and all wrapped in the um react app uh generating proof in in browser but it doesn't do anything interesting. So we will do one step further and introduce some extra logic to the app. So now if you are uh following the process and everything is uh okay with dependences and and all you can switch to the next branch which is yeah which is called oh yep uh the app logic

right and uh yeah so in this branch So we will change our circuit a bit, right? So we'll introduce some extra logic. I wanted to do something simple yet uh something that would showcase uh some important concepts. And I wanted to do the following app. I want a uh a contract that will accept integers but only if they are perfect squares like 4 96 100 256 like and so on right sounds simple okay but on top of that I want a two extra properties so

first I want my contract to prevent me submitting the same integer twice okay so in case I already submitted four let's say uh next time if I try to submit four it would reject that right this is the first property the second property is that I want to hide from public the exact number that I submit so whenever I provide like an integer to my contract it's not clear what is it exactly from the outside but uh still the properties should be preserved right so It it it has to be um checked that this is the perfect square and uh no

single integer can be submitted twice. Okay. So how do we do that? Uh let's go one by one. Right. So starting from the first constraint, it's quite simple. We just need to check that whatever the input private input, right? because we're like we're are hiding the integer from from the public. uh it is a perfect square meaning that there uh must be a square root that is an integer and uh and a way to do that is to implement uh uh square root uh algorithm in in in no uh and that will would be quite involved

program and it will also h have certain limitations. So here uh we will use one of the I think like important concepts in ziki um ziki circuits is nondeterministic computation or uh uh in noir it's called unconstrained functions. The idea is uh for certain computations it's quite hard to compute something but it's quite cheap to verify and this is true for square root. So while it's quite well the implementation for square root algorithm in no would be quite involved checking that something is equal to uh certain number power to two it's really

cheap it's just simple single multiplication so instead of taking square root in in wire we will just compute the square root outside of the circuit provide that as a uh as a hint And then we'll just check that this hint power to two is actually equal to our input. Okay. Uh so this is very powerful mechanism and it's used a lot. It actually it's it's used in Gaga in order to make it really performant. Uh it's also a source of numerous issue and bugs in the circuit. So if you're using this mechanism be super careful and uh just

make sure that you understand what what you're doing. So here I have really simple binary search algorithm for finding uh square roots. Uh it is unconstrained. Uh the benefits of using unconstrained is that for instance I can have unbound loops. This is something you can you cannot uh have um in uh within the circuit. And uh yeah, I just check that the uh my input is is a uh square of some some some number. And I don't really care like how we obtain this, right? So the only thing I care is that my input is a perfect square. So this is simple constraint. Now uh how do I uh prevent reusing the same integer

twice? Right? So if my input was public, so that would be quite simple, right? So I would just need to keep a set of used integers in my contract and every time I submit new integer, I would just check that if that integer like already in the set that I would u refuse that otherwise I would accept and just add to the set. But I cannot do that because my integers are private. So what could I do? Uh first like first thought might be let's just take uh a hash of those private inputs right so uh whenever I

submit a number I would check that the hash of that number is actually in the set or not and uh if not it means I can accept that. The problem with this this approach is that although it sort of hides the uh uh the original number, it's still possible to deduce uh which ones I used right so I can prempute as an adversary like an external observer I can premputee hashes for like four for 9 for 10 or sorry for 100 like 256 like etc. And every time I see someone sub uh submits those hashes, I will just I will instantly understand that someone has provided four or I

don't know like any any other perfect square, right? So we need to somehow blind this hash or like a commitment, right? So we need to blind the commitment and uh this is actually a quite common uh problem uh in uh when you develop ziki apps and uh the mechanism for uh resolving this problem is typically called uh is solved by introducing nullifiers. So by name it's something that nullifies the state. So it's something that tells you that this state has been used or like this state uh um has been updated or like the value is no

longer relevant. And uh uh the way we blind the commitments is that instead of just hashing the numbers we will hash this number plus some another random number and together like since this another random number I will call it secret key is not known to anyone now it's impossible for you to premp compute commitments for u certain like possible inputs and deduce which spec which particular square uh perfect perfect squares I'm submitting on chain okay uh okay great so last problem remains is

that how do do I ensure that uh this is exactly the number this the same number I'm using for all the nullifiers and in order to enforce that I need to um do something that is called uh ziki signature. So it's another interesting concept. It's uh we're used to uh ordinary like a common signature schemes based on elliptic curves where our private key is a scalar and the public key is a point on the on the circle curve. So here our private key is again uh is a scalar. It's a field element but the public key is just a hash uh of of that element. All right. And you're when

you provide a signature, you're just providing a proof that you know the private key that corresponds to the hash of that private key essentially. And uh uh ciring back to our nullifiers if we uh keep the hash of that secret key of our uh blinder in the contract. So every time we submit a nullifier, we can actually ensure that this nullifier was obtained using the expected blinder. This is important.

Okay. In the result, so we have three constraints. We are we're checking that our input is a perfect square. We check that the uh whatever the public key is it corresponds to the secret key. So here I'm using this the Poseidon uh hash function of player. I'm just using this because we have the same function in Gaga. Uh other than that I I I shouldn't just hash it twice. I could just use it once. And we also check that the nullifier is the hash of the pair secret key and the our input. Okay, great. So this is the new circuit. Now we just do

the same steps uh as as we did before. So we uh sorry we will uh build the circuit. Uh we will uh generate the verification key. Then we will regenerate the um verifier contract.

Then um what we need to do is we uh we need to redeploy the the um verifier contract right because now it has different class hash. So we need to recompile again everything uh while we're waiting for compilation. So if there are like any questions or um notes regarding the uh what we did with the circuit um so please let me [Music] know. Okay. Okay. Where the secret key

is stored? Um okay. So the secret key and the input of private inputs. Uh so that means that they are they remain they remain on the client side. So they're like they stored nowhere. Uh like of course you need your secret key you need to keep your secret key uh so that you can consistently produce nullifiers. So you need to store this there on the client. So in practice uh you would like this is something that your wallet would do. uh or you would need to like derive this key from your master key somehow. Um but yeah, we kind of keep

this thing outside. But it's actually very important question because it's you know like kind of this implementation detail that's uh you know it's not that fancy and and and and cool but it's it's super important because you you you don't want it to lose your um blinder key for the nullifier otherwise it would be quite troublesome. All right. So we have our uh verifier declared and uh we deployed it. So I will just again uh update the contract address. Everything else stays the same.

So we haven't changed anything. Right? So our app still stateless. So I will just uh I just wanted to make sure that the application runs fine with the new. Yep. Yes. So we don't do constraints are not satisfied because the input is not perfect square and yeah everything is great. Okay cool. So

now we're moving to the um okay so now we actually wanted to introduce some state right because we need to keep track of the nullifiers and we also need to make sure that the nullifier that the blinder that they use to produce the nullifier remains the same right so for those who are following the process so please check out to the next branch which is called app state, right? And this is where we will touch the car part.

So, so before we had just one contract, the verifier contract and that contract was stateless. So, we just use it uh to verify the proof. Now we wanted to introduce some state and the uh of course so we could modify the contract that Gaga uh generated for us but more cleaner way would be just introduce another contract and I called it main and it has just one function that is called add solution and it also accepts just the serialized proof right so remember that everything we need the um the public key and the um nullifier they

are they are public circuit inputs therefore they are contained within the proof right so we just need one argument and uh so this contract will have states as I said we need to keep track of nullifiers so it's like a I implemented the set as a map where the key is the nullifier and um the values just boom so if the nullifier was used it will be true and the public key. So we use the unsigned 256 type uh to account for the um so that we can store field elements uh in noir we are using the BN 25 uh curve. So the elements from this

field fit into into this type and now the implementation. So uh first thing that that I I I told you before is we need to verify the proof. So we need to access the verifier contract. But actually since this contract is stateless we we don't need like instance of this contract. It's enough for just uh relying on the class hash. And uh what we do here is we do something that's called library call. Uh so now we use our uh verifier class hash uh to access the library for verifying the proofs. Okay.

And instead of just calling one contract from from another, we do this library call. So it's similar concept to what you have in solidity in UVM. And uh yeah, so we uh call the proof verification. we des serialize the result we uh so remember so if the proof is valid so this will be sum if it's incorrect we will none and those are will be our public inputs uh public key and nullifier respectfully respectively and uh after that we will just uh check two things so first is that the public key uh is the one we expect is the one that we uh specified during the cons the

account contract deployment and second is that the nullifier is not in the set. Otherwise if if uh it's contained in the set uh if it's sorry if it's not in the set we will add it and uh yeah so that's it. So pretty straightforward. So now uh the flow will be roughly the same. It just uh the we will need to uh declare one more contract. Right? So as I said before we don't need redeclare the uh verifier contract, right? But we need to um declare our uh

main contract that contains the state. That's what I'm going to do right now. And uh Okay, cool. And then yeah, I will deploy the contracts. Copy the address. Good. So things that will change um sorry that will change on the on the app side.

Uh remember that before when we were interacting with the verifier contract we were actually calling the view method. Okay. So now we will actually submit the transaction and therefore we need an account to interact with with our uh with our network and uh uh what I changed here is that uh I now introduced an account and I used uh again so I used hardcoded key keys here for simplicity please don't do that in production.

Uh so this is one of the pre-eployed key available in the development network and uh once I do that I can actually submit a transaction and uh wait for for inclusion. So yeah I will just update the contract address and uh yes run the app. And so note that for all the steps um so there are like there are logs in the uh in the development console. So you can check the bitness the proof the uh

call data and finally the transaction hash. So yeah everything is is good. So we just have submitted the proof on chain uh and uh yeah it was accepted just like to show you that if I try different secret key uh it like the proof will be rejected because uh on the contract side yeah so it is rejected. Similarly, so if I try to use the same input twice like now the proof will will also be rejected.

Yep. And uh right so we are running out of time. So there is a third step that I invite you to try uh on your own and it's about how we go to the public test nets and connect the wallet. So it's nothing like really really complicated. You will just need to figure out how you create new accounts and uh find it from from the faucet like etc. Uh but it's yeah it's quite easy. So to sum up uh what we have achieved right. So now we have uh like a proper privacy application uh with the uh noir part on the client

side with the proven in the browser uh and uh we have onchain part which is a car contract that keeps some state and everything is uh glued together with Gaga right uh yeah if you have this scar sharp format error. That's okay. It's just like because there is mismatch in the uh tool versions. So it might error but it it doesn't matter really. So it's it's all right if you if you see this error. Okay, cool. So I think we can wrap up. So if you have any more questions about the circuits or the car

part of Gaga um proven so please ask otherwise I'm available uh in noir discord so you have if you have any issues with ko or gaga so feel free to tag me so uh uh and uh also we have a support chat for Gaga we have support chat for car developers. So regardless of what your issue is, we're you'll get help. Thank you.

Cool. Thank you so much, Michael. Um yeah, thank you Maya. I appreciate the the time and the excellent uh workshop and uh like you guys have any any questions in the discord uh be it around deployment on starknet cairo um and especially about noir uh you feel free to ask and they also have a discord which I'll share um for any like more specific questions um and uh yeah feel free to reach out also to me directly in our discord cool thanks guys thanks everyone one. Thank you. Good luck.

Bye. Byebye.