Kick off an initial compilation right now so that the code has time to compile while we get oriented.
To compile the entire project run cargo build.
While, that compiles, let's have a look around.
In the node directory, there is a nearly-unmodified copy of the Substrate node template.
We will use this standard Substrate client to run our node when we are interested in doing so.
Our work will begin in the tuxedo-template-runtime directory.
This folder has only a single file,lib.rs, so take a look.
If you have ever seen a FRAME runtime, a lot of the contents will be familiar.
Let's skim this entire file to get a sense of its structure.
We import items from Substrate, Tuxedo Core, and two Tuxedo pieces (Money and Runtime Upgrade).
The Opaque module houses definitions of types that will be used on the client side.
This includes a few consensus keys types as well as our OpaqueBlock type which is based on Substrates OpaqueExtrinsic type.
The idea behind opaque types is that they are all basically Vec<u8> under the hood.
This allows the client side to just see them as bytes and have no understanding of their structure or meaning.
Only when these types enter the runtime will they be decoded into Rust types.
All Runtimes must provide an implementation of Substrate's RuntimeVersion. This looks nearly identical to a FRAME runtime.
Each runtime needs to provide an implementation of BuildStorage to allow a chain to begin with some initial, or "genesis" state.
This runtime begins with two coins in its storage. One is owned by a private key, and the other by a multisignature. We will be able to mint our own tokens when working with the chain, so we don't need to worry much about the genesis tokens.
Next we encounter several type aliases including, Transaction, Header, Block, Executive, and Output.
Each of these aliases takes a generic type from either Substrate or Tuxedo core, and fills in the generics to provide fully-concrete runtime-specific types.
Next we see the OuterVerifier enum.
Every Tuxedo runtime will have one of these Verifiers and it is required to implement the Verifier trait.
This enum is an amalgamation of several other individual verifiers. In this case, we use the three that come standard with Tuxedo:
UpForGrabs- Allows anyone to spend a UTXO.SigCheck- Allows a UTXO to be spent with a signature from the proper key. This is the most common and represents simple private ownership.ThresholdMultiSignature- Allows a UTXO to be spent when enough members have signed.
Tuxedo developers can extend this enum by writing their own implementations of the Verifier trait.
However, we will not need to extend this while writing our dex.
The next section of the runtime is typically piece configurations. Currently our runtime is sufficiently simple that neither of our two pieces need any configuration. We will need to add a configuration for our dex later on, and you can see a comment showing where that will happen.
The OuterConstraintChecker enum is also an amalgamation enum that implements the ConstraintChecker trait.
That means that each of its variants represents a separate constraint checker.
This enum represents all of the different transaction types in the runtime. This template runtime includes two pieces currently. The first is a fungible token (token id 1) provided by the Money Piece. Second is the ability to perform wasm runtime upgrades using Substrate's forkless upgrade mechanism. These pieces are included because nearly all runtimes will need them. As a runtime developer, you can remove either of these pieces, or add more from the wardrobe or that you have written yourself.
We will add to it this enum several times throughout the tutorial.
Next we declare the Runtime struct.
And on it we implement a few consensus-related helper functions.
If you find that you need a helper function in the runtime, you can consider implementing it on the Runtime struct.
Finally, we see Substrate's runtime APIs implemented. Implementing these api traits is what makes this program useable as a Substrate runtime. In this sense they are the most important part.
However, most of the functions implementations are short and call into the appropriate helper in Tuxedo core. So in this sense, they are least interesting and will rarely need to be modified.
This brings us to the last of the directories: the dex directory.
In this tutorial we will write a new Tuxedo piece that represents an order book dex.
It's code will live in this dex directory, and we will spend most of our time there.