ZK HACK III - Introduction to Noir - Aztec
2 Dec 2022 · 1:49:37
Aztec engineers introduce Noir, a Rust-like language for writing zero-knowledge circuits without cryptographic expertise. Noir compiles to an intermediate representation, so programs are not tied to a single proving backend. The session covers fields, range-constrained integers, structs, generics and standard library functions backed by custom gates, then walks through creating, proving and verifying a project with the nargo tool. Participants then build a private quadratic voting system together: a voter circuit checks the token budget and outputs a Pedersen hash commitment, while a ballot manager circuit verifies every commitment and sums the votes.
Topics
Transcript
foreign Workshop I am uh Maxim I'm a software engineer slash language designer on the Noir team here at Aztec and I'll let Joss introduce himself um I'm on the Noir tooling team also at Aztec So today we're going to give an overview to start with an overview of Noir uh which is our ZK DSL and then after that Joss is going to take you guys through
kind of a code together example project uh there is uh I'm going to provide a QR link later to our CLI tool for doing everything but there was an email that was sent out uh like right before this session so if you want to there's a link to our installation page if you want to get started on that before like a little earlier so first we want to ask why should you as a developer care about Noir we want to enable developers of any background to easily get started writing CK circuits as line says here write ZK programs without being a cryptographer so now the properties of ZK proofs
enable us to greatly expand the number of useful applications that we can have we now can actually have privacy preserving applications that are also very efficient to verify however for a while now writing ZK programs has been quite challenging a lot of ZK circuits were written using the apis of a given proving system and then interacting with that proving system usually required some knowledge of how the ZK proof construction operates or also the underlying cryptography that makes that ZK proof system possible in the first place and then if you wanted to switch proving systems you also had to rewrite your program in that API of the new proving
system and aside from Noir there has been a lot of development of ZK dsls to make these programs a little easier to write however there's still oftentimes limited uh in their scope and the proving systems that they support our solution to making CK circuit writing easier is Noir so what does Noir offer Noir is our as I mentioned our zkdsl it is written in Rust and it's fully open source for our native field data type which uh I'll mention we'll go into detail a bit later about is based upon the artworks Library
but the main benefit that we try and what makes Noir unique is that we aim to be more flexible in our design than other domain-specific languages that are currently out there Noir compiles down to an intermediate representation that we call the abstract circuit intermediate representation this IR we call it the Acer can be compiled down to a rank one constraint system or pluckish languages really any MP complete language this IR can compile down to you can think of this as being analogous to something like the Lov Mir but rather than converting down the IR to a machine's specific instruction set architecture we are converting our IR to
the constraint system of a given ZK proof Construction this then enables us to have the decoupling of the back-end proof system and the language we currently have one fully integrated back end that's the Aztec brettenberg library with that uses turbo plunk however we do have plans for further Integrations such as grass 16 Halo 2. we do have an integration with Marlin however there are some missing features still so I can't call it a full integration and due to the fact that we have this our IR allows you to have essentially these proving system optimizations which essentially means custom Gates
and this is with Noir we're providing an interface where you can optimize circuits on the proving system layer so we have these black box functions that we call like they're part of our standard Library we call them black box because their implementation is done by the proving system few examples of some of our standard Library functions are shot 256 Patterson Merkel checks however there's many different optimized functions that we support Noir was started with three main goals in mind safety Simplicity and performance by being more high level Noir can abstract away much of the cryptographic
safety that would otherwise be necessary in a CK circuit language the standard library that enables usage of cryptographic Primitives with relatively little knowledge of the underlying checks and constraints necessary to keep that ZK circuit safe and like cow Noir is rust based we are also rust-like in our syntax as well with some slight adaptations we try and have common programming constructs within Noir just as you would in any other normal programming language and make them simple to use you can constrain variables based upon conditions and loops and you can also constrain on any integer data type as they will all ultimately translate to
our native field type we have flexible code organization so that you can separate your code into modules and external crates which will enable developers to easily create libraries for for Noah programs however although Noir is a very high level we do not look to sacrifice performance while adopting these higher level Concepts Noir compiles down to an intermediate representation similar to lovm before then compiling further down to the Acer we optimize both the this intermediate representation as well as the Acer and then do the fact that Noir has this Acer and is back in diagnostic
we can also optimize at the proving system layer as well optimizing on the proving system layer is what enables us to significantly reduce our circuit size and thus speed up proving time as we will now have a smaller circuit I want to take the chance though to highlight some more of noir's more important features that are supported and show you some more of the Noir syntax before we just dive straight into the coding example first this right here I want to show you how you can easily separate your circuit logic into modules a developer can import functions as you would in any other programming language
such as rust and then we also have globals that can be accessed inside multiple functions of a module as well as function parameters and then they can also be imported like a function would in the same manner you would expect it's important to take note though that we currently restrict globals to only literals such as fields or ins and then there's also array literals in the pipeline there are plans to possibly enable compile time expressions for globals but right now they're currently restricted with an easy to reason about structure we hope to make it easy for developers to construct libraries for their circuits and organize their projects as this is the first Noir snippet that I've shown you I want to take the chance
to highlight the field type as I've already mentioned it a couple times this is noir's native data type which is derived from the proving system in the case of Aztecs breitenberg the field is a 254-bit finite field value from the vn254 Curve and then all of noir's integer data types will ultimately translate to this field as they're just field types with range constraints where we say that it has to be within this within this uh size bit size so this field type though can be can doesn't have to be 254 bits for example with Marlin you can have a field based off of the BLS 381 curve so but with Aztec you can always think about it
being 254. Noir also has compound data types such as arrays tuples and structs in this snippet I'm highlighting two of these compound types specifically arrays and tuples many of you may immediately already notice what is happening in the snippet we are generating a Merkle root from a provided hash path and leaf node this logic can then be used to construct a Merkel inclusion proof circuit in Noir this method does live within our standard Library and this is why you might see the usage of that create prefix when I'm importing different functions if you were to write this in your in your own Noir crate separate from the standard Library you
would have to import using the sdd prefix rather than the create prefix and you're going to see that in some later examples and also the the coding sample and if you've already not taken note you can see specifically the usage of tuples and the snippet inside that main if expression in the for Loop and that's we're using that to set our left and right side of our like the Merkel nodes that we are going to be compressing to get to the Merkel Merkle root so here's also an example of our structs that enable you to easily group data these structs can be nested and they can Implement public functions on them we do
also have the concept of self as you can see in the snippet and this is obviously very beneficial to you as a developer to be able to group data in this way we support for loops and if statements and also logical and bitwise operators in this snippet here I am transforming a field element into a byte array using our standard Library two bits method if you look inside the inner for Loop of these two for loops you can see how I'm utilizing bit shifts but also the or bitwise operator as I'm using bitwise or on u8s here it will act as you expect for a bitwise or I also support bitwise and
however this bitwise or and can be used to mock the what a logical or and operator would perform except you would that would be if you're performing it on a U1 our Bull type translates to a U1 type so if you were to perform a bitwise or operation on two Boolean statements you can expect it to act as a logical or operator and so this is how we currently mock logical or an end in Noir I want to show a bit more of the control flow so here's a basic quadratic sort written in or you can as we did in the previous site you can see I'm nesting for loops and conditionals it is then possible to constrain upon values altered inside of
conditionals and loops when specifying constraints uh directly a lot of this conditional logic usually is handled in kind of an arithmetic expression such as a multiplexer however we abstract away much of the constraint generation for the developer so we want to enable you to continue programming as you would expect in a classical ZK programming language but now you are in a ZK DSL we also have recently added generics which are highlighted in this snippet here there are two examples where the generic is defined directly and also where the type is implied uh first class functions are also uh
active work in progress we don't yet have a trait construct but once these first class functions are implemented it will be possible to mock the functionality of traits using first class functions generics and structs so just a little uh warning Noir is a work in progress um do you expect bugs and do expect some limitations with the language however uh we're proud of where it's at right now and expect uh uh constant improvements as we are going to be continuously iterating upon Noir so now let's get into how we would actually go about writing into our program
so typical three-step process we have to set up and write our Noir program and then because we were writing a ZK circuit we then have to prove and verify that program so here is noir's native package manager this is the also the link that was sent out before the workshop so for whoever wants to follow along please uh scan that QR code and follow the instructions for installation so nargo is a noir's package manager that is comparable to also rust's package manager cargo uh nargo provides also all the necessary tools for proving
and verifying your circuit aside from just uh compilation and proving and verification though will always require the back end proof system So currently nargo has to be compiled with an integrated backend system so there we have binaries on that installation page for your respective environment and you can also compile it from Source however unless you already have a setup environment I recommend just using the binaries as the uh the back end system is a big c plus librarian compiling it from Source might not go perfectly for you so I'm gonna just wait like two seconds let people uh
install it if they can uh give people a couple couple sec I see someone posted the link thank you for that um and I'm gonna move on right now but there will be I'm just going to do a basic setup walkthrough and then there will be time to to get nargo set up once you you have nargo installed we can make a very basic project so create a directory where you want your project to live and then you can if you've uh followed the instructions correctly nargo should then be installed into your path and so that you can just call nargo anywhere on your machine so you should
be able to do a nargo new cast ballot and this will create a very basic program that'll have a nargo Tomo file and a source file containing this main right here that looks like this uh is just the packet is a package's manifest file similar to Cargo Tomo that you would see in rust or package.json in an npm project if you're unfamiliar with rust this is where we specify the compiler version as well as all your dependencies the standard library is an external dependency but it is automatically added as a dependency so that's why you don't see it you're not going to see it listed under the dependencies there and if you
look at the project the snippet on the right I also Show an example of how you can import a local Noir crate and use it as a library in your Noir project uh this we also allow specify like specification of git dependencies uh that would just require instead of a path you would have a GitHub URL and a git tag and this can be seen you can see how to do this in the know our book so once you are assuming you're within your the nargo project that you just created you can then run a nargo build and it's going to look at your your like main your main.nr and look at the main function and see what inputs
and outputs you have if you look here you can remember I have two two inputs one of them though has this Pub Pub keyword so all inputs to Noir are going to be private by default and you just have to use that Pub keyword to say I want the verifier also needs access to this input so that's why you see when we do this nargo build we have an X Y in the provertomo and then just a y in the verifier total so now we're actually then going to prove the execution of our noar program this is going to be done by whoever wants to prove something to the other party so this could be one of the
players of a game this could be someone you touching the finances of a company or for example what we're more familiar with a roll-up sequencer who's rolling up all your uh programs to submit to ethereum so once your provertomo is filled in because our circuit is just checking that X and Y are not equal we're going to pick one and two as our values and then we're going to run nargo proof p will just uh be the name of your profile that gets generated into and and spit out into a proof folder and then now we can actually let's verify our proof so in the examples I talked about earlier the verifiers would
be the other player in the game an external auditor or in the case of a roll-up sequencer the smart contract that's where you're verifying your roll up however we can just verify nargo here so we're going to do a nargo verify P it's going to look into that proofs folder that was created by nargo proof and we're gonna run a and it's gonna use that proof to run verification of the of the program and then you'll see the verifier tomal is also Auto filled for the public input as it can get it from the prover uh so one thing to note here though is if you were to change your like X and Y to both be like one or both be two
nargo won't even let you generate a proof If you it'll it'll return like all constraints not satisfied because that proof is going to return false you could theoretically get around that and generate a proof yourself but then if you try and verify that proof that does not fulfill the logic you're going to get a proof verified false so you can try that as well right now if you're curious but it should uh not let you generate a proof so just to recap we have uh our typical Noir flow of setup prove and verify a setup it might be you might have noticed it's missing the something that you might if you're familiar with ZK proof systems we don't
have any kind of trusted setup that we were doing this is because we're using the Noir brettenberg back end so the common reference string that we're using for all our proof programs is the same one from the Aztec key generation ceremony all the way back in 2019. So this avoids the need for a trusted setup at the moment but as we hope to have like growth 16 Integrations and stuff in the future we will probably enable you to also do a setup through through nargo okay so now I'm gonna take a chance to look at if there's any questions um and answer them before can you take an array as public input
uh yes you can actually yeah yeah you can you can take it in a right you can also we just recently added you can also have uh structs as inputs however those those structs have to have either just arrays or field or or integer types uh is Noir currently using the Aztec back and rust repo yes that is our current back end that's the one uh we have the breitenberg crypto Library that's written in C plus but we have to do some extra rust over top to have it interact with Noir correctly will you know be supported soon uh I don't know the timeline for for edoms in
in Noir um but you you probably could mock this functionality is the field always the same uh the field would differ depending on the on the proof system so right now like with the Aztec back end it is going to be uh 200 it's going to be 254 bits and you can do uh like operations on it such as addition multiplication uh addition division but you can't compare Fields though the comparison operators aren't going to work because Fields aren't necessarily ordered so you have to have integers where there's those like you u64 u32 where you've construct you've had put
range constraints on your field oh well we have a lot of a lot of questions here uh there is there isn't a full documentation of the standard Library yet but there is uh you can you can look in the main Noir repo and there's a one of the main folders is the Noir standard lib and you can look at everything that's supported supported there ignite SRS is the common reference yeah and when you're answering these questions can you just remember to say the questions because for the video after no one's going to know what you're right you're right thank you I think I there's so many I stop I stopped saying
them out loud uh I think you have three more okay so one of the questions is what is ignite SRS that's the common reference string from Aztecs uh ceremony all the way back in 2019 it's what we use to uh it's our common reference string for all of our Noir programs with the Aztec back end um that lets us generate our our approving and verification keys what kind of optimizations do we perform at the IR level that's a good question so there's like technically uh a couple things that get done because if you if you think about it uh we have the intermediate representation and then we
also have I have the Acer so that intermediate representation we do a lot of the optimizations that you would you would have in a the normal kind of lovm SSA pass we have inline it we have inlining we do common sub-expression elimination uh we do uh unrolling loop unrolling uh and all that in our SSA pass and then also with uh like the Acer we do some basic optimizations as well where we kind of we simplify some of like the by variate equations and we also like remove kind of all
coefficients in our equations that might have zero just so that we can reduce the number of gates that you're going to have in our representation and then reduce your circuit size we actually if you look at our documentation we have a compilation overview and you can get the exact details of how we go through the optimizations for the for the Acer are you planning for any security related tools for Auditors uh that would be that would be awesome we don't have a immediate immediate plans for that at the moment uh but the that that would be nice to have um any word on IVC recursion vnor
but IVC recursion I'm not sure what IBC means but I'm assuming you just mean proof recursion nor and there's that there's that's one of the main things we want to add that's one of the big uh yeah that's one of the immediate things hopefully it should happen is on the pipeline all right I think I've answered a bunch of questions just now and it would be a good time to move on to the next part of the presentation but just throw them in and we're going to take periodic breaks to answer more q a questions throughout all right uh I'm gonna stop sharing now and I'm gonna let Joss take over
all righty um here we go that coming through okay I can I can see it cool all right so uh the example we're going to be building together is on a simple quadratic voting app so uh first off what is what is quadratic voting you may have um come across a concept or a similar form of the concept say on um uh get coin they have a quadratic financer uh so we're going to look at it in the context of voting uh here we got two ballot cards for a range of candidates um
and the idea is that you buy your votes for a particular candidate by spending tokens but the cost of each successive vote is more expensive so you see the cost of one vote is one cost of two votes is four three is nine Etc so um on the right we've got a ballot being cast by somebody who really wants candidate five to win that's all they care about so they've just spent all 100 tokens that they that they're um allowed to spend on buying votes for this one candidate this other person here they also want
candidate five to win but um they're willing to put aside some of their tokens to express what compromises they're willing to make and because they're able to because they're willing to do that uh they have more voting power uh the voter is incentivized to consider what compromises they're willing to make you see they're eight their their vote is 80 more powerful than the person who is not willing to consider compromises so we're going to be building such a system and because we're building it with Noah we're going to be able to have the voters hide
hide their different preferences from everybody else apart from the ballot manager who they're going to submit their ballots to the the ballot manager will be able to see everybody's votes but they won't be able to censor or modify them because they're going to be summing those ballots via a verifiable zero knowledge proof so here's a a uh simplified view of the architecture we got two voters here Alice and Bob they've both got their ballots and they're going to feed their ballot into a a circuit locally
and that circuit is going to Output a commitment which is going to go on to a Smart contract or doesn't actually have to be a smart contract could be appear to be a network something like that and then they're also going to send their ballot to the ballot manager and they're going to aggregate all the ballots together and then send a zkp to the smart contract again who is going to verify it and say yep I can see all of the commitments have gone into this proof and the result that you've given me must be valid so again this is what each circuit does so we've got a user circuit who is going to enforce the quadratic voting rules so
check that the numbers add up correctly expose a commitment which is going to go on to the smart contract and then the manager they're going to take the ballots and send them together and also prove that all their commitments have been incorporated into this summation and the smart contract is going to validate both of these groups or in the case of the users every single proof submitted by a user a voter and it's going to store these commitments to be used later for validation of the the summation the aggregation proof so in a bit more detail here we've got a voters ballot
so they've expressed their preferences their votes for each candidate to keep things simple candidates are just identified as index in an array so we've got zero one two three also included in the ballot is a secret now the secret is important because um if you didn't provide a secret when you come to Hash your different votes the commitment that you output is vulnerable to a Brute Force attack um it would be pretty trivial to consider what all the different permutations of votes are uh hash them all see what all the different commitments are there are that can be
produced so we need the secret ingredient to to add some noise here so the commitments all look unique uh and the other thing this circuit's gonna have to do is check the constraints so we've got to check that each of these numbers squared is going to be less than or equal to the Token budget uh the manager they're going to take these ballots they're going to also perform that same hash that the user performed and check that it is consistent with the commitment that was provided publicly earlier posted on the smart contract then at the end they're going to Output the summation so four plus zero four
three plus four seven Etc so first exercise um we're going to be looking at the enforcing of the the QV rule which is checking that sum of the votes squared is less than or equal to the budget and we want to do this because this is how we know that we're following the rules of the game in order to write this we're going to be using a few of Noah's Concepts we're going to be using mutability because we're aggregating a sum we're going to be looking at a few types
we're going to look at the global type for sizing the arrays um the integers which are going to be summed together and the array that we're going to be iterating over which is going to contain all the votes you're going to iterate using a for Loop and we're going to be using the constrain keyword and now this is a an important concept which if you've not written circuit code before it is new you won't see this in more traditional programming languages this is the ingredient which allows you to say this circuit tells you that a certain thing is true so it looks a bit like an assert statement in other languages um except if you played with circum it's
different from the asserting Circle which won't actually affect witness generation but in in the case of Noir it does uh right on mutability this this is what declaring a mutable variable looks like you need the mute keyword if you don't have that then reassigning it is going to throw an error this is what a global looks like uh globals are constant um you don't need to worry about a global getting reassigned and causing confusion later an unsigned integer it's has its type constrained using the uh the U followed by the number which specifies the number of bits so this is
an 8-bit integer and an array it follows this um syntax here of saying what type the element is and then the number of elements you can assign it as a literal there's also another literal assign you can do which is like the first element is the uh how you want to initialize every element in the cell and then you have a semicolon and then the number of elements um what a for Loop looks like so you've got the range operator which is familiar from rust um and here's a constrained keyword so you can just have whatever
uh binary operation you want to use here so we're going to give you a bit of time to mess about with these Concepts um if you go to the docs page you'll see all of these ideas that we just covered there and we'll give you a bit of time to check that you can compile a program assign a variable do a for Loop and then once we've done that we'll look at the spec for the first function that we want to implement and then we'll go on to the implementation in the meantime it's probably a good time to take some questions uh so in Maxim's part of the
presentation we saw that we can have an array which without specifying a length is it a feature only available for the main function oh hang on dot dot main function parameter so for the main function you will always have to specify a length of the array because uh when the circuit gets compiled down it's it has to have fixed length arrays when you are writing more general purpose functions uh you you can write a an unsite array as your function parameter you might have seen it in the I think my compute roof root from Leaf function uh
the hash path is a it looks like a variable sized array but that method is going to be called from a main function and the main does have to we do have to know the array size we don't have uh variable size arrays from from Main just yet so the compile I would then figure out that the array being passed later down to another method that has a variable size parameter uh what what that array says what that array size is you currently do need to know the index of an array it has to be compile time got another question where do we see no
r a year from now um and what features does the team want to see integrated so all right I think in the short term uh there's a lot of um a lot of features which just uh need uh fully integrating with each other so we have arrays as inputs but it'd be great to have uh arrays obstructs I think that's going to be a great Improvement to the language this is what I'd personally like to see um other big work we're going to be doing is um related to the Aztec free road map at some point we've got to consider
um how we want to make the language extendable to consider Concepts like private state getting and setting a private State on contracts that kind of thing note that no R itself will never be a contract language that would be an extension to a NOAA which would enable that concept yeah I think uh stateful Noir is one of the big things that could be happening um a year from now um some extraneous features like recursion and uh like proof recursion inside of Noir and other things uh should hopefully be happening sooner I think the more exciting stuff is stuff
like yeah stateful Noir and the extension language for smart private State like Josh just mentioned yeah I'm excited we have pre-fercussion that should enable a lot of new use cases uh Thomas asked how could you do a tornado cache like proof where you want to prove that a hash is included in a list of all user deposits uh if your list has to be fixed size well you could do that through uh that compute roof root from leaf leaf method uh you you would just have tornado cash doesn't necessarily have uh a list of all user deposits it stores it as a Merkle tree
um so if you provide the correct Leaf node and you provide the hash path up to the root of that tornado cache uh the tornado cash contract where the Merkel tree is stored you should you can do a tornado cache like proof um yeah you you could theoretically mock it by having you know user deposits of a a list of uh of a Max size of some sort um but it's you you can also do it through a Merkle tree instead and the hash path will always probably be like depth of 32 or something like that uh what take one more question uh and then we can maybe move on to the next
part uh all right we've got is reference type I.E Ampersand not implemented yet no it it is not um there would be a bit that's a little bit challenging of a of a thing for a ZK DSL that would that would essentially mean we have uh non-determinism this is actually very powerful though um and it's something we want to implement but we have to be careful about it and we we hope to have that eventually but right now no cool I'll move on so here's the spec for the function we want to write
we we're going to be checking this quadratic function so we are going to be aggregating the square of each of our votes and then checking the that summation is less than or equal to the budget so a function is going to have two inputs it's a budget that we're adhering to and all of the votes that we're going to be iterating over squaring summing and then at the end of this function we're going to be performing this constraint check so uh if you haven't already as um as Maxine prompted earlier create a uh a Nago project a Noir project using Nago new
go in there and open your main file and get coding and we'll uh I think we're going to give you seven minutes to have a go at implementing that function in the meantime we can take any more questions if people want to ask yeah if you have errors you can we can maybe answer them too although we're not looking at it's hard to see what exactly uh everyone's coding but yeah just maybe we uh we go back to the spec
someone just asked can you uh give a link to the specs maybe we go back to that page yeah so uh wisdom you asked uh cannot find module uh if you installed it using the that that's reminiscent of uh in an old error that I'm surprised you're getting uh if you installed using the binaries you should be using uh it should be installing with a tool that doesn't use the uh this old wasn't based backend we had you could also try to use the uh compile
from Source you're just going to have to use the wasm executable back end it's in that installation guide it's going to be option 2.1 um you're gonna have to replace the a dependency in cargo tomal but that should hopefully uh solve that I'd say it's worth noting if anybody is using an old installation of nargo it's It's Worth updating because it it changes quickly uh how can you pass in an array as input in the provertomo uh so that would be you would specify it as as you would in a list in a Tomo file normally you would
just have two brackets and then your your list of your list of numbers um I'm actually gonna drop a link in one moment to our nargo tests that should have some examples of uh just some some of the different inputs and and all that so you can get a look at it so here's a link to an array test um inside of Noir you should be able to see in the prover Tomo there uh how you would specify an array in the tunnel file
there's also from that same link you can go back into the test data directory you'll be able to see a bunch more examples where we test Noir we have a question sorry oh is it no you you got it should we call our function Main or check within budget and call it from Maine uh so I would create a new function uh check within budgets and you can call it from within main you don't actually need to call the function in order for the program to compile at this point we just want to check that you
know how to write the right syntax but if you want to build and run it then yeah you would want to call it from Main oh right sorry I I did not bother explaining that candidate count is a global uh I should have said that so if you put that at the top of your file and set it to some number like 10 is what we've been using so you'll have Global candidate count equals 10 semicolon and then you can use it later on in your in your function signature and if you do write a main function that
calls check within budget and you you'd also be taking in uh yeah just like that there you can you can use that candid account uh in both the function signature of your main and then your check within budget function as well we'll give you another three minutes we got a question is Noah suitable to be
installed in Ubuntu 18. uh it uh it should be um the the I recommend just using the the binary for this presentation but you should be able to compile it uh from Source on Ubuntu actually probably easier than on Mac or Linux uh due to the C plus plus backend but I've mainly been working on a bunch of uh 20 or and some people have done 22. but I don't see why 18 would be a problem we have a question
uh could we give a sense of what schemes are supported via what back ends and if and where a solidity verifier is available and do you have a road map that we can use to plan contributions so at the moment the only back end that's fully supported is the berettenberg back end and there is a command for generating a verify contract for proofs in this proving back end as for other proving systems do we have a road map
um I imagine we'll be putting out grants perhaps um we're in discussions with some people who want to integrate uh back ends with regards to someone planning contributions you can take a look at our GitHub we have issues a bunch of issues we probably should label which ones are better to get started with for the first time but I would say it's not a road map but it's somewhere to look if you're planning to contribute shouldn't token budget be a field type so the reason that we're not making it a field type is because of this part of the spec here uh laser pointer
we've got a range check here if it were just a field you wouldn't be able to do a range check the concept just doesn't exist for Fields they don't necessarily have an order but integers do have an order so we need it to be an integer um Can ins in some an integer sum overflow although you failed that one yeah but it will we do you can have uh you can have you can have overflow uh same thing with you know multiplication and all the other uh with like operations like that
cool that's time we'll come back to more questions later uh so here's a solution so Global defined as stated is our function here's your our function signature so we've got the token budget our u32 type and the array of votes which is of length candid accounts and all the elements are of type u32 is our mutable variable our mutable u32 that we're going to be aggregating into we're going to initialize it as zero and we're going to iterate over every element in the array and that arrays of
length candidate count and for each one we're just grabbing the vote we're going to square the vote and we're going to add that onto the existing value of token spent and then at the end we're going to check that token spent is less than or equal to the budget um that's it uh I mean this is just one way of implementing it you could there are other valid solutions to this so when we've gone full I guess I can answer a couple questions though while he's out um so just specifically I saw one of them I made your same solution but I'm getting an error for I in zero to candid
account the range of a loop must be known at compile time I'm surprised that is that's the thing I mentioned earlier with how array the array index must be known at compile time um but I'm surprised you're getting an error if you wrote the same exact code I'm going to be posting the answers I just posted it in the chat this is for what the example 2.1 that we just did so you can copy this code if your snippet isn't working and you want to continue following along with the other sections and I'll continue posting updates like for the new Snippets once we once we get there so if you have that error Josh you want to test out your audio real quick how's my sound now yeah you're good wonderful
uh right I've got a ton of questions filter on again so do you have simple debug tool like print line macro to trace the circuit not yet um we really want to add logging um this is something we we do want to add you can kind of debug using the constrain statement um to determine like where something goes wrong in your in your circuit um but it's right now very manual on the developer to debug and we we do want locking um it's one of the main things internally these u32s should be represented as field elements yeah all our integers ultimately translate to our
our native data type the u32 is just a field type with range constraints and that's also why we're using but we need those range constraints to enact some type of order for when we do comparison operations like greater than and less than will we get a plus equals operator soon uh don't know maybe right now uh right now no um you're uh I don't it's you can mock it with uh without it's not a high priority because it's you you don't have to use it to achieve the same functionality I saw the loops end with semicolon uh why is it necessary so we use this is a
kind of long story how we got here but um we used to support that you could uh aggregate the result of a for Loop into an array but we remove this functionality but we were planning to add it back right now we just added that like literally like yesterday or something that semicolons are no longer necessary um they're optional for four Expressions um I don't know if the recently updated binary will yell at you for that but in this in these examples I believe we we have semicolons behind all our for Loops but won't no longer won't be necessary anymore is the VEC macro not supported no we don't we don't have a we don't have those those macros right
now the only macros we really have are the ones that tell you whether or not a function comes from the back end and I'll answer this last question and then we can go to the next section does the main function always return nothing can it return a vowel which can be a public output yes yes uh you can return values from Maine uh we just have it yet and in the examples I provided Maine has not had any output and the output has to be public it's essentially treated like syntactic sugar as like a you could think of it as like a public input as well um but we we you can return stuff from Maine and I'll let Joss continue with the presentation
yeah we're going to see that shortly in fact uh so moving on we're going to jump over to the counterpart circuit we're going to go over to the ballot manager circuit who's gonna count up these votes with producing on the other end so we want to reveal the totals of all of the ballots summed together so that we know the result of the vote we're going to be touching on some similar Concepts again to do this we're going to be aggregating again so we're going to be using mutability um and we're going to be defining array lengths in globals and we're going to be taking in votes as
integers so we'll be summing them as integers um and we're going to be dealing with a nested for Loop so at the moment we can't currently do 2D arrays so we're going to flatten our array of ballot switches kind of like a 2d array each ballot has got 10 votes on it so if you've got an array of ballots and that's like a 2d array but we're going to flatten it for our purposes um until we do have support for that but we're going to need to do a nested for Loop to iterate over that flattened array and then we're going to look at return statements as well uh so this is what a nested Loop looks
like pretty much what you'd expect one Loop inside another and you can see here's an example of some uh 2D array index arithmetic here is a return statement so like in Rust uh if you want to return something at the end of a function you simply just don't have a semicolon at the end so that final expression is what gets returned uh is a function that returns 42 and then his main which is returning the value which is returned by get answer and again there's no semicolon here notice at this point we have specified a return value for the main function and as Maxine was saying earlier it has to be public so we we do
explicitly state that it is a public type and when you come to run the the logo proof on this if you leave the the return property in the provertommel as blank then Nago is going to infer that it should automatically generate it for you and it will do that in the the verify term also here 2A that's 42 in hexadecimal so we're going to give you a couple of minutes again to mess about with those Concepts um again you can look them up on the docs and then
we'll probably take more questions while you do that and we'll return to the specification of the function that we want you to implement after that we've got somebody saying that they were able to compile their four expression without the semicolon so that binary must be out well that's good then so I guess uh not necessary to have the semicolon you can still have it um but don't need it question would you mind explaining the contents of the tummel files a bit more so there are three tunnel files there's the Nago Tamil which is where you're going to State your dependencies for your program in the case of this one
we're not using any external external dependencies so you won't need to touch that file then you've got prover.tommel this is where you can mock your inputs to the Circuit so you will write x equals whatever value y equals whatever value and return equals whatever value if your public function sorry if your main function has a return then the uh the return property name is what gets matched to that then there's also a verify toggle once you've generated your proof you will want to verify it so inside your verifier toml you are going to State Properties again but those properties
are going to be whatever public inputs you have to your main function foreign what do we have to do for this task sorry that so the task hasn't started yet uh we were just talking about the concepts you're going to have to use so the returns the nested loops and using uh generating a uh a return automatically we're going to move on to the task now so here's a spec we're going to write a function call it some votes and that is going to take a 2d array of a flattened 2D array of elements of all the votes and it's going
to turn that into a 1D array of totals so here's what our input variable is it's uh notice that you can actually do arithmetic of globals inside the type declaration here so if this is a vote account of 10 sorry a vote account of we're just going to do to Alice and Bob but you you could do whatever number in principle it's just easier to test if we're doing two for now candid account will want it to be the same as we had in the other circuits so we'll set that to 10 so Global candidate account equals 10 Global vote account equals two and they're going to get multiplied together so that the signature here is an array of u32 of length 20.
and then our function is going to Output our array of totaled votes and that's going to be of length 10 the candidate count so um yes important to note we're now doing this in a counterpart circuit we're not doing this in the cast ballot circuit anymore so you'll want to go up a level and create a new nargo project you can call it count votes go into there go into the main file and start writing your function in there we'll give you seven minutes to try that out but it's seven minutes too generous how
are we doing for time we've got like 30 minutes left we would call that uh five minutes actually I think you have a bit more time oh yeah I think you have I mean our current trajectory is at seven or like at seven UTC uh so in 50 minutes we start the job fair oh okay a little earlier we have a few slides but not too much and there are a few more questions in the Q a right now I just and also just a quick did you answer the dot tummel file question the explaining the contents of that yeah so we talked about the three tomal types uh Nago the
verifier and the prover okay so I hope it's okay if I Mark that as answered but yeah there's two more one one is like yeah just not sure so what do we have to do for this task one uh that's I think he asked that before we we got to here so uh that one should be answered uh maybe we can go back to the to the specs so people can have a look at it then if so but there's one more question I didn't answer understand very well we need to recreate a project yeah so the previous the the previous uh like circuit that we just wrote that function check within
budget that's checking on the person who's voting side they're they're submitting a ZK proof for that but then there's going to be a separate circuit for the actual like ballot manager who manages these these circuits um so it's going to have to be a separate project um so you're gonna like CD out of that old project you made for the check votes within budget and you're going to create a new one for the ballot manager and that's where your sum votes method is going to live foreign of the circuits once more but
essentially you're going to have two separate two separate uh entities here how do I create a new array foreign type something in the chat or yeah if I do let x equals oh I see someone posted a a reference to the project but I would say uh hold off on that until we actually uh unless you want to get a peek at the answers um
but there's some good examples of how to declare stuff and other projects in uh in the nargo tests is the input flattened in this weight in this way uh vote one one vote one two vote two one vote two two um yes though uh it will be more than two
votes per user it'll be ten so it'll be vote one one vote one two vote one three vote one four etc etc until you get to vote to or actually it will start with vote we're indexing from zero right so vote zero zero vote zero one but um let's say that Alice got their commitment in first and then Bob got their commitment in so all of Alice's votes followed by all of Bob's votes maybe it's okay for us to share the gist of the prover input for the
ballot manager since that's not actually a solution you doing that Josh or should I grab the link uh if you beat me to it I got it right here the cougar tomal for the manager yep yep here though notice uh in that prover it's also got some extra ingredients that you don't need yet you only need the votes so you can comment out the other bits give it a two more minutes I guess
yep I've got two on my timer does a silence mean that it's easy
everyone's already done it or very hard question do you need to allocate the
output array foreign sort of you need to declare your mutable array element sorry your mutable array variable and you'll probably use an array literal and that's going to have a length in it so you're sort of allocating the number of elements in that array then I don't know if you'd think of it as allocating the traditional sense since memory management isn't really like a concern of Noir as far as I'm aware what's the constraint here there is none uh actually
so there's an implicit constraint which is the output of this program is consistent with what it's supposed to compute but you don't have to use a constrain keyword perhaps we should uh reveal the answer now yeah let's do that so we've got our two globals the candidate count 10 the vote account Alice and Bob two here's our function signature it's going to take all of the votes so that's our flattened 2D array which is of size 20 which is those two globals multiplied together we're going to Output what is the
uh the uh if you imagine that you had a matrix you're just going to compress that Matrix down to a vector so that's going to be just the length candidate elements here is where we're allocating our our array that we're going to aggregate into that the totals array so we're just starting with every element in the array being zero and it's of length candidate counts so using a semicolon here to denote that and now to [Music] to index over this flatten 2D array we're going to iterate over rows and
columns I and J um and we're going to do some index arithmetic here with uh I multiplied by the candidate count and then you add J we're adding that onto whatever total is already in there so it's kind of similar to how we were having to aggregate all of those squared votes before we're not doing any squaring what we're having to deal with is the indexing so that's the uh the puzzle in this one and then at the end we're returning the totals notice no semicolon that's that method and uh Maxine's gonna
post a gist to that snippet so that you can compiler yourself if you if you're behind and that's also going to have the main function hooked up in it so you could also prove on it if you wanted all right we've got another QA section but we don't have anything in the QA yet so anything in the chat I think we uh hit up hit all the questions for this one all right perhaps we'll move on then we're going to go back to the user
circuit now we're gonna be outputting the commitment of your ballots so this is important because if we just State how many votes with how did I do that uh yeah without outputting the commitments we've we've got nothing to be held to later when it comes to counting the vote for producing this ballot commitment we're going to need to use a hash function do you remember earlier we talked about maybe I'll just go back to the architecture slide uh [Music] not that one
this one here we go we have a ballot it's got a secret and when we want to produce a commitment we're going to Hash that secret with all of the the votes in that ballot this is how we make our commitment um Brute Force attack resistant jump forward again so the concepts we're going to need this time we're going to be dealing with the field type up until now we've been using integers but the field we're going to need to use
because of the interface on the hashing function and in order to access that interface we're going to have to cast our integers into Fields so we need casting and to use this hashing function we're going to need an import statement the hash we're going to be using is Pederson you might be used to other hashing functions like Poseidon I think we've got a grant out for implementing Poseidon but uh Patterson is good enough for what we for our purposes because we just need a collision resistance um so this is an example of a field in use so remember that a field is something that you're not going to come across in other traditional programming languages
it is specific to uh the realm of ZK programs because a field refers to the uh the type that is used by the proving back end here's what it looks like to cast so we start with an integer and then we say that we want to treat this integer as a field an integer already is a field but now the program knows that it should be handling it as a field and here's what it looks like if you wanted to cast your u8 into a u64 is what um including the standard Library Mains namespace looks like
and here's that used in conjunction with the Pederson hash so it's part of the standard Library it's part of the hashing crate um it's going to take a transcript this will be an array of fields here and notice that we're only interested in the first element that gets returned by this by this method um the reason being is Pederson is going to return an elliptic curve point and we just want a single field element so we're going to have an X and A Y we're just going to use the X that's sufficient um this is what the function signature looks like for the standard Library Patterson um this is you can check out the other
standard Library methods if you go to the uh Noir project in in GitHub and go to the Noir standard library and source and then hash dot Noir corresponds to the crate there are all the other standard Library crates sitting alongside in that directory you notice that we've got this macro here the foreign Peterson we're just saying that we're using an optimized gate a custom gate from the proving back end in order to use this function oh did I just give the answer there I thought that was a hidden slide no okay I was just confusing myself uh
so um we've touched on this already but to recap why don't we just use Fields all the time we've been using units until now and the reason is because we want to do that range check you you can't do the range check with regular Fields so in our earlier sample we needed that range check um so have a go at importing the pedeston have a go at doing some casting we'll just give you a couple of minutes to mess about with that syntax and answer any questions and then we'll go on to the actual tasks so the task isn't set yet we'll have the spec on the next slide
can you give a prover toml file um I guess you want the prover for you asked that five minutes ago so that would have been for the uh the ballot manager I yeah I think I sent in the one for the manager and then I also just sent the one for the user because they're about to they're about to do a user the user circuit again so I just sent both of those cougar Tomas okay the return uh someone asked if they can the return be empty in tomal yes it can um but right now
only for uh individual like integers or field elements we actually I think like literally have a PR open that is just being reviewed to enable returning arrays uh with an empty you can autofill arrays in the verifier total as well so that will be happening soon as well uh you see yeah you just write return equals uh an empty string one more question I get expected two number of values but got four number of values when trying to prove the ballot manager so you're gonna have to comment out some of the
some of the value uh probably some of the values in your approver total because we haven't finished the uh manager circuit just yet and there's some extra inputs there that are going to be part of the next part of the workshop um you just need to match up the number of inputs in your main function and in your prover total all right let's move on here's the spec for what we're going to write oh and also this is now back in the user circuit so we started in the user circuit then we moved over to the manager circuit now we're moving back to the user circuit so CD up go back into cast ballot and go to the main file in
that this function we're going to write is calculate ballot commitment so that's going to take us input what we saw on the architecture slide earlier so it's a secret followed by all of the votes you can just put them all in on array together and then that will be your input for the pedeston function so the input to this function we're writing is all of the votes so that's the candidate count length again and then also this Secret and then you output the field which is going to be the x coordinate of the Pederson um
so the challenge here is forming the array which is the transcript which is going to be the secret followed by all the votes and then passing that into the Patterson hash we'll give you seven minutes to try that out one more question we have uh is nargo compile not yet implemented in the Linux binary version uh the nargo binary should be feature complete um perhaps there's some unique architecture Edge case that's
messing with that um it please like uh hop in our Discord or something after this if you're having issues still with the the binary um we would like to not have make sure you don't have those issues um no I'm not sure I why that might be going wrong in a bug report would give us a lot more info um it should be it should be working though and you can also try compiling from Source if the binary isn't working for you um and it should be it should work on Linux with the wasm back end uh yeah is there support for big in in Noir so
good question uh not yet we actually do have a grantee uh working on a big in implementation like written into war itself and that should hopefully be not far away um but there is we we do are in discussion about putting big in directly into the compiler as well because we think it's would be much more efficient that we can make it much more efficient that way um but that's that's just uh it's something that we definitely we definitely really want um yeah and there should hopefully be a Noir implementation soon and then someone asked can you go back to the spec uh Joss already got it and he's put it up
foreign uh just a quick reminder to folks just
be sure to put your questions in the Q a right sometimes I see them a little bit in the in the sessions chat right I see that now uh could you guys reveal just how to import the function to do the hashing yeah sorry I'll go back to that slide that was here so we're using the standard Library main namespace it's going to be standard Library colon colon the hash crate colon colon in the method yeah and you might see that depth keyword that essentially means it's uh it's an external dependency um but like that's best because the
standard Library we automatically incorporate into into Noir you're not going to see that in the nargotomo that's why your nargotomo doesn't have any dependencies um for example when I earlier showed uh like if I have like utils equals some like local path in my dependencies I would also have like use depth colon colon utils and then I can use functions and that from that import so we're doing the same thing here we just automatically are incorporating it I know when I get to this part of the code when I've used this my most common typo is to use a single colon instead of
a double you can get thrown off by that compiler error one more minute would it be possible for someone to run
a version of cast ballot that ignored the token budget I.E does the system mean that the count votes role is verifying that the budget was respected so when you come to counting the votes you don't need to um check that the budget was respected because when the user cast their ballot in the first place they would have produced a zkp which stated that they'd respected the budget and then that commitment and proof would have gone to a Smart contract and that smart contract would have verified that proof and said yes this voter here has respected the budget and so when the ballot manager comes to aggregating all these votes together it just knows this
is a valid ballot it's okay because the smart contract has already verified it or the ballot manager could verify themselves um is there Neo Vim syntaxford star.noir I I don't actually know anything um we have we have various like a preliminary vs code syntax highlighting um that you can install from the vs code Marketplace I've actually never used uh neobim I'm sure it would be easy to Port over uh that Port that over but right now we we don't have a I don't think so for any
of them um and what about a formatter is another question we don't have a formatter it would be great to have nargo fmt um would make things really nice um this is some of the things that we will add as we're we've been heads down writing the language now we can start adding a lot more tooling and that will be hopefully a part of it all right I'm gonna move on now is our solution so we're importing that namespace here's our function signature we're calculating the ballot commitment using a secret which is a field and then the
votes and then we've got to form this transcript the transcript is going to be the length of all the votes plus a secret so we've got a length of plus one here and uh it doesn't really matter what value and you initialize it too because we're going to assign all of them we assign the zeroth element as a secret and we're going to iterate all the over the remaining votes and do that index plus one assign it and we're going to cast it to a field as we go because the Pederson hash requires it we input an array of fields and we are returning the x coordinate of the of the elliptic curve point that
comes back from the Pederson again no semicolon because this is a return you see we've got this field being returned in the function signature and I think Maxime is going to share a gist of that if he hasn't already in fact that will now be the complete user circuit so that just will also complain how uh we'll also show how to hook it up to Main uh have we got any more questions at this point do you plan to support exporting to Cairo that would be uh
extremely challenging if not impossible um Cairo is very specific to uh starknet and they do have like hints that enable private inputs or something um I I need to look a little bit more but uh you Cairo I don't think you can have uh basically like this hidden data like we do in or um you could theoretically have Acer oh for a verifier oh that that would be neat um but it's not something that we've uh been able to allocate resources towards but if someone wants to write a a Cairo
verifier for Turbo block that would work with Noir um and then as we upgrade our proving systems if someone continues to also upgrade uh solidity verified also be a Cairo verifier that would that would be great that would be now you could export Noir programs to starknet one more question here transcripts inner type is inferred as a field uh here do you know what that question means Josh sorry oh okay yeah I think oh so from there okay I've what have I said yes um so it's a we've only called it
zero right we haven't specified a type uh so I guess at this point it's a polymorphic integer is that right Maxine yeah so when you don't specify a type it's going to be a polymorphic end and then the first place it's used that's going to be the end type so here the first place we use uh transcript 0 we're caught we're labeling it secret so it's gonna it's gonna infer that uh transcript is a array of fields it's actually a good question I wasn't sure what he meant by transcript but cool no questions so I think we'll move
on all right we're jumping back over to the counterpart again back to the ballot manager so we've now got the user circuit producing these commitments so going to the smart contract or whatever consensus system we're using um and now the ballot manager wants to take all of those commitments and check that they're valid foreign sorry we're not covering any new Concepts at the moment we're just going to combine everything that we've learned up until now uh we will be needing to recalculate all of the commitments for all of the
ballots which are being inputted into these managers circuits so remember we've got that flattened 2D array of votes so the Alice's votes followed by Bob's votes um so we're going to have to take that chunk of votes and then combine it with a secret and you can see here are our inputs um we've got an array of Secrets these arrays are all going to have to follow the same order so this array of two elements is going to be Alice's secret followed by Bob's secret this array of commitments is going to be Alice's commitment followed by Bob's commitment and then all of these votes is going to be Alice's votes followed by Bob's votes so that's a task
um and of course you're gonna have to do a constraint in here you can actually do a constrain on all of the hashes as you calculate them so go back over to the ballot manager circuit have a go at filling out this function check commitments will give you seven minutes for that this is the last exercise by the way if you made it this far well done hmm should we reuse calculate ballot
commitment from the other file so you can try and do this but you're going to run into some challenges um you'll probably find yourself rewriting that function because of this flattened to the array of commitments it is possible to get something that looks close to that function but you're going to need to add an extra parameter which would be like an offset inside this 2D array where you want to inspect and then if you do that you're going to have to get into some other advanced concepts like uh uh compile time arguments so if you want a challenge you can try doing it that way but I'd recommend
uh re-implementing it using it um using a nested for Loop it's a not a way to use the array as a pointer and just shift it so this this kind of relates to the old question about references we don't have uh arrays are technically like a pointer underneath but once again we don't support this uh non-determinism uh with arrays and uh yeah but not right now it's a it's a especially it's a bit more adding that to uh a ZK circuit language um adds a lot of complexity and it's
something it can be very powerful we want to add it but it does not exist right now you have to set your arrays so that they're known at compile time foreign question
earlier you mentioned you did not support early return this is by Design or something which may be supported later I have no idea about that one Maxine yeah so you can kind of mock early return through other means so we haven't necessarily uh we haven't we just haven't added it um we just you can only return at the at the end of uh the last statement of a function right now um it may be supported later but it's it kind of requires a you're almost like short circuiting um and that's something that
it's just we haven't uh we haven't prioritized just yet we'll give you one more minute yeah is seven minutes moving on
here's the solution or uh our solution anyway so you're importing that namespace again we've got our two globals we already had those before to check the commitment so we're going to need all the inputs which are the commitments the secrets and that flat 2D array we're iterating over every voter so Alice and Bob and in each case we're going to have to reform their transcript so again that's going to be an array length of 11 10 plus 1.
and we set the first element as a secret according to the order of the voters so this will be Alice's secret first and then on the next iteration that'll be Bob Secret and then we've got to do the same business of copying in all of the votes and casting them to Fields but this time we're doing it with some um 2D array index arithmetic and then at the end we're going to constrain whatever input commitment is at that position in the array to the output of the Pederson hash or specifically the x coordinate of it notice that we're performing this constraint inside of the
for Loop you could if you wanted um have another mutable variable which U.S that you set a Boolean on if any one of them wasn't con correctly matching the pedeston and then you could just constrain it at the end to either way is valid um so any questions oh yeah maximum did you uh post that in the the gist cool thank you I haven't posted the circuit inputs once more um so you don't have to scroll up sweet so at this point we've got two complete circuits
um so you can try running the prover and the verifier on them um you'll notice that the sample inputs for the user circuit has got the inputs for one of the voters commented out I can't remember if it's Alice or Bob but you can just switch the commenting out around and then rerun it and then you'll notice in your verifier tomml that you'll see the commitment being outputted and if you look at back over at the user manager inputs those are the commitments that got copied in the output in that verify tunnel and the user manager inputs is going to contain the complete complete set of inputs to say that I
have got a valid summation of all the votes and then that would get posted on chain it would get verified and so concludes the election foreign we got any questions is there a way to get more information about the line that caused the issue in an error I get index out of bounds the length is 20 but the index is 20. so you're probably indexing incorrectly as it sounds like an index indexing error and the the size of the old votes array
should be 20. um so you might be uh just somewhere somewhere the indexes is off um perhaps your transcript array needs to be uh or well it's actually length is 20 in the index is 20. so it's probably related to your all votes array there But to answer your question as to whether you can get a line number I think at the moment you can't do that um yeah this is we have to add a bit more around I guess the some of the error handling um specifically when evaluating the program we have some pretty good error handling
with regards to compilation but and building but there this is part of our tooling improvements that need to be done cool well I guess we're nearly at time and I can't see more questions so this might be where I oh sorry yeah you might have seen it in the gists but in case you hadn't seen it in the gists this is what it looks like when you assemble it all into the main function so this is a user circuit so you're going to do the constraint check you don't care about the return because the constraint constraint check is happening inside that method and the calculate commitment you do care
about the return so notice the lack of semicolon and notice that we got this public field being outputted uh here are those Tamil files we were talking about so in goes the inputs out comes the commitment here inputs his commitment and then we copied that oh and then we assembled the main function for the manager circuit so we're checking all the commitments and then we're outputting all the summed votes and that's what the inputs look like here uh feel in the near future you when you um
when you execute this yourself you won't need to specify the return but I think with the current build that's out you do need to um because it's an array of returns returned integers it doesn't know how to auto generate that just yet the fix is on its way out um and if you want to see the complete example you can go here contains everything you've just seen I think um sorry there were a couple of slides for maxim to finish on these ones will be fair so uh we do we do support uh generation of a solidity contract based off of our uh
like you're in a war circuit um and this enables a lot more powerful use cases so you don't have to have you can actually have a verification in the smart contract rather than in uh just like an individual verifying a circuit and this can combine it enables autonomous execution based off of your your ZK proofs actually I'm noticing someone asked a question how do you get the user's commitment we're assuming in this case that the users are sending it to the ballot manager who's then using those commitments but for example if we had a contract where the user was verifying their circuit the ballot manager could fetch the commitments from
that smart contract and also see that these votes uh the budgets are valid and the users have submitted valid ZK proofs you could go to the next slide Joss and then be in order to easily interact with uh the these circuits and the solidity contracts we also have typescript wrappers this is one of the main places though that we are going to be working on Tooling in the coming in the coming months and you can expect lots of improvements and hopefully improvements for the developer experience to so you can easily have Noir circuits that are interacting with salinity contracts and or just in
typescript if you prefer developing that way and here's a bunch of uh the resources that might be uh relevant to you uh based off of this from this presentation please join our Discord as well if you have any questions or errors while you're maybe uh programming um yeah I hope everyone enjoyed the presentation foreign [Music]