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

Loading player…

How to develop an application in Noir and build a frontend around it by Ian Brighton

Ethereum DenverMon, Oct 9, 2023, 12:00 AM

Speaker

This talk will go over Aztec's new zero-knowledge domain specific language (DSL) Noir. This talk will begin by showing how easily Noir proofs can be written and integrated into smart contract infrastructure. It will then go onto show how this can all be integrated into a frontend of a Dapp

Transcript

a grant the past few months for their new domain specific language Noir and what we did is we took a pre-existing project called battle Zips uh rewrote the ZK circuits in the language Noir built a front end around it and also produced an eight-part video series that'll be live soon along with a live app all right so while we're here talking about essentially building a video game it's important to note that this is really just meant to be a simple example of what you can do with zero knowledge battleships is a really great example of an adversarial multi-party hidden information game and that might sound like a bit of a mouthful but it this relationship actually pervades most of our economic interactions and I'm sure some of you in the audience who are who have these preconceptions of how they want to use zero knowledge uh will likely be able to uh use it so uh the point is to take it and uh ideally um man you will be able to start your Noir Journey with a lot more speed and on that note let's get into what Noir actually is so as mentioned before Noir is a domain specific language created by Aztec Network for the sole purpose of writing zero knowledge circuits uh now let's break down that term domain-specific language so a domain specific language is a language that has a narrow um narrow application or a narrow use case so an example everyone might be familiar with here is CSS CSS is used solely for styling front-end applications in the browser another example would be SQL which is used for acquiring uh relational databases similarly Noir is a language solely used for writing zero knowledge circuits now a question you might have is why would this be important um well for those of us who have done it in depth with zero knowledge cryptography before we know that there's a lot of underlying math and uh uh cryptographic principles that make it a rather complex topic to get started with so I don't think many of us can say we've graduated from a university with a PhD in cryptography so dsls are a way of making the process of creating zero knowledge proofs a lot simpler it provides a high level interface to be able to create proofs without really needing to pay mine to any of the underlying math or cryptography uh so incredibly important for uh making it so we can get to a point where we focus Less on the overhead and the makeup of zero knowledge cryptography and focus more on exciting use cases that it could be applied to uh Noir specifically is a language derived from rust and it inherits similar syntactic structure for anyone who might have experience out there in the audience uh so for Loops have a similar range um uh similar range spread operator uh there's similar types such as um structs that make it a familiar experience and for those who don't have prior experience with rust I personally didn't have a ton of experience going into this but it took me you know a couple hours to really get comfortable with the language so overall it's not very hard to get started um the cool thing about Noir is that it's proving system agnostic so uh what it does is it compiles to an intermediate represent uh representation called Acer and this basically allows you to choose a proving back end of your choice right now Planck is supported as well as Marlin and uh there's another ZK Library implemented and go called gunnarik that is uh currently in the works of being implemented but eventually other things like Halo um will be put inside so it's cool that you're able to really choose your uh proving system of choice and not really have to change the way you interact with a circuit you'll still be able to use the packages that Aztec provides for uh generating and verifying proofs um and that being said it provides a few npm libraries so you can generate verify Ai and test proofs in a typescript context and it also provides a command line interface called nargo and uh I think this is a good time we hop into a bit of a demo here um try and work with this um yeah all right so we'll start off by creating a new Noir project um we run the nargo new command and we specify a directory name of our choice so uh we'll call this quick demo for um bigger sorry it's a little messed up um here we'll go ahead and create the uh directory let me um there we go okay that's a little bit better more okay um Control Plus yeah that's what I'm doing all right sorry it's a little messed up um let's go ahead and open the uh book demo directory and now this will pop the project open in vs code and this is a um see if I can control plus this yeah okay um this is a very Bare Bones Noir application so we have a norgo datomo configuration file this is for specifying dependencies that might be included in the um and you are a Noir project as well as metadata that goes along with it uh you have a source directory with a very Bare Bones basic implementation of a circuit um popping in here um so this is where uh similar to rust you have a main function to specify all private public inputs that might be involved in your circuit as well as return values which we won't get into detail here about um to generate constraints in Noir you see constrain keyword and on the right side uh right hand side you have a Boolean comparison now what differentiates Noir a little bit from other dsls you might have experienced is that we have more flexibility when it comes to generating constraints so instead of having just a equality comparison like other languages offer we also have negation we have comparison which I personally think allows a lot more of a familiar experience for a traditional developers coming into the CK space um but now that we've shown that off let's go back to the original setup and show how we can improve and verify um bigger bigger okay foreign way bigger okay let me try better too much two more two more okay it's a lot bigger on my screen I'm sorry about that um okay that good okay um let's show how we can go ahead and prove and verify uh or yeah prove and verify proofs via command line so uh we first want to generate our approver and verifier files we do this by running norgo check and this will generate a proven automo and a verifier.tomo approver contains all public private inputs as well as return values um we'll go ahead and specify Y is two x is three and then specify Y is two here in the verifier.tomo and verifier is just for all public returns and uh public inputs so now that we have those implemented we will go ahead and run norgo prove and specify an arbitrary file name the stick uh convention we'll call it P and this will generate a proofs directory with our pdot profile with this now generated we can then verify our circuit um so nargo verify p we can see the proof is verified at a demonstrate system checks out to true just to show what it would look like if uh it were an invalid constraint system if we tried to run norgo proof here I would say could not satisfy all constraints um just because we don't have a lot of time we're not going to go over everything that nargo can do but uh last important feature is that you can generate a verifier contract through your proof quite easily by running norgo contract this will uh create a new directory and you'll be able to find it here and we'll go more in depth on what verifier contracts can do how they're structured in the coming slides but uh next we'll move on to showing how our circuits are structured for battle zips so in order to start a battleship game essentially each player needs to submit a board proof and this locks them into their board configuration for the duration of the game and the board circuit encodes basically the rules of how you can place a ship down on the board in zero knowledge and it accepts the ship ordinance as inputs and then it will take those and essentially construct a 100-bit number that is a serialized 10 by 10 board so once we've verified the veracity of the board State we actually need to export it into the public domain via some sort of commitment and in the version we have here it's a little imperfect we use the Peterson hash which is readily available uh however it only provides computational binding as a property it would be pretty trivial for a well-endowed threat actor to Brute Force the actual uh commitment here so what you could do just off the bat in fact some of you in the audience if you're kind of looking to start playing around with this this would be a really easy thing to do is to just add a assault a private salt so that would be a private input for the proof that it's hashed with the rest of the hash so that would provide a computational hiding but we can actually take it one step further and this is something that isn't quite ready for uh Noir I think but in another code base um individually we contributed to uh we actually use the Peterson commitment which is very close to Peterson hashes but a little bit different and commitment schemes they provide the computational bindingness but also perfect hiding which is really important so ideally you want to be using a commitment scheme but for now we are going to be using a Peterson hash so um essentially to sum up what the boardproof does it exports a public commitment board commitment along with the zero knowledge proof that says that this board commitment is a Peterson hash of a valid battleship board and we can take that commitment and send it to the smart contract which we can then use for uh shot proofs later on so the shot proofs are a lot simpler most of the heavy work is in the boardproof it does the same thing where it verifies the pre-image of a board is the public commitment and this is where the smart contracts are very important uh essentially you want to have the board proof output your public commitment store that in the smart contract and then for subsequent shot proofs the smart contract will inject the board commitment without you having the chance to put anything else in so this is the way that smart contracts and zero knowledge need to work harmoniously together in order to enable true trustlessness so uh basically uh we've got the board State Bound now uh the circuit is also going to take uh shot coordinates coordinate pair as well as a hit or miss assertion and uh this will check in zero knowledge it'll check whether or not that hit or miss is correct without revealing any information publicly about the board state and finally along with the use of shot nullifiers in the smart contracts we basically just look for 17 shot proofs that say that a hits occurred and you know that the game is over it's been won so now going back to the topic of verifier contracts um as mentioned before Noir allows you to generate contracts very easily from pre-existing circuits uh you can do this here uh either via norgo or from their typescript libraries um diving into the smart contract infrastructure just go back to the code base um one sec make sure that everyone can see it this time um this thing is like five times bigger on my screen than up there okay so now that we have this open let's look at the board verifier so there's a lot of low-level assembly code in the verifier contracts we're not really worried about uh all that we're really concerned about is just verify uh function there it is that this verify function here um it takes bytes I uh proof as an argument of types bytes called data and returns a Boolean result um whether it's a valid proof or an invalid proof um You can call verifier contracts directly which if you want to just directly verify a proof I guess you could do that but what's really interesting is when you integrate it into existing smart contract infrastructure looking at the Battleship game contract uh here we have it so the board verifier is integrated and we cannot start a new game unless there's a valid board Place fed um the same with the join game function if you're joining an existing game um and then finally uh looking at the turn function when we take a shot um you're not able to update game State unless you have a valid proof there um so by integrating smart contract or verifier contracts into pre-existing infrastructure uh you're able to achieve trustless adversarial multi-party computation um in a way that wasn't achievable before um moving on to the last part of uh the project it was the front-end integration of our um roofs and this was definitely one of the most difficult Parts because although there are npm libraries that support um interactive with no waterproofs and typescript they're not browser native so it took quite a few hacks and tricks to actually get this to work so pulling up the front-end repository um anyone's back here um the first thing you have to take sorry I lost it the first thing you have to take into consideration is the fact that later versions of react scripts after version five uh do not support automatic poly filling What poly filling is is it's a way of taking no native packages and turning them into a browser compatible format where they can be ran there um and you have a few ways of doing this uh one thing you could do is you could eject the entire react app running the eject script uh but I personally don't like this because it's messy it exposes all of your configuration files and also all of your dependencies or all the dependencies that exist inside of the react dependency and your product check just ends up getting very cluttered so um not a way I would personally go luckily we don't have to do this all the time there are a host of libraries that allow you to override configuration without actually ejecting the app um a notable one is react app rewired another notable one is craco and we ended up going with that so what you do instead of ejecting your app with one of these libraries is you specify configuration file where you're able to specify your polyfills other configuration overrides you might need and avoid all the headache of exposing the underlying packages and off files you wouldn't necessarily want to expose um the next notable challenge is just running the packages in the first place so we have to take the webassembly files for the npm packages and paste them into the browser so going to the public directory here you have to have the Aztec back-end package the breadenburg package and the Noir webassembly package on top of this you also have to have a bufferized version of your circuit Acer again Acer we touched upon before that's the intermediate representation that the warrior compiles do and you also need the bufferized version of the circuit itself we can see here we have this for board as well as for the uh the shot so a bit of consideration before integrating this into our front end um it could definitely get heavy copying and pasting all these files but uh if people are interested in check um checking this out on their own we did make a script in our main repository to Auto generate these files and copy them to a subdirectory so you can just copy and paste them over to your front end um we're going on to where the proofs are actually integrated looking at the give me one sec here can't see anything uh looking at the build board view we're going to look at where the board proof is integrated so we have a start game function which kind of um abstracts away from the contract tolls so what we do here is when we start a game and I actually this is uh for starting a game and joining a game um based on whether there's an ID in the URL um but you start off by converting these ships looking at the head of the chip that is where the ship is first placed on the board uh getting the x coordinate from there the y coordinate and then the Z value which is orientation whether it's placed uh horizontally or vertically on the board uh after that we pass the board into a boardproof function we create a hash of the board and we use the Aztec redenberg Library uh to generate a Peterson hash in typescript and there's a lot of other helper uh helper functions that it provides as well we're not going to get into here but we take that hash hash it into the ABI for our proof uh flatten the board because Noir only supports 1D arrays right now um so this is going to be an array of length 15 representing the position of all ship heads um and then we pass the ABI and the name of the proof into a generate proof function and in here um we take two arguments we take the proof type which uh can be either board or shot uh we have the input which can either be the boarded ABI or the shot API specifying each respective um proofs input um we then initialize the Noir webassembly package imported here um and then from there we take our circuit files the circuit itself uh transform it from a buffer to a U.N 8 array and then the same for the Acer file but instead of leaving it as a byte array we then use a function called Acer from bytes um imported from the Noir webassembly package this allows us to get a valid Acer representation for the circuit in the browser finally we pass it into a setup generic prover function and uh we're not going to jump into this because it's quite complicated and it's going to take too long here uh but you pass on the circuit there and the explicit size of the circuit and then it will output a prover on your front end the next step is to generate a web worker now this step isn't critical but with larger proof sizes in the browser you're going to end up running into a webassembly memory error so um a web worker is a way of executing code off the main worker thread um and instead of running it in the background so it doesn't uh disrupt the main execution flow of a JavaScript program um and when you initialize a web worker you check for an error promise and a result promise for a on message event so passing in the uh what we pass into the web worker is the Acer representation of the circuit the input for the circuit and then the document URL just jumping into the worker real quick we uh take what we passed into our message um event handler and uh convert it to hexadecimal initialize the Aztec backend which is uh imported up here and then finally uh take the function and take a function imported from there called compute Witnesses compute those what is uh the witness from the browser um pass it back through the event handler and um going back to the uh loss of file here going back here um finally get the witness after the promises resolved use the prover we generated before to create a proof and then return it back to the uh build board View and then finally we return the ship hash and the proof and going back to our smart contract function we apply these to the um uh function parameters inputted to the smart contract convert the hash to a big number and uh pass in the proof and either call join game or new game uh respectively based on what you're trying to do so that's the board circuit and then for the shot circuit we go to the game View and similarly we have a wrapper function here for uh taking a shot uh or calling a shot function on the smart contract so um one thing to note real quick is that the first shot is not going to generate a proof If you think of Battleship you know you only have a confirmation whether there's a hit or not from the report from the other players so what we have to do for this we pass a report back in these secondary shots of follow the first one um so all secondary shots uh generate a proof but the first one we'll have um but for the secondary shots we go through a prepare shot proof function we pass in the last or the shock coordinates which is a array of length two representing the x and y coordinate of the shot and then a hit at the station whether or not a hit or a shot is actually coming contact um we do uh similarly to the board proof uh convert these ships to a for my friendly to the circuit uh pass this into our shot proof function generate a ship hash again uh convert the Boolean value of hit to a binary value one for hit zero for Miss flatten the ship array so it's a 1D array again the key passions of the circuit and then finally pass in that 2D shot array um and then finally going back to that um the shop function again we then take these uh take the proof and the other parameters we need pass it into the smart contract function and uh if everything is valid then we will update the game State and that is a uh overview of the proofs integrated into our front end um one thing I do want to mention because this is quite complicated uh Aztec has been working really hard the past few months on integrate or implementing versions of their MP at npm packages that are browser native by default so uh this might actually not be a concern in the next few days so um if you want to check it out see how we implemented it our repos for links but uh you might not have to worry about that anymore um but yeah that touches up on our proofs integrated in the front end yeah so and also there's there's a lot of stuff coming out for uh Noir Ultra plonk uh CLI is right around the corner browser integration is a little later in March so um lots to be excited about that'll be huge for recursion anyways um hopefully you were able to learn a little bit about Noir and uh maybe apply a little bit to the hackathon but it doesn't have to stop at ethanver there's a ton of work that can be done with Noir if you're interested uh that includes uh right now Noir exports evm verifiers so you can use any like ethereum chain but uh Solana starkware Cosmos all the other chains you can think of that aren't evm uh could possibly have Noir verifiers integrated there's a ton of circon projects out there Macy um Dark Forest tons out there that can simply be ported over um pretty easy project there's a bunch of cryptographic Primitives that have already been built and are in the standard Library super useful but there are some that are also not there so you have the ability to work on some of those which would be standard Imports for everyone else using Noir uh and if you have strong conviction in your own ideas um you should bring that to Noir if you have a really good idea they will work with you to uh or asdaq you should work with them to uh try to bring it to reality so um yeah so just to really quickly put it up there um we've got a battle Zips Discord where it's basically just uh any developer question around zero knowledge um come in there ask it and we'll do our best to figure it out um there is the Aztec Discord which is uh fantastic for getting first party help on Noir it's by far the best place you could seek out debugging tips uh and just another mention is the if if you are interested in zero knowledge in general one of the absolute best places to be would be the ethereum foundations privacy and scalability Explorations Discord which Powers a lot of the ZK space so um the end thank you yeah thanks uh I hope you got that yeah uh I I think I got most of it um so the question was essentially what does it look like when you're interacting with all of this sure so zero knowledge proof has two sides uh the prover and the verifier uh and the verifier is what goes on chain it's important to have that on chain because that lets you like decentralize the verification of it that's kind of like how actually Roll-Ups function so well is because they verify all of that in that one go um and then so from the browser or from a CLI whatever you're using like you could hook it up with test scripts um you would generate the um proof itself in JavaScript so again that looks like the web worker in um in the browser but it's very easy on front ends or on back end so but yep do you generate wasm code for the verifier as well uh what wasn't code for the verifier yeah yeah it comes from a uh a package that Aztec provides it um which one it comes from the uh breadenburg package I believe or yeah yeah it's a Brandenburg package so yeah that is wasm that's generating it I don't so are you asking if the circuit artifacts are wasm yeah yeah uh I I don't think the verifiers are in webassembly I I don't think so yeah so I I think that the verifiers are are pretty simple uh when it comes like you could store it in Json it's the proving stuff that is in webassembly so um it's it's just not heavy enough to really need that so I might I might have it wrong um the verifier right lives like you say on any chain effectively that's the important part but this interesting part that Noir brings to the party is this intermediate representation so that you can compile down to this thing that can eventually land like on EDM or wherever right yeah yep yeah um I I would say that the acir is probably a little bit for proving systems right yeah um but yeah the and I think they only have vvm right now so I think actually you're probably right uh once you start getting those the acir will be able to just go from any proving system to any chain so that will be very nice I'm one last question um so is this interactive where I need my counterparty to be online or is all of the provable material so like we commit to a hash and even though I've committed something on chain I can't actually understand the board state but I can probe it so I'm curious can I also just effectively offline try all these different states like if I had like let's say you know I can basically find your board and I discover it so that would be the computational hiding thing we were talking about um the way this is implemented yes you could brute force it period um but that would be again very simple to solve in a basic way uh you would just add another input to that hash which is like a trapdoor or um something like that um and you just make that a private input and you've basically solved that uh computationally and Peterson commitments would be just one step further but yeah you absolutely could do that um and then on on the topic of having to be online really quickly you don't um it's as long as that data is there when you log back on it's fine I think we're out of time here so we'll be over to the left hand side of the stage for any more questions but uh thank you

Automatic transcript — names and jargon may be misspelled.