ZK HACK III - Mina zkApps: 🛠️ Zero-Knowledge Programming with TypeScript
9 Dec 2022 · 1:05:37
A ZK Hack III workshop introducing Mina Protocol's zkApps, smart contracts built with zero-knowledge proofs using SnarkyJS, the TypeScript library O(1) Labs built for the chain. The session covers Mina's zkApp architecture and how developers can get started writing zero-knowledge smart contracts, part of a four-week virtual event pairing workshops with puzzle-based protocol challenges.
Topics
Transcript
foreign hi everybody uh thank you so much for being here and for attending our Workshop Zeke hack is really cool so thank you for them to having uh thank you to them for having us um and today we're going to be talking about snarky Jazz and the Mina protocol um so there we go first a little bit about me I'm uh my name is Jack servia I live in Denver um and I'm a developer relations engineer for Ln Labs so I I end up doing some engineering work um you know some devrel stuff like this and then also some business development and other stuff um you can follow me on Twitter at
jackservia and um yeah uh so what is of one Labs uh of one Labs is uh basically is your knowledge proof technology company and we built the proof system for the media protocol the reference node implementation and now Starkey JS the the smart contract language for the media protocol um so our relationship to the Mina Foundation is kind of like that that of uh you know ethereum Foundation to ethereum versus consensus to ethereum we're kind of like the consensus to mean a protocol um and so here's what we're going to talk about today first we'll run through starkeyjs uh kind of briefly what it is why it's interesting and uh what you can do with it and then we'll talk about the
Mina protocol um which is uh you know this this layer on blockchain that we can deploy these snarky.js smart contracts too and it has a whole bunch of other interesting properties and then finally uh we'll we'll dive into two code examples so first we'll build a Wordle game and then we'll actually make it recursive which which uh means that we'll be able to play this game without uh sending any transactions to the Mina Network until until the game is over um and so this way we don't have to wait for for blocks to get mined or pay transaction fees every time that a user makes a move um we just sort of exchange these proofs between the two users and then eventually we have a final proof that you know attests to the validity of the entire game and then we send that on to
to the Domina Network and then we'll have a little bit of time at the end maybe 15 minutes for questions and answers and then to talk about where you can learn more um I guess kind of a a meta a meta thing is is that uh you know there's a lot going on here we built a a whole new uh blockchain and and it's very very different from for many existing blockchains and so uh this presentation will kind of try to introduce you to all the things that are interesting and cool about it and give you a sense of uh you know what it looks like to to build applications on it um but it won't be comprehensive by any means and so we have things like office hours and good documentation um there's all sorts of ways that you
can learn more you know after the presentation so if some things sort of slip through the cracks that's perfectly okay the point is is to give you a kind of a high level understanding uh okay so on to snarkyjs uh it's a typescript library for defining zero knowledge proofs and it's also the smart contract language for the media protocol um you can use it without the media protocol and then when you use it with the main protocol it it sort of acts like um uh I don't know what the analogy would be it's um basically a smart contract on the media protocol is a superset of a of a Starkey JS program um it looks like this uh so you can see this looks like something that you can
probably learn it's it's typescript um and it's pretty idiomatic uh and so you can keep using the tools that you're familiar with you can use uh you know vs code eslint prettier npm all the good stuff um we don't have to reinvent the wheel with a lot of this developer tooling because it just already exists uh it's very easy to learn um we have super good intellisense uh doc comments so you can actually probably dive into a code base without looking at docs or anything and get a feel for what's going on just by hovering over anything that that sort of sticks out that you you don't know what it does um and this is actually probably a good way to to get started if you want to is just dive into a code base and start you know poking around at things we also
have very good documentation and tutorials and office hours and all sorts of resources to help you get um you know up to speed if this doesn't work as well for you but this is definitely an option for stock ejs uh Starkey Jess is also extremely powerful um this is for two reasons one is kimchi which is our proof system so we've built this uh kind of from the ground up obviously it you know is sort of informed by the design of other proof systems that are state of the art today um and it has a number of unique features that make it really well suited to to our use case so the first is fully trust the setup um we have custom constraints for Poseidon elliptic curves and encryption and we can add more of these um and so these If you're sort of not familiar are kind of
like you can think of it as like almost Hardware acceleration inside of your zero knowledge proof so instead of having to kind of program things foreign you can you can sort of just like call into this thing that already exists inside of the the framework and um there's really significant efficiency gains here so you know hash functions for example we can build much larger Merkle trees it's not just that it's faster it's that it actually opens the door to being able to do things that might not be possible in another ecosystem our proof size is constant thus ovon lab's name um constant size and constant computational complexity to verify it's recursive it's infinitely
recursive and you can we can branch and merge arbitrarily so what this means is that we can create a zero knowledge proof and then verify it inside of another zero knowledge proof and that first year of knowledge proof is you know the same size as the second zero knowledge proof that it's verified inside of but we can also do is we can verify like five zero knowledge proofs inside of one zero knowledge proof and um that you know top level proof is the same size as each of its constituent parts and so this is really cool for scalability and it also opens the door to um being able to do a couple a couple of other unique things you can do things like run smart contracts asynchronously um you can attest that a sort of a process has been going on correctly for
an extended period of time without having to remember all of the history um and so I'll talk more about this later and then finally we use a blankish arithmetization so we can add new features uh sort of as as that kind of part of uh I guess like research moves forward um so we have things like Dynamic array access that that you know we're working on right now uh and so the point of this is is just that we've put all the horsepower that we can inside of snarky JS um it's really uh uh state of the art um and so you know like under the hood we have you know everything you could want and then when it comes time to use it we've
actually you know also tried to empower people sort of on like the developer side um the the thing itself is very powerful and the interface to it should be very powerful and sort of expressive as well um and so there's just a few things I'll highlight here the first is that we have you know method chaining uh which makes the programs sort of easy to Think Through you can think about you know what is my data how do I want it to change and then you know what do I want to do with it after it's changed um and this makes it simpler to ensure that you're you know writing uh smart contracts that are fully constrained and and just easier to think about in general um you can see what this looks like you know we have uh here we've got is not red Peg um is is you know in this case
going to be a Boolean uh and we get this by you know accessing um this value in index I of guests uh checking if it's equal to zero and then also you know calling this not method on that I mean so if guess I is not equal to zero then is not red Peg is is true um this should look pretty familiar and kind of you know not not too fancy and that's kind of the idea is that um it's uh it's very much like the kind of things you've used before um and and even though it kind of looks simple it's actually pretty complicated to make things work this way and so we've we've put a lot of effort into making it feel like something that you've used before uh another feature that's pretty cool is that we have structs and you know these
are what they sound like they provide a layer of abstraction um that makes your data quite a bit easier to think about and so you can see here we Define a struct um my struct pier and it uh has you know some different values on it and each of these values oops sorry um are themselves structs not necessarily literally when you dive in deeper some of the stuff again is kind of like built into the proof system but you can think about it as you know each of these values being structs and you can compose structs from other structs and so what are the kind of fundamental requirements of zero knowledge proof systems is that um you know of all of them uh is that data has to be represented uh in in this field type field is like a um well it's an element of a finite
field which is kind of like a complicated set of numbers basically that have properties that are pretty familiar for the most part uh with a few caveats and they're kind of big caveats things like division work quite differently um and so this can be confusing for people now it's also very efficient so there are reasons why you would want to use it but snarky Jess uh gives you the ability to to compose these field types into um structs and then you know compose those structs into into even more abstract structs and so on and so on until you get a data type that works like you expect it to um and kind of feels natural and so you can see um we can do things down here like pass these structs into a method of our smart
contract and we'll kind of get into that in a second um and then finally a lot of the stuff that you need is already implemented in snarkygs and we're working on implementing more things every day um and also if you're a member of the community who wants to add something that would be awesome uh we're super interested in getting the community uh contributing even more than they already are adding these little features and and stuff um and and there's Grant programs that I'll talk about after that that can help incentivize that kind of behavior so we have um all of these different types or you know you can think of them as structs as we sort of talked about earlier some of them are again implemented way deep down in the proof system for the sake of efficiency but they behave exactly the same instructs
um and so we have you know these for unsigned integers uh Boolean scalars uh you know public Keys private key signatures and we have more coming soon including things like string um and uh and a few other types um we have efficient Poseidon hash function so this again means that we can not only do things faster but we can you know do more things we can build larger Merkle trees than you could build uh in in in a different framework and this is really powerful um we have efficient encryption and decryption also very powerful you know we can pass encrypted values into our smart contract without it being a huge number of constraints we have efficient signatures and then we have a API for Merkle trees actions and reducers um and a few other kind of uh more
complicated structures that you wouldn't want to implement yourself but that you might need to use and then finally we have the recursion API which makes you know building these recursive proofs much easier uh a question that we get asked a lot is why we chose typescript and um you know lots of people have strong opinions about it but the truth is that it's it's sort of uh quite good at this point in time um I think a lot of the I don't know kind of jokes about JavaScript uh you know originated like 10 years ago and it was more confusing than it is now um there was sort of like obvious features emitted that would be good um and some idiosyncrasies that have kind of been rectified since um but the real reason that we chose typescript is because we're ecosystem focused and uh so we
really think that there's a huge amount of value that we can capture by um or not even capture just create uh by basically connecting people who want to work on very complicated you know powerful magical crypto stuff with people who want to build user-facing products um something like Dark Forest is kind of an example of this where uh you have you know kind of two sides that create a really really unique and and Powerful um cool cool new thing uh you know there's this kind of cryptography problem side and then this like you know let's build a game side uh and usually these kinds of people don't interact as much as it it would be nice if they did and so the idea of snarky just is that you know somebody can build a crazy complicated crypto library that could be
incentivized by a Dao or a grant or something um or do it just for fun and then they can just you know npm publish it or put it on GitHub or you know however they want to distribute it um and then when somebody comes and they want to build a a user-facing product they can just you know npm install this library and get going um so uh yeah we we hope that we kind of get people working on both sides of this and that the result is super cool projects like things like um we have a thing called the zika app Builders program and uh it basically it's what it sounds like it's a program where we we help get people up to speed building ZK apps and then you know hopefully they build um really powerful things and so one of the
the participants in the program uh this cohort um which just closed up a few days ago uh built uh like a bunch of Primitives for games like card shuffling um and so card shuffling is pretty hard you know it's like a kind of a hard crypto problem um at least for most people um and so by just having this card shuffling Library available now anybody who wants to build a card game can um yeah have have a shuffle deck without having to figure out like all the complexities complexities of this you know like how do I prove to you that I shuffled my debt correctly without me knowing the order of the deck or you knowing the order of the deck um so that's really powerful um this is kind of a rehash of that uh this is for in case you want to go back
and look at slides after there will be a link to them um maybe it's already been shared but uh kind of a rehash of what we went through um okay so how does snarky jazz work um here it is in five sentences this is a really high level explanation uh and there's a bit of abstraction it's not like entirely accurate but it's a good sort of place to uh to start your understanding and then if you're curious you can come to office hours or something and learn a little bit more um so it's a typescript library um there's no sort of other component to it it's you know Standalone uh and all the information in a starkeyjs program is represented in one of these compatible types which is either a field or a struct that's composed of fields um and the idea is that uh you know if we
operate on like a number or something um we we can't necessarily like a JavaScript number we can't necessarily prove that we've done this correctly but by using these snarky Jazz compatible types um anything that we do using one of these snarky just compatible types we can prove that we've sort of done it in the way that it was intended to be done um and so you know we represent our all of our data in our program using these types um and then starkeyjs provides classes and functions on these types or or you know just as Standalone things that you can import and they're compatible with you know the field type or the structures that are composed of them and so you can do something like add two Fields together by calling the add method on one of these uh field types um and then passing another field type in
is an argument and so um when you do this it does what you expect it adds the two Fields together but it also does it in such a way that later on it can prove that it did it correctly and that's kind of um you know where the magic happens and so any of the operations that we do on these field types can be represented as this you know kimchi arithmetization which is basically a big math problem that represents our um our program and then this is what we actually use to generate the zero knowledge proof so when a user interacts with the snarkyjs program they can basically remember all of the the values of these you know uh variables that they've used within the course of their program and then they can pass them into this math problem and do some other stuff and basically get a
zero knowledge proof that their interaction was allowed um so that's how snarky Jess you know sort of program works but how do smart contracts work uh so developers write the smart contracts and typescript and they deploy the verification key to a zika app account so they you know write the program they call a method that generates a ZK um sorry a verification key or more likely than not they use our developer tool the Z key app CLI and it'll just do this automatically and we'll actually do this at the end of the presentation uh and so then they send this verification key to the media protocol in a transaction and the verification key you know goes on and gets added as like a piece of metadata to an account and then when it comes time for users to run the smart contract um they just you know run the code
normally they get it from a CDN or ipfs or some sort of data availability layer um you know wherever they want to get it it could even be stored like on a flash drive you know it's just typescript code um and so they run it in their browser and then after they're done running it they generate the zero knowledge proof of their interaction that you know proves that they ran the code correctly and so even if they do something like change the code um they just won't be able to generate a valid zero knowledge proof there's you know this is uh like entirely robust there's no sort of security concession relative to something like uh the sort of ethereum model where you have a bunch of nodes do the thing and the user requests that the nodes do something um and so the user runs their smart
contract they get a transaction which is you know basically a zero knowledge proof and some other data and they send this to the media Network and if the zero knowledge is valid that mean it accepts the transaction and if it's not then it drops the transaction uh and if it does accept the transaction then what it also does is it commits any relevant State updates so when we you know generate our transaction when we run our code we might generate something like an event that we want to emit or a value on chain that we want to change I mean these are associated with our proof and so if Munich can validate the proof then it just you know sort of blindly I mean not actually blindly it knows that everything happened as it should have uh by the zero knowledge proof but it it um
can just basically validate the zero and all the proof and then do whatever other things the user says and it knows that the person can't make a valid zero knowledge proof unless they're requesting things that are legal um and so yeah it just gets like a list of events that should emit um updates to State whatever uh and so here's kind of what this looks like we have the smart contract method and we pass into it um uh you know this is sort of like again like a superset of this uh you know zero knowledge proof program idea um we have is there an all-proof program where we've defined some of the um some of the functionality and the logic ourselves and then have some other logic that handles things like how does this smart contract interact with the state of the world and uh you know the
state of other smart contracts that kind of thing and so what we end up passing into our smart contract when you call it basically and this is abstracted away from the user um they just you know pass in the same things that they would pass in to a normal um like an ethereum transaction but under the hood we passed in you know the the arguments that the user passed in um these method arguments and then we also pass in the state of the smart contract at the time that we're generating the proof and then we also passed in some States from the outside world so this could be like block height or or something like that I mean we pass all these things in we run our smart contract method and we prove that we did it correctly and what we get out is this
list of updates um and you know like these are State updates events whatever and then updates to the state of the world um so this you know I guess would also be like events um permission changes that kind of thing and uh as your knowledge proof also and so we send the zero knowledge proof and these two lists of updates to the blockchain and if the zero knowledge proof is valid then we apply these two updates this is again kind of a rehash and so now let's talk about how you know zika apps work so we have Smart we have programs and we have Smart contracts now about how do zika apps themselves work um and it's actually really simple you just install the smart contract uh into your UI repository and you deploy it and that's it uh you know the smart contract is is just typescript code so
um you can do whatever you want with it you can run it in electron or node or you know a browser um and and you can call into it from your UI code um just like you would call into any other Library um and so yeah you can publish your smart contract as you know a library or an npm package um again it works just like normal JavaScript code is kind of the idea um and we have a tutorial on this too um so okay that's snarky JS but what about the Muna protocol um the amino protocol sort of the consensus of it is pretty complicated and so if you want to go dive into that again we have docsport office hours and and you can also um
you know read the white paper that kind of thing but we'll kind of give you like a high level idea of what makes it different from other protocols um so it's a layer on blockchain and it proves its entire finalized State using these recursive zero knowledge proofs um this is really unique uh because it means that the amount of information that you need in order to verify the current state of the mean of blockchain doesn't grow so with the blockchain like ethereum you basically need to remember every single transaction and kind of sum them together in order to get to this like final like edge of that um you know kind of like transaction history which is is the part that's true and this means that you know ethereum nodes grow over time and that uh it's very hard to basically make an ethereum
node that only uh sort of validates a part of this state um it's really All or Nothing uh and this means that you know people in practice end up using things like Alchemy and inferior as endpoints and then just RPC calling them from um uh wallets that don't really do anything uh so with Mina we have this you know 22 kilobyte um blob and what this really is is it's uh the state route for the amino blockchain a proof that we got to the state route via a you know a valid sequence of transactions I'm sorry via a valid you know um sort of application of the consensus protocol um and then also uh we can include any
actual state that we want to to use and so for like a a block producer node um you might record the current state for every account and this would mean that your your node Size Doesn't grow relative to time it grows just relative to the number of accounts on the blockchain um and so that's you know really nice this means that it's very fast to spin and panode anybody can do it and these nodes have all the account information so they can generate transactions um but we could also do something like make a uh like a single account node and so this would store just again this proof the state route and then a Merkle path down to a single person's account and then all the information for the account and so that's all that you would need in order to like generate your own
transactions and and basically uh not need to connect to some sort of other endpoint like inferior or something um and then there's also another kind of node that I guess I'll just touch on here which is called the archive node and this is a node that just remembers everything um and so it doesn't you know this isn't required for consensus but sometimes this is something that's nice for like a block Explorer if you want to do like um analysis of like previous chain history um this is another thing we get lots of questions about so feel free to drop into office hours or something if if you need more clarification on this uh okay so this is a very different way of doing things um oh and I guess I'll also kind of explain how this works so instead of
summing up all of our our assigned transactions what we actually do with Mina is We have basically a zero knowledge proof that represents uh the validation of a bunch of transactions uh so the transactions themselves are zero knowledge proofs and then we validate them inside of another zero knowledge proof and then when we want to add more transactions we can basically just uh validate these new transactions which is your knowledge proofs and also the last batch of transactions that we validated which is also a zero knowledge proof and get another zero knowledge proof out and so once that's done we can drop all these previous transactions and the zero knowledge proof that Aggregates them because it's attested to inside of this new zero knowledge group so we can just do this over and over and over again you can kind of think of it as like taking a
picture of a picture of a picture of a picture of a picture um if I wanted to prove that I like went to the park every day I could go to the park take a picture go to the park again the next day hold up the picture of the last day take another picture and do this over and over again and that's kind of how Mina works this is like a high level abstraction it's not exactly how it works but um I think it gets kind of like the general idea across uh and so okay is this cool or is it useful um and it's both uh for a couple of reasons the first reason is privacy um so in ethereum smart contract runs on every single node so that all the information is public and you know it it's required to work this way by kind
of like the um I guess like the assumptions of the consensus mechanism uh you know we call some sort of method and then every single app does does our call for us um I'm sorry every single node does our our executes our call on our behalf um so it's very hard to to build private applications in this way but with Mina the smart contract runs in the browser um and the arguments in the intermediate values are private by default um so that makes it much easier to build something like private Dow voting or some sort of limited information game or verifiable credentials or um you know the list goes on and on uh and I guess I should also highlight here that
um the circuit.js and the media protocol are designed uh in such a way that the users prove these things themselves your browser does the work to generate the proof and sends the proof off to the to the media Network so it's not like I run the smart contract and then I sort of like send something off to like a data center somewhere that then does this final kind of like proof generation step um we generate the proofs ourselves um and our proof system is efficient enough that this is as uh feasible and and a relatively good user experience um so yeah this is really really cool um the thing that's not private I guess also highlight is the on-chain state now this isn't a problem and and it has to
not be private you know this is like kind of like a fundamental um uh requirement like where would you put the private key if you had encrypted on-chain State basically you you know it has to live with um sort of a relevant person and if that if one person has the private key for all the chain State then you know that person controls the network basically and so uh what you can do to kind of get around this is um you can store commitments to things so like if I want to uh have like let's say I have a piece in a game and I want to uh commit to the place that it is so that I can't like teleport all over the place willy-nilly um but I also don't want to tell anybody where I am um I can you know take my location let's
say it's an x and y coordinate and hash it and store that hash on the blockchain and then the next time that I want to make a move I can pass in my location and we can check if that location um matches the hash that we have stored on chain and then make our move get to a new location and then hash that and store that on chain um uh again if there's questions uh feel free to ask at the end or come to office hours um okay so yeah the the user runs their method themselves and they send just this state update and and the proof to the blockchain and so the blockchain just verifies the proof and updates the the chain state it doesn't actually have to know exactly what you did it just needs to know what do we want to change and did we do
something that allows us to change these things uh another thing that's very different about Mina is is um yeah kind of the way that you can scale applications so there's no gas Model Z caps run off chain and the amount of computation doesn't affect the transaction cost um so you can do a lot of computation or a little bit of computation and no matter what all that Mina has to do is verify the serial knowledge proof which is always the same size and you know it's very easy to to verify um the other thing that you can do is you can build these application specific Roll-Ups using recursion so that you can actually do an unlimited amount of computation like if I wanted to prove that I had kept the correct moving average of uh I don't know some the price of some sort of asset for an
extended period of time I could prove that I did it for the last you know hour verify that proof and then prove that I did it for the next hour you know verify that proof and prove that I did it for the next hour and so on and so on and I can forget all of the prior proofs I just need the most recent one um and so you know this let's this means we can do you know an unlimited amount of computation and have this proof that it tests to the fact that we did it correctly um so use application specific Roll-Ups maybe kind of think Cosmos app chains um with some other cool features somewhere between app chains uh ZK Roll-Ups on ethereum and kind of some stuff that's all its own but it's very powerful and this is actually what we'll do with the wordal example later
um uh oh sorry it looks like we skipped the slide so uh the other thing that's different is decentralization so because it's possible to validate the entire mean estate using only the small zero knowledge proof um there's no need to rely on trusted third-party node operators like inferior now this isn't exactly like practically true today it's true in theory but nobody has built a wallet that does this yet you can imagine that it's a bit more complicated than building a normal wallet because you're kind of building something that's somewhere between a node and a wallet but chainsafe is working on this right now I think they have a demo if you go to their GitHub for it um uh so yeah um theoretically possible people are working on making it
practically possible um and you know theoretically impossible for for all other blockchains as far as I know uh another thing that we can do differently is bridging uh so smart contracts on other chains they can Bridge the entire mean estate uh just by verifying the most recent proof and so we can uh do something like writing ethereum contract where a user can call it and pass in as arguments uh are proof and um the the state route for the amino blockchain and the smart contract can just verify the proof and then know that the state route is correct and so um you know you could add some other logic that says like as long as the this uh proof and State Route are for a block height that's higher than the last one that the contract is is remembering you know update
um and so in theory anybody can do this then right we have the whole mean estate the whole mean estate route tested to in this root node um and then you know a proof and we can verify this proof on ethereum and Bridge the whole mean estate over uh and and again uh this is something that's not possible in practice today but uh well I guess it is sort of possible in practice just not on mainnet um so the nil Foundation is working on this from a joint Grant from the ethereum and Mina foundation and this is a smart contract for uh the evm uh um architecture uh that will let you uh yeah Bridge the Homing estate over to another chain and so they have an example I think we have a link to it also at the end of the presentation um and you can experiment with uh this I
it works today for bridging to I forget which test net but um one of the test Nets um what are the ethereum test Nets finally oracles work a little bit differently so users will be able to create zika Oracle proofs that bring data from any website onto the amino blockchain and I don't know a lot about how this works specifically it's kind of complicated and has like a sizable MPC component but we have a couple of people owe on Labs who are working on this um you know sort of practically what it will allow allow you to do is go to a website prove that you went to this website on um you know at a certain time and that it responded with some data um and so you then you have this non-interactive proof that you can pass as an argument
into you know a smart contract or even just give to somebody and so you can do something like go to let's say your um bank account website look at all of your personal information prove that you went to your bank account website uh that you're you know uh bank account website is kind of like the real one I guess like um that the person who sent it to you really has the certificates for that institution um and then you can also prove uh you know some things about context and so then we have this proof that says we went to our bank account website and we can actually pass it in as an argument to another proof that can do something like check um
I don't know is my uh is my credit score above some certain threshold or something like that and so we can obfuscate this data and then we can just have a proof that says hey I'm unique person and I have a uh a credit score above X therefore maybe I can get a loan um or something like that or you know I'm over the age of 21 anything like this um if you're curious about this um yeah also come to office hours uh I yeah I won't dive in too much about how it works because I'm not sure that I'll say things that are exactly correct but uh very interesting feature also not live today but we're working on it and and hope to have it live soon um and it should be you know really disruptive uh so what else is possible uh well we
actually don't know everything that's possible yet and and this is uh why we do things like CK hack and hackathons and other stuff is so that um people you know we can get a lot of Minds together and and kind of uh explore all the different avenues that this has opened um probably like once a month we find something that's really cool and really powerful that we didn't know was possible the month prior um and Yeah by getting more people involved we hope that you guys are able to also find you know really novel solutions to problems uh and and then you know work towards implementing them together uh okay so here's kind of a rehash again and now we'll get on to the Wordle example so I'll switch my screen share real quick
to this um and so this we have a link to this repository on um I think in the chat right now uh this is oops sorry what did I do uh this is a Wordle game I don't know probably most people have played Wordle if you haven't it's a game um that uh basically there's a five letter word you guess what it would be and you get uh based on your guess um some of the letters in your guests get either filled in um green or yellow and if they're green it means that you have the correct letter in the correct place and if it's yellow then it means you have the correct letter but not in the correct
place um and so uh this is something that would be hard to build on another blockchain because you how would you store the word basically and then you know even if you like encrypt the word how do we check that um you know the person who generates the hints for the word um you know the person who determines uh or the service in most cases whether these tiles should be you know colored green or yellow or black um how do we know that they're you know doing uh doing their job correctly um and you know so the answer is is you know zero knowledge proofs um for Mina and so uh usually I kind of have the code broken up into different slides but
I actually thought it was more confusing for this example uh so kind of walk through this um together first this you know just normal Wordle example um and then the recursion uh uh example later uh so this whole project was scaffolding using the ZK app CLI which is just an npm package that you can install we'll have like a slide for it at the end of the presentation um and uh it's our only piece of developer tooling it's very powerful and it's very simple um it's super easy to use and intuitive uh basically uh we called ZK project um Wordle and it created and scaffolded this this whole project with things like linting all the stuff necessary for our
deployment to uh the networks um uh a GitHub repository so we can publish this uh you know npm stuff um testing setup every everything just works prettier uh sort of the whole the whole thing just works and it also adds usually a an ad contract and I've deleted this in this case but the ad contract is a very simple example smart contract that you can play around with if you uh yeah want to dive in it's as simple as just npm install it's the cap CLI ZK slash I'm sorry zkc Space Project space hello and then open up the hello repository and you can deploy straight to Berkeley or play around with the code whatever you want um but for now we'll dive into this wordal example so uh first things first we import uh you
know all of our stuff from stocky.js that's pretty pretty normal and then I'm actually going to scroll down past this and jump to this smart contract part and we'll kind of explain like what the anatomy of the smart contract looks like so what we do is we just extend smart contract into a new class Wordle um and then generally we we Define our state up here and so this is uh this state decorator basically tells snarky Jazz hey these are variables that should be stored on chain and we should be able to update them but when we do update them we should prove that we're updating them in a legal way basically um and so you can see that they all have different types um one is a field you know this is kind of like our primitive type um and then we have this unsigned
integer of 32 bytes I'm sorry 32 bits uh which is is you know something that's provided and then we have this word type which we'll scroll up to in a second I mean this is something we've defined ourselves using struct um so uh the next thing that we have generally is this init method and this is a method that usually runs um after the smart contract is deployed but before the uh before users interact with the smart contract and so in this case we use this to set uh you know to initialize our our state variables to appropriate values um there's also a deploy method that you can't see here it just um uh it's kind of behind the scenes until you need it to be in front of the scenes
um but this is uh something that you can use to define like what happens when the method I'm sorry when the smart contract actually gets deployed to the network but in most cases people won't have to to um to fiddle with that too much uh so yeah I have our knit method where we're just initializing our state um and then we have these user-defined methods uh which um uh we have this uh I'm sorry these user accessible methods so we have this method decorator in front of them I mean this basically tells Nike Jazz hey a user should be able to to call this method you know in a transaction and when they do prove that they did it correctly uh generate this list of of you know updates to the on-chain state and and you know do all these other kind of like housekeeping
tasks um and so we have two of these we have one for published guests which is uh going to allow the person who's playing the game to guess a word um and so you can see we pass into this Our Guest which is of the word type um and then we also have publish hint and so this will be called by um either the person who's generating the hints or in most cases this will be just like a service um you could have uh you know just like a a Docker container running somewhere that does this and so publish hint again we have the method decorator and we pass in another word but this time it's our solution and so the solution is is you know the the um the the word that the user is trying to
guess and um we pass it in but it doesn't ever get revealed to the network or anybody this you know stays on the the person who calls this methods machine and so we can check that the hint is valid for the solution that we um uh uh the hint that we generate is valid for the for our solution without having to reveal what the solution is to the rest of the world um and then that's it so so this is kind of how how smart contracts are generally structured with State up top uh an init method and then and then the methods that users will be able to call um now we'll kind of jump up here again into our state and we'll talk about what
each of these things do and then we'll jump into word and so solution hash um is what it sounds like it's a hash of our solution and we use this to store a commitment to the solution so that the hint generator can't change the solution mid game um this way we have you know one solution for the whole game and uh we can check that uh we're generating hints for the correct solution um without revealing the solution we we uh just hash whatever we pass in to solution down here and and check that it equals this solution hash that we have stored on chain uh we also have a turn number which is again what it sounds like um this is the number of turns we use this to determine whose turn it is so that the hint generator can't like
generate a hint on the guesser's term for example um and then we have uh last guess which is is the state that we use to remember the last guess that we made and then also this gets mutated um in order to communicate the hint that the hint generator has added um for a given guess um and so you can see that this is of this word type and if we scroll up here we can see um that uh this word type is is you know created by extending struct um and it has this encoded word key uh with an array of five field elements as the value
um and so you know word is in this case pretty simple it's just basically a an array of length five field elements but this could be much more complicated we can create significantly more complicated um uh types using this this struct um the other thing that we've added is this static method from string and what this will do is we can pass in a word which is you know a an actual string like a JavaScript string and we'll we'll first we'll you know convert this into lowercase um then we will iterate through each of the the um the letters in the word and we'll check if they are uh you know this regular expression just means check if
uh we're a letter between a and z and not like a um some sort of special character like an at sign or a dollar sign or something like that um and so we test this and if uh it's true for for this index um then we take this encoded word array and we push onto it um a field with the value of the character code of the word minus 96 and so we do this uh you know this is uh calling character code on word is going to basically give us back like the ASCII value for this character um and then we subtract 96 in order to uh you know make a equal to one basically and so we push this onto this array
um if this is true and then if it's false um you know if the character is not lowercase then we just push uh one um which is in a character uh and you know this is kind of a weird default Behavior but you could make something more complicated to catch these errors better um in this case I've just used one or a as basically like the default value um so what we do then is we you know call word and then we return um word but with this encoded word passed in and so what this means is that if we you know um want to create a word from a string we can just call this from string method on it and what we'll get back is a a word that uh contains this encoded string so we'll get back you know a word
um which is is basically these you know these five uh um field elements in an array um that that is associated with the word that we passed in as a string we also have a a method um uh which is hash and and so this we can call this and what it'll do is it'll return um the hash of the encoded word and so this you know Poseidon is our hash function here and we just call this hash method on it we pass in our encoded word which is you know an array of fields and when we get back a single field element which is our um let me see yeah we get back a single field element which is the hash of our encoded word um and so uh yeah we've now defined kind of another data type that we can work
with um and we'll we'll have last guess equal this and so um now when we jump down to init uh the first thing we do is we set our solution hash um and we do this just by calling you know this solution hash and then set um and uh passing in what we want to set it to and so in this case we you know word uh from string and we pass in hello so now we have a a word uh you know basically an array of five field elements that is associated with hello um and then we we call the hash method on that and we get a hashback and so then we you know set this to our solution hash and so in this case the the solution for this game is hard coded just for the sake of Simplicity but you could just as easily have this be uh
something that's you know configurable using a method that checks that you're like an approved user to change the the solution or something um the next thing that we do is we set the turn number to zero and so in this case we have this unsigned integer and we initialize it with a value of Zero by passing in you know a field also with a value of zero um and we use unsigned integer for a reason that I'll get to in a second as opposed to field um because we need one of the unique properties of unsigned integers that Fields don't really provide and finally we'll set the initial guess um to AAA ah so um it doesn't matter what this is because it won't be possible to generate a hint until the guesser updates this
um so yeah we just set it to five A's by calling you know word from string and then passing that into the set method for last guess um so now this runs and our smart contract is is you know live um and there's two methods that users can call the first is publish guests and we'll pass in our guest which is another word um and so there's a few things we have to do the first is that we'll grab the turn number from the media Network and you know we do this this is simple we just uh um you know Define a turn number here and we set it equal to you know calling the get method on on the turn number uh State up here and um what this does is it basically grabs
this value from the Mena Network you know it grabs what's the most recent turn number value and it dumps it into this variable now we need another line below this and this is something that we're maybe thinking about making a little bit more magical because it seems to confuse some people um but this line below it what it does is it basically confirms that the proof was generated and the transaction was generated um for the same turn number value that's currently live on the Mena blockchain when the actual transaction gets validated and so this basically grabs our value for runtime and then when it comes time to actually you know uh submit the transaction this basically checks that this value is still true and
so this is important because what if somebody grabbed a turn number you know created a zero knowledge proof and a transaction and then waited five hours and sent it later and by that time the turn number had changed um well we need this you know uh assert equals in order to to basically communicate that we want uh the um the we want the transaction to only be valid if the turn number that we ran it with is the turn number that's still on chain um the next thing that we can do is we can check that it's the guesser's turn and we do this just by calling this mod method which is something that doesn't exist on the field type and so this is why we have to use the the uint type on turn number and then we assert that it's equal to zero in this case so you know
uh half the time it will be zero um half the time it won't be zero um but this way we know that it's it's our turn if it's zero and then the next thing that we do is we increment the term number um and we do this just by instead of calling get this time we call set on the turn number uh variable um or I guess like on chain State and we just pass in our current turn number plus um an unsigned integer uh with value one uh the final thing that we do is we check that all the values are between 1 and 26 that means that they're you know valid letter configurations um so we just iterate through uh each index of of our encoded word on our on our guess um word and we assert that it's greater than equal to one and less than and
equal to 26. and finally we set the the last guess to our new guess and so now last guess gets set to the new guest that we passed in um so this is really basically just incrementing the turn and checking that our input is valid um and now once that's done we now have a new guests in this state variable and uh it's time for the you know we we can't call publish hint any or I'm sorry we can't call publish guests anymore because um this assertation will fail um you know we've incremented the turn number but what we can call is publish Hampton so this is what the the hint generator will will um will call and again this could be a service probably in most cases so uh uh we passed in a word again but this
time it's our solution instead of the guess um and we grab our turn number this is the same thing we've seen and we check that it's our turn and we do this just by adding one and then exactly the same thing mod 2 and then assert that it's equal to zero um so this will be true when this is false and this will be false when this is true um so this is how we know it's our turn uh and if this assertation fails not only will the code exit but you won't be able to generate a zero knowledge proof anymore so even if you found a way to like make the code run no matter what level of the stack you you uh fiddle with like even if you change the hardware of the computer to make this uh sort of just run through
um the proof that you would get out would still not be valid okay so then we increment our turn number same thing and now we grab the solution hash from the Mina Network and we check that the solution that we pass in matches the one on chain and so we do this just by you know checking we'd call Hash on our solution that we passed in um you know our solution word has this hash method and then we assert that it's equal to the solution hash that we just got from the on-chain state uh we also grabbed last guess just one note you have 10 minutes left that is okay awesome thank you so much okay so um
uh okay now what do we have to do well we have to check which letters should be green so we iterate through every single uh index you know for for both the solution and the the guess um the last guess and we check uh if the last guess is equal to the solution for this index and if it is then we set is correct position to True um which is of the Bull type in this case which is again uh you know sort of constructed out of these field types and then if this is the case then we add 200 to the letter in last guess and so we use this circuit.if we pass in you know is correct position and we select basically whether um last guess uh you know the um index in in that array should be uh
updated to you know uh either nothing or we should add 200 to it and so the point of adding 200 is that we retain the same number like if we have seven um then we have 207 so we can still tell what letter was guessed here but now I have this 2 in front of it which basically says Hey seven was a was a you know a correct letter in the correct place um and uh and and so yeah this ends with last guess uh being updated to have these hints for uh when the letter is correct and in the correct place um the next thing we do is we have to check for these yellow letter hints which are if the value is correct but it's not in the correct place and so how we do this is we iterate through every possible combination of indexes and we
check if the letters at these indexes match um so now instead of you know last guess and solution both being indexed at I one is index I and one is index of J and um if the letters match then we add 100 to the letter in last guess and so we're mutating this you know last guess word um if this is true we add 100 again we know 100 means this is the correct letter but in the wrong place 200 means this is the correct letter in the correct place and we maintain the letter in these last two places and then the final thing that we have to do is that we don't count these letters multiple times is we basically cross them out in the solution array and we do this just by setting them equal to zero if this is true that way we don't count them twice
you can imagine like every time we iterated through we would uh get another letter so for example um if we had one e that we had guessed correctly but the word had two e's or let's say no let's say we had guests two e's but the word had one e um without this uh block here um the the we would get hints for both E's even though we really only want hints for one and so the final thing that we do is we set this last guess um to our new last guess uh uh um which includes the hints and uh and then now the the guesser can can uh you know uh guess again and so there's some things that you know are missing here
like in terms of if you wanted this to be a cool usable smart contract and we've done this just for the sake of Simplicity for this explanation but we could do something like have um you know if the user guesses the correct word in like X moves then we pay some amount of meaning to them or something like that um yeah we could have it more configurable in the sense that uh some permissioned user could change the word um but you know this is a very simple wordal example um and we have a test for it um that I think I was planning on um explaining in more detail but I think we'll kind of Gloucester it really quickly because it looks like we only have 10 minutes left um we can jump into this test though still um we'll run it down here and uh
um so yeah snarky Jess I'm sorry the zika app CLI scaffolds all of this for you so you don't have to worry about it too much but it's pretty clear what it does I won't explain it for the sake of time here but we have our first test which you know generates and deploys our smart contract um and then we get into kind of the more interesting one uh down here we test things kind of incrementally eventually you get down here to um uh this one where we're gonna basically do like an example flow um and so all that we do is we you know this is something in this case is on the test but you could just as easily do this in your front end um we take some sort of string in we create a word from it and store it uh
you know in Exile here and then we just call on the ZK app this published guest method just like you would expect in past Exile in then we can prove that we did this correctly and then finally send this transaction off um we can you know then grab these values to see how they've updated and in this case we check that they you know have updated to what we expect and then also console log it um or that might be sorry I'm one test too high um uh down here yeah we console log these values and so if we scroll up um we can see what this looks like all of our tests pass um but in this case we have the word hello as our you know correct word and if we guess Exile um you can we can see it's turn number one and this is what our guest looks
like and so a b c d e you know e is the fifth letter in the alphabet um here's our encoded uh word um and now uh when we you know when the the hints generator runs this uh we get Exile uh you know on turn number two um and now they add one for the e um 100 for the E because it's there is an e in hello but it's in the wrong place but you can see that X style also ends with an e but we don't add a 100 to this one because we've already you know sort of occupied our correct e we can also see that L over here Exile and Hello both have L as the second to last letter this you know 12 means L but now we have 200 added to it and so now we can use this you know your your front
end could use this information to color the the tiles correctly um and uh and then we go back and forth a few times until eventually we guess hello and we get to the correct values so um I guess uh now we can talk really quickly about recursion there is more information on this and maybe if you're curious uh yeah come to office hours and we can talk more about this um but uh recursion allows us to do is it allows us to change this smart contract from a smart contract into a ZK program which is just exactly what it sounds like it's a program that we can prove but this program can take as an input um it's a proof of itself and what this
means is that uh now instead of playing this game you know on the blockchain like we normally would where we create a transaction pay the gas I'm sorry pay the transaction fee send it wait for it to get mined and then the next pair can make a move uh we have this system where we can just send this data peer-to-peer and by passing the last proof as an input into the next proof we get a final proof that represents that the whole game was played correctly and then we can pass this as an argument into a smart contract to finally settle the game um so this code is available like I said there's a link to it um we'll not dive into it too much here but basically very much the same thing we copied and pasted almost all of the code from uh the normal example to make
it recursive um and we can see what this looks like to run to uh uh and we'll let this run for a second while I talk about some of the stuff at the end and come back so you can see we're compiling the contract um and you should kind of be able to get a sense for uh how things work differently so now I'll switch very quickly to our wordal example uh sorry to our slides again uh and there's two things I'll highlight here also one is that we could have just as easily built this with a UI if you're curious tutorial 4 in the docs explains how to build this with the UI I didn't for the sake of
sort of clarity um uh just that there's kind of only one thing and we don't have to like you know wait for transactions to mine on testnet and stuff um but uh yeah we built a smart contract tutorial for teaches us how to you know like integrate it uh with a UI um and now uh we can kind of talk about um you know I guess how do we get started so uh yeah so just npm install the ZK app CLI um and calls EK project name you know make it hello or something and you'll get a scaffold project just like this with an example ad contract um how can you get involved you can me uh you know visit me as developer docs
there's link to that in the chat um you can apply for a retroactive Grant um you can build a ZK app this is definitely something that like everybody should do because it's pretty easy um you can get something deployed to test fat in like an hour um and then finally you can join our ZK ignite cohort zero which is a um a program that has uh 250 000 I'm sorry 250 000 Mina tokens associated with it um and basically we give prizes to people who who make like good faith zero uh good faith CK apps and and uh extra prizes for people who build like particular cool things uh you can learn more about it from the link down here um in the chat
um and we also have a QR code uh so yeah I think that's roughly all um uh there was a couple things that I didn't get a chance to do but I'll just kind of explain are possible um I was going to deploy our our um Wordle contract to uh the Berkeley test uh Berkeley testnet which is our uh basically it's the test net of what Mina will look like after zika app functionality is enabled on it um and then we're going to interact with it there so you can uh do that if you're curious it's pretty simple um and also outlined in I think tutorial three um and then yeah building a UI um uh in tutorial four uh so I think that's roughly it sorry I kind of got a
little bit like discombobulated at the end here but the general idea is Mina is really cool it's really different you can build a lot of really cool things with it snarky.js is super powerful and it's also very easy to use um and you should explore all of these things because hopefully you know uh we're kind of opening the door to uh uh like uh a lot of really cool things that weren't possible before with blockchains um or even with traditional applications uh yeah I think that's about all thank you so much guys oh I I see that my microphone was uh off
let's jump to q a because there is plenty of questions over there and uh we'll have to also read them up loud for the video for our future uh audience to to see cool uh we have what would happen if you throw an error here if you comment reply to your comment Andrew with where here was I will answer that but I don't know where here was anymore unfortunately um do you have a developer grant program what should we do to apply uh o1 Labs
does not but Mina Foundation um has uh lots of information about their Grant programs on their website um so that's a a good a good place to kind of explore um yeah what's available to you there and then for Derek we have looks like most statements ultimately are a call to a Smart contract method or a field method like a DSL is that right you can use any JavaScript statements in particular can you import and use external Javascript libraries so this is a good question the answer is is basically yes um uh uh I would say that the experience of using Starkey Jess ends up feeling a lot like using react or something like that where it's not like too magical it
it kind of is still JavaScript but you're using it in sort of a unique way um but still very intuitive uh so you can't just make an arbitrary JavaScript statement and the reason why is uh because snarky.js won't know how to prove it uh and kind of like there's a couple different reasons for this but the simplest one is if you have something like a string JavaScript won't know how to represent this as a field uh element and all of our information has to be represented as field elements in order for uh like sort of the under the hood stuff of the zero knowledge proof uh system to work so um yeah what that means is that you can't
just import a random JavaScript library and use it but you can make snarky Jazz specific libraries and then import them and use them and you'll get uh you know completely constrained code um you can also I mean you can just use normal JavaScript um anywhere that you want to but it won't be proven unless you use sort of a fancy trick so like as people get more advanced with this there are some times where you actually will like where you might want to if you have like a certain kind of routine that there's an efficient way to do in JavaScript uh and you have some sort of like way that you can check that it happened correctly without having to do
it um then then you can sort of Escape out of snarky gs do your thing and then jump back into snarky Jess and verify that you did it correctly um but this uh is like a pretty Advanced pattern you kind of have to like have a strong intuition for what's going on in order to be able to do this right now um oh for a net what would happen if you throw an error here uh uh I actually don't know exactly what would happen I think um I think it depends on the context maybe Gregor who's in the chat has like a good good idea I think I think I mean I think that if this happens on um uh uh I think that if you write a smart
contract deploy it to Berkeley test net and then you run the init method and and something goes wrong um well first of all I think that the the zika app CLI should catch this before you get that far but if you do manage to get that far then I think that um what will happen is that your transaction will just get dropped uh and then you'll have to redeploy your contracts maybe I mean I think you would want to read a player contract in that case and I think that's all the questions [Music]