 Hello everybody, first of all I would like to thank you to the Debcon organisers for giving me the chance to do this talk and also thank you all of you for attending the talk. My name is Ignasi Ramos, I work for Polygon GKBM and I am at the protocol team. It's been a year, a year and a half that we've been working very hard to release the GKBM and I am very happy and very proud to announce that on Monday. It was announced the release of the GKBM on Publicternet. So I would like you to do an applause for all the Polygon team that did that effort, that it's enormous. So thank you very much. The title of the presentation is GKBM versus EVM, full equivalence. Okay, so a little bit, what are we going to talk about? First of all, I will do an overview to keep some context about what is a GKBM and then I will go more concrete on what is the Polygon's GKBM. After that we will go to the topic of the talk, which is the difference between the GKBM, the Polygon's GKBM and the EVM. So what is a GKBM? There are three statements that I think that they define the minimum of a GKBM, which is that it is a virtual machine that executes smart contracts in a way that is compatible with zero-knowledge proof computation. And why would we like to do this? Because what we want to do is scale Ethereum. We want to increase like the throughput of Ethereum, the transactions per second. At the same time that we lower the fees. So how can we do it? We use GKSNAR technology to make cryptographic proof of execution of Ethereum-like transactions in a summary. Now, when you process like a batch with a lot of transactions, you get a result, you get an output, you get an state. So how can other people, how can other ones to trust you that this process, this process of the batch, has been done with correctness, has been done correctly following like the EVM constraints. They have to process also, do transactions and see that the output is the same. With zero-knowledge proofs, we can like do it easily because we can, after processing all those transactions, create a zero-knowledge proof. And if someone wants to validate that these transactions have been processed correctly, like following the constraints of the EVM, of the CKVM in this case, they only have to verify that proof. And this is faster. Also, the verification of a proof is always constant, which is very interesting. Actually, this is like a game changer in the ecosystem. I remember it was around the FCC that a lot of companies were doing like release announcements of releases of CKVMs. And it created like a lot of noise, especially in social media and many places. And a lot of people was very confused because a lot of new words appeared there like compatibility, equivalence, what is the prover, I don't know. But luckily, we have like Vitalik that he did a very interesting blog. Actually, I strongly recommended to read it when he classified the CKVMs in five times. He created what I like to say like the CKVM dilemma. Like, if you have more performance, you have less compatibility. And if you try to have more compatibility, you will have less performance. Actually, at Polygon CKVM, we aim to be from type 2. We are not there yet because we still have to finish the precompiles, but we will be there very soon. I told you I liked 2.2. So, the advantage of this type 2 is that it has a lot of compatibility. It has as much compatibility that we can talk about equivalence. The disadvantage is the performance. In Vitalik Post, he said that it takes a lot of time to generate the proof. Well, this is a bit relative. I mean, what is a lot of time? Now we are generating proof in around five minutes, but we still know how to do it and we have a lot of ideas in mind and how to reduce these to up to five minutes. And also, it's not that big problem because you also can parallelize the proofs. First of all, I would like to explain very simply. When we talk about equivalence, what are we talking about? We're talking about putting the batch of transactions in the EVM and putting exactly the same batch of transactions of the same block or whatever to the ZKVM and get the same state. And when I say state, it's like the same state root. And when they have the same state root, it means that the storage, the state of the blockchain, is exactly the same. It means that all the accounts have the same balance with the same nones, with the same bytecode, with the same storage, with whatever. Exactly the same. So are different black boxes because internally they work differently, but the equivalence means that for the same input, they have the same output. It could be like a lot of time explaining how we've done it and there's people here sitting that could explain it by far better than me. So I just do some sentences just to put some context. Also it's not the topic of the talk, but we can discuss about it later. But at the end what we're doing is a processor. And a processor has clocks. So each clock is like a new state. And we're playing with these new states as steps. So as all processors, you can build an assembly at the top of them. You can build an assembly language to define these steps. And this is what we've done with a language called ZK assembly. With ZK assembly, we tried to replicate the behavior of the EVM in an assembly language. When this assembly language is compiled, it creates like a build, which is a big trace of all the steps that will define the processor. On the other hand, we have the build, the polynomial identity language with it's like one step more of 2.0. It's also a language done by our tech lead, Jordi Bailina. And what the executor does is that he gets the ROM, which is the build of the ZK assembly language that I just explained. He also uses the build where there are the state machines of the Ethereum defined there and he verifies the correctness of each one of the steps of the ROM while it process the transactions. So more or less, this is how it works like. I'm just scraping the surface that this is how it works the ZK VM. And of course, as all other processors, we also have a ROM and a storage. Now let's talk about the variances between both of the EVMs. As you may know, the EVM uses a Patricia Merkel tree while we are using a Sparse Merkel tree where the leaves are indexed. In each leaf of the EVM, we store all the information of the account. They have the nones, the balance, the storage roots and the hash. But we are doing it differently. On each leaf, we only store one property of the account. So this brings me to the second difference, which is the hash. For the EVM, it's used the KTAC. But we are using the Poseidon with the Goldilocks prime number as the finit failed. This is for performance reasons. So when on Ethereum you want to get the key of a leaf, you have to hash the address. But as we only can retrieve one property of the account for each leaf, we have to hash the address with a property key. For example, if we hash the Ethereum address with the property key of balance, we will get the leaf where is stored the balance. Another difference is that Ethereum uses more than one tree to define all the system. As you can see here, in one of the leaves, there's the storage root. The storage root points to a different state tree where the storage is stored. We are doing it differently. We only have one tree that defines the whole system. Another difference is the memory. The EVM uses just a lot of memory, 8 bits, 1 byte. And we are using 256 bits, let's say 32 bytes. So we are working with a bigger memory slot. This makes that when you are querying to the memory, the information that you get is the same. But the way that you obtain the information is a bit different. The internal logic of some of the codes had to be changed a bit. I will show you an example now. For example, for the code, Mload. With Mload, you load 32 bytes from the memory. There are different cases. Some are more tricky than the other ones. This is the easiest one. When you want to get just 32 bytes, you just ask for it. And you have to return the fullest lot. In our case, it's the fullest lot because we have a slot of 32 bytes, the fullest lot of the memory. In case of the offset, it's different from zero. When I say different from zero, I'm talking about mod 52. It means that the beginning of the slot is not the beginning of the memory that you want to retrieve. Maybe you will have to get half of the memory from one slot and half of the memory of the next slot. And it gets a bit more tricky. Sorry, when you want to retrieve more than 52 bytes. In this case, for example, more or less than 52 bytes. In the first case, for example, we are only retrieving some bytes of one slot. In the second case, just the bytes in the middle of the slot. And in the third case, it's like if you want to do it without offset, different from zero and also more than 32 bytes, then maybe you have to get some bytes from one slot, and get the whole bytes of the following three, four, five slots, whatever the length is, and some bytes from the last slot. The CK counters, yeah, is another difference. Probably this is very new for a lot of you. I will say that the behavior is like gas, but it doesn't replay gas. I mean, we are computing the gas exactly the same way as the cerium does. But as I said before, we have like a limited number of steps in the processor, right? So when you are processing a batch, you have a limited number of steps, and also you have a limited number of state machines that you can consume while doing an opcode or an operation. So in our implementation of the CKVM, I will show an example just after this slide, we have to check that we have enough counters to process that opcode. If we go out of counters, for example, the CKVM throws an error, which is out of counters. This error is not a user fold, actually. It's like a fold of the executor, but it can be solved easily like processing this batch with less transactions, because it means that the number of counters to process that batch has been exceeded. Here we have the different names of the state machines. For example, the binary one is just consumed when you compute a binary operation or the key check when you do a key check hash. I will show you an example of an opcode. Well, it's a widely used opcode. It's the equal one. The equal opcode, he compares the two last values in the stack and takes if they are equal. As you can see, this code is from the CKVM assembly. As you can see, the first two lines, here I am checking that I have enough counters to process that opcode. As you can see the binary, I'm checking I have at least one binary counter for the state machine of the counter, one binary counter to process this opcode. It's because here I use the equal and the equal consumes one binary. Also, I check the steps. Each one of the lines of the CKVM assembly is a step of the processor. Here I put 120, although the number of lines is less. It's because I will go to read code, which means that all the process has been correctly in the best case scenario. But in the worst case scenario, I may fall out to a stack underflow or maybe out of gas or stack overflow and I will need some more steps to handle this error. We don't use the self-destruct. Actually, this is a difference now, but we guess that it won't be a difference in the near future because probably Ethereum will accept the EIP4758 where it replaces the self-destruct by send all. So we're not using self-destruct from the very beginning. We're using send all. And I'm happy for it because self-destruct creates a lot of problems. What does the send all does? Instead of removing the bytecode and the storage of the account when you call the self-destruct, what it does is to empty the account and send all the balance of the account to the account caller. At the end, we're just following this EIP. This is also a difference that will disappear in the next months because we are really working hard to finish this and this is why we're not still type 2, but as I said before, this will be over in a few months. Actually, we only support 3 pre-compiles from the EVM. We support the C recover, the identity and the mode X. This is one of our priorities. We are working to finish them all. Actually, the S8J 2.56 won't be that hard because we've only done the C recover. Maybe the AC biting is a bit more tricky, but it's working progress. One of them is the code of the Xcode hash. Obviously, if we're using a different hash, we're using the Poseidon instead of the Kitchak. This Xcode hash is returning the hash with Poseidon. Also, the block hash. This one is not really a difference because it's not a variant because now on the EVM, you only can get the block hash of the last 256 blocks. We are supporting to get it from the blocks in the blockchain from the very beginning. And the memory limit. We have a limited memory of around 40 gigabytes. This is different from the EVM because the EVM is unlimited. It's set by the gas. You can put 50 million gas in one block. Actually, this limitation makes that in a batch, you can put 8.5 million for each transaction. This is the cost of the memory expansion and we won't have any more memory. But I have to say that a transaction with 8.5 million gas should be enough to do whatever you want. It's also very easy to do different transactions. If you have a very big transaction, it can be splitted in different ones. And also, this is currently the last one. It's a different now, but it won't be a different anymore because we are also working on it and it's one of our priorities, which is that we are actually not supporting EIP-155 and EIP-2718 transactions, but it's a matter of time. So in conclusion, well, you all have seen the slide from before, but this is now the most important moment of the presentation. Oh no, why is it happening? Now, exactly. It's that we are passing the 97% of the Ethereum test suites. I think it's the best way and the most empirical way to show to the people that we are compatible with equivalence with the EVM. So this is the final remark. We are fully EVM equivalent, and I also would like to send a message like this in the second point, which is that the difference that I've been explaining now, most of them are for aim to be more equivalent and with a better performance. I mean, we've been building the ZKVM with a different toolkit that what was done with the EVM. So we have to take some technical decisions with different tools, but to reach the equivalence, also taking in account the performance. So I think that also we have learned a lot from all those years of the EVM processing a lot of transactions. And actually, I think that probably people from the Ethereum foundation, if they had to do the EVM again from the very beginning, they would do some things different, and some of the things are the ones that we're trying to do. We've learned from them, we've learned from the EVM, and we've tried to do it better. And finally, to finish, I'll just tell you what I said at the beginning. We are on public internet, so we really encourage everybody to try to crash it, try to test it, play with it. I mean, it would be very good for us if you crash it so we can find a bug and we can iterate and deploy again, fix the bug, and all this. So just to finish, thank you very much for being here. I hope you enjoyed the talk. Thank you.