Getting Started with Parity Substrate

Substrate logo — © Parity Technologies

Parity Substrate is a blockchain development framework with many cool features like upgradable blockchains, modular architecture, customizable block execution logic, and hot-swappable consensus. For an overview of the Substrate framework, watch this talk from Dr. Gavin Wood (Web3 Summit, October 2018).

This article is about how you can get started with the Substrate framework to build your own blockchain. Let’s jump right in.


The first step towards getting started with Substrate is setting up your development environment. The Substrate team has created a bash script which installs all the dependencies and compiles the relevant packages as part of installing the Substrate framework.

Run the following command in your terminal, and it will set up your machine ready to hack on Substrate.

curl -sSf | bash

The command takes a few minutes to complete (depending on your hardware) as it also compiles all the Rust packages needed for the Substrate framework.

There is a faster option also available, but it installs only the dependencies and does not compile the Substrate packages. To use this option, run the following command.

curl -sSf | bash -s -- --fast

Note: In the faster option you will not have the Substrate CLI installed globally in your system.

Substrate Node Template

Once the install script finishes execution, along with the dependencies, you will also have a couple of commands installed on your machine.

One of these commands is the substrate-node-new command which helps you set up a template node. Think of this as a project scaffolding template. The command downloads a Rust code base and compiles it. This codebase packages together all the bootstrapping code needed to set up a Substrate runtime.

You can get the node template by cloning the following repository:

The Substrate Node Template has the following directory structure.

substrate-node-template directory structure

The runtime sub-directory houses the blockchain runtime related logic. The runtime can be called the business logic for your blockchain. It is further divided into runtime modules and each module packages together its own state (storage) and behavior (logic). The runtime directory contains files for the runtime modules.

The src directory contains the low-level code which brings together all the components of the Substrate framework for execution of the runtime.

The scripts directory contains a script which allows us to build the Substrate runtime for the Wasm (Web Assembly) environment.

Building and Running the Substrate Node Template

After cloning the node template, run the follwing command to compile it.

cargo build --release

Once the above command finishes execution, it would have compiled the source code of the node template (takes a few mins). At this moment, you can start the node, and it will begin producing blocks. To start the Substrate node, run the following command, in the context of the node-template directory. The following command will start a Substrate node based on the node-template using the dev configuration. In essence, it is running the executable generated by the compilation of the node-template codebase.

./target/release/substrate-demo --dev

The command will produce output similar to the following.

2019-04-08 17:28:31 Substrate Node  
2019-04-08 17:28:31   version 1.0.0-x86_64-linux-gnu  
2019-04-08 17:28:31   by demoauthor, 2017, 2018  
2019-04-08 17:28:31 Chain specification: Development  
2019-04-08 17:28:31 Node name: adorable-wind-3578  
2019-04-08 17:28:31 Roles: AUTHORITY  
2019-04-08 17:28:31 Initializing Genesis block/state (state: 0x4397…ab51, header-hash: 0x0353…30ef)  
2019-04-08 17:28:31 Loaded block-time = 10 seconds from genesis on first-launch  
2019-04-08 17:28:31 Best block: #0  
2019-04-08 17:28:31 Local node address is: /ip4/  
2019-04-08 17:28:31 Listening for new connections on  
2019-04-08 17:28:31 Using authority key 5FA9nQDVg267DEd8m1ZypXLBnvN7SFxYwV7ndqSYGiN9TmTd  
2019-04-08 17:28:40 Starting consensus session on top of parent 0x03534673f220e0514d5324acd179438094e05f4c2419f33226c42e33f5cf30ef  
2019-04-08 17:28:40 Prepared block for proposing at 1 [hash: 0xdc6de1c9b04607fe51bf4abed8cfdbd6313a74e9eeda78e3db4f6d2b60e69903; parent_hash: 0x0353…30ef; extrinsics: [0x0421…0149]]  
2019-04-08 17:28:40 Pre-sealed block for proposal at 1. Hash now 0x1e5375649660d9e8b8e41fde74c861185a1e55153285e4332111dd0aa240684a, previously 0xdc6de1c9b04607fe51bf4abed8cfdbd6313a74e9eeda78e3db4f6d2b60e69903.  
2019-04-08 17:28:40 Imported #1 (0x1e53…684a)

As you can see, the node has started producing blocks.

Building a Substrate Runtime Module

Now that we are all set up with Substrate and our template node is working as expected, let’s build some custom logic for our blockchain.

The business logic for the blockchain resides in the runtime modules. A collection of runtime modules constitutes a runtime.

Let’s say we want to build a simple blockchain runtime for a token transfer functionality. To implement this, we would be needing the following:


  • Total Supply of the token
  • Accounts and Balances mapping


  • Initialization of the token (total supply allocated to the owner account)
  • Transfer of token between accounts

As mentioned before, a Substrate runtime module packages together its own state and behavior. We would be creating a custom runtime module with the storage items and functions.

In the node-template directory, inside the runtime/src directory you will find two files — and

The is the Rust crate root for the runtime. It imports all the necessary dependencies and types. It also initializes the runtime modules using some Rust macros part of the Substrate framework.

The is a template of a Substrate runtime module which is included in the node-template. It contains some dummy state and behavior (with a description in code comments) and is fully functional runtime module in itself.

To implement our token functionality described above, let’s make some changes to the file.

Declaring Storage

Firstly, let’s declare the storage items needed for the token functionality. In the decl_storage! macro call, let’s add the following two items for total supply and balances mapping of the token.

TotalSupply get(fn total_supply): u64 = 21000000;

BalanceOf get(fn balance_of): map hasher(blake2_256) T::AccountId => u64;

In the first line, we are adding a storage item TotalSupply to save the total number of the tokens. We are also setting a value to this storage item (21000000).

In the second line, we are creating another storage item as a StorageMap with a mapping between an AccountId and the token balance associated with it. We are calling this storage item BalanceOf.

The full storage declaration code for this module looks like the following. (Note: We’ve removed the dummy storage items which came with the template module.)

// storage for this runtime module  
decl_storage! {  
  trait Store for Module<T: Trait> as Template {  

    TotalSupply get(fn total_supply): u64 = 21000000;

    BalanceOf get(fn balance_of): map hasher(blake2_256) T::AccountId => u64;

Implementing the Runtime Logic

Now that we have the storage defined for our Substrate module let’s write some code to manipulate these storage items.

In Substrate modules, public dispatchable functions are defined using the decl_module! macro. We have two functions to implement the simple token transfer functionality in our module. These are the initialization of the token and the transfer function.

In the following snippet, these two dispatchable functions — init and transfer are defined in the decl_module! macro.

decl_module! {  
  pub struct Module<T: Trait> for enum Call where origin: T::Origin {

      // initialize the token  
      // transfers the total_supply amout to the caller  
      fn init(origin) -> DispatchResult {  
        let sender = ensure_signed(origin)?;  
        <BalanceOf<T>>::insert(sender, Self::total_supply());  

      // transfer tokens from one account to another  
      fn transfer(_origin, to: T::AccountId, value: u64) -> DispatchResult {  
        let sender = ensure_signed(_origin)?;  
        let sender_balance = Self::balance_of(sender.clone());  
        ensure!(sender_balance >= value, "Not enough balance.");

        let updated_from_balance =
        .ok_or("overflow in calculating balance")?;  

        let receiver_balance = Self::balance_of(to.clone());  
        let updated_to_balance = receiver_balance.checked_add(value)  
        .ok_or("overflow in calculating balance")?;  

        // reduce sender's balance  
        <BalanceOf<T>>::insert(sender, updated_from_balance);

        // increase receiver's balance  
        <BalanceOf<T>>::insert(to.clone(), updated_to_balance);  


Note how we are accessing the module’s storage withSelf::total_supply() and <BalanceOf<T>> to get and set values of these storage items.

Note: From a security perspective, these functions do need a bit more in terms of checks and validations. But to keep things simple, let’s skip them for now.

That’s it; we have now defined the state and behavior of our tiny blockchain runtime.

The full module code is available in the following GitHub gist. In this gist, we have removed most of the code that came with the file and have only included the storage items and functions needed for the token transfer functionality.

Compiling and Running the Node

Let’s now run the Substrate runtime we just created with the token transfer functions in the file. Similar to how we did it before, run the following commands in the context of the repository directory to first complie and then run the node.

cargo build --release

./target/release/substrate-demo --dev

The node should be up and running, producing blocks.

Connecting the Substrate node with a User Interface

Now that we have the Substrate node running with the token transfer runtime, let’s connect it with a UI to see it working.

The simplest way would be to use the Polkadot Apps Portal. It is a hosted web app primarily made for connecting to the Polkadot network nodes but it can also connect to a local Substrate node.

To try it with the Polkadot Apps UI, follow the following steps,

  • Once the local node is running, open the following in your browser,
  • Go to the settings page and select Local Node in the remote node/endpoint to connect to drop-down menu. Click Save .

The apps portal would be connected to your local Substrate node and if you go to the Explorer page, then it should show the blocks as they are produced. The following screenshot shows the Explorer view of the Polkadot Apps portal with a local node connected.

Calling the Dispatchable Functions from the UI

To initialize the token, call the init() function under the template section in the Extrinsics page of the Apps portal. See the following screenshot for reference.

As you can see, there is a pre-selected account Alice and it will be used to sign the function call when the Submit Transaction button is clicked.

When this transaction is finalized in a block, the account Alice will have all the 21000000 tokens as per the logic in the init() function in our module.

Querying Storage Values from the UI

After calling the init() function from the UI, the account Alice should have the updated token balance of 21000000. Let’s verify that by checking the storage values from the UI.

Recall from the previous section that we used a storage item called BalanceOf to store token balances against AccountIds. Let’s check what is the balance stored with Alice’s AccountId.

You can use the Chain state page of the portal to query storage items. Navigate to this page, select template from the first drop-down menu (list of modules) and then select balanceOf(AccountId): u64 from the next menu. From the AccountId menu, select Alice. Now click on the + button. It will show you the updated value for Alice’s token balance (as shown in the following screenshot).

That’s it. We have built a simple blockchain runtime and connected it to a UI in less than 20 mins.

Yes, it is really that easy to get started with the Substrate framework.

This was just a tiny demo for kind of a “hello world” tutorial purposes. You can further extend this runtime module by implementing more functions like approval, transfer_from, etc. (from the ERC20 interface).


Here are some resources to help you learn and build on Substrate.

  1. Substrate Official Documentation — The go-to place for developers building on Substrate.
  2. Substrate Collectibles Tutorial — An in-depth tutorial covering all the basic concepts in an interactive, hands-on way.
  3. Substrate TCR Guide — A set of tutorials covering how to build an end-to-end solution with Substrate (runtime, UI, unit tests, storage patterns, etc.)

Originally published at Hacker Noon on April 10, 2019.

Blockchain, Decentralization, Substrate, Parity, Web3
comments powered by Disqus