Kautuk Kundan, Danilo Kim and Remi Gai I Practical Zero Knowledge Proofs | Pragma India 2023
ETHGlobal·Wed, Oct 9, 2024, 12:00 AM
Speaker
n this deep-dive panel from Pragma India 2023, ETHGlobal’s Kartik Talwar sits down with leading Web3 founders—Kautuk Kundan (Stackr), Danilo Kim (Kakarot ZK-EVM), and Remi Gai (Inco Network)—for an unfiltered discussion on building practical applications with zero-knowledge proofs, fully homomorphic encryption (FHE), and next-gen micro rollups. This conversation demystifies how cryptographic tools like ZK-SNARKs, ZK-STARKs, Cairo, FHE, and micro rollups are powering the future of privacy, scalability, and composability in Web3. You’ll learn why performance, accessibility, and UX matter just as much as security, how new architectures like Kakarot and Stackr are changing the developer landscape, and what trade-offs exist when balancing decentralization with real-world usability. 00:00 Panel intro: ZK, FHE, and rollup builders 00:44 What is Inco Network? Confidential EVM with FHE 01:18 What is Stackr? Micro rollup framework explained 01:52 What is Kakarot? EVM written in Cairo 02:31 What is fully homomorphic encryption (FHE)? 03:36 Real-world FHE use cases: games, DeFi, coordination 05:10 ZK vs FHE: key differences in computation 06:43 What are micro rollups and why they matter 07:41 Example: token transfer via micro rollup 08:40 Building rollups in any general-purpose language 09:11 Why Kakarot chose Cairo: speed, safety, and trade-offs 10:25 Cairo advantages over raw circuits 12:20 Why build an EVM in Cairo? Compatibility benefits 13:28 Kakarot compatibility and remaining limitations 14:41 Why Inco chose EVM for encrypted smart contracts 15:17 Stackr’s broader vision: web2-like UX in web3 16:54 Real-world dapps without Solidity: rideshare, ticketing 18:45 Stackr’s trust model and verification layers 21:05 Do we need powerful provers? Hardware and costs 22:11 FHE scaling with FPGA and validator roadmap 23:40 ZK parallel proving, mobile-friendly validation 24:42 The future of cryptography and consumer devices 25:42 Advice for hackers building ZK apps at ETHIndia 26:46 How to approach ZK hackathon projects 28:23 Use libraries, avoid reinventing the wheel 28:50 Hackathons = the birthplace of innovation 29:18 Try FHE with Inco Network during ETHIndia 29:46 Final thoughts and closing thanks _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 🇮🇳 *Pragma India* The final Pragma of the year took place in Bengaluru India in December 2023 with a curated series of high-quality talks that sparked thought and discussion. Pragma India 2023 was an opportunity discuss the future of web3 and reflect on the past. Watch the full Pragma India 2023 playlist here: https://youtube.com/playlist?list=PLXzKMXK2aHh4rHV1H4J7y0wDok4bIS17t&si=lb8ttkU1HS2tpnUP ETHGlobal's Pragma series takes place in cities around the world, and is designed to be a different kind of event. Pragma is a one-stage conference with founders-only on stage, bringing together a small group of curated attendees and speakers to discuss the future of web3 and reflect on the past. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ✅ *Follow ETHGlobal* X: https://x.com/ETHGlobal Warpcast: https://warpcast.com/ethglobal Website: https://ethglobal.com YouTube: https://www.youtube.com/c/ETHGlobal _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _Are you interested in Ethereum development and entrepreneurship?_ 👉 Sign up for the next ETHGlobal event: https://ethglobal.com/events 🎁 Get exclusive access and perks with ETHGlobal Plus! https://ethglobal.com/plus 📣 Want us to throw an event in your city? Tell us where! https://ethglobal.com/city _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Transcript
OK. So, let me start by saying that “practical zero- disclosure proof” is a bit of a misnomer, because not everything here is based on ZK. So the first question I'll ask Remy. Tell us in a few sentences what the Inco network is and what is behind its work. Hello everyone.
I am Remy. I am the founder of the Inco network. Inco Network is an EVM with on-chain Inco Network is an EVM with on-chain privacy that uses a new cryptography called fully homomorphic encryption. Maybe we'll come back to this a little later. Cook, for you: what is Stacker and how is it different from other ZK rollups?
Hello everyone, my name is Cook. I am creating Stacker. This is a framework for microrollups. With microrollups, we are going back to the basics, rethinking what rollups are and should be . This allows people to build rollups in general- purpose languages, separating execution from verification.
Perfectly. I like concise answers, it gives you more time to delve into the details and finally tell me what you're working on. I'm currently working on Kakarot. Kakarot is essentially an EVM written in Cairo, and because it's written in Cairo...Cairo written in Cairo...
Cairo is a proof-supporting language . Anything executed in Cairo can generate evidence that turns Kakarot into ZKVM. The Kakarot team does not do low-level cryptography, so Kakarot is a second-level solution, an EVM on Cairo, that will run on the Ethereum network. Now, maybe for the audience that doesn't know what Cairo is, can you explain the context a little bit? Yes, Cairo is a language developed by the StarkWare team that generates execution traces to create Stark evidence; It is a subject- subject- oriented language that allows you to create Stark proofs.
Perfectly. So, you have ZK-SNARKs, and with Cairo you get ZK-STARKs. Yes. Returning to Remy. What is FHE and give us a better understanding of what homomorphic encryption means.
Yes. FHE is a different type of cryptography than ZK. FHE is based on lattices. To understand FHE, let me give you an example: imagine you have an image. You encrypt this image and send it to me.
I have your encrypted image, but I can still make changes to it. So, let's say I can add certain values to the RGB values to the RGB values or, let's say, subtract or multiply. I can essentially change pixels on top of your encrypted data. And by the time I send it back to you and you decode it, you'll have an automatic filter, a new filter applied to your original image. So, FHE image.
So, FHE is cryptography that allows not only to encrypt data, but also to perform all kinds of operations, mathematical operations mathematical operations , and transformations on top of encrypted data. So we add FHE to EVM . The idea is that today all EVMs are completely transparent and public. So for us, online privacy means that you can store things directly in encrypted form right on the network. For example, if you want to build a poker game, you can store encrypted hidden cards directly on the network, and if you want to build DeFi applications or DeFi applications or any applications that require state changes on top of encrypted data, this is where we can use FHE to transform the state.
This effectively means that we can provide the ability to compose on top of encrypted data directly on the network. Imagine everyone here sending a hidden bitcoin price. We can still calculate the average price of Bitcoin in a covert way using FHE without decrypting the data throughout the process. And in general, I think gaming would also be quite interesting quite interesting , because today, when we create games on EVM networks, everything is public. All game states, player statistics.
But for us, it fundamentally allows us to create new types of games related to bluffing. You can sabotage, spy on people, consume resources. The idea is to bring this Web2-like experience to Web3. If you think about it, today, when people come to Web3, they often realize that they can only build those cases that make sense in a transparent database. But Web2 works completely differently.
What, how do you want to create a poker game? What if you want to hide certain information? That's why I think we want to offer a new experience and allow people to build apps that are a little more flexible about what to hide and what to leave public, and that's based entirely on cryptography. You know, there were other types of solutions that used secure enclaves or zk solutions outside the network. What sets us apart is that it's all completely FHE and completely online, making it very easy to build any applications that require coordination.
Yes. no, that's great. Um, maybe I'll ask one more clarifying question. Could you give us some insight into how exactly the execution of operations on encrypted data differs in FHE compared to what we call ZK- call ZK- based? Does this mean it needs to be decrypted?
Does this mean it is never public is never public , or does it need to be made public? How best to think about this? Yes, that's a really good question. So, everything you do with ZK do with ZK usually happens offline. From the data you are trying to hide to the closer and the diagrams.
ZK the closer and the diagrams. ZK is essentially proof of computation. Therefore, most state transformations must occur off- line over plaintext. The difference with FHE is that it can happen directly on the network over encrypted data. This is where, you know, if you want to implement any coordination use case that requires composability with ZK, it gets a lot more complicated because you need off- chain coordination, and also off- chain computation on the plaintext to generate a new ZK proof.
FHE, on the other hand, allows hand, allows anyone to simply send a hidden transaction directly to the network. The private sharing layer works directly on the network, so you don't need any coordinator outside the network, and, yes, it's all based on cryptography. Great, I also don't want this to turn into a turn-by-turn survey. Obviously, you are all in the same ecosystem. Feel free to add, disagree, or agree— agree— do whatever you want.
Um, my next question is for you, Kek. What is a micro- Kek. What is a micro- rollup here and why use a micro-rollup instead of just switching to some existing ZK- existing ZK- rollup? Yes. I think in the current space we have a certain mental model of what a rollup is and how applications are developed on top of a rollup.
But at some point we forget why we need a rollup—after all, a rollup is used to have a computation model off- network that performs certain actions that are verified on- network. We build roll-ups that look like chains; we deploy applications in these chains and they are limited to the chain's virtual machine. So the way we see rollups is that you build a machine of states, and that's what Stacker allows you to do. You build your own state machine and build it according to your logic, any business logic, and business logic, and any calculations you want to perform. Give us a more specific example of what that would look like.
OK. So now, if you want to make a token transfer, right? You write a smart write a smart contract, for example, an ERC20 smart contract, running on an EVM blockchain or something else. But what about implementing the token transfer logic directly into the state machine itself? Then the state machine does nothing but transfer tokens, and does it very efficiently.
You take this machine of states, you make it proof-of-concept, and that's how you achieve extraordinary levels of compression and cost- effectiveness, and of course, throughput also becomes a consequence of that. So, if I understand correctly, this means that I don't have to write code in Solidity? Yes. You can create such rollups in any general- purpose programming language. Rust, JavaScript, Go—you can use use anything.
You simply define your state, define how it changes, and the SDK takes care of it , collapsing everything into blocks, which are then passed to another layer. So, we have an intermediate level of verification that acts as a kind of marketplace for closers. It works between all applications and L1, proving computations using different methods, and you can specify exactly how you want to compute these proofs, which then go into the chain. Surprisingly. And I will say this in the mildest possible way.
Why did you do this on Cairo? It's a huge job huge job to create a DSL that is compatible with EVM. Tell us what the difficulties were. I don't mean anything negative, but it's very difficult. So why did you decide to spend the time to create an EVM-compatible DSL?
So, I think, first of all, it started as an interesting challenge. It didn't start with the idea of " start with the idea of " let's build a company," no. It was, "oh, this looks fun "oh, this looks fun , we have a weekly hackerhouse and hackathon, why not try it, right?" And we ended up where we are now. And in the process, we realized that, first of all realized that, first of all , Cairo is a difficult language to start with, but once you get the hang of it, there's you get the hang of it, there's not much you can do there.
It is very limited, similar to how Solidity is compared to JavaScript. That is, once you master it, you know the whole map. It may be difficult at first, but once you get started, you can make significant progress pretty quickly. Second point: if you want to build ZKVM today, then commands like ZK sync, Scroll, Polygon zkEVM—they all build circuits directly. This is much more complicated than writing in Cairo itself, so there is some compromise here, right?
Kakarot is almost like a virtual machine on top of another virtual machine. This is an EVM on top of the Cairo virtual machine. Of course, there are some resource costs and some inefficiencies compared to directly writing schemas, but there are also many advantages, for example, it is much easier to audit. The Kakarot ZKVM codebase is 10,000 lines of code. You will find significantly more Cairo auditors than pure scheme auditors.
The second point is that we can move faster. For example, when the push zero opcode was released , our codebase changed by only five lines—it's like writing in a lower- level language instead of dealing with polynomials and other math. So we really believe that DSL has a great future, especially for applications that can be proven in parallel and for rapid iteration of proof backends. There 's also another point that the Cairo team talked about: at first they were making schemes for dexes, NFT schemes for dexes, NFT marketplaces, but then they realized that every time we create an application create an application , we have to make all these schemes and all these polynomials, and it's really hard. That's why they developed Cairo: it's better to have a little less efficiency than to waste a lot of time trying to achieve it.
Eventually, they realized that even with this overhead, the Cairo version proved to be more efficient than pure schemes. And that's because when you have a language that's more understandable to people, you can design algorithms that are more efficient than when working purely with diagrams. For example, if you write a program in bits, you can be much smarter and more efficient if you write in Python, for example, compared to the same bits. So there are some advantages to DSL, and we believe that in the long run, because we can move quickly, implement and iterate solutions faster—that's where our advantage lies. Wonderful our advantage lies.
Wonderful . So, I have an additional question: if Cairo is already an abstraction that eliminates the need to write a lot of schemes and polynomial mathematics. So what was the reason you wanted EVM there? Do you want people to just deploy the same contracts there same contracts there , or is there another answer, or does this open up more possibilities? I think for us, the ability to choose the ability to choose is what allowed me to be here in the Ethereum ecosystem.
We truly believe in the power of Starks, but we also truly believe in what is already being built in the Ethereum ecosystem, in all the technologies currently being developed. We saw a market that hadn't been explored and thought: why not, right? This is great, I wanted to ask if there are any limitations of ZKVM on top of Cairo, or is it 100% Cairo, or is it 100% compatible and we can do whatever we want? Now we have all the opcodes, and eight out of nine precompilations, only one thing is missing — the only one thing is missing — the AC pairing. It's a little more complicated because of the Cairo field, the size of the Cairo field, but I think it's a matter of time.
And I would say the single pain point or the biggest challenge biggest challenge is how to make it efficient, not just 10, 20 TPS, but how to get to hundreds and thousands of TPS, which is the goal of our rollup. I think the Starware team is doing a great job; There are a lot of developments in the field of ZK every year, so it's only a matter of time. Amazingly, Remy, you also chose ZK or, excuse me, EVM for FHE. Tell us why EVM is important in the context of encryption. Yes, technically we could build this VM with other languages like VM with other languages like Solana or even Move.
EVM for us is the most accepted technology; Solidity is the most widely used smart contract language, and the entire Ethereum ecosystem of tools, such as Metamask, Hardhat, Remix, are the most popular most popular . So it was an obvious choice for us to start with this. The idea is also that when people come to a new ecosystem, it's always quite difficult: learning new tools, setting up new wallets, dealing with new debuggers and other similar things. So, you know, being able to reuse existing tools that are already pretty well- accepted—for us, that's a pretty practical approach to this issue. Yes.
Perfectly. You interestingly chose not to necessarily have an opinion on EVM compatibility, because you want to give much more options. So maybe my question is different: tell us about more real-world use cases that you think won't be possible if people have to bother learning Solidity. Yeah, sure, I think I have an opinion on ZKVM, but yeah, because let's get to it. Let's get to it.
We have time. Good. So, what do I feel—what is our mission as a Web3 developer community? Is our mission to create the best technology, or is our mission or is our mission to ensure Web3 is as widely adopted as possible? Of course, there is nothing right or wrong here.
We can definitely create the best technology. We can have amazing cryptography. We can have great systems that are really good, maintain privacy, and solve almost all the problems with centralization. But at the same time, at what cost? If you build systems like ZKVM, or we have a system like Solana, which is very computationally intensive and very difficult to manage, does it really reach the masses?
This is where I disagree somewhat, in the sense that ZKVM is obviously a great solution, but again , the problem is precisely in the aspect of mass adoption. So ZK-based systems are very expensive, and very expensive, and ultimately the costs fall on the shoulders of users. So is it worth it? Here is my opinion on this. No, that's quite fair.
So, in this case, maybe show us what a hypothetical use case on Stacker would look like and who would be responsible for what in that example, right? Again, delving a little deeper into thought processes. So, there's crypto, and there's Web3, right? And most of the time they overlap, but crypto is more of an applied aspect, and Web3 is more of a way of thinking about decentralization, ownership, and giving people control over data. So, at Stacker, we focused on the Web3 part— porting existing applications that are centralized and have certain limitations by opening up part of their data or part of their execution.
One example I keep coming back to is a ridesharing platform. Now it is centralized, and everyone is at the mercy of companies in setting prices; Drivers get paid little and passengers can't find drivers. So why don't we decentralize this part, where the process of requesting a ride and having it accepted by the driver would become a matching mechanism. This is something that can be ported to blockchain, and of course we still need to get there to make it more accessible to others, but it's a great use case use case . There are many web applications that can be ported to the Web3 space.
Another example would be a ticketing tool. People just stand in lines for concerts, no one knows how the process works, whether there are even tickets, and in the end no one gets them, or they end up on the black market at inflated prices. Everyone knows this. This is a great example of making things transparent and more accessible, and also more accessible, and also if we think about the social consensus around this, where a community of fans who are genuinely passionate about it, not about business or money, can become validators or verifiers of such systems. Ultimately, it's about allowing some of the sequencing and other elements to be controlled by the community.
Social consensus is enabled , and everyone gets a share of ownership in their ecosystem. It is these types of use cases that, in my opinion, we should think more about and create more of. Yes. No, it's just great, no one here is objecting, I guess we have a consensus—this is exactly where we want to be. I have a question.
How does it work in Stacker? What language do you write the code in and how is the proof generated? Yes. We now have three levels. The first level levels.
The first level is, of course, the parent chain parent chain . The second and third levels are essentially what we are building. The highest level is the application. You define your own state machine. You define your own steps for how the state is updated when input is received , and it's one system where the user interacts with the application, and it's completely Web 2.
You can even run this in a centralized environment. Then you take that state machine and compile it into a format that can be proven. So now we use pessimistic verification. It's a sovereign space, but it can evolve into something much more provable, in fact cryptographically provable. But we want to stay within the social consensus.
So, applications collect all transactions, and the verification layer knows how to generate proof for that system. So during deployment, the application shares its state machine with the verifier. This is similar to running a full node for an application: when a transaction comes in a transaction comes in , it groups it and sends it to the verifier. The verifier re- executes it in a secure environment, and this is a slightly different trust model compared to full L1 or fully off-chain or fully off-chain solutions. But again , once the proof is generated, the committee of verifiers validates it, and it goes into L1.
This also allows you to create different types of user experiences. Confirmation at the application level is instant. Confirmation between the application and the verifier takes a little time, and between the verifier and L1—a little longer. You can build more scenarios around this and essentially choose what exactly the application wants to wait for. I think you both mentioned, and I think it applies to you too, Remy, the fact that there is a separate level of "I need to compute this hard operation," whether it's just proof or verification ( verification ( in fact, there's no verification, just proof generation or checking " can I reproduce this" can I reproduce this" ).
It seems like everything is moving towards the point where we need either a centralized marketplace or just a market of verifiers who have the powerful hardware and computing resources to just make sure everything is correct, and to me that looks like Bitcoin again. Is this the direction we are moving in? Is this a good position for us, or are we simply betting on complex cryptography complex cryptography to somehow simplify calculations in the future? What exactly does the long-term perspective look like in this context? Because it doesn't seem to be getting any more accessible.
On the contrary, it creates even more isolated systems. It was for everyone. So It was for everyone. So , for us, since we are doing FHE, it would be ideal to use specialized FPGAs that can perform FH very efficiently. To give you an idea, performing operations on ciphertext ciphertext , i.
e. data encrypted using FHE, is 10,000 times slower than performing operations on plaintext. Therefore, this requires specialized ASICs optimized for these specific mathematical operations. So the reality is that yes, we'll start small. Today, on a CPU, we can do about 5-10 TPS, and later, thanks to these specialized FPGAs, we will be able to scale to 100-1000 TPS.
Of course, this means using specialized equipment, which will be expensive at first , but as we've seen since 2000, the cost of the equipment typically drops by 90% every five years. So similarly, I think in the coming years as we move to specialized equipment, that will be the highest price point, but over time we expect those costs to come down. And in general, I think that long-term decentralization involves having specific validators, perhaps hundreds, who will do all this work. But everyone should be able to at least run a lightweight node or client to be able to verify as well as easily send transactions in the future. It seems to me that this is a practical approach for most networks outside of Bitcoin and Ethereum outside of Bitcoin and Ethereum .
Yes. I would like to add to this. I agree that a more powerful proof generator is needed now to generate evidence. But now technologies such as parallel proofing are emerging parallel proofing are emerging , which allow work to be distributed in a decentralized manner. In addition, I see that before ZKs become efficient enough to prove on your own phone, even if you have one more powerful prover, you can generate a proof, and have thousands of validators running on each user's phone.
So I think that even though we're moving towards a point where one prover is doing all the work, now everyone in this room this room could probably become a validator, because now all you have to do is verify the proof, and then the ecosystem itself becomes more secure, and the same guarantees are maintained. Yes. Uh, I, I agree with that. We're kind of going back to a computationally complex environment complex environment , but I also feel like once , but I also feel like once it becomes more mainstream, well, if you think about it, 5 years ago the field of AI wasn't that popular, and we were still struggling with training our models and stuff. But as it became more consumer-oriented, companies started creating chips specialized in AI computing, and Apple, for example, did a great job creating its processor.
So I feel like once cryptography and all of these things become mainstream, consumer hardware will also get a lot better. So personally, I see a future where we don't need chains anymore. Everyone only makes peer-to-peer transactions. Everyone runs a light client on their mobile phone and just sends transactions via airdrop or something, I don't know. But we will be able to generate evidence at the level of the equipment itself.
And once we pay more attention to this and get more development, we will get better hardware. So the idea of running ZK proofs on mobile devices, maybe in 10 years, won't seem so crazy. I mean, it would be an incredible world. Oh, and our phones are also getting incredibly faster. So there's also this, and it's like doubling the speed every two years or something.
So ah , amazing. Well, I guess maybe my last question is, ah last question is, ah , what all three of you have in common, besides, ideally, a love and passion for privacy, encryption, and building real applications, is that you all came through ETH Global and in many ways started your journey here. And when I look at those who will be hacking tomorrow and this weekend at ETH India, the most common theme I see is people wanting to do things related to ZK. And that means we'll see a lot more experiments more experiments . We will see many more people trying to implement the craziest ideas and simply "screw" ZK to them.
Also, much of this will be done for the first time, as we are still figuring out which tools work best, what is possible and what is not, and what can actually be computed within the EVM or other systems. So what advice would you give to hackers trying to experiment with ZK toolkits? Is there anything to avoid, something to not waste time on, or what you did yourself when you were creating Stacker, Inco, or Kakarot—how can they best use their time this weekend? Yes, I can share my experience: I think I've participated in about nine global hackathons and I plan to participate in more, because it's very interesting and you can always learn a lot. My approach has always been this: when I come to a global hackathon, I try to set a goal that I currently consider unattainable.
And I try to make the most of our amazing community. So, essentially, I come with a project without knowing how to implement it, but I'm sure there are so many mentors and sponsors who can help me with it. I usually do this: let's say do this: let's say I want to learn more about ZK. I will find out who sponsors the ZK direction. I sit next to their table and ask questions non-stop.
I remember one of them even went to another room after a while. But in the end room after a while. But in the end we became good friends. So use the community, I think it's one of the most powerful tools—you can learn from many smart people who have been in the ecosystem for a long time and who are now close to you. It often happens that many sponsors work with us all night, hacking together.
So yes, I would advise you to choose a topic that seems unattainable to you, consult with community members, and everything will work out. Yes. I think I have two points to discuss. So, one piece of advice, in support of Kartik's words, is to not just implement ZK anywhere just because you can ; use the right tools. There are so many things that can be solved much more efficiently without using ZK.
So just remember So just remember that you shouldn't do it just for the sake of the process. This is, first of all. And secondly, if you really think that ZK really think that ZK is something you want to work with and add to your application, there are many projects that already do it. They have ready-made libraries, so you don't have to start from scratch. Try to do some research and find the right tools.
There may be niche solutions you should delve into. You can spend too much time reinventing the library, so it's better to focus less on that and try to find ready-made options and just use them. Make sure that the core element of your project is the main focus, not the library it is based on. So yes. Yes, for me, as for Danilo, I've probably been to more than nine hackathons.
I really love hackathons because that's where the smartest people are concentrated. I've been in this field since 2017, and I can say that this space is unique because every six months something new appears—primitive or innovative concepts like proof of stake or new designs that slightly change the landscape. So participating in hackathons and interacting with sponsors allows you to quickly learn about innovations you can create or implement to move this space forward. So, yes, and if you want to experiment with FHE, we have it directly integrated into EVM. This is abstracted from the user.
By the way, we created a completely on-chain game a few months ago on Global NYC. This is a completely on-chain game with hidden information. This is a whole new type of experience. So if you want to try it, feel free to try Inko at the hackathon. And yes, we will be there too.
We will build something interesting. Perfectly. Thank you all three for this incredible conversation, see you this weekend. Thank you.
Automatic transcript — names and jargon may be misspelled.