 Julien, you are a host and we are live stream, so you can start. Yes. Okay. So I am Julien, PhD student working for ODF, which is a French multinational electric utility company. And where I'm supervised by Pierre Yves, a research engineer, and I'm going to represent you with Francois, a research engineer working for the CEVA, an overview of our work on formally verified chain code generation. This talk is divided in two parts. In the first one, I will start by describing you the framework of our work. I will, you will hear about the use of hyperledger fabric chain codes in the nuclear sector along with the application of formal methods regarding those chain codes. I will then give you an overview of the different steps composing of our generation of formally verified hyperledger fabric chain code that suits our needs. In the second part of this talk, Francois will present you his work on the implementation of a shim with the OKML language that we use to make our generated chain codes work on hyperledger fabric. But first, a little bit of context. The research and development department of ODF identified the need to manage and trace convincing data from industrial operations of the nuclear industry in a more secured and transparent way. Therefore, they are thinking about decentralized ledger technology-based business process management system to control and track the course of those industrial procedures, which makes it a critical system in several regards. It is used to classify the criticality of a system into four categories. In the case of our system, a failure or an erroneous behavior would not threaten anyone's life and would not cause a stop to ODF operational activities. However, a system failure could harm the company image and the trust its partners and customers place in it or result in a leak of sensitive information. It is thus easy to understand the need to provide strong guarantees regarding the proper execution of the system, which will make interact operators and subcontractors of those industrial operations, but also regulators, which are authorities that will check and audit convincing data while following the course of those industrial procedures. On this topic, the idea to galvanize exchanges in the nuclear sector and to provide more transparency and trust concerning regulators has been investigated by Finnish and Australian energy provider as well. And back to our system, we decided to use the Hyperledger Fabric Blockchain in order to enable secured and transparent interactions to all these industrial actors by leveraging a chain code to encode the business application of each industrial procedure wanted. We can justify the use of Hyperledger Fabric Blockchain by listing the main advantages it provides to our system. Thanks to Fabric, we have a permissioned blockchain technology that enables us to control the participants. We also have smart contracts or chain code confidentiality and private data collection to secure sensitive data. Those three features provide substantial guarantees by answering the critical aspect of data security that we need. And as for the critical aspect of the proper functioning of the business application encoded within a chain code, smart contract, we relied on the Hyperledger Foundation whose community is really active as well as a detailed documentation of the Hyperledger Fabric Project. But all of these points, all these points are not enough. We need for more guarantees at the software level of the business application to justify its proper functioning, which means we have to set up solutions on top of Hyperledger Fabric to reach that goal. The use of formal methods is a suitable response to this necessity of guarantees because mere testing is not enough as it never fully tests a program. But thanks to formal methods, we can obtain guarantees of correction at different levels and degrees. First, we can use a strongly typed programming language. We can prevent runtime errors of the program, such as division by zero and overflows. We can also certify functional properties over the code with suitable tools. And lastly, we can carry out a formally verified program generation, which is the method providing the most guarantees. It leads us to our contribution and positioning in a previous Hyperledger Fabric webinar, SHIM, developed in the Askel programming language, has been presented. This language relies on a strongly typed system, which enables to implement chain codes in a safe typing environment and thus strengthens the trust in the code. Our approach is not only based on the use of a strongly typed language, but on all of those four points of formal correctness. We especially rely on a formally verified code generation, starting from a graphical specification of which here is an example. So it's not an industrial operation, but a simplified version of the tiramisu recipe represented with our specification formalism, which can be considered as a subpart of BPMN, so business process management notation, with only interesting features for our project. So at this stage, we want to specify the execution order that must be enforced between the tasks. And in other words, enforced a workflow. It is sometimes a strict order with sequential tasks following each other and sometimes a looser order, where tasks can be performed commutatively, which is represented with the dotted boxes. It's important to note that each task to be executed will be encoded within its own method of the chain code that will carry out the whole procedure. Once we have a graphical specification of the wanted procedure, several steps must be performed in order to get an executable chain code ready to use on hyperledger fabric in our industrial consortium system. We must first generate a logical specification and an implementation in YML. So it's a dedicated programming language of the write-through tool that we use. This deductive verification tool enables us to prove the correctness of our implementation in relation to the logical specification. So here you have a write-through sample with the mean function, where a precondition with the required keyword, and a post-condition with the ensures keyword are specified. So the first one must be true at the function call, and the post-condition, obviously, must be true when the function returns. And once the presentation is over, you will have the possibility to attend a write-through tutorial that Francois prepared, and during which you will be able to experiment it yourself easily. From this formally verified implementation, the write-through tool makes it possible to extract a correct by-construction executable code. And we can then deploy this program in the form of a hyperledger fabric chain code to run the encoded procedure with the Okamal and thus on the hyperledger fabric blockchain. Now let's focus on the different steps, performing this formally verified chain code generation. We go back to the first step, the graphic code specification of the procedure. In this example, a simplified version of the peer review mechanism is specified as a procedure, and I'm going to run an instance of it for you to understand its semantic. So first is a color for paper performed by the editor, which enables a submission of an article. Then the first reviewer purses a favorable view, but not the second one, which leads to another submission. After that, both reviewers separately agree on the new version of the article, which enables the journal to publish it, and finally to close this call for paper procedure instance. As you can see, this formalism includes a notion of rendezvous, represented by the plus symbol and a notion of interruption with the minus symbol, which takes precedence over the execution of the tasks running inside the box. Then comes the code generation from the constraints expressed with the graphical specification. So we produce a logical specification and an implementation in the YML programming language, dedicated to the Raspberry tool. And we can then prove this implementation in relation to the specification automatically through the use of solvers, and in our case, Altego, CPC4, and Z3, which of course requires proof engineering and some experience with the tool. However, it is not that easy to express and prove all sorts of interesting properties within this tool, such as temporal logic ones. These very kind of properties could be useful to test the workflow specification and convince the user that the graphical phase was performed well. And proving those properties could be achieved with model checking, as it has already been explored on Solidity Smart Contracts, adopted for business processes. As the generated code is only a workflow enforcer chain code derived from graphical ordering constraints, it is easy to fill each method with a code, implementing the business application of each task at the YML level, and to provide a specification of it to prove its correctness. This way, we can enhance the chain code by tracing specific data while leveraging the Y3 proving environment. From this YML code, we can finally extract an OCaml implementation. But in order to hand this to the Y3 tool, we need to fill the holes in the YML generated code. Given that YML is not an executable programming language, the interactions with the shim are abstracted. They are declared and specified but not implemented, which means that we have to provide to the extraction tool the way to call the function gate set input state, for example, in the OCaml environment. And we can thus extract executable code from the YML implementation of the chain code. And I will now let François talk about his work on a shim implemented in the OCaml programming language. Thank you, Julien. So the shim is an important part of the Hyperledger Fabric. It is communicating with the endorser, which executes the chain code. And each endorser are connected to the order of Hyperledger Fabric. So the interesting part about the Hyperledger Fabric is that you can, in fact, use many different languages because the endorser just runs a Docker virtual machine and connects to a program using the GRPC communication protocol. And so the program needs a little part that is a shim that is able to understand this protocol and runs the chain code in the language. Currently, we are only the shim in OCaml only work in the development mode. So the development mode allows someone to directly connect to the endorser, the program directly connected to the endorser. And so it allows people to restart, modify, and restart the chain code at will. And the reason is just that currently, we have not explained Hyperledger to the endorser how to start Docker instance. But we should be able to do that in the future. So the shim architecture is quite simple. So you have at the base the libgrpcclibrary and which communicate with the endorser. And we have a GRPC module that is the OCaml stub for this C library. Then since the GRPC use the Protobuf description protocol, we can use OCaml protocol plugin in order to transform the Protobuf into OCaml code, which describe the protocol. So we take the Protobuf Fabric Protos that describes the Perledger Fabric protocol. Then it generates the Fabric Protocol OCaml code. And from this description, and GRPC protocol plugin that is able to run the protocol, then we can have Fabric chain code shim that is really the shims that the user can use. We can see here a little example, an L-word example. So at first, we open this module. So it's for any OCaml code. And then the two function query and put are the methods that are going to be the method of the chain code. They are very simple here. The only thing they do is to get the key, the value of a key, or the put method, modify the value of a key. Then at the bottom, we have some boilerplate which starts the interaction loop for the protocol. So we have a function that is called during initialization. And a function that is called, each time the chain code is invoked by the endorser. So you can see that here it's really boilerplate because we just recover from the message the function name and the arguments. Then we match from the function name in order to know which method to call. And with that, you can communicate from our OCaml code. You can create. We have this chain code in OCaml. You can see a little demonstration. So what we do here, we have a legal script that will create and compile all the endorser, the orderer, start them, create a little playground so that we can use the chain code. It's a little longer. I speed up the video. And so at the end, we have the pure chain code invoke command available. And so in the other terminal, I can start the OCaml code using dune that built it and started it automatically. And then we can ask the value of a, the key n. So we have the answer 90. We can modify the value. And on the right, you can see that the log of the chain code. And that code, the chain will be used by the code after restriction, by the Y3 code after it's compiling it to OCaml. So this work has been simplified a lot thanks to the ASCEL shim because we have been able to look at their work and all that work because sometimes the documentation, in fact, the real implementation is a very good explanation of what a shim should do. The protobuf description simplifies a lot the work too. And yet the protobuf is not completely explicit. And for some message, it's hard to know where to find each important part and to know which data is available for the different messages. But still, we have been able to do it quite well except that the iterators, we have not yet implemented the iterators and that are the complex queries on keys. We'll do it later. And perhaps thanks to the OCaml 5.0, where we will have a multi-core support. So we presented you the different steps carrying out our formally verified Apple Agile Fabric chain cogeneration, implementing procedures, and in our use case, industrial procedures in the nuclear sector. We also presented you a shim implemented with the OCaml programming language that we use to make work our generated chain codes. And for future work, we could enhance our graphical formalism with more BPMN, so business process management notation features, or simply take this notation as our graphical entry point. And it would obviously require your work at the code generator level to handle those new constraints in the Y3-proving environment. And as for the OCaml shim, François. Yeah, the main part is to be able to use it in not only in development mode, but also that Hyperledger Fabric is able to run the Docker automatically, to start the Docker automatically. Thank you. OK. So thank you for your attention. And feel free to ask any questions before the tutorial starts with François. So we can take the question of Shane. So perhaps with the tutorial, you will see an example of code, why So the question is, why do we want to have verifiable chain code generation? So the important part is that you can have bugs in your code, as in any other code, of course. But for chain code or smart contract, often it is a very small piece of code, but that are quite important because since you are putting them in those blockchains in others so that other people can look at them, other people have to trust them. And also, you yourself need to be sure that nobody will use it in a way that you don't want or you haven't expected. And so proof allows to show to yourself and to others the behavior of the program and also to remove a usual programming error, like arrays overflows and things. So that's really in order to be sure of what is your chain code and what your chain code does. So yeah, the question from a clinic. So can we extract to a more traditional hyperlegia of fabric native language, like we have Go, Java, and JavaScript? So that's the first thing we tried. And just so we can extract from Y3 to JavaScript and to Go, I tried that, except for the async part, it was not really that was possible, but it was quite cumbersome and more problematically the feature of the language of Y3 were quite limited because Y3 has that structure that are not easily encodable in the other language. So that was really, yeah, that was quite not really nice. And we can, for example, we have done a work for the blockchain to encode Y3 to Solidity and Y3 to also compile it to EVM. So things are possible. But just you lose a part of the Y3 language. And since hyperlegia of fabric allows you to use other language, we thought it was really a nice way to use this feature of hyperlegia of fabric. Just a high level fabric contract model. I'm sorry, I don't get what is this feature. I will take another question before. So this question is about the chain code I'm telling an approval for each organization, but can each organization have a different chain code? I think it's possible, but really I'm not a hyperlegia expert. So I think I have seen things like that where people have different chain codes, but it must be for different things. They can't have the different chain codes for the same feature, for the same thing. Yeah, it is in hyperlegia labs. So yeah, we haven't put a pointer to it, but it's there. And also for the question that yes, it is certainly possible as long as they produce read, write, set that match at the end. So yes, that's an interesting feature that yes, it's just that if all the endorsers have the same computations, then yes, they agree. And so it works, indeed. Nice. So perhaps Pierre-Yves will copy paste the GitHub link. So is there any other question? Otherwise, we should maybe dive into the tutorial. Yes, I'm going to share. So yes, hi, everybody. So the tutorial, so it's a tutorial, but since we have a lot of people in this session, I will take any question you have, but I will not be able to look at all your, if you try to do it, to see what you do. But so you should really not hesitate to ask questions if you want to try it yourself now. In any case, if you want to try it later, you can see that it's, I will put it in the address here in the chat. So you can, it's part of the rich tool box, which is a European project that wants to bridge the gap between tools and user. And so there are a lot of tools that you can look at. Other tools you can look here. And so it is not directly, completely a tutorial for Hyperledger in the way that we are not using Hyperledger API. It's more something that is akin to Solidity API. But I hope it will still be interesting because it will show you what we want to prove, what properties we can prove, how the proof is done. And another interesting aspect of Y3 is that you can, you have an online version. In fact, it is just a JavaScript version. So you can go from OCaml to JavaScript. Here, everything is run inside your browser. So my advice is to use the Y3 tool directly on the desktop. But in order to just test a little, it is nice. And you can use the Altair Go automatic solver. So if we go back to the tutorial in itself, so the goal is to just prove a transfer smart contract or chain code. We have the balance for each address, for each user. And we want to code a function to transfer token from one to the other. So it's really the first chain code you can write. Someone who wants to write, a very simple one. But we are going to see that, in fact, there is many pitfalls that proof helps avoid. So here we have, at the start of the file, you have a lot of definition in order to express what is something like the solidity data structure. For example, you have address. You have what is a mapping, what is also a message, and that you can have a sender inside the message. All this part for Hyperlegia Fabric is already written, for example, by Julien. So here, you have it just in order to have a standalone file. And at the bottom here, we have all smart contracts, the code that we want to prove. So this code can be compiled to solidity, to OKML, to KKML, to many other languages. And now, also, a green to OKML. So we have this transfer function. People, what it does, it just takes from the message. We have the sender. We have the number of tokens that is given as argument. The receiver also is given as argument. And we want to remove this number of tokens from the sender and add them to the receiver. And I don't know if people can find what is the problem here. But we are going to run the tool. And here, there are some parts here that are not proved. So one thing you need to add in the settings, the default step limit to add to 1,000 is the number of step limits of the altergo prover. And you need it because at the end of the tutorial, some proof needs a more step to be proved. And we can see that we have two VC. So it's called verification condition that are not proved. So first line and the second line. And we can see the task if we want that it is a formula, the mathematical formula that is generated. If the mathematical formula is true, then this line is correct. But here, it is not proved. And we can see that there is a problem of integer overflow. Indeed, the Solidity used inside the integer with 256 bits. And when you remove some token, we can go below 0. So the semantic of Solidity is a wraparound semantic. But it's really, we don't want that because it's not the semantic we have in mind. And so we don't want something that is unexpected. So the semantic we choose is that here, it is an error. And we ask this when we have this kind of computation that the computation will not be below 0 or will not wraparound. So in fact, we can see here that it's asked the computation to be inside the bounds. So what we are going to add, we could add a requirement to this function requires in order to ask when you call this function, you must something must be verified. However, a smart contract, you can always ask to execute a smart contract. So we use more something like the usual Solidity way, which is to abort the computation if something is not verified. So here, I copy pasted the line that we explain what it does. We add this require. So it's a function that test is a number of tokens. It requires that the number of tokens is smaller than the balance of the sender. Otherwise, we stop the computation with this message. Now that we have this, the Y3 tells us that this expression raises an expression require fail. Indeed, Y3 requires that all the exceptions that can appear inside the code must be listed. And at first, it can be thought as something that is quite just a copy paste of what we have below. But in fact, we'll see that it's quite interesting for multiple reasons. The first one is that if you have a very big code, in fact, inside those multiple call function calls, you can have other require that will also stop the computation. And so here, we are sure to know in which case the computation will stop. Here, we are sure that the computation will stop only if we have this condition that is very fine. So now, we can start again. Oh, yeah, my copy paste, perhaps. Why do I have this? Oh, yeah, sorry. I forget to add here. Since now, we are using, in fact, many mathematical integers in order to express this part of the formula. It is not a bounding integer. It's a whole mathematical integer. And so here, we can ask to do the verification. And this one is verified. The exception of this code condition is also checking that it's indeed only in this case that the require failed is raised. But we still have another one. Because indeed, in fact, there is not only the fact that someone doesn't have enough token, which is what we think at first. You must not give more than what you have. But the problem since we have finite integer that you can have too much token. Because if the receiver have a lot of token, and here it's really a lot because it's 256 byte long integers. But it can be a problem. And here, we can find it. And we'll see something interesting here. What we want to say is that if we have the number of token of what we want to write, if something like that. That if I take the maximum, the max of wind 256, I want the number of token plus the balance to be smaller than this. If I'm using the, oh, yeah, I forgot to define it. In fact, it's not defined up here. So now I can try to do the verification. And I have a new integral overflow verification checking, VC. And it's, in fact, here, the problem is that when we do this computation, in fact, OK, it's because here. And don't observe. So here, this one is not proved. This computation of the requirer is there is a problem indeed. I'm doing exactly the same computations and shears. That was already problematic. Because when you do something like that, in fact, the test must be written in another way. It must be written like this. And that's not something that indeed you could think that the requirer was correct at first, that you wrote a requirer to test that. But in fact, with the Solidity Semantic, the previous test was always true. Since with the Vrapornos Semantic, that it is something of this tip is always smaller than the maximum. But now everything is proved except here, because I have another reason why the requirer can fail. And the second interesting part of this, or the reason that we re-express the requirer is that here we can use unbunded integers. So here I can write it in a way that is more simpler to understand and simpler to check that we are doing what we want for someone that will read that. So here we can write it in this way, because here we have mathematical integers that can go beyond it 200. Yeah, sorry. So what is the problem? I'm saying here, when the requirer fail, it's when it is bigger than the right. So here everything is proved. So I know that when I'm going to execute this function, no computation will run per hand. And I know that the method will fail only in those two cases. But now we could. Do you have some questions? Some people? I don't. OK, no question. OK. So here. Now we can go beyond that. Now we have just something that will be executed in a safe way. But we are not sure that we are computing it. The behavior of the function is the one we want. Because what we really want, for example, one property that we are interested in is to, for example, be sure that we are not creating token. Because if I removed this line, everything will work. It will be proved also. But in fact, I'm creating token. And that's something that I don't want. And also, for example, the DAO attack, it is a well-known attack, old, now, attack on Ethereum. And someone had been able to gather a lot of money from a smart contract because it was not removing the money. The balance was not correct. And so it's what we are going to try to prove now. We are going to prove the property that the number of tokens is constant. The sum of the number of tokens is constant. And for that, I did some functions here that talk about sum that express what the sum of balance is and what the sum of mapping is. And so we are going to say that the sum of the balances is always equal to initial. So we have a number of initial tokens. And at any point, we have always this number of tokens. So it's not at any point. In fact, during the execution of a function, we allow the invariant to be broken. What we check is that at the end of the function, the invariant is restored. So it allows us to do, for example, this computation here where we remove some token at some point that we added later. So in the middle, the number of the invariant is broken. But at the end, it will be restored. And so what I wrote is that here we have the invariant that the sum balance is equal to the initial value of the number of tokens. And this buy is to ensure that the invariant is verified, at least by one pair of balance and an initial value. So for example, if we have the initial balance where everything is at 0, in fact, the sum is equal to 0. So because in Y3, we don't want type to be inhabited. We don't want to type where the invariant is always false. So now I wrote this. And I need also the default values. What I need is defined. It's just because, OK, just in the tutorial, I asked to add this function, I hope. But here it was missing from the definition of mapping. So now we have, so it's typing. And now we have, for example, here, the invariant, we prove that the type is habited and that it is possible to verify the invariant for some value. And here, the type invariant is verified here. But why do I have this one? I think I will just cheat. Sorry, I will take this one. I don't know what I messed up. Here it's, yeah, OK. Because here the requier was not the right place one. So if I just do this, that will work. So now we have been able to prove that the invariant is verified at the end of the computation of the method. And for example, here, if I forget this line, we can check that indeed it is not proved. OK, so do you have some questions about all of that? That was quite fast, sorry, perhaps. But in any case, you can take your time with this tutorial if you want at another time. The initial date. Sorry, what is the initial date? Do you mean this one? Then is this that? Oh, presentation date. Oh, of course, of course. Yeah, yeah, of course. We are going to, I think it will be on the Meetup page, perhaps. OK, so I think we can close this session if we don't have any other question. Igor, can we upload the presentation on the Meetup page? Igor? I think Igor said that he had to leave. OK. Yeah, he's not here. He's just recording on his computer. But I can close the YouTube live stream. And we can do this when we want. Great. OK. Thank you. So you can close the stream, I think. Yes.