 I'm Maxim Beznov, and I'm a software engineer slash language designer here at Aztec Network, and I'm going to be introducing you to Noir today. Noir is our Rust-based domain-specific language for writing zero-knowledge circuits. I'm going to walk you through a basic circuit and then also show you how to go about proving and verifying that circuit in TypeScript. So first, I want to talk about what actually makes Noir unique. Noir aims to be more flexible in its design than other domain-specific languages that currently exist out there. And we do this by, rather than compiling to a specific MP-complete language, we're compiling down to an intermediate representation. We call this intermediate representation the abstract circuit intermediate representation, or the Acer, as I'm going to refer to it throughout this talk. This IR can then be compiled down to a rank one constraint system or a plonkish languages, whichever you so choose. This is analogous to the LLVM IR, but rather than converting down the IR to a specific instruction set architecture, we're compiling down to the constraint system of a given ZK-proof construction. This actually enables us to essentially decouple the back-end-proof system and the language. We currently have one fully integrated back-end system, and that's Aztec's Brettenburg Library. And we also have plans for integrations with the ArcWorks Proving Systems, such as Marlin and Groth16, but if you can compile it down to whatever you'd like. This, to our knowledge, is the only DSL that currently has fully integrated proving system optimizations. So rather than just having an interface for language system optimizations, we actually have it on the proving system as well. But where do we actually get from this? So we now, different use cases require different kinds of systems, and now we actually have a language that separates the front-end, middle-end, and back-end of a language, and developers can then converge on a common architecture standard. The fact that Noir has the ability to support proving system optimizations enables us to have the addition of optimized black box functions. A few that we have are listed right there, but if a back-end system has integrated that specific black box function, the front-end can then access it. The ultimate goal here is to lower the barrier to circuit development by incorporating cryptographic safety into the language itself while maintaining performance. So I'm mainly going to be talking about how to prove and verify in TypeScript. This very high-level compilation overview also shows our package manager Nargo that I specifically want to note that allows for proving and verifying circuits. This is very similar to cargo, so you can build your circuits using this, but because to actually prove you have to require a proof system, you see that line on the top going all the way over to the proof system as well. In order to compile Nargo, you need all integrated. So now I'm actually going to take you through what a Noir circuit looks like, and I'm going to use one of the most common examples where ZK proofs are used to enable private transfers. And rather than simply showing you the entire circuit at once, I'm going to walk through each part of the circuit, and this is to highlight Noir's unique features and also for those who may be unfamiliar with how to write a private transfer circuit, how that may be done. If you're already familiar with it, you may have to deduce from the inputs that the circuit essentially boils down to a Merkle membership proof. Similar to how Noir is Rust-based, the syntax is Rust-like as well, but the main thing to note here is the usage of the pub keyword. All inputs to the Noir circuit are private by default, and that keyword allows you to then say this also has to be supplied to the verifier as well. Currently, anything outputted from the function must also be public. And to take note of our native data type, that's called the field. This is in the Aztec-Brettenberg backend, a field on the BN254 curve, but we also support smaller data types, such as U32, U8, and even have U3, but these are less efficient as they require range constraints, but that's all to the needs of the circuit developer if you want to constrain using our data types rather than directly in the circuit yourself. Now we can actually get into the logic of the circuit, and we're going to start off by using two of our standard library functions, the Schnorr fix-based scalar multiplication method, so we can construct a public key from the private key that was supplied to the circuit, and then also a Pedersen hash function which is going to take in a list of field elements and return a point on the BN254 curve. We first use the random input secret that was shown in the previous slide to keep our note commitment private and not associated with any one account. Once again, this is using the Aztec-Brettenberg backend, but if a backend supports these functions, then the front end can access it, and now we actually have the meat of the circuit where we're first going to generate a nullifier, and this nullifier has to be unique, and this is used to prevent double-spends and the circuit, the contract that integrates the circuit is going to have to make sure of that where we provide the note commitment that we just calculated in the previous slide, the index of this note commitment in the Merkle tree, and then the private key to act as that identity differentiator. And then finally, we have a check membership function that's going to take in the hash path, the index, that note commitment, and a note root. It's going to calculate a note root using the hash path and commitment provided, and if it matches the note root there, that we provided from the circuit, which is public, we then know, okay, that the note commitment that was calculated within the circuit is actually the person proving it does possess that note commitment. And finally, we return our nullifier and our recipient. This is actually constraining these two values with the outputs. It's a little syntactic sugar that we have for our return values. You could instead, for example, not have the nullifier be returned as public output. You could instill supply it as public input, and you would have to then write constrain nullifier hash equals nullifier index zero there, but this is happening implicitly when we return it from the circuit right there. As the circuit, as the title of the presentation is, it's noir private transfer in 10 lines, so we don't really show a lot of what the noir syntax looks like, so I wanted to quickly highlight what also exists in noir. We do have compound data types such as arrays, tuples, and structs, as you can see right there, and you can then we also have submodules, so you can easily separate your functions as you see fit. Also, just recently added global consts, which you can also import as you would in any other programming language such as Rust. For control flow we have for loops and if statements, and we're looking to add recursion soon as well. We also have recently added generics, which is highlighted right here, which is a great benefit to the developer experience. Just to recap, we try and be high level as we want to make this, the developer experience easier, but also abstract away some of that cryptographic safety that you might be familiar with in other ZK circuit languages, or where you have to directly specify essentially every constraint. And that's the ultimate goal of noir, to have safety and a greater development experience. Now I'm actually going to kind of walk through how you would use our wrapper to prove and verify this circuit in TypeScript and then ultimately in the browser so that clients can, you can prove on the client side. We have a noir.js package which has been created to allow developer to, you can directly compile your circuit in TypeScript as you see there, but in this in this package you can also read in from the acer from file that would be generated by the noirgo package manager. That's a choice of the developer, but in this example we just show you how to compile it directly in TypeScript. So after we have an object representing our acer, we then just have to specify our ABI. And ABI is what the prover is going to be providing to ultimately construct our proof which has our private and public inputs and that's going to be used to generate the witness and ultimately generate the proof. So because noir is back-end agnostic though, we have a separate wrapper around the Aztec-Brettenburg back-end and that's any other back-end that gets integrated is going to have to do the same thing as well because this back-end has been made to match the acer interface in order to set up the prover and verifier. We simply pass in the acer as you can see right there and then that ABI that we specified earlier to construct our proof and then we just pass it along to our verifier. One thing you might know though is that you don't see any public inputs being passed to the verifier even though we have that in our circuit. Currently the proof that gets spit out by Brettenburg is prepending those as 32-byte hex-string inputs but we plan to separate that as developers might like to have those inputs separated for their own development purposes but that's just to take note of why you don't see any public inputs being passed to the verifier there. So we can this it's cool that we can actually verify in TypeScript but we want to be able to also enable this in smart contracts as well. So Aztecs Brettenburg back-end does allow you to compile from a Noir program to an Ethereum contract. Proving systems looking to integrate Noir are going to have to provide their own implementation of how to generate a Solidity Verifier or if you choose to use any other smart contract platform you're going to have to provide that implementation yourself if you're integrating a back-end. This script here shows you how to generate a Solidity Verifier using that Aztec Brettenburg back-end and it's important to take note though if you change your circuit and don't change your you don't regenerate your Solidity Verifier with this script, your circuit is ultimately going to fail as you're going to have a new Acer and you're going to need to regenerate that verifier in order to have accurate verification and finally we can actually have our Tadah moment and verify our circuit in Solidity. So using your favorite deployment method you can deploy your Turbo Verifier as you would any other smart contract and then you can take that proof that was spit out from Brettenburg in the exact same way with the public inputs pre-pended pass it to the verifier and if your public inputs are correct and you specified your circuit correctly it should ultimately return true. In the case of our private transfer we're going to be checking is that the Solifier hash been used before is the root the correct root and upon having verified proof we can actually then perform a private withdrawal and that note that will be entirely private so that's it there and you can see a more full example with the simple shield but ultimately here the benefit is that we can enable autonomous execution in contracts based off verification of noir circuits and I want to also discuss some of the future work that we're going to be doing in noir one of the main things that we want to add is verify proof this will actually enable us to have recursive snarks inside of noir itself which enables many more use cases than you can currently have the wrapper itself is pretty new and we want to improve this development these development tooling significantly to make it easier for anyone looking to integrate with noir we also want to integrate it with Rapples such as ZK Rapples if you're familiar with that online IDE integrations, other debugging tools a language server, lots of development tools to add and in the medium to long term we're going to be adding noir contracts and noir contracts are going to be the next stage of Aztec's platform where we'll actually have public and private state which has its own challenges which you can attend Mike Connor's talk at 230 from Aztec who's going to be discussing that infrastructure and how we actually are going to enable smart contracts in noir if you have any questions please shoot and thank you thank you so much Maxim so we have two volunteers there you go hey good afternoon very impressive right now how does your tooling work for this you have to compile the noir contract and then deploy it into the layer 2 or the layer 2 test net or something not right now that's the next iteration of Aztec's platform when we add the noir contracts this is a purely ZK EVM DSL right now where Aztec can generate that solidity verifier and you're going to be proving circuits on an EVM platform you can like I showed in that example you can compile your circuit in TypeScript but you can also use our package manager which I briefly mentioned to generate that intermediate representation that intermediate representation can be used the same way that it was used there you just have to you're reading it in from file using our wrapper methods so you don't have to do anything extra for serialization that's handled by our wrapper yeah, right now but you can verify without the EVM as well you can just verify using TypeScript and you don't have to necessarily have a verification using a solidity contract that depends on your needs but a lot of people like to have that autonomous execution we have time for more questions one over there and the left side then we have two more here hey hi, it was amazing I wanted to ask, let's say as a developer I have the choice between SIRCOM and NOIR now both as an end user feature provide proof systems with Planck and Grott16 exactly the same value proposition so why would you say that we should experiment with NOIR instead of just going with SIRCOM sorry to put you in a position no, no, it's okay they do serve slightly different use cases, SIRCOM is definitely much more low level you're going to have to be specifying a lot of the constraints individually while in the language we specify those constraints for you a basic example there when I talked about if statements you can constrain your on if statements you don't have to use a multiplexer and things like that that make it just easier for the developer and kind of lower that barrier from someone who's maybe moving from who's never coded ZK circuits before and also constrain on data types outside of just our native type everything that we have ultimately translates to that and we do have I know you can currently do Planck but I believe right now NOIR is the only language that actually has truly fully integrated black box functionality where the proving system is specifying the custom gates and making those functions faster hi why base NOIR off Rust are there certain properties of Rust that make it you know a better language for this? Well we want to one of the main focuses of NOIR is safety and Rust that same thing in Rust right and Rust is also just a nice language thanks a lot for the talk I was wondering do you have some tools where am I looking sorry hey hello thanks for the talk do you have some tools for testing the logic of the circuits right now it's essentially you're going to have to write your tests in TypeScript we hope to add debugging tools that's one of the main things that need to be added to make the tooling more effective you're going to have to essentially test it either in TypeScript you can test it in Rust too and use the Nargo package manager that's up to you but I only highlighted TypeScript here because most contract developers are probably going to lean towards that okay thanks we still have time for more questions five minutes more there you go on the right just a quick question on the first like code sample you had I could see the STD package was under a depth namespace and I was wondering what that is that's just our I guess native kind of dependencies and that's how we do it like we you can also import from GitHub or you can have modules as you would only in Rust within your where it would be like mod something and you can also import packages from within a crate as well where it would be like crate this and that would be the import that's just how we import our standard library yeah like Rust crates our Nargo it's not like a copy of cargo but it kind of mocks that functionality with crates and modules so you can have you can import modules from within your crate using use crate and then whatever else you'd like it's a very nice talk in the next phase of Aztec 3 can you talk about the process of converting existing circuits to noir what do you mean existing circuits do you mean contracts like the so in Aztec 3 you're planning on converting existing circuits to noir I assume so that's actually probably you'd want to go to Mike's talk to see more it's very interesting how the infrastructure works essentially though each function in the contract is going to be a circuit but how that actually gets integrated into the system you're going to have to attend Mike's talk to get more info on that it's very interesting we have someone from the team here as well if you want to compliment anything like to add on top of the conversation hello yeah I just want to ask so with Aztec 3 we're not actually trying to be ZK UVM compatible right it's a separate no right just making sure cool there's one more over there this side oh yeah that was my question again that was he said he they made a preamble to the question so that means that noir the noir is going to target to EVMs Aztec 3 is not going to be using noir for its circuits so we're going to be using noir for circuits but you don't necessarily have to target the EVM there we just Aztec's back end does allow you to compile an EVM verifier from a noir circuit and that functionality will still exist but noir contracts and Aztec's platform are not going to be ZK UVM they're going to be noir so yeah so that means that you also have the you right now have the target for Aztec you are going to have or you're going to build it yet sorry can you say again the compilation target right now it's only EVM but you are planning to to be able to migrate to to be able to compile as well to Aztec in the future yes yeah so currently noir is just a language for creating circuits and you can create a solidity verifier that allows you to verify those proofs on the on the once we extend extend the syntax to have a contract terminology Aztec 3 will be built and it will have its own VM and you can compile those contracts to the Aztec 3 not the ZK EVM hi well I am now in noir right now it's so new for me and I would like to know whether the main applications that they are using now are right now the main applications using noir right now yeah well there hasn't been many mostly the examples you can find on my github or inside the noir repo testing the language but there is anything you can think of where you would need to verify a proof and do something based off that ZK proof you can theoretically do in noir so that can be quite a lot of things anonymous proof of membership private games on public blockchains lots of different things alright big round of applause to Maxime from Aztec