Build Your Own Blockchain | Unitize Day 2: Developers and Hackathon Track

Bruno walks through Polkadot's Substrate framework for building blockchains from scratch. He covers runtime upgrades, WebAssembly, and the technical foundations developers need to launch their own chain.
Chapters
Always find me on Twitter and Telegram or LinkedIn or wherever you want, or just email me Brunoeb3foundation if you have any questions about this presentation or anything else regarding Polkadot Kusama substrate, our whole ecosystem, anything at all, I'm always at your disposal to answer any questions. So, at Polkadot, we believe in a decentralized and fair Internet where users control their own data, where users also control their own identity and their destiny. And to do this, we need a free, open, decentralized and censorship resistant web 3.0. And to do that, we are building a suite of blockchains in a way which will let other blockchains connect to each other. Now, in order to. This is the link that I mentioned in the intro, but if you haven't gone through it, please go to Bit ly polkaprep this will be. This will prepare your entire eco, your entire environment on your computer to compile and build these tools as we'll be playing with. So in our mission to decentralize the web, we've built this Polkadot blockchain, which allows other blockchains to connect to it and to talk to each other through it. There are quite a few projects that claim to do the same thing out there today. The difference in this case is that Polkadot's connected chains share their security, where in other shared blockchain systems you may have a problem of the whole ecosystem being only as strong as the weakest chain. Because imagine for a second if the weak chain sent a message to a more secure chain, and that message includes something like increase that user's balance by a million coins. If that weaker chain then gets hacked or reverted or forked or something, what happens to the more expensive chain? Well, that chain is in trouble, right? Because it doesn't know which version of the past to trust. And so that makes the whole system only as secure as that weak chain. In Polkadot, every chain that connects to the ecosystem is as strong as every other chain. This is possible because they're all connecting to the relay chain, which is the master chain coordinating everything between the master chain. The relay chain has these validators, and the validators are validating random connected chains at random periods and giving them finality. So the chains that are connected to Polkadot, they get their finality, they produce their own blocks, but they kind of seal those blocks into finality through the help of the validators on the relay chain. So the entire system is only as secure, is as secure as every other chain. And the more chains are connected, the more secure the system is the more validators there are, the more secure the system is. But this sounds really complicated, right? How are all of these chains connected to each other? And how is this relay chain built at all? Well, this is built by the development company Parity from Berlin, which has built plenty of blockchains for enterprise users and other use cases before. And they realized at some point that they were repeating a lot of the work that they were doing. They were constantly reinventing the database, the networking, the consensus layer, the transaction queue, and, and a lot of these other things that blockchains typically need. So they decided, why not abstract all this and why not just turn the knowledge that we have into a framework? Why not build a common starting ground from which we will all, we will build all of our future blockchains? We'll do that really well. We'll improve that, we'll let it out into the open for others to build on as well. We'll have a really solid base so that people who are building blockchains don't have to spend spent two years researching and doing who knows what kind of research and development. Rather, they, they get this database, they get the consensus, they get the common pieces, and they can focus on their application logic right off the bat. That's really powerful, right? So Substrate came to be from this idea. And Substrate is an open source, modular and extensible framework for building blockchains. That's all there is to it. It's just, just like a template for building blockchains. Think of it as your blockchain's bootstrap. So Substrate provides the core thing that I just mentioned. So that's the database layer, that's the networking layer, the consensus engine, the transaction queue, and a library of runtime modules which we'll go through next. And each of these modules can be extended and customized to your liking. So you can be as specific in your application logic as you want. Your chain can be as application specific as you want it to be. And one of the key selling points of Substrate is its runtime. The runtime is composed of these different palettes, and these palettes are part of this system called Frame. These palettes are rust modules that have certain functionality, but that functionality is encapsulated in that palette. It doesn't leak elsewhere. So it's all very Lego blocky. You know, you can connect all of these functionalities together into one common runtime that then makes sense and is useful for you and for your blockchain. So how does that work? Well, for example, you can see up here in the circle, that's one runtime, right? And that runtime contains the palette system. Babe, sudo, grandpa. Indices, timestamp, balances. These are all different palettes and they're, they're marked with the pink border in the table below. But there are many other palettes as well, and these are not all of them, these are just some of them. But for example, if you want smart contracts in your chain, you would add the contract palette in there and then you would rebuild. And when this recompiles, the new binary will contain the smart contract functionality. Your chain will automatically have smart contracts built in. So why is this special? This is just adding features, right? Well, it's special because of webassembly. And webassembly is something is like this binary code format which takes up very little disk space and very little memory. And the advantage of this is that it can be executed in a wide variety of environments, even the browser. Why is this important? Well, because this runtime, when we build it, when we compile it, when we compile this circle of things, it results in a wasm blob, a wasm file, webassembly file. And that file has, along with the native file, along with the binary that you get from compiling the rust. So you get a program that you can run that contains the runtime, but along with that you get this wasm file that also contains the runtime, the runtime logic. And this wasm file contains all the logic that a blockchain needs to progress from one block to the other. So this contains all of the rules that the blockchain needs to be built, you know, to continue building itself. And substrate based chains all have this common functionality. They will all produce this wasm blob. And this wasm blob is stored on the blockchain itself. So why is this important? Well, previously, whenever you needed to upgrade a chain, like for example in Ethereum, if you wanted to change some opcodes or something at the core level, that would change the gas mechanics. If you wanted to add new crypto primitives into the chain or something, you would have to hard fork, right? You would have to develop this functionality, add it into the clients that are out there, and then you would have to get everybody who's running a node, who's running an Ethereum client to upgrade that client to the new version. And everybody who didn't upgrade would be left behind on an outdated fork, which is no longer the canonical fork. You would have to get in touch somehow with everybody who's running your node which is difficult in a system where most people who run your nodes are anonymous. And they would have to be aware or actively pursue updates and be aware of changes that are coming so that they can jump in and do this on their own. And that's an arduous and frustrating process for any hardware coordinator. Especially in a world where we are still communicating through centralized media about upgrading decentralized technology.
Right.
That means that anybody who would just stop if Google decides to. No, no more discussions about this. It's very difficult to reach those people. And we have maybe one or two platforms through which we communicate. That's GitHub, that's Twitter, and that's maybe Google. And we rely on these platforms to communicate to everybody. Obviously that's not sustainable long term. If you look at it from an absolutist kind of view, we want to decentralize to the maximum. So what substrate based chains allow you to do is they store this wasm blob on the chain itself, that's like maybe a couple hundred kilobytes and it contains all of the logic. And now when they are running, when you're running a substrate based client, so a client, a node of a substrate based chain, any chain that chain is reading, that node is reading data from the chain and it also reads in that wasn't blob that's on the chain and it looks at the version of the runtime that's written inside that wasn't blob and it compares it with the version that it has locally and its own native code in its binary. If those versions are the same, it will run the native code, the binary, because the binary is always faster than wasm. WASM needs to be interpreted, executed and so on. So it's orders of magnitude faster to run this locally, like bare metal and the native rust code. But if the wasm codes version is newer, then the client will use that, it will download that new WASM code that's on the chain and it will treat that as the canonical runtime that it's supposed to execute. And while it will be slower to run, it'll use a little bit more resources of your computer. Your node will actually upgrade itself. So if you replace that wasm blob on chain, that chain will upgrade itself while it is still running without you actually having to tell anybody to install a new node, to download new software, to replace their software that's running, and so on. This is extremely powerful. You basically get forkless upgrades, you basically get the ability to upgrade a blockchain with new functionality without having to talk to a single person except those in charge of changing that wasn't block. Now how that change occurs, there are two different ways. One is through the sudo module, and you can see it here in this runtime, the sudo module is included. Now the sudo module is just like an admin module that lets you execute any function of the chain at any time from one single key. So that's like an admin key to the chain. And this is often useful when a chain is just launching so that you can do fast incremental upgrades without having to go through on chain governance to vote for these changes. Right. So with sudo you can just replace that code and it'll go into effect immediately. The other way, which is the decentralized way which you deploy after you're done with sudo and after you're fairly certain that all of the kinks have been ironed out, is the on chain governance way. And the way you do this is every token holder of every substrate based chain has the right to vote on decisions that we call referenda. And these referenda can be anything from changing a simple value of the chain, like the maximum number of validators who are allowed to validate to the complete replacement of the wasm blob for the runtime. So when I have some new functionality that I want to deploy into a chain, say for example, Polkadot is running right now, and right now in Polkadot you cannot transfer dots the native tokens. That's by design because we are still, there's still the sudo module, the chain is still in like early launch phase. And during this phase we definitely do not want to enable people to speculate with tokens. We don't want to endanger any economics of anything of the chain. And so the transfer functionality is disabled for good until the community enables it and the community alone can enable it. The sudo module will be removed and replaced by the democracy module very soon. And what's going to happen is the community, every dot holder will be able to trigger the function, the runtime change to allow balances to occur, to allow balance transfers to occur. And when they propose this, other people will be able to vote on this decision. And there are some mechanics on how to prevent plutocracy and how to make sure that the election is fair and how to make sure that the, that the voting is, you know, both civil resistant and bribe resistant and so on. So this, that's a topic for another time, but the democracy is fairly fleshed out. We've been running this on a sister chain called Kusama for eight months now, and it's worked fairly well. We have made over a hundred runtime upgrades already and many different other types of upgrades, and the chain is progressing very nicely. So it's like an earlier release of Polkadot that's existed for eight months now so that it's verified to be working. But what matters here is that this forklace upgrade mechanism is available to every single substrate chain. Every single blockchain that builds on substrate has this ability to make an upgrade to itself without having to hard fork. You can, of course, hard fork, that's always an option, but you don't have to. You can avoid that nightmare of coordination now by executing these updates on chain. So what happens when the node takes the new wasm blob from the chain? It loads it in, it starts running it, and then it's up to the node operator, to the one running this client, the software to upgrade when they feel like upgrading. They don't have to do it. They can do it. They can do it whenever they want. The only thing that's in it for them if they do is a bit better performance, right? The the node will run native code, because when they upgrade the client, the versions of the runtime will again match and the client will no longer run the WASM blob. It will run the code that's native. So the native code will be equal to the code in the wasm, and the client will be running the code natively in a much faster way. So some performance to be gained there. This is important for validators, but for barely anyone else. So if a validator cares about performance, and they should, then they will of course keep track on the updates that are coming out and upgrade nodes whenever they feel safe about upgrading, like maybe wait a day or two after release to see if everything's fine and so on, and then upgrade as soon as they can. Because not upgrading can make them slower than other validators and then they might lose out on some rewards. Right? But that's basically why they would want to do it. So, in this workshop, what we're going to do is we're going to play with the substrate node template. And the node template is a working substrate node. It's like a very basic chain prepared for you, prepared for your experiments. And it's actually what most blockchains start out with when they're building their blockchain. So most of them start out with this and then build custom functionality on top of this, this is like the base starter kit. So Substrate is the framework that enabled the node template, right? Substrate is just a set of code that allows this to happen. So the node template is something you modify and turn into something you want. So we will have the sudo module in here. So we will be able to execute administrative functions through an unlocked and very rich account that will be, that will summon through the dev flag. So we'll run a development chain which will have this account unlocked and we are also going to build a custom palette for this chain. So a custom module that will allow us to do some very application specific logic so that you can see how easy it is to customize a blockchain that you built on Substrate. We will also be using Polkadot JS apps and that's an official front end for interacting with substrate based chains. The beauty of substrate based chains is also that because of the way they're built, because of this framework, every Substrate based chain exposes a bunch of metadata from its run panel. And this metadata is available to any client that connects to that node. And this metadata will contain information on all the events, all the errors, all the functions, every single thing that the chain can do, all the constants, everything will be in this metadata ready for consumption by any connecting client. And this is like, kind of like if you, if you think, if you're familiar with Ethereum and their smart contracts and you have the ABI. So the ABI is like an interface, a JSON file, a JavaScript file, a JavaScript object file which just defines which functions and values exist in this smart contract. This is similar. So a subject node will expose this metadata about itself and a UI will be able to customize itself by based on this metadata. And polkadot js.orgapps is one such UI. So this UI is generic. It lets you access any Substrate based chain and it will modify itself according to the modules that this chain has. For example, if you visit Polkadot through this chain, you will see all the regular functionality in there. But if you connect, if you switch the connection to Edgeware, which is a smart contract chain based on Substrate, you will get a different layout, a different color, and the menus will now contain the option contracts where you will be able to interact with smart contracts which is not present in Polkadot or in Kusama when you connect to those. So the UI can self modify based on the metadata that is being fed to it from the chain itself. And that's really powerful as well because it lets you build generic wallets for all Subset chains and imagine how powerful that is. So we'll also be dealing with the substrate front end template. Now, Polkadot js.org apps is a behemoth, right? It's a big application suite that contains every single possible function, like in a simple button format. It literally contains. It's for power users. Basically. It contains everything you can do to interact with a Polkadot with a subset based chain. And it's too much for everyday users. That's why we have. And it's also very heavy to build. It results in a huge website that uses a lot of memory and so on. That's why we have the substrate front end template, which is a lightweight react based template that lets you interact also with any substrate based chain, but in a very primitive manner. This is something like it's going to look there. So we'll get a bunch of unlocked accounts, we will see our blocks, we will see our balances, and we'll be able to interact with different palettes inside of our runtime, as you'll see. Now, what's important to know when developing palettes and when customizing subject based chains, we will be making heavy use of macros. And macros are like magic magical code that expands into more code. So macros let you write very little code that becomes much more code during compilation. For example, if I make a macro that lets me Type the number 2 and then plus and then maybe the asterisk button and then the number 7 during compilation, that macro could expand that little symbol to mean that the number two pluses itself like two plus two plus two plus two seven times.
Right?
Stupid example. But that's how this code expansion macros works. And so we'll be using four main macros that everybody uses when they expand substrate based chains and denote template into their own application chain. Those are declare storage, declare module, declare errors and declare event. Declarestorage is used to tell the chain how you want to save your data. That's it. It just tells the chain which prefix to use in the data tree and how to fetch that data, how to save it. The declare module is like the main body of the palette. It's like the main part inside it you will put all your functions and various other declarations that go. It's just the meat of it is the logic. Declare event will list all of the events your palette can emit. And an event is like if you send a balance to somebody. Excuse me, if you send a balance to somebody, the transfer event is emitted. And anybody who's reading data from the chain can listen for events instead of reading the blocks and parsing the data inside the blocks. And declareError does the same thing for errors. Any error you can encounter while using your palette will be documented. DeclareError. So we can actually. Yeah. So the basics of runtime development in Rust here, it's important to note that in substrate based chains in general, there is no such thing as a rejected and reverted transaction. So transactions always leave an effect on the chain and they will always charge a fee for doing anything, even when a transaction is invalid. So if, for example, you try, you have one dot and you try to send one.it's going to reject that sending because you didn't leave enough room to set to pay for the fee. But it's still going to charge you the fee for the attempt because it has to leave a mark on the chain that you tried this and that it failed. Whenever you issue a command to the blockchain, you submit what's called an extrinsic. And an extrinsic is just like an outside input into the chain. And this chain will make a log of this attempt and all of the extrinsics failed or successful will be logged in the blocks of this chain. And that's why you're charged and that's why you should keep in mind how to develop these modules. So you always have to. You always have to keep partial state changes in mind, right? You can't really rely on the, on the module to revert your transaction if it only went halfway. So you have to build your logic in a way that will fully revert if something failed, or that will execute only when all the sanity checks have passed. That's a caveat that you have to be aware of. So this is the basic layout of a module. We'll do imports at the top, we'll define the trait and that's, that's just where we put our common types and so on. And then we have our macros into which we put the logic. This is how we declare storage. Actually, let's get into the meat of things and start developing because we are going to run out of time otherwise. So let me just skip out of this one and fire this up. So we have here the substrate node template. I hope it's big enough to read. And this as well. Okay, so if you've gone through the prerequisite guide to set things up, you should have this up and running. The node template you can compile with the command cargo build release. And so it didn't do anything for Me, because I didn't do any changes. I just compiled this a while ago. Now, compiling takes a while, especially if you're starting from scratch. The good thing is that if you're only changing some files, it'll only recompile those files. So it'll actually be much faster when you make little changes. But the first compilation might take a While. It takes 10 minutes on my desktop rig. It can take up to 40 minutes on a laptop. It'll depend on your on your machine. But luckily you only have to do this once when dealing with a specific node. So if you go into palettes here, you will see the template subdirectory. Now, the template palette is actually the one that's included with the node template by default. This is something for you to hack on. This is here as an example. And the files that we'll be modifying are in source librs. So that's the meat of our module and cargo toml, which defines our dependencies, the packages that we need to pull in. But before we do that, let's check this chain out, shall we? So I'm now in the folder of this node template and you run it by running just dot slash, target release. So every, every build will get put into target release. And then the binary in this case is called node template. You can run it by just doing this, but it's not going to work because if you do this, this is not a development chain and it's going to expect a validator. It's going to expect actually two validators. So you would have to run two, two nodes that connect to each other to produce blocks. And it wouldn't work, it wouldn't move. But if I do dev, it's going to run a development chain that just produces its own blocks and does its own transactions and has some unlocked accounts for you to play with. So this is great for testing your logic locally. And then when you're ready to deploy, then just remove dev. It'll start a new chain in a new location with a new database, and you can distribute that binary to anybody you want to run your node. And then you'll have a blockchain, but for now let's just run it with dev. You can see here that it is now working and every time it makes a block it'll send you all of these messages. Now, my Unicode characters are a little bit broken in this bash emulator here, but if you're using something native like Linux or Mac os, you will see beautiful emoticons here being output in your in your logs. This is just a Windows issue for me. So now the chain is running and a substrate chain by default listens on port 9944. So let's open that up. Let's actually use our substrate frontend template again. If you went through the prerequisites post, you will have this folder here, Substrate frontend template and the front end template can be started with just yarn start. So now it's starting this development server and it's running the page for me. And this page will automatically connect to localhost9944 so that it can read our blockchain connecting to substrate. There we go. So what can we see here? Let me zoom in a little bit. We can see here that we have some accounts and we can switch between them. This is the account from which we are acting. So this is the one we are logged in at. The metadata that I mentioned that's being exposed by every substrate chain can be seen with show metadata. And you can see here it's just a JSON file and it's quite big, right? That's because it contains literally everything the chain can do. So let's try and find in this whole mess our template module. And actually let's look at what the template module contains. So in this case it contains like out of the box. It comes with some definitions, it comes with some. This we'll explain later. It comes with some imports, it comes with a trait definition that enables events. This is just boilerplate for enabling events. It comes with a definition for storage. So it stores something and it comes with a definition for an event that the event screams that something was stored. And it also has some errors here. And then there's the meat of the module. So I'm not going to go through this because we'll go through it when we'll be coding. But we have two functions in this module. One is do something and. And the other is cause error. And this will just demo an error. You will see what an error looks like. So the error still changes the state of the blockchain, but it errors out for the user. And this function will just store a random some data that you save into the chain and you will be able to fetch it back out. So sorry. Yeah, so actually let's demo this right away. So we have here the function called do something. Let's try and find it in our metadata. There we go. So we have a call, let's do something. And that expects a unsigned integer 32 bit so something. It expects an Argument called something. And the documentation is here. So anything you write in a. Whoops, wrong one. Anything you write behind a triple slash above a function becomes its doc block becomes its documentation. And that's why we can see this here in the metadata. The documentation is here, just a dummy entry point, blah, blah, blah. And this is how you actually add documentation to your metadata as well, so that the various UIs that connect to it can actually present this to the user. So let's try and interact with this chain. It's already on block 40 with the finalized block at 38. Pretty cool. So we have these accounts here unlocked with a bunch of coins. And we have these other accounts here that just don't really matter. These are from my Polkadot JS extension. So if you install the Polkadot JS extension, you'll be able to keep your keys in this extension. And so this will let you connect to various web3 websites. So websites that interact with subsidy based chains, you'll be able to interact with them. Okay, let's first demonstrate a simple transfer of units. So let's demonstrate. Let's find. So Alice will be sending to Bob. Let's copy this address. Let's put it in here, Bob. And let's put.
Put.
2 million. So this one unit is all of this, because we are showing this with the smallest possible unit with planks. So we'll send two units over submit. And now it's being submitted. There we go. It passed. So transfer succeeded. And there we go. Sorry, this is our event. Balances transfer event happened from account to account. How much? And there we go. And it's finalized. Wink. So we get an event when it's included in a block. And then we get another one here notification when that has been finalized. Of course there's no change here because these are millions. And we just sent two units. So nothing there. Now we said that we have this template module, right? And the template module has some functions. And the template module has two functions. Do something and create error or whatever it was called and cause error. Yeah. So let's check it out. We can interact with a palette by building an extrinsic ourselves. So we find the palette that we're looking for. There we go. There's a template module and we suddenly see, you see it automatically offered only the functions in that module and that's because of the metadata. So the metadata just was parsed for this and now it offers me only these two functions. So let's cause an error. Now let's submit. There we go. So this Extrinsic failed. That's an error. And we got a dispatch error. So we got the information about this error that occurred. But if we do do something, let's put in five. There we go. Something stored. Success. Just a dummy event. So we got the event that something was stored. And now look at this. So this UI here is a custom UI developed just for this node template as a demo, and that's for this substrate front end template. And we'll be modifying that later for our use case. So we now have the current value here at 5. Now let me demonstrate that forkless upgrade that I was talking about. So we go to substrate node template and now notice that our chain is still running. Right? Our chain is still running. I'm not going to turn it off. And what I'm going to do now is. What I'm going to do now is like this. So we are going to rename this into cause an error, insignificant change, but it. It's changed nonetheless. It should be visible. So now we will go to runtime of the chain, of the chain itself, of the. So there's this parent runtime that loads all of the palettes, templates and we need to change some information in this parent runtime. There we go. You're looking for spec version. So if you change spec version to this and then recompile, the wasm that is the result of this compilation will be different from what is running natively. And then the chain will actually grab the WASM from the chain and run that. Let's try that out. Hopefully it works. So now we've saved this, we have changed our function and we have upgraded our spec version. Now we need to recompile. So we'll open a new tab for this. There we go. And now just a typical cargo vault. Now notice that it only starts from like the very end. So the last four modules it needs to rebuild. So it's going to be fairly quite a bit faster than it would have been starting from scratch. You can see that this728 this means this is how many crates it has to build. So how many modules it has to build compile in order to get to the final one that we are using. That's a lot, so that takes a while. But in this case it'll be done much faster because it only needs to do the ending the final part. Okay, so while that's happening, let's also start with. We can't really start with this just yet because it's compiling, but let's try and do. Okay well, let's go through some basics. I think it already went past resensitive parts. Yeah, let's explain some things. All right, so at the top here you saw this line. So this is also just copy paste friendly. We'll be copy pasting this. You will never be typing this out from scratch. Actually, most of this stuff, you'll never be typing it out from scratch because it's all boilerplate that you can use, but it's still warranted explaining. So in order to build substrate based chains, you cannot use the Rust standard library, because that's big and that would be too big to include as a WASM blob. So there's this no standard mode. And all this, this really means is that. Sorry, all this really means is that when you're not using the standard feature, then activate the no standard mode. This is just something you include in every module that you build because you want this standard, standard Rust module mode to be disabled. Otherwise the WASM compilation is just not going to work, it's not going to complete. What else? This here is interesting and should be familiar from other languages. So you just import the things from Substrate. So these are the actual code that we want to share. So this is the framework's code, do we want to reuse? So we import frame support and then from frame support we import all of these macros that we'll use. So declare module, declare story, declare event, declare error and dispatch, which you don't actually need to import it. Otherwise here from frame system will also import itself because the system will let us access some system level values, like the block number, for example, and a macro that lets you ensure that something is signed.
Right.
Actually not a macro, just a function. So whenever you submit something from outside of the chain, like the extrinsic that has to be signed, in most cases there are some non signed extrinsics that you can submit. That's a miscellaneous use case. But in most cases you need a transaction to be signed, so you need it to be signed with the private key of a wallet that somebody is interacting with the chain. This function will just let you extract who the signee is, if he exists. If he does not, an error will happen. So that's what this function does. It's like a shorthand convenience method for checking that a call is signed. Okay, this is done. So let's take a look if we can make this work. You can see here that we already have an upgrade, right? Runtime shortcut function. I don't. I wonder if this works. I'VE never used it. Let's see. So we need to find the wasm file here. All right, Template. So the. The wasm time, the wasm blob will be a target release W build node template runtime. And there it is. Node template run runtime compact wasn't. And this is the file that you need to upload. So if we upgrade this, let's see what happens. Ah, so we just saw two events happen. Code was updated. That means our upgraded code was successful. And a sudo just took place. So we got an event that in admin did this. So this, this little module here, this little component in React that somebody built, this already applies the sudo call to our forklift runtime upgrade mode. And let's actually see if this works now. Right now it's not gonna. But if we refresh it should cause an error. There we go. So now our function is called differently, it has a different name. And we did all of this without even restarting our chain. The binary is still chugging along. And why is this possible? Because it just downloaded the wasm from the chain and it's running on that. And that's why the function name changed. And our runtime upgrade was successful. We didn't break the chain. We didn't need to hard fork. We didn't even need to upgrade our built binary. We didn't need to do anything and it just worked. So if we wanted to do this manually, like without this shorthand convenience component, we could do this through the palette interactor as well. So we could pick the sudo and we could pick sudo. Unchecked weight. So this unchecked weight function is what you would call when you're doing the Focus Update. It's slightly more complex. This is why it's abstracted here in this part. Then you have the call which needs to be encoded, and then you need to add the weight which you expect. So weight is like a. If you're familiar with GAS in Ethereum that limits how many calls can fit in a block. This is weight here. So weight is the machine code. You can see above a method here. Weight equals 10,000. So there's a limit of weight per block. And you like any, any function call that exceeds that limit is not going to make it into that block. It'll be queued up for the next one. So it's very similar to gas. I should note that this only takes into account the time to execute the function. So this is CPU time. Weights are based on CPU time and the cycles that it consumes, but it's not based on transaction size, so it doesn't take into account state growth and stuff like that. So this is just computationally how much it costs to execute a block. And there are some benchmark tools that you can use when you're building your own palette. How to benchmark your functions to be in line with the weight that we.
Expect.
You need to be within a certain limit or otherwise you are going to have trouble including your transactions. And also some processing might be so heavy that your validators will start lagging behind. Right? So if you leave unchecked wait, then you might apply too much for the validator to process quickly if there's too many heavy function calls. And this can interfere with block production. So this is why the wait system is there to limit this whole CPU processing per block to a reasonable number. Anyway, I can't really fill this out off the top of my head, so I can't demonstrate this. But then what would happen is when we fill this out with some data, I don't know, we would click sudo right and then sudo would execute the sudo module. So only the sudo command will invoke the sudo powers of our ALICE account. ALICE is the sudo when you run the dev chain, ALICE is the pseudo account. The sudo button would invoke the ALICE pseudo powers to call this combination of extrinsics and produce the same result as this upgrade runtime thing did for us. Now let me show you something else. Actually, we are kind of running out of time, so let's go into building the custom thing. Let's delete everything from lib RS and don't worry, I'm going to share a written version of this tutorial after the workshop with you. So you can, you can follow along with this at your own pace. You don't have to rush along with it. Let's check it out. So like I said, you will first have to import something, right? So we have here the configuration flag for no standard and that's just always has to be there. Then we are importing some macros and here I have changed it to include also the Ensure macro. And the Ensure macro just is like an assert. It's like make sure what we put into parentheses is true or emit an error. And we need the storage map to store some values into our chain. Now what we're going to be building here is a proof of existence blockchain. A proof of Existence blockchain lets you log the existence of a file or some Data at a certain point in time with your. And make it cryptographically verifiable. So if you have like a song and then somebody comes out and says, no, this is my song actually, then if you registered it on the Proof of Existence blockchain, you can actually.
Prove.
That you registered it at a certain point in time. That's the point of these. It's like a blockchain notary. Right, so we'll do that. So for that we will need to kickstart our module. And I said that we need to define the trait. And inside the trait we put this type event. So if you don't, this is again boilerplate code. If you don't put this, your module can't even image events. That's it. And then we have these macros with their fake bodies here, here, that we will be filling out. Let's first put this in. So the module is defined through a struct. So you define this pub struct. Again, this is all you're going to be just pasting this in. But what matters is that this origin thing, whenever you're building your custom palette, your custom blockchain, the very first argument of every single function inside of that module will be origin always. And origin is where that transaction is coming from. And that's what we will be ensuring is signed. So origin is the origin of the transaction, and it's always the first argument on every function. Now, to activate these basic metadata sharing functions of our chain, we need to include these two lines as well. So we need to declare a type of error and we need to set the function of deposit event to be default. Again, boilerplate code. You would be including all of this every time. This just makes it possible for the module to emit errors and events at all. Otherwise it can't do it. Now, we will need to, because we're storing strings into our blockchain and I mean we're storing hashes, and hashes are just strings. We will hash a file, we'll store it, hash, and then we will register that on the blockchain. So a hash is just a string. And since we're storing strings, strings in rust are represented as vectors of bytes. So we will need a vector structure to use so that we can store. So that we store vectors. So, so we'll import that, and we'll import that from the standard palette, we'll import vectors, but we can't just import that without actually adding the dependency in as well. So this is where we will be modifying our. This is where we'll be modifying our cargo TOMO file. Sorry. So let's modify this cargo toml. Let's put it at the bottom here. Okay. And then we will add this. So we have SP STD std. So now we have this standard library loaded in and it should. It should work. We can add a comma here. So now we have this dependency. When we build, it'll pull this in. It'll build it for our module. We now have access to our vector. Right. So let's now define some events. We said that we wanted to register our file on the blockchain. So there are two events that we could fire. We could fire that A. If I'm. If I'm registering a file, I'm registering a claim for that file. So I'm claiming that it's mine and I register it. So we can call this claim created and claim revoke. Very straightforward. So this is how we do events. You have an enumeration, so a list of events where this account ID will become available to us from this trait through the account ID type. And the triple slash above events is again the event description, the event documentation. So when an event is emitted, it will have this description inside it, available for reading by any client that connects to it. Again, helping the UIs and helping the wallets build things. So we have two events. One is claim created and that will emit account id. And a vector of bytes which will be our hash and claim revoked will emit the same thing. So anybody listening in can just read this. A caveat here that trips a lot of people up is that events, event enums, and enums in general in these macros, because these macros are not pure rust code. They're macros. They have some caveats that are designed to minimize falling, you know, shooting yourself in the foot. But sometimes it trips people up. One of those trips is the ending comma, the trailing comma on the enum list. It has to be there, otherwise it's not going to even let you compile.
So.
So these enums need a trailing comma at the end then. So now we have these. Now we have these events for claims right now. What kind of error can we encounter in our palette? Well, somebody may have registered this claim before. The claim may not exist if we're trying to delete it. For example, if you're trying to revoke it. Or we can.
We can.
Oh yeah, you can. You can try to delete the claim and not own it. Right? We don't want any, just anybody to. To delete anybody's claim. Let's put that in as well. Again, an enum, a list of errors and messages for those errors are here. Okay. Finally, let's declare the storage. And I'm gonna speed up here because I'm running out of time. This is how this works. So you define a trait store for module T. And this part here is important. This is what defines the prefix in the database. And whenever you're building a palette, this has to be reasonably unique among other palettes in your blockchain because if they share this, they will share a prefix in the database. This is going to get hashed as a prefix and the data is going to get appended to it. And so if I name this through and somebody else named it foo, names their storage item foo, then our data will clash. That's not good. So make this as unique as you can every time. No need to do random numbers or something. But if you just call it like your palette should be enough. If people are mindful to look into what kind of palettes they're including in their chains. This is the name of our storage map. And that's going to be a map of hashes. And these hashes are going to be hashed by Blake2 128 concat hashing algorithm. This is the default, but it has to be verbose. You have to express it like this. Again, very copy pasteable. And these hashes will map to tuples of account ID and block number. So we're going to store account ID and block number for every hash that we include. And these hashes are going to be those file hashes. Finally, let's build those functions for our module. I'm going to just. I'm just going to paste this in because we are very much out of time. So we now have these functions in here. So we have a create claim function and we have a revoke claim function. Let me just put this into build mode so that we can maybe attempt to run it. But let me explain it while it's building. So we define a struct for this module. This is again copy pasteable template. You will be using that. These are the template functions we included before. Now these are the individual functions and you can see that they are heavily documented. This is from that tutorial that I'm going to share with you. So the createclaim function is going to do the following. It contains, like I said, the first argument is only the origin and the second one is the proof. The hash, the hash of the file that we're trying to save. So first we'll grab the sender by ensuring that the origin is signed. This here the question mark means either return the origin, either return the sender or error. So this just is a one line for give me the sender of this transaction or error out. Then we'll ensure we'll make sure that the procedure proofs storage map does not contain this proof that we're trying to save. If it does, we emit the error that the proof is already claimed, somebody already submitted it. Then we store the current block from the system module, grab the block number, and we insert this proof into our storage map. You may be wondering why this ampersand here. This is because of a Rust mechanic called borrowing. In rust, if you send a variable into a function without borrowing, then that variable stops existing inside the context where it was sent from. So we would be unable to use proof if we didn't use this ampersand here because it would disappear from our context here. But the ampersand means do what you need with this and then send it back. So this is why this happens and this is why we don't need them here, because we'll no longer use them in the function. This is where the garbage collector can discard them. And so we save this into the block, into the blockchain, and then we emit the event that the claim was successfully created. So the revert function does a similar thing, but in reverse. It also checks if the sender is the owner, which we'll go through if we have time. Let me see how this is working. Okay, it's still compiling. So we have here the sender again, we grab the sender. We then ensure that proofs exist, that this proof that we're trying to exist, delete exists. And if it doesn't, then we emit an error, no such proof. Then we get the owner of the claim. So we take our proofs storage map and we get get is a built in function in our storage map. So no need to specially define it here and declare storage. This is built in. So we get our proof out of this. But since we are binding our hash to a tuple, so two values, account ID and block number, we would get that tuple here, here. So the way we extract the owner is we say let. And then like this, the first variable that we extract from this tuple will be applied to the owner variable and everything else will be discarded. This means discard. So it will just grab the account ID stored here. It'll just discard this. We don't care about the block number. And then we ensure that the sender is actually the owner. So we equalize these two and if not, then we emit an error and we stop the execution. Again, if we stop here, the state of the chain changed so far and we have to charge the user a fee. So this is still going to cost them some money. If they failed, then we remove the proof from our map and then we emit the claim revoked event. Okay, let's try and test this out. Hopefully. There we go. It compiled. Now, since I failed to increment the spec version, this wouldn't work as a forkless upgrade. So let's rerun the chain. In this case we're going to stop the chain and rerun the binary. Now let's try this out. Hopefully this works without purging the chain. But even if we purge it, it's not a big deal. Let's interact with the palette. You can see here that our template palette is. The component is gone, so something is different. Let's see. Template module. And we have here create claim and revoke claim. So now if I put in here the bytes, let's say this, this is obviously not a good file hash, but we'll just put that in, let's sign it. And we have just created a claim for this file. So we have just claimed this hash. Now let's try to claim this from the BOB account. The same thing signed. Let's see. Ah, failed. Alright, so we have failed this claiming because this proof is already claimed. Let's try and revoke this claim from the BOB account. Again, failed doesn't work. But if we try to revoke this from Alice. There you go. We revoked the claim, so now we have deleted this claim. That's basically it. So this is how easy it is. You know you can see in a. Like there we go, under 100 lines of code, including comments. We just built a custom palette for our blockchain that allows you to do some very application specific stuff. And this blockchain can be connected to the Polkadot ecosystem to share the security with all the other blockchains. So this is how we are building the huge ecosystem that is going to be Polkadot. And this is how we're going to connect to the other chains by building functionality that makes it very easy to get started, very easy to get very specific with your logic and still not deviate from the very practical shortcuts that we've built into substrate itself, like the metadata sharing, like the forecast upgrades, like the UI compatibility and so on and so forth. Thank you for listening. If you're interested in this, if you want to check out more content, if you want to check out more tutorials, Please go to substrate.dev and go to tutorials there, including this tutorial. There's a bunch of others there that you can try out. Setting up your own private blockchain, building visualizations, stuff like that. Go there, dive in and I hope you'll have fun because this is designed to be fun and easy and approachable and I hope to see you in the Polkadot ecosystem. Thank you very much.
Sa. Thank you for the overview, Bruno. It's great to see building your own blockchain can be so simple. For those of you that are just joining us now, if you have any questions during any of the workshops, please feel free to ask them in the chat box. Our speakers will answer them accordingly. Now for our next talk we actually have a two part workshop called Terra A New Platform for defi Dapps with CosmosM. Ethan Frey, co founder and CEO at CosmosM will guide you through how to build using CosmosM. William Chen, who leads developer relations at Terra, will teach you how to write smart contracts on Ontario. Ethan and William, the stage is all yours.
I am William Chen, Developer relations at Terra and today I'm going to be covering smart contracts on Terra and why you might want to consider building your next app on Terra's DEFI infrastructure. So Terra is a decentralized stablecoin with global ambition backed by its sister Token Luna, which is the native staked asset of the Terra blockchain. Luna collateralizes the entire Terra economy and provides governance voting rights to its holders. Luna effectively represents a long term investment in the the Terra economy by trading the instability of day to day price fluctuations and providing stability to the Terra ecosystem. Luna holders receive a consistent stream of TX fees that only go bigger and stabilize the incentive to hold Luna. So the main topic is why build on Terra? So Terra's smart contract feature is new and nascent and definitely not mature. But I'm going to just go over a couple reasons why you might consider Terra as a potential candidate for your next smart contract. So first of all I'll have to go into the consensus and block finality of Terra. So Terra is a delegated proof of stake consensus chain based on tendermint BFT as a Cosmos SDK chain. How it works is that the top 100 validators in Lunastake participate in the block production process and we're lucky to have a proactive validator community who's actively developing tools such as Block Explorers and Validator notifiers, other tools. Currently we're at six sections per block with finality and we have support for potentially hundreds of transactions. A second Terra is a chain that is ready for defi applications. So our stablecoin mechanism was built with world e commerce in mind. So we currently have the Korean Won, the US Dollar, the Mongolian Turkic, and it's just a marginal cost to add an additional currency to the Terra ecosystem. We have a robust price Oracle system that reports on the price of Luna every 30 seconds and we have fast native on chain swaps between currencies, between Luna and Terra, between Terra and Terra currencies. So Terra is really implementing something called money as a protocol whereby we're creating money that has its own algorithmic and monetary fiscal policy. So this coupled with the governance feature enables Terra's economy to act as a sovereign economy driven by its users. The main appeal of Terra, however, comes from the growing highly active user base with real world usage. So currently Luna is third in transaction fees right after Bitcoin and Ethereum. There are a total of 1.6 million total accounts after one year of release and this number is constantly growing. We're integrating with real world apps with actual use cases. So some that come to mind are definitely Chai and Mimichat, which are payment processors that provide discounts to attract users. Chai in particular is responsible for much of Terra's growth as growing out from Terra. And what's cool about Chai is that it's gotten so big that you can use it at convenience stores, buy groceries with it integrated in places like We Make Price and tman and currently partnered with some of the largest e commerce retailers in Korea, including Nexon and Kyobo Books. Another interesting use case that Terra has been implicated in is with High Yield Savings products. So Terra provides this stability feature where for Haro bank and Trinito you can deposit KRT and earn high interest on that KRT compared to a traditional savings account with a bank. So right now I'm going to spend the rest of the presentation talking about how you can use terra with the SDKs and how you can start programming things with Terra and eventually use smart contracts. So There are currently two Terra SDKs released. One is called Jigu, it's for Python 3 and the other one is called Terra JS, which is for JavaScript. In this workshop I'll be using the examples with Jigu, but the concepts will be easily translatable into Terra JS with a bit of looking at the documentation. So how JIGO works is that that it is a library that enables you to talk with an LCD node. An LCD node is something that a terad node runs that exposes its functionality through an HTTP interface. So instead of having to make raw HTTP calls and do serialization and deserialization of the request and response, GGU will handle that all for you and enable you to work within Python as if, well, without realizing that you're working with strings and raw blockchain data. So it allows you to create Pythonic code that works with the Terra blockchain. So once the GGU parses your requests, your request is sent to the LCD and propagated through the rest of the network. And this is how your Python application can interact with the Terra blockchain. So you can get TestNet tokens@faucet.terra money. And this may be useful if you're wanting to follow along with this tutorial. So a JIGU does one of two things, and the first thing is querying data. So the blockchain exists out there and you want to get information about the blockchain into your program. The first thing you want to do is create a tera object that connects to the lcd. And once you've created that, okay, so here I'm connecting to Soju 14. Soju 14 is the official testnet as of time of recording of the Columbus 3 mainnet. And I'm using the public LCD node at V dot. And you'll notice that each of the functions are neatly packed into its own sub module within the SOJU variable. So I can get the blocks by doing SOJU blocks. And there's even an iterator which allows me to iterate through the blocks. I can get the balance for an account by using the bank module. I can get the exchange rate for Luna in USD using the Oracle module. I can get the market parameters and printy print them using the market module. So it's really short and it's really easy to get data from the blockchain by using the functions within each sub module. So the second thing that the Terra SDK is able to do is to affect change on the blockchain by creating transactions broadcasting them. So like before you're going to connect to an lcd, here we're going to make a wallet, and a wallet just is an abstraction around a signing key. Here I'm using a random mnemonic key which gives the wallet signing features. So I'm going to create a message, and a message basically contains all all the Things I need to interact with the module to change its state. Here I'm using a message send, which is the most basic way of telling the blockchain to move my balance into someone else's balance. So I'm specifying a balance of 23 Luna. Here the unit is U Luna, which is micro units or 10 to the negative 6. So, so 23 million microluna is 23 Luna. I'm going to specify a fee.
And.
I'm going to send the message. I'm going to sign the message and create a transaction. And then finally I'm going to broadcast that message. Then you should see a successful transaction. And then you can go into terrafinder, look up the transaction hash, and you can see the exact transaction being posted from Python. So I just wanted to point to the fact that you can actually put multiple messages in a tx so. You can. Okay, here I'm doing two swaps, one from Luna to USD and another from Luna to krw. And first I'm going to specify a fee that's higher than the one before because this is going to require more data. And then I'm going to sign the messages and create a transaction and broadcast like before. So this is how you can put multiple messages inside a transaction and broadcast it at the same time. So you can think of messages as transactions in Ethereum, because messages kind of are the ones that are actually performing the state changes. So now that. So now if you've gotten a bit more comfortable with the SDKs, just exploring around the documentation in, in exploring each of the different modules and each of their functions, as well as creating different types of transactions such as message delegate, message undelegate, and playing with other things other than message send and message swap. Now we can progress to this smart contract section. So smart contracts are powered by CosmWASM, which is led by the Confio team. And I'm going to include a video after this where they explain more about the system they've created. But what they've been able to do is create a system where you can execute WASM smart contracts or Webassembly smart contracts on the Terra blockchain. So what makes WASM or Webassembly an ideal execution environment for smart contracts is that it is designed to be a portable compilation target with small binaries, small dependencies, and works at a sufficiently low level to be, and is designed to be portable, safe, which are all the things that we want in a smart contract execution environment. The other thing is that the way that cosmosm has designed Smart contracts is that they have potential to be multi chain smart contracts. So in one sense of the, in one sense of multi chain, you can almost like write one contract and then deploy on multiple chains. And in another sense, once IBC rolls out, Contracts will be able to call other contracts on other chains through ibc. So currently we only support Rust for writing smart contracts. But. But the Cosmo WASM team has expressed the possibility of porting the libraries that they've created to other things such as assembly script and tiny Go. So the scope of possible languages to cover Cosmos smart contracts is potentially much larger. But right now the only sort of language runtime for which mature tooling exists is Rust. So unfortunately we'll have to use that. But I don't think that it will be. It will hinder too many people from using CosmosM because the amount of rust you need to know is actually quite minimal. You just need to be familiar with the simple borrowing. And because smart contract logic isn't supposed to be too complicated, if you can implement your contract with a bunch of read and writes and managing balances, doing a bit of arithmetic, you should be good. So I'm just going to go over the smart contract architecture, what you need to write order to write a smart contract. So a smart contract revolves around three entry points defined as functions in your in your Rust code. So the first is the constructor which sets the initial state of your smart contract and this is sent in a message instantiate contract. The second one is a hand handle method which will implement the different functions of your contract. So for instance, if I had an ERC20 token, the handle method should be able to receive different requests on or different functions through the handle message and implement things like burn, transfer, approve, etc. And finally you have to define a querier which tells the contract how to get data and interpret it back into a form that users can understand. So this is just the workflow of how a contract writer creates a contract on the Terra blockchain. So a contract writer will write his program first in Rust and then compile it into a WASM binary that he will include in a message store code. Once he has this message store code, he will send it to the blockchain and the WASM module will sort of will sort of store the code on the blockchain. So here Cosm WASM has decided to learn from Ethereum and realized that they should decouple the storing of a blockchain of a smart contracts code and the actual instantiation of a contract. For example, there can be many contracts that use the same code, such as one ERC token code ERC20 token code being used by multiple ERC20 implementations. So here we see the same code being used in two different contracts by contract creator A and contract creator B, each with their own INIT message which customizes the contract. And then the module assigns a different contract address to each contract that has been created, as well as contract's own private state. So here's an example of how you can use Jigu to upload code to the Terra blockchain using using these messages. So as before, what we want to do is create a message, put it in a transaction, sign the transaction, and then broadcast it. It's a very simple process, so I'm just going to walk through. First you're going to load the contract file and then encode it into base 64. Next you'll create the message like before and then you'll broadcast the transaction. And at the end you'll get the code ID which is in the in the blockchain events where. And that is just the code ID of the code that you uploaded. But no contract has yet been created. Next we'll go over how to instantiate a contract. So remember that we have saved the code ID from the uploading the contract before. Now we want to instantiate a contract and then we're getting a contract address back. So here I am creating a message using the code ID I had that was returned to me from the last execution. And you'll realize that the INIT message that your contract understands is actually a message in JSON that gets automatically parsed by your contract into the right configuration. Here I've decided to name my token William coin with the symbol W I L L. And you can see that you can also put an initial amount of coins to fund the contract. So I'll just broadcast the transaction and get the contract address, and this should create my contract. So now my contract will exist at a normal Terra address. So this is just simplified flow of how a contract gets executed. So the contract user will define the function that he wants to call on the contract, such as transfer or burn, and put that in a message called a message Execute contract. And then he'll sign and broadcast the message Execute contract, which will get handled by the WASM module and load the contract code with the handle message specifying the arguments to pass to the contract's handle function. Next, the contract will be able to access the state and commit more state. And finally, when the contract finishes execution, the contract can Affect the rest of the blockchain by producing by like, by emitting its own messages like Message swap, messagesend and message delegate. So here's an example of executing a contract. So we'll create a message and we'll use the contract address that we got and you'll notice that the message or the handle message is JSON. So here we're trying to use the transfer method of the contract with 5,000 as the amount and a random account as the recipient. And there is also an ability to add coins to the contract with your contract call, which will be required for some contracts such as like a vending machine type contract where you have to deposit some Luna to effect an execution. And the contract can actually pull which types of coins have been sent sent to it and see if the fee paid is enough. So we'll just broadcast the transaction and that should execute the contract. So it's that simple. So finally, how do we get data actually out of the contract? So since for my last example I transferred some coins from one account to another, the one thing I want to be interested in is perhaps the balance. So I need to create something called the query message that the query function on the contract will understand. So the query message is JSON, like the INIT message and handle message and there's no transaction needed, just query the WASM module and the output is JSON. So as you can see, the Terra integration for smart contracts is very simple and just adds three messages and a querying mechanism to the Terra blockchain. But this allows users to commit arbitrary code to the blockchain and finally allows third party developers to add their own logic rather than depend on Terra's native modules. So I'm just going to talk about the developer tools that we're working on that we'll be seeing in the next couple months. So the first is Local Terra. Local Terra is a one click blockchain and ecosystem tool for Terra. So what it does is it spins up LCD node, which is a Terra node rest API server. It spins up fcd, which is a block indexer, which is the backbone for Station, which is a wallet and Finder, which is a blockchain explorer. And it gives you a way to quickly control and inspect the world state, which makes it easy to speed up smart smart contract development and testing. Next we're going to create an easy way to set up the general boilerplate for writing a DAPP front end. So we want to make it as easy as creating a new React app with Yarn Create Teradap and this is going to allow people to quickly get set up with a usable front end to use with their smart contract. This will lower the barrier to entry by getting you set up quickly with Terra blockchain. And finally, we're planning to release a Chrome extension version of Station which will bring the Metamask or Myether Wallet experience to Terra and allow you to allow users to directly interact with smart contracts from within a website. So that mainly covers how you can get started with smart contracts. And you can get started today with the smart contract documentation on the Terra official documentation available at Docs Terra Money. Right now I'm going to pass it over to Ethan Frey of Cosmo and he's going to explain more about the mechanism that allows Terra to run smart contracts. Thank you.
Hello, my name is Ethan Fry and I'm the co founder and CEO of CosmosM. Today I'll explain what CosmosM is and why it might be interesting to you in your project. First of all, what is CosmosM? Cosmos is a multi chain smart smart contracting solution. That means we are not a blockchain. Rather we are a module that can be embedded in many different blockchains and is currently many different blockchains. That is a very powerful point. I'll break it down in a few ways. What it means currently is if you are a developer, you can write contracts that run not just in one chain, but many different chains and leverage the same contract and same knowledge many places as a blockchain and you want to add smart contracting capabilities. You can embed CosmosM into your blockchain and that allows you to access existing contracts in dev community from many different blockchains. So we don't have to lock each one and learn a new language for each blockchain. We can have one that is generally extensible. We also have deep Cosmos SDK integration. Currently the only platform that we are integrated with is Cosmos SDK. We would like to extend that in the future once we hit more stability like our 1, 0 release. But that allows There are dozens of different projects currently building on the Cosmos SDK. Most of them have lots of different modules written in native code go code to add custom functionality. And this allows us to have contracts that don't just run side by side, but actually call into those native contracts this native code and allow the native code to call into the contracts. So we allow deep integration into the runtime that can be customized for every different blockchain. We have a security first design when designing Cosmos and we didn't start with what's the easiest way of making something. Let's copy solidity. We said, how do you make a secure platform? Typically we see Solidity is really easy to get started writing a contract, but pretty hard to secure one. There's a huge rage for bugs in there and audits and a huge community there. And that seemed very dangerous. So he said we can raise the bar for writing a contract, make it a little harder to write a basic contract, but lower the difficulty of writing a secure contract. And this space here is a space of actually functional but insecure contracts. So we're trying to lose that space and say there's not much space for that. There are some issues which you can document, but you try to limit the number of issues that you can bite you when designing smart contracts. And we are now refining the user experience, make it easier and easier to write contracts on that system. We are based on the Webassembly virtual machine. We do not write our own virtual machine. We are using Webassembly. Webassembly is available in all browsers, but also there are quite a few native runtime solutions that run it. One is Wasmer, but there's Wasm Time and cranelift and there are quite a few other out there that run as binaries multi platform systems. We are using that virtual machine. It's a well defined virtual machine. There are many implementations that run run it run code from the virtual machine and optimize it compilers and there are many different mature languages you compile down to it. So we don't need to reinvent the wheel. We can choose one of the virtual machine implementations to use and we can choose various languages they compile down to it. We currently focus on Rust and we're looking at more. There are probably six to eight languages compile well to Webassembly and another dozen or so that are working on that support. And we're currently live on testnets from five projects. So this is not a theoretical idea. This actually does have users. The history of cosmosm where did this come from? So first of all, my name is Ethan Fry. I was a third developer, Cosmos, if you've heard of them, they're probably top 20 chain now somewhere. And yeah, I got inspired by them with a tendermint. I started working Tendermint and then got involved with them. I came in there because I had been working a lot of backend web design and wanted in the blockchain. I was frustrated with the tooling on Ethereum for example, and solidity 16 and wanted to say I want to have Secure development. I wanted easy development on blockchains, and it was amazing what they were offering. With Tendermint, you just worry about the app logic and not all of the rest of the blockchain. And it was written in go, which is a language I knew and had good tooling. So I started, actually built the first cosmos SDK in 2017. I worked in the IBC white paper then, and I'm really committed to the Cosmos ecosystem. So I've worked. I've left Cosmos and worked on other projects around them, building on the same technology. And at the Cosmos hackadem in Berlin 2019. Really nice, cool team. So we ended up with Aaron from Region Network, Jehan from Altea, Shane from Trustory, and Pedro from WalletConnect. And we also had around like five leads of projects. We made a little team, we said, let's build something, and ideas went out there. And one of the ideas that just stuck, we were sitting around there. It was just starting Saturday and Friday evening, we're sitting around the table drinking and chatting ideas. And it came out. Let's build a smart contract engine, Webassembly. You know, there's tooling around it now. Everyone's doing this thing. Can we build a webassembly smart contracting platform and integrate it into SDK in two days? And, well, the later at night it got, the cooler the idea seemed because, well, seemed like a stretch goal, but an awesome project. So we tried it and we basically banged up code for two days. Very, very little sleep. I'm very, very thankful to Yehan, who was a rust expert. I was just learning it while coding and I brought a lot of the Go Kyle in there. So we were working on the go side, rust side. We integrated it, learned from each other, and got a working prototype in two days. And Pedro threw a UI in it so he could actually view the contracts. So that's pretty amazing stuff to get done in two days. So we got there, presented it, people were impressed, and we got a grant to follow up from the Intergene Foundation. And I worked part time on that alone, basically from September 2019 to January 2020, and got a 06 release, which is basically stable. It was usable in gas metering. Yeah, you had the basic functionality to write contracts. It didn't have deep native integration, but you can move tokens around and it was actually pretty cool. And people started using it. I got docs out there, people started building on this. They're very interested. And since then we've built out. We've got another grant and and we've gotten some contracts and built up partnerships with people. They're building on it to get to the five different projects, building on it actively and many more interested. So we have a small team now, we have five people working on this to bring it to really production ready and we've added quite a lot of features that people have requested and we run currently on a few incentivized testnets and this is getting very, very close to mainnet ready. So we are currently planning a 1.0 release around August. This will be stable, Forge compatible. We provide if you write contracts on 1 0, we will provide upgrades for the module, we will allow those 10 contracts to run on a 2.0chain, etc. So this is really something that can run a mainnet. We have an audit at this one point, bug bounties on it and we'll start building out developer tooling around it because you have a stable framework to build on. Currently we support Rust and both the runtime and contracts are written in Rust and we are working currently on prototyping GO via Tiny Go and assembly script contracting languages and they're waiting on the stable APIs and we have some first experiments on them. We're also working on a front end framework to build DAPPS that wraps it called Cosmjs which is similar to Web3 in goals. It's different design but similar to goals. They can Quickly add a JavaScript front end that will talk to your Cosmos contracts and on that we can start building that are done. We have UX tools, deploy tools, debug tools, analytics tools because we have a stable API and guarantees that there's a clear path to port it in the future. Your 1.0code should work on 1.1 and 1.2 and we should have a clear path to port it to zero. So this is the point. We can really start building a large community of people building lots of tooling around us. So we're really excited to get more people using it. And it's really going from early adopters to, you know, from pioneers to early adopters. So it's usable now, not just on experimentation, but really going to be usable for building production software. And we look forward to building custom solutions, helping people build contracts and integrating with their custom chains. So really we have capacity to help people build the solutions they need. So we are looking to onboard more developers and more projects onto the system principally. So if you want to have CosmosM on your chain, talk to us. And if you want to learn how to CosmosM contracts and run your Contracts on lots of different chains. Yeah, great time to learn it. After that. Our next stop is IBC support. IBC is inter blockchain communication. It's Cosmos flagship design. It was written in the 2016 white paper way ahead of its time. I worked on refining a very clear technical spec in 2017. Chris Goes has gone 2019 a very very much more extensible spec. It's basically TCP IP of blockchains, SSL on top, TSL and everything on there. It allows super secure ways of proving with light clients on both sides. You can send packaging blockchains. It's asynchronous message passing with receipts guarantee delivery in order timeouts, all of it on the protocol level guaranteed. And you can start building distributed systems on top of that. So you can make API calls between blockchains. Your contract writes something and you guarantee it will read it or get an error message passed back within certain bounds. So that allows you not to trust an Oracle or special privileged relayer. But really it's really powerful. So you can start building multi chain solutions that you can have contract and chain A and chain B communicating with each other. So you can have your DAO or this chain controlling sending money here and controlling your assets and decks another chain. You can move your tokens over here, you can trade them, you can stake them for staking derivatives, you can send them back over here as you want. And that all can control a logic on multiple chains. This is coming out in Cosmos. Stargate should be later this year and we will have a 2,0 release built on Stargate that supports that and that allows we will allow not just the chains, the native code, but smart contracts to send messages to contracts in any other chain. Currently only supports Koswa's SDK. Many other BFT consensus engines with proof of finality can be adapted support light clients and IBC. That includes Polkadot's Grandpa Avalanche from AVA Labs and Near Protocols 1. Those all been are theoretically compatible with IPC because they provide infant finality and they can provely say this block is in the chain or not rather than probabilistic proof of work finality. So this allows a truly multi chain solution. Once that's implemented, not only will you be able to run the same contract on multiple different chains, but these contracts will be able to run over the chains. So you can have some options contract running on the Dex chain which actually has native code. Run a dex really high quality and you can have a DAO chain that has maybe things here and maybe you have a ZK snark chain that has a bunch of primitives for running zero knowledge proofs and you can pass over to the Mixnet and you can actually customize stuff. And these contracts, not just you as external user, these contracts can then move stuff around there and control that with their own logic on chain that I think opens a huge door design. And by allowing not just native code but smart contracts to do that on both sides, smart contracts and communicate on both sides, we allow a huge space for rapid development in this area, which I think is really the new frontier of blockchain interoperability. So we look forward to seeing that end of this year, early next year. And we are waiting for Cosmos Stargate to finish and we are following their development with our IBC development. So I think this could be a really huge shift. So if you get in now on Cosmos and building your contracts that run on many chains in, you know, half a year or so, you'll be able to have those contracts actually talk to multiple chains, one contract. So I'm switching gears now, now that you're. So if you're techie, this is where it's focusing tech heavy. If you just wondered what it is and how it's used for your project. Well, we covered that. So digging the tech here. How does cosmosm work? We use Wasmio to run the bytecode. It's a Rust project. It's pretty solid thing. A lot of other people running it in your protocol, for example, and we pre compile it. Does it pre compiles webassembly to sandbox native code? It has different back ends. We're using single pass, which is a very quick compiler, has no real attack surface and it makes a bit slower code. It runs about 20 times slower than native Rust code. You could use an LLVM compiler. It takes that WASM compiles a really, really optimized native code and actually runs about half the speed of native Rust code. So your WASM can basically run more or less native code and full crypt on it. The problem with that one is it takes a while to compile. So the compiling step could be a tact surface. So we're looking at doing some permissioned control of uploading it permissionless with single pass. And if you need the extra performance boost, we can have a permission step that has some people validate this. Okay. Before compiling it down to llvm because otherwise you can kind of slow down the blockchain considerably by running bad or malicious wasm that can just slow down the compiler a lot. But yeah, so we are. It does that as lots of different functionality here. And it runs native code that's completely sandboxed. There's no access to syscalls. It is metered with gas, it injects gas metering involved in it. And all CPU usage is metered and is isolated memory space. It records its own memory, it has metered CPU usage and it can touch nothing in the system. The only thing it can touch is imports. We provide some imports there and we can then write defensive code to guarantee these imports are safe. That's our virtual machine layer which wraps around wasmr. So we have cosmosm vm which wraps around Wasmer that provides our custom imports. We provide read and write access to a subset of blockchain space. We provide like a sub key under the prefix under the blockchain Merkle tree. And in that prefix it can read and write and nothing else. And we can limit how much it can read and write to that space. It can query other modules, read only in a very specific API to other native modules and contracts. And we can add more blockchain specific APIs which are also called precompiles. This will call out into the blockchain itself to do some stateless logic. Currently we have address formatting because we support multiple chains. There are different native address formats, so we can't compile that in a blockchain. We have to say, well convert a string address to a binary address is blockchain specific. So we call out to the blockchain itself to do that. We could add things like, you know, signature verification, like Ethereum does pre compiles. Other stuff could go in there and we can meter everything with gas. We allow no network access, no non determinism and no jailbreaking. We also disallow any float operations which are theoretically non deterministic. There's no random access here obviously, because no syscalls and we don't. So we basically guarantee cannot break consensus state, they will act deterministically. We don't allow multithreaded. There are few WASM arguments. We go through all the WASM opcode and if they use anything is not in our safe set of wasm, we reject the contract on upload memory versus storage. So while we have this, we make the difference explicit in solidity. They mix them together. Instance variables and state storage are transparent the user, which can be nice for development, but it's hard to reason about. In our model, the code has fast access to ram, negative speed. It has almost unlimited ram. You can allocate currently, unless you set another limit yourself. You can allocate 4 gigabytes of RAM contract. You can explicitly set that less 32 megabytes or 5 megabytes but you can get up to that much. You can't actually use that much because CPU limits, you cannot write 4 billion zeros in space in a CPU gas limit. But you can allocate as much as you need. So any memory you can write to, it just will give you that memory access. So great. Memory is cheap, CPU costs and writing storage and reading is very expensive. The price there is much, much higher. So we want to make that very explicit. You have to explicitly read and write to the database. So we have a simple interface that allows you to read and write typed data from the database. Great. But you have to explicitly do it. I think it's a critical difference from solidity. Also security. First we define security. So we looked over the list of of OpenZeppelin exposes the top 15, 20 security holes exploits that are known in Ethereum. And we went through that and made sure that we could patch all we could. Reentrancy is impossible to design. We use an actor model. I'll get to soon overflows and underflows. Rust will panic if you do that. We said it that way. Unexpected Ether is a bad design pattern. You have trivial bugs because you we can send tokens to contract delegate, call. We don't allow it. We have another way of doing those proxies of migrating code default visibilities. You have to explicitly set them. So we went through this whole list basically enclosed all we could by design. In particular, we used the actor model for dispatching messages. This negates all possible reentrancy attacks. So rather than your contract A calling the contract B and then conduct B calling A and contract A has not persisted all their data in state, some memory and some in database. And that gets all kinds of little subtle flaws in Ethereum kind of like limit the gas. This has it can't really call back into your contract. This is really bug prone. What we do simply is use the actor model. That means actor model. You get a message and you return messages. So your contract will process it and return the message. So if I want to call that when I say basically I do my work, I save my work and I return a message that we execute another contract. That means I do not get a result from it. That means I am done, have saved my work before it starts. All you get to know about is whether errored or not. We run all the messages you dispatch in the same transaction. If any of those contracts fail, then it will revert the entire transaction. All state changes get reverted. So I can basically say if an escrow happens I will optimistically update escrow got sent. I delete escrow and return a message to move the money. If that succeeds, great. If it fails, then it reverts the whole transaction and act like nothing ever happened. My deletes grow command is also deleted. That is usually the error handling you want. It's only when you have here you can do complex logic to try to get other use cases there. It is kind of possible. Returning messages back is possible. It's not. It's a trickier and we'll demonstrate that. But basically the standard use case of just assume it works and if it errors or rollback everything is the only one you get by default. Unless you really try to do something else. There's no reinterrency possibility. And you don't forget to check the return value of ascend. It might return a 0 or false if it worked. Don't worry about it, just always check that. Like you said, we have built in overflow checks. We have explicit API for query and handle methods. So you have to explicitly add those methods you want to be exposed. They don't just happen to be exposed. And yeah, everything's very explicit there. You have to call into stuff and make sure that there's no loops possible. And we use the Rust language. We ensure the Rust language has a lot of functionality to ensure contract safety. That means we take advantage of they have a lot of control of type safety, of memory usage, of mutability issues. And so often you compile code and it yells you a few times compiler and you realize hey, these are subtle bugs that I forgot to handle. I didn't handle this error case here. And so the compiler will give you warnings or errors on many, many possible cases. And by utilizing that you can avoid large causes of bugs because the compiler checks your logic quite a bit. Whereas our framework doesn't allow these larger design issues to happen. Rust also provides first class test tooling. They have quick check, they have fuzzing. You can do very, very complex testing with Rust as unit tests on the Rust code before you compile to wasm, which allows you to get very, very high levels of reliability and security on your code. You don't have to upload code to virtual machine and run it. You can actually run it as Rust natively link stuff. And then when you've tested that heavily unit test, you Then compile it and run high level integration tests on it, seeing how it works in reality with a real thing. But you don't, you can get much lower ones, give you full stack, trace exactly what failed and it's really, really nice compared to try to debug solidity for example. So yeah, contracts and native code is love. We are not trying to make a general purpose smart contracting platform. There are many other ones that are doing that very well. For example, Neoprotocol is just allowing me to write smart contracts on their platform and they did an amazing job doing that. Also using WASM and also using WASMR background. However, it's just contracts and for some people that's amazing. Many other platforms however are currently building up native code. They are building a blockchain with custom native functionality that may need privileged access to various things. Might need privileged things. You don't want exposed to generic contracts, right? They control the valor set with their staking algorithms. They want to have very optimized cryptography using native code. They want to have that native code. So we allow the integration between contracts and native code. And I think that's what really differentiates us from any other projects, which are awesome projects, but we are going for a different route. We are basically not generic smart contracting platform. We are one that ties deeply to native code. So you can currently call into the bank, which is coin transfers and staking modules in Cosmos SDK and other contracts, but you can easily extend that. So for example, on Terra they wrote a swap, more of a trading swap Dex thing and Oracle modules for exchange rates in go native code. And they wanted to add smart contracting capability on top of it. So we allowed that. We worked with them to add extensibility. They can now expose an API and don't have to recompile a Rust code or anything. They expose it in their blockchain. The API they want to expose and is passed down into our contracts. A contract, a generic contract can run on their platform with no modifications. And a contract can import a crate to add their extra custom types. And it will then mark a feature flag that needs Terra and that contract then has access to their swap and Oracle modules, certain queries and messages, and it can call into that native code very nicely, transparently, just as easy as it calls into the staking module. However, that module isn't flagged with the TerraFlight, which means if you try to upload that Terra specific contract to another blockchain like Enigma, it will reject it because it requires the Oracle and swap contracts. So we Allow you to flexibly do this. So you can have very generic contracts that rely on none of these extra pieces which can run any code. And you can have custom contracts that are really chain specific, that make use of all the native APIs of one chain and really chain specific. But all that learnings you've had for tooling for dev environment is the same setup you have. You just have no new API call extended for this chain. So we allow these contracts to run in one chain or or multiple chains and the more you customize it, it's great. But all that knowledge you have, all that learning you have as developers can be ported to other chains. So if you learn how to write Terra Civic contracts, that's wonderful. And now if you want to write contracts for another chain, just if you don't use the Swap and Oracle modules, that contract works everywhere else you can write your, you know, ERC20 modules, your NFTs, you can write your other stuff out there all you want, your daos. As long as you're not relying on those modules, the same tooling you've learned will work anywhere. So to really opt in to native code. And now I hope you've enjoyed this and I'd love you if you're interested in CosmosM, you think it's cool for your project, if you want to embed it into your blockchain, if you want to start developing on it, that's wonderful. You can learn more about us cosmosm.com also links to our documentation and gives you a little overview. And links to our Twitter account and our Medium account are various other things. Find us on Twitter, please follow us there for Latest news on GitHub you can find CosmosM CosmosMI entry point and we have a number of other repos as well. And on Vimeo you can look for CosmosM to find a list of our community calls. We have a bi weekly community calls which are recorded and you can see our updates. So we get a half hour to an hour discussion of our current updates and roadmaps. If you like to watch videos and follow our current progress, it's a very nice way of keeping your eye on it every two weeks. And finally we will be involved at the hackathon. So we are working with Terra on the hackathon in the next few days. So please join that. I'll be doing a workshop on that one and there's a lot of resources that Terra has also assembled on how to onboard. So come please join that. Write your first contract, learn how to use the Terra decks with Smart contracts and write plasma smart contracts in general. We've read a lot of stuff so I'd be very happy to see you there and get your hands dirty as developers using it. If you are wanting to, you can also join a telegram channel. We have discord channels that's all linked from our website. If you are a zone that is interested in building it, reach out to me. My name is ethan@confiotech or ethanosmosom.com you can reach out to me and I'm also curious after 10 we're curious about integrating with other blockchains besides the 5 or 6 we are currently working on. Thank you very much for your time. I hope you enjoyed this talk and look forward to seeing. Thank you William and Ethan for the deep dive. It was great having you. For those of you that are just joining us now, if you have any questions during the talks, please feel free to ask them in chat. Our speakers will answer them accordingly. For our Next talk, Connor McEwen, who is the mobile team lead at Celo, and Josh Kreitz, partner and product lead at Celo, will be giving a workshop called A Global Mobile How Celo Works. This will be a deep dive into the Celo platform and their newly released Wallet. Ballora, Connor and Josh, the stage is all yours.
So I'll start with kind of our onboarding flow. Now, I'm not sure if anyone else remembers this, but I remember when I first started using Venmo and got invited to it. I was actively recruiting my friends to start using it and I would send them some money and say, hey, when we're at dinner and I'm not going to put my credit card down, I'm going to send you $20 on this app and you got to install it because it'll make your life way better. Unfortunately, with existing cryptocurrencies, there's no real way to do that. Right, because you can't send someone money without knowing their address. What's great about our lightweight identity protocol is that it solves that problem and I'll tell you how right here. So if you're inviting someone to the Celo network, what you'll first do is generate a new private key and transfer a little bit of money on it. This money is enough to verify. And so then you'll text that private key to whichever person you're trying to invite to the network. So that person will take the small amount of money on the invitation. Private key. They'll generate a new private key in their app, transfer that money and then use that small amount of money to pay for verification. So then they have a new verified account. And the last piece is that when you initially wanted to send someone money, you can actually escrow a larger sum of money with their phone number and that private key that you sent. So only after verifying their phone number are they able to withdraw money. So if I wanted to pay you back $20 for dinner, I'd transfer a little bit to that private key. I would escrow the rest of the $20, and then only after verifying would you have access to that $20. We think this is a much more secure experience than sending private keys around, but also provides really great usability and the ability to invite new users to the network. As I mentioned before, if you're curious, we'd love for you to take a look at our escrow contracts so you can understand a little bit more about how it works. There are a few other features that I love to talk about too in Velora. One of them is key storage. We believe that while it should be non custodial, there should be no central entity that holds a user's funds unless they want to. And so we designed Velora such that users are the only people who have access to their private key and funds. This is an important thing to worry about though, right? Because obviously we want people to keep their key safe and we don't want anyone to be able to take a user's money. And so what we've done is encrypt the private key using both a client side generated pepper that's random as well as a pin, so that even if someone is able to get a file system access to the mobile wallet, they will not be able to unlock the phone to send funds anywhere. We also spent a while trying to make sure that we educate users about how to custody their account key, as we call our backup phrase, that you might have heard as well, because that's really important in order to be able to keep access to your funds in case you lose your phone or anything like that. Another feature that we built because of our experiences out in the field is Data Saver. So even though we have made the Light client as light as possible in terms of syncing block headers, in some cases the latency and the network conditions are just so bad that it's impossible for a user to use a Light node, in that case, we enable people to still keep their keys on their device, but use a hosted full node in order to communicate with the network. This we found gives people who otherwise wouldn't be able to access the system the ability to access it. And then the last piece, as I mentioned is you might have heard me talk about cpdodo and the stability protocol. Well, we make it really easy for Velour users to exchange between Celo dollars and Celo to participate in the stability protocol in the app. And that's again using that contract kit that I mentioned before to make it really simple to interact with the contracts. A couple lessons learned from spending some time building this mobile wallet. I think the first one is, as I mentioned, full stack is really hard. Many layers means that there's many places for errors, and especially in the early days when we were developing the protocol quickly, it was difficult to keep a stable environment to keep up with changes, and to make sure that we could deliver that wallet experience that we wanted to. However, I think that trade off, as I mentioned, is really worth it because we can develop a product experience that's really compelling. There's no oh, we're dependent on this thing that we don't control, or we have to wait for longer blocks, or it just gives us the ability to iterate quickly and to work on a product experience we're proud of. The second piece is that good async handling is your friend. As I'm sure folks who have developed a blockchain before, things might take a little bit longer than you're used to, and it's really important to have good asynchronous.










