 So, I'm a professor of computer science at University of Illinois in Urbana-Champaign and I also run a startup company which is licensed by the university. The company is called Runtime Verification and what we do, both in my lab at the university and at the company is to develop software analysis tools and techniques based on formal semantics of programming languages. And at the company we are working mostly with large institutions and companies which are very interested in making sure that their code is safe, like NASA, Boeing, Toyota. And also, more recently, we started working with companies in the blockchain space like IOHK and the Ethereum Foundation. Initially we didn't have a plan to get into the blockchain space, we were just developing our general purpose, language-dependent program verification tools. When we received an interesting message from Charles Hoskinson who said that, hey guys, you know, your techniques could also apply in the blockchain space. You just have to switch to another language. And this is something that we preached for so long that program verification and software analysis tools can be language-dependent. You just have to plug and play your programming language. And Charles really understood that and he said, you can plug and play languages that are used in the blockchain space like Solidity or Ethereum Virtual Machine and then you can verify smart contracts which is so important. And then the first question I asked myself was, who is Charles Hoskinson? And then I read a bit about him and then I started getting a bit deeper into the blockchain literature and space and I realized that actually he's right. We can do that. Let's go for it. And then we started collaborating with IOHK and it was like a very fast ride since then. There are the same problems that we encounter in any software, bugs. So software has bugs and the larger the software is, the more bugs it has. It's very hard to write software without bugs. The question is how to detect them or at least how to make sure that hackers cannot exploit the bugs. If you think about airplanes and cars, they all run software, lots of software. But that software cannot be easily attacked by hackers because software running in cars is not even developed by the car developers. Like Toyota doesn't write the software, there are others who write the software and Toyota doesn't even know what that program, they know what the program does but they don't know how it is implemented, they don't see the code. So what is different in the blockchain space is that all the code is public. Everybody sees the code. So if it has a bug and it can be exploited, somebody will exploit it. And that raises unprecedented challenges in terms of security and using techniques like the ones that we have developed for many, many years and using the context of safety critical or mission critical software. Suddenly, all those techniques can be applied to the blockchain space as are. We don't even have to make any changes except to define formal semantics to languages in the blockchain space. Back in 2003, I started teaching programming languages at the University of Philenoise and I took the lecture notes from previous professors and they were mainly like many other universities about implementing interpreters for programming languages, ad hoc interpreters for programming languages. So implement an interpreter for a programming language in another programming language and this is how people learn programming languages and how they design programming languages. And I always felt that something is missing because when you implement an interpreter, you just implement a program. It's not like you have a mathematically grounded definition of your language and what you really want is to have a mathematical definition of your language which you can use for everything you want to do with that language to verify programs, to execute programs, to even compile programs. So I always thought that that's what a language framework should be like and I decided back in 2003 to not follow the approach that was used previously to teach programming languages and which is still being used at many universities. Instead, what I decided to do was to use a language called MOD which is a precursor of the K framework. And I defined rewrite theories, mathematical theories, encompassing semantics of programming languages in that language mode. And then I realized that all definitions follow a certain pattern and it didn't take long until we realized that actually we can somehow frame that pattern into a domain-specific language for languages and that's how K was born. Basically, just adapting initially MOD to do what we wanted it to do for programming languages. And then we sugar the notation and we defined several large real languages like we started defining languages like C, Java, JavaScript and before we realized we had a framework and people started using it and students started defining real languages, large languages in it. And then we just had to maintain it and to make it better and better and better and now we've got to a point where it's kind of stabilized. So the current version of K is stable, now we just need to implement it to be faster and better. So K has nothing to do with EVM. So K is a framework for defining languages or implementing languages, all kinds of languages including EVM. In the simplest possible language I would say that K is a language for languages, a meta language. It allows you to implement programming languages in a very useful way. Once you implement a programming language in K then K will give you a suite of tools that you can use to analyze programs in that language. One major advantage of using the K framework when designing a language is that you understand your language better from early stages when it is really the most important moment to understand your language. You can understand the syntax of your language, you can play with the syntax of a language, you can do what designers do, you can design and play with the design of your language and experiment with it right away. So that's the very immediate benefit of implementing a language in K. So imagine this, you want to design a language, how would you start? You have to define some syntax, then you write some programs and then you parse the programs, then you want to execute the programs. So for each of these you would have to implement some ad hoc tool, you have to implement a parser to parse the programs, then you realize that I don't like these syntax, I have to change the parser and that may not be immediately trivial, how to change the parser or to make the parser do exactly what you want. And then when you run programs, you also realize that, oh, I didn't mean this program to do that, I have to change how I run the program. So basically you change the design and K makes it really easy for you. You can add new semantic features to your language without having to go back and change the existing features. That's typically very inconvenient for language designers. And unfortunately most semantic approaches out there do not take that into account. And one of the reasons I believe personally, and this can be subjective, is that one of the reasons we do not have large programming language definitions in other frameworks or in many other frameworks is exactly because of their lack of modularity and reuse. Each time you add a new feature to the language, you have to go back and change what you have in order to accommodate the new feature. And that's very demotivating, you do not feel like adding a new feature to your language because there is a lot of fault that comes with it. While in K, you just add a new feature, you add additional components to the configuration, you add additional rules to take into account your new feature, and you have the feature. So it's like plugging and playing features into your language. You build your language brick by brick, and K really allows you to do that easily. So that's the first contact with K, the first impression that you get when you start using K. And most people actually like it right then. But that's only the beginning, the bigger benefits come after because once you do that, once you have your language defined or implemented in K, then you can ask the K framework to give you tools for your language, not only a parser or an interpreter to execute programs, but tools like a model checker, for example, or a symbolic execution engine or a deductive program verifier. Tools which allow you to reason about programs in your language. You can prove that programs do what they are supposed to do using this framework. So you get everything from one formal definition, one implementation of your language in K. So why implement your language or different tools for your language in lots of different other languages and then to have to keep up with updates and changes in the language when you can do it only in one place and then generate all the tools automatically from it? So that's the promise of K, and I think it got to a point where the promise started to be delivered. So formal semantics is a very, very old field in computer science, probably as old as computer science, almost. The first semantics approach is what are proposed in the 60s, early 70s, and they are mainly related to how to compile or translate a program into a mathematical object. Like in the notational semantics, you put these double brackets around your program and you get a mathematical object. And then once you get a mathematical object, you can reason about programs using mathematics, which we understand because we developed mathematics for 5,000 years, where programming language is only for 50 years or so. So programming language semantics, yes, it's an old field of study and there are lots of different semantics approaches proposed by various famous scientists. And what we do in K, really, we build on their work. So we stay on the shoulders of giants. So what we did with K was to understand all the very semantics approaches. I think we literally looked at more than 10 different semantics approaches developed by different groups, different researchers and tried to get from each of them what was really nice and useful, trying at the same time to avoid limitations of each of the frameworks. So I could say that K was engineered. It was engineered from the existing semantics approaches in order to get a semantics engineering framework. So the framework now allows you to engineer your languages, but the K framework itself was engineered from the existing approaches. And then once that happened, then theory came. So K now has a very solid theory in place, which all the other semantics gives meaning to your programs once you have a semantics in K. Take Java, for example, to have a Java semantics in K. Now what K will allow you to do is to take a program in Java and interpret it as a mathematical entity. And then the K tools are generic. They can reason about such mathematical entities. And this way you can use the K framework to reason about your Java program. The K framework was used to define large languages like C, Java, JavaScript. And then the resulting tools were used to analyze programs in these languages. And as I mentioned, Charles Hoskinson came with the idea that you can use a K framework actually for lots of languages in the blockchain. Then when we looked at the languages in the blockchain space, actually all of them compiled or translated their high-level programs to the Ethereum Virtual Machine, which is a binary stack-based language, very low-level language. And if you want to verify smart contracts at that level, then you need a semantics of the Ethereum Virtual Machine. And this is how we started working on formal semantics in K for the Ethereum Virtual Machine. Interestingly, it started as a class project. So a couple of students defined the first version of the EVM. Actually, it started even before Charles raised the issue. And then when Charles came and he looked at the project, he said, let's accelerate this. Let's get EVM all done quickly and then let's use the K suite of tools, the K ecosystem, to verify smart contracts based on the semantics. And that's what we've done. And why you want to verify EVM programs? First place, because many security weaknesses, security attacks are rooted in errors, coding errors in the program. So if you eliminate those errors, at least you know that there are no security loop holes related to errors in the coding. There could still be security weaknesses or leaks due to the overall protocol that is implemented. Some cases that were missed by the designers of the protocol. And that's unavoidable unless you formally specify exactly what you want, which is not always easy. But at least verifying the code based on formal semantics of the language allows you to eliminate the silly errors that you may have in your code, simply because you didn't realize as a programmer that there was a little case, like a division by zero, for example. You didn't realize that there is a certain value for the inputs for which the program will run into a division by zero. So this kind of error should not happen. They are not meant to be part of the design. When we define the semantics of the EVM, we realize that certain features of the EVM were not very easy to formalize semantically. And one lesson we learned in time, defining many different languages, was that when some features are not easy to formalize, maybe those features are not very clear or they may have problems. They may also be problems in programmer's mind when they program. So we decided that certain features of the EVM could be possibly replaced with simpler features that can achieve the same objectives or even more secure objectives. And also we verified lots of smart contracts as part of our business in runtime verification. And we learned that many of the verification attempts that gave us a hard time or even failed were due to certain features in the EVM that if they were different, then verification would be easier. So based on all these lessons that we learned from formally defining the semantics of the EVM and from verifying smart contracts, EVM smart contracts, we kind of formed our own opinion how a virtual machine for the blockchain should be like. Also, since we come from the University of Illinois where LLVM was born, we like LLVM, so we thought that it would be great to have an LLVM-like virtual machine for the blockchain. And that's how LLVM was created with this in mind. So we wanted LLVM to be modified for the blockchain, taking into account everything we learned from the previous experience with defining the semantics of EVM. And I am personally very proud of LLVM. I think it is exactly what we wanted. It's even better than what we initially planned. And if we were to do it again, I would do it exactly the same way. That's how I think a virtual machine for the blockchain should be right now. So one thing that I particularly like about LLVM is that it is the first time in the history of formal semantics when a real language has been designed using formal methods from bottom up. And not only that, but also the implementation, the virtual machine itself, has been generated completely automatically from the specification. So in the past, we either defined formal semantics to existing languages like C, Java, JavaScript, or we did what I just said before for toy languages, but not for real languages. So now it's the first time when we show that programming language research, fundamental research, semantic research in programming languages, finally got to the point where it can deliver the promise on the promise. Because that's how we want to design languages, formally, mathematically, and then to get the implementations automatically correct by construction from the specification. And LLVM is the first time this happens. And as a programming language researcher and formal methods researcher, I cannot be more excited than I am about this. But now once LLVM is there, it opens the door for a lot of opportunities. For example, we are working on an LLVM back end 4k, which means that it will take programming language semantics and generate LLVM implementations for those languages. Since LLVM is LLVM-like, it is very easy to switch to LLVM instead of LLVM. And we are going to do that. And when that happens, then you can take any programming language for which you have a semantics in K and generate a LLVM interpreter for it. And these combined with semantics-based compilation, where you can take a semantics and the program and generate another semantics, which captures the semantics of the programming language only. And then we generate LLVM out of it. What you get is a correct by construction compiler to LLVM from any programming language. So this way with K in the middle, you can write smart contracts in any programming language out there. All you need is a formal semantics for that language. All right. And then semantics-based compilation will take that program you write in a programming language, which you already have on the blockchain, whose semantics you already have on the blockchain, and generate a LLVM binary that then will be executed with the LLVM machine that has been itself generated automatically from its specification. So if you look at the whole picture, everything is either a formal specification or generated automatically, correct by construction, from a formal specification. There is no line of code written by humans, which has not been verified. And notice that you need formal specifications anyway, right? You can say that, well, now you don't write programs, but you have to write formal specifications. Well, you have to write formal specifications anyway if you want to verify properties about programs. Because without formal specifications, you do not know what programs are supposed to do. So what I think the vision can be here, it's my vision, I hope everybody will embrace it, is that you can actually go only with formal specifications and all the code to be generated automatically. And the technology that we are developing now will take us in that direction. And I'm very excited about the opportunities in the blockchain space where the need for correctness of software is at another level compared to safety-critical systems. It's a place where formal semantics can shine and the formal semantics will shine and they will make a difference. Because without formal semantics, you do not have formal verification. And without formal verification, you cannot have security.