Learn Noir in an Afternoon (Parts 1-2)

Aztec Network Talks · September 2023 · 34:00

Aztec Labs developer relations engineer José Pedro Sousa hosts a hands-on workshop at zkSummit 10 on learning Noir in an afternoon. Parts one and two cover an introduction to zero-knowledge proofs and the Noir language, an overview of the example project, and then coding the application together. Workshop resources are published in the noir-in-an-afternoon repository.

Speakers

Topics

From Aztec Network Talks, hosted by Aztec Network.

Transcript

Intro

hello welcome to learn more in an afternoon or get your money back I'm Jose petza I'm a devil engineer at AE clubs and today we're going to be talking about Noir the ZK DSL developed by a clubs we're going to be talking a little bit about ZK uh what is ZK what can you do with ZK we'll also talk a little bit about Noir uh why are we doing this why is Noir needed why what can you do with Noir that you can't do with other DK dsls then we're going to present our

Rundown (Agenda)

project our little project for today and finally we're going to hack it and yeah just start hacking stuff so we know that zero knowledge proofs are really powerful you can do stuff that you can do uh you can't do with any other um Tech basically but usually with great power come uh univariate poal commitments and this is kind of the problem because if you don't get the math behind ZK usually you're just left in the dark and and basically the purpose of mar is to make this go

Zero-Knowledge

away and just abstract all the complexities from the mathematical part of the ZK space so we need this usable Universal ZK domain specific language um and yeah we like rust rust is cool uh so yeah we just went and copied the syntax from rust and so if you tried to find the difference between the two programs they're yeah they're usually you're going to have a very bad time and so this is just an example if you try to spot the difference between these two um Snippets yeah you're not going to find

Noir

them one of them is rust the other one is nor and as you can see there are little differences in this case there are zero differences we want you to write code instead of writing circuits so if you if you used other GK dsls in the past maybe you've written like circuits on on a piece of paper and then connect the wires and that's basically how you write your circuit we we believe that the best Paradigm is the one that we are used to which is just writing code like just writing actual programs like like You' write solidity or JavaScript or or rest and this also allows you like for

very um very experienced Developers to just use Noir to abstract their own stuff so maybe they just want a very easy way to use ecdsa signature verification for example so maybe they don't want to uh write their own stuff and just use like modules or external libraries uh while this is still easy for beginners to start using ZK So today we're going to building a little project I'm going to show you next what it is and we're going to divide this in like three chapters the first one is literally about Noir and

Our Project

especially nargo and NOAB how can you simply get started with the new n project we're going to be talking about the syntax of no we're going to be writing tests uh actually they're built in with nargo but I'm going to show you how to make them fail and stuff and and finally what we we all care about which is proofs actually generating the proofs and verify them uh we're going to also be integrating some libraries um namely the standard Li standard Library uh that you'll find many of the built-ins in in more and other libraries like external libraries built by by the community or libraries

that you want to build yourselves and finally uh we're going to be looking at the browser usage um yeah it's a bit of a beta but you can still you can still do it and you can use it in in your dab and I'm going to show you how uh we're going to be leaving behind the verification of proof Sun chain I'm going to show you basically how to generate to contract but from then on I'm I'm assuming that you know how to deploy a contract with Foundry or or car hat or truffle is not around anymore unfortunately so that's it um I'm just just raming here so it should get started finally yeah you should check out uh the

workshop resources as well um special the workshop resources you're going to have uh repo there with the stuff that we're going to be using for today so I highly recommend you to to scan this QR code um also the noard do uh this is basically the documentation that the nor team has been putting putting on uh it should give you most of the answers you're looking for uh and finally my my blink TR it's not blink tray I think it's a Lio yeah it's a limo thing you can you can check out their all my like Twitter handle and and Telegram and stuff so you can talk with me and ask questions if you if you want to and so

Let's Hack

that's it let's let's start hiking basically so I'm going to pull up my uh vs code uh editor here uh uh as you can see this is already in the in the workshop resources I just um mentioned to you and if you check out the rme you're going to find uh this norup tool um so norup is if you used to CLI tools like rust app or Foundry app uh which is actually here it's basically a CLI tool that we install uh will install nargo and if you used to rust you also know cargo um which is kind of an PM thing that will install like package it's a a version

manager a package manager and also Runner and run scripts and stuff so that's basically what nargo does so to install nor app you just go and install it like can just copy this you can trust me bro and just just copy this thing it will install nor app for you it's going to take a little bit longer for you so just pause the video and wait for it to to complete and yeah it says that you should just just uh run Source like and just Source the the The Bash file uh or just start a new terminal session and then finally you should have norab round and you can check what exactly what this it does what does it do and you're going

to get like the options for it and so it's pretty powerful you can install like specific versions and branches PR commits and stuff uh in this case I will even though I think the latest version of Naro is 0. 10 uh let's just go ahead and install like a specific version for that and so I'm going to install like version uh 0.11 um so let's you just go and install that and it will download and install for you I guess that's one I had already because it was really fast and then you can just go and run Naro version and finally you should have your your version another thing that you could probably find useful is the vs code

plugin so if you use vs code you can just go here on extensions and basically say just uh right Noir and you're going to get oh yeah here Noir language support so yeah this is it's a very Alpha version but it's really cool and it can run like it has some cod lens that can be useful for you to run uh you also get like syntax highlighting which is which is always cool so with nargo you can basically do all kinds of really cool stuff like running your code and installing package and starting a new project and that's basically what you're going to be doing uh so you go you can let's just go run

nargo help to see what can you do with nargo uh in this case we're going to just use the new command and just call it like nor project and yeah it will generate a new project here and you have two files basically nargo toml is basically the source of your project uh you can define whether it's a library or a binary so yeah also Define dependencies and workspaces here uh for now we're just going to leave it as it is don't change it also nor generates um a main uh main not file for you which basically has a very basic circuit you can you can test and run and and do whatever you want um and so yeah let's

just go over it and see how how can you run your own and so let's start with f and syntax which is means function basically and you need to have a main function uh that's part of it because you're running the main uh the main file if you have other files yeah you can have like modules and stuff you can look at it in the documentation and you also need to Define like the name of your input um and also their type um and you also need to to define whether they are public or private so we think that private privacy is normal so you only need to define the stuff that you want to make public uh and so the biggest difference is that obviously if you have

something that it's public you got assume that the verifier has that in their possession uh while for private it's stuff that it's only on your machine that you don't want to reveal but you still have want to prove some calculations on it uh in this case we're going to use the field type which is is uh basically um an element of a of a finite field um and so you can treat it pretty much as a kind of a big integer and make all kinds of really cool um really cool operations arithmetic operations on that and that's basically what what field is uh for practical uh purposes uh if you want to Define an array for example then you just do it

just like in R you define the type and then you find the how many many how many elements does your array have one thing that you just you should notice is that you need to know this at compile time uh there is no way of just passing like a slice uh this doesn't work uh with basically any of the zik languages I'm I've ever worked with so yeah this is not new another thing you can use is like some really cool return values so you can have like public field and make this return field and so you can have like for example let Z and say x + y and then just uh assert like X is different from Y and then just on Z and and yeah

this this will return you uh fi and some people ask you ask me like why why should I have like Public public outputs for for uh yeah for return values you know why why why why why do they have to be public um and the reason is like basically the way it's it's treating the return value it's actually as as an output as an input so this would be just the same as like returning um something like this public field and then just constraining at the end so as you probably noticed I already use some arithmetic on it uh you can yeah you can you can sum them up you can you can subtract them you can do all

kinds of really cool stuff and if you want to know exactly what kind you can do with Fields uh you can actually just check the the Nardo I'm going to do that for you just here are the nard dos you can go here like on um the language Concepts and see uh all the things you can do like logical operations and just send them and even like B bit shift and stuff as long as they are integers um and yeah so this list will hopefully give you some examples as well you can you can skin through if you're interested also the Shand operators which are really really useful at times you can also use uh loops and

control flow stuff like ifs and else and stuff um so basically the way you write them it's just uh just like in R you would say like for uh for for I in some kind of range you you say oh thanks thanks GitHub cool palot uh it already knew some example for you you can run like your for Loops for Loop just like this um and you can also do it like a conditional so you can say if if X is not one or if it is one then then Y is something like this so yeah you can run you can run um if else is uh just

like you do with with rest there's also the Asser key qord that you probably saw at the beginning um that you're going to say assert uh X is different from y um so this is something that you don't get in rest so yeah if you try to run this it will say it'll complain that doesn't know what what assert is and this is basically what you want your program to do basically I want this proof to generate some constraint and say that this proof will only be valid if x is different from Y and I don't want to reveal what x is and and so that's that's what a sort keyword does another really cool thing they can do is struct so yeah you can

Define like a new struct and say struct person for example and just have some stuff like uh not strings uh we have strings but yeah they they are yeah let's not not use them not today um so you can Define stres and just pass them like you can pass that here x could be a person for example example with with x x age Etc so for our project let's imagine that you are the owner of a Fight Club so you're going to say that each fighter is a person um and that person has has an age which is going to be a fi for example and you want to check that only people with a certain above a certain age are allowed into your Fight Club you

also want to check for example that they know like the password uh to enter your Fight Club there secret password that you don't want to bouncer to know what it is uh and so let's let's just go through it and say yeah there's there's a person uh this is going to be a fighter um that has a certain age um and then you're going to have like for example a password and obviously a password is a private input so let's not reveal it uh but the hash of the password that's definitely something that can be known because it's very difficult to figure it out and so it's just get like password hash password hash going to be a public input and let's say it's going to be also going to

be a field and so in in your program uh all you want to do it's basically uh two things one is just like check if H is bigger than minimum age um and second thing is like you want to check if the password hash is equal to the hash of the password so yeah GitHub uh copal already know how to do it um yeah let's just see how can you use this hash thing uh another thing that can be useful in this case for example is global so you can go and say Global uh and say um Global minimum age is going to be a field and let's say it's 18 because I'm in Europe uh yeah I don't know if it

would be different in any other country and just get some get ourselves some space here and and so yeah let's let's just go and you can literally r two lines of code and see a fighter age of the fighter needs to be higher than the minimum age um this takes care of your first assertion and and I can I can just go and test it already I can I can go and say um let p uh is a person uh with ag for example age 19 and so I can say 19 19 is here I'm going to just pass whatever random values for the other two um

yeah and and see and see this should pass I going to go and run Naro test uh okay oh sorry I need to C into that Nar project and then go and Naro Nar test [Music] um oh wait sorry sorry I forgot uh is p um yeah it to complain that Fields can be compare uh yeah that's that's that's something that's true you can you can compare Fields so let's just cast them as you wait um let's say actually make this already a new weight so it's easier

and yeah this will hopefully pass them another really cool thing you can do with nargo least the latest versions is to is the writing test that should fail and this can be useful very useful I guess uh and just go and call uh test that should file and then you can run and test that should file um let's just go I hope it okay good that's he knows already he knows so yeah you can you can go and run nargo test and this should pass because this test should file regarding the password so we have our password and know that verier know what knows what the password hash

is so that means in our circuit we need to hash our password and just check if the provided if the hash that everyone knows is equal to the hash that we are calculating in our own private input so basically we are saying the hash of the input that only I know is equal to the hash that everyone knows because it's like in smart contract or just everyone knows for some some other reason um and how can we do that we basically do that with the standard Library so you can the way you import it it's very easy because uh you can just um you can just like like this it's it's just a standard

Library so just dependency standard Library I don't you don't even need to add anything to Nar it will work out of the box um let's just go on on the browser to see basically um what you have there and you have a World chapter for our standard library and this you have like really cool things like recursive proofs and Merk trees and and stuff and also All The cryptographic Primitives that we currently support as for the ash for the hash methods uh you have many hashes that we have implemented already some of them are what we call blackbox function and

this basically means that this is just provided by the back ends so if you use different backends you may have uh um they may not be implemented if you're looking for a hash method to use I would recommend it to use some very some ZK friendly hush that would be for example Pon or posidon let's just go on posidon because I like it and and yeah the way you import it it's just like this so I'm I'm actually going to copy this so you can see um and go over on my PS code window as well uh and just just place it here so I don't forget how to use it and so the way you

import it is um you have SD so you can actually go here and and import it here and so you can have more granularity on what exactly are trying to import and and say let's just just let's just leave it at is as this is and so this way you can you can have your program be a little bit less foros and just have the module you're you're importing specifically uh and so in this case uh we want to check like you want to uh yeah it's not really that as GitHub says so you can have you just want to check that your password hash is equal to the hash um that you're trying to to

do in this case you just go and run a password and the reason GitHub thought I was trying to pass um an arrays because yeah password should be an array so it was kind of right um so yeah in this case as as I told you you need to know the size uh at compile time so yeah I'm hashing two Valu so I'm passing the hash two so it would be three or four or five whatever depending on what exactly are you trying to to Hash um it says that's not being used which is which is a lie okay now it's that's okay and yeah that's it now for for testing basically it will complain

that yeah it expects a field too which is kind of true um and so here's what the utils uh folder can be useful uh because you do have like an implementation of posidon that you can actually run on your machine and see how how does a hash look like um so you just go here you just change your inputs and then get run this like with TS node uh for example and and you're going to get an output so in this case um I think I already have two values here um that can be used like for for POS so if you have like one two for example uh the

hash of that should be this so yeah in this case I'm going to just paste and say yeah the password is one two which is a very weird password but let's let's forget about it and just say the password hash is is this one and while we are while we're here let's just go and do the same for for the test that should fail so I'm going to just change and just change this a for a b and this hopefully should pass like both tests um let's go and try yeah as you see they all pass this one passes because the value is correct this one passes because the value is incorrect if you've seen the U folder you also have another one called kachak

which is basically the same thing but for using kachak um which is uh yeah which is a hash function that is widely used in in etherum it's not very ZK friendly so one thing that you want to do basically is to prove stuff and that's all fine to run tests uh but they're just they are just tests you actually want to proof and verification stuff so the way you do it is just run run nargo check and you have this prover and verifier files and yeah this is basically where you put your values and to be proved to be proven so in this case like we know what they are

already so I'm going to just go and put like my my password here um just here and my password hash uh in quotes um inside quotes here and my and the age of my fter is going to be 19 so you want proof on this and because it's ISR it's as easy as just running Naro proof you're going to see here like the proof you there's has the name of the project and yeah it's very difficult to understand but as you can see it's kind of sucin which is what we want again it's a snark right it's it's it's supposed to be sucin if you want to verify that you just do the same thing

just go Nar verify and you're going to verify the the default proof that's going to be in this directory with the name of the project at this point you're probably asking how can I do that in in a smart contract um and as always it's pretty easy you just go and run nargo code the Gen verifier and it can take a little bit but you it will generate a smart contract for you um it was fast actually this time so you have a smart contract here uh which was written by very very smart people um and yeah it's going to be a little bit difficult to understand all of this but yeah this is a smart

contract you can deploy uh the relevant function here is probably the verify function and this is basically what what does it expect to be passed on at this point you may want to explore a little bit more about the standard library and you probably notice that yeah it doesn't do everything you want and that's that's okay we want we expect that and so uh there was a very easy way to just import other libraries uh one of my favorite libraries is the EC recover Library um and this is by uh one of our community members called Colin and Colin just put the this library to um

basically recovered an address from um a signature how how can you use that so let's go back to V code and just go on the nargo tunnel and here you have dependencies here um and actually there's a there's here yeah just an example of how can you use EC recover uh which is like this you go isy recover you you check the tag and then if you want to import it uh it's it's very easy you go here and you just import it just use dep easy recover and there we have it so as promised um I'll

show you how to use this in in the browser so the way you can do that uh let's just we don't we're not going to use nargo anymore I believe so let's just just close this just leave the circuit here um and basically the way you do it is um with three packages so when as as as I've explained before there is Noir and that's basically the language that you're writing and that compiles into AER which is the intermediate representation and then you have two more packages which is the acvm that will translate that into constraint system and then finally your actual back end and so the way you use it on the

browser it's just importing these three packages separately um so here in in our project folder you have the browser browser package uh sorry browser folder and this is a basic react uh page if you see here like my component it will I'm going to input some numbers um X and Y I want to check if that X and Y are different kind of the other circuit that we know already and then once the user clicks calculate proof it will calculate the proof and so yeah it will generate mids and generate the proof so the witness is like this acvm part and then from there with the

witness you can generate your proof so you have here the class no and you you are in initializing as Noir new Noir um and so yeah let's let's get started I'm not going to write the all thing but there is a a um file here we can we can just go and copy line by line and just check and see uh what exactly does it do we're going to import um our actual back end which is BR then finally we're going to have um we're going to have also the init acvm this is needed only for the browser uh that you need to init the scvm it's going to be doing some lome stuff in the

background um and then finally the execution of the circuit and and the compress witness uh if you need to compress it and we're going to do that we're going to need that youve probably noticed that uh there wasn't any Json file in our project and that's because I just forgot to compile the circuit and yeah basically that's what we're going to do so we are in that folder already so I'm just going to go and run n Go compile and it will compile my circuit into the target folder then we are finally like big stuff we are initializing brenberg with four threads so you can actually make this six or eight or whatever um yeah just basically

there's multi-thread support in Ren and that's why it's actually so fast um we also getting like the circuit size because we need to allocate some memory uh for for our BM uh stuff so this is basically what it's doing and finally we are just storing the uh ACO composer which is um very handy interface to to uh generate your proofs as for the proof generation I'm just going to go back to my chats um file and just copy this just last two things and yeah while we're here also copy the destroy um method and let's just go over

them um yeah this is this is actually the easiest part easiest part so if you have have the witness already you just call uh AC CR proof from your initialized API so if you remember this API comes from the brenberg and so you've done a bunch of things to brenberg to make it ready so then it's just easy to go and call AC create proof and you you need to pass your AC composer and the buffer uncompressed and and yeah you need to compress decompress your winess because it comes out of acvm uh decompressed um and this false you can just ignore it it's meant to be used for recursive

proofs and so we are actually also abstracting this away from you and finally you should have your proof here um that this should uh output your your proof as for the verify proof it's kind of the same thing and then yeah you you have like the the verify proof actual verify proof with the AC composer and proof and that flag that you can ignore regarding recursive proofs and this is how we do uh how you would do that in um in in the browser or basically uh also in in nodejs so I'm going to show you in the RAR we have some examples um one of them is the next hard hat which is

basically our project but in a it's uh ready to use um so you can you can see like utils also into greates ether so it already verifies onchain your proof as well and and yeah that's it there was a circuit circuit is again very very easy circuit you can you can see it just really really basic so yeah it's as you see this is initializing the Noir uh like that init function then I'm passing just like two different values and yeah you see this is really really fast you calculated your windows your pro verified it and then verified on CH and

this is it for morning and afternoon uh I hope this is was useful um just let us know if you have any questions if you want to do something uh more difficult and you're going to you're having trouble uh just reach out there was the Noir Discord you should join um and also yeah you can just get in touch with us on telegram or Twitter or by any other means thank you