How to launch a private local substrate blockchain
Tags: blockchain, rust
Published: 2023-01-10 17:07:23

In this tutorial, you'll see how to launch your own private local blockchain with trusted participants. 

What you will learn:

- generate the keys required to authorize a node to participate in the network
- how to configure and share information about the network with other authorized accounts
- how to launch the network with an approved set of validators

Prerequisites:

- Install [Rust](https://www.rust-lang.org/tools/install)
- Clone the [substrate node template](https://github.com/substrate-developer-hub/substrate-node-template) repository

# Start basic nodes with default accounts (optional)
*If you are familiar with substrate and running nodes using default accounts like `alice`, you can skip to the next section.*

Start a local node using the `alice` account by running the following command:

```shell
./target/release/node-template \
--base-path /tmp/alice \
--chain local \
--alice \
--port 30333 \
--ws-port 9945 \
--rpc-port 9933 \
--node-key 0000000000000000000000000000000000000000000000000000000000000001 \
--telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
--validator
```

Start a second local node using the `bob` account to connect to the local network:

```shell
./target/release/node-template \
--base-path /tmp/bob \
--chain local \
--bob \
--port 30334 \
--ws-port 9946 \
--rpc-port 9934 \
--telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
--validator \
--bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp
```

The `--bootnodes` option specifies the following information:

- `ip4` indicates that the IP address for the node uses the IPv4 format
- `127.0.0.1` specifies the IP address for the running node
- `tcp` specifies TCP as the protocol used for peer-to-peer communication
- `30333` specifies the port number used for peer-to-peer communication
- `12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp` identifies the running node to communicate with for this network

You can validate that both nodes are now on the same network by:

- verifying the genesis block hash is the same for both node outputs
- the first local node discovered the second one

```
2023-01-09 17:21:08 discovered: 12D3KooWCzPnRRYHyVh2TQy2VaqmqxCkaFKGXhcscUhvJotrZsAE /ip4/10.0.0.144/tcp/30334    
2023-01-09 17:21:08 discovered: 12D3KooWCzPnRRYHyVh2TQy2VaqmqxCkaFKGXhcscUhvJotrZsAE /ip4/10.1.43.0/tcp/30334 
```

To purge local chain data, run the following command.

`./target/release/node-template purge-chain --base-path /tmp/bob --chain local -y`

*Note that the base path will be different depending on which account was used to start the local node.*
# Launching private network blockchain

## Adding trusted nodes

Adding trusted nodes to our network requires us to generate an account with keys for each node.
To generate a key using the `node-template`, run the following command.

`./target/debug/node-template key generate --scheme Sr25519 --password-interactive`

Once you input your password, you should have a similar output:

```
Secret phrase:       hen corn install jaguar spring pink neck squeeze account enough ahead bounce
  Network ID:        substrate
  Secret seed:       0xd4883e547610a9543e1f68db1100833f3f57586b0e7a70437c84cb558ecd7cbe
  Public key (hex):  0x42e88babfc903a7f3c12e576f52288144487f019ff9d2605df0f558c617a6909
  Account ID:        0x42e88babfc903a7f3c12e576f52288144487f019ff9d2605df0f558c617a6909
  Public key (SS58): 5DaS6dzomvqS3MpKcKgxz54GgEJje5Y11L1PHjyeMVniBrEM
  SS58 Address:      5DaS6dzomvqS3MpKcKgxz54GgEJje5Y11L1PHjyeMVniBrEM
```

Polkadot uses [sr25519](https://wiki.polkadot.network/docs/learn-cryptography#keypairs-and-signing) for its key derivation and signing algorithm. 
The `aura` consensus protocol (proof of authority) will use the `sr25519` public key `5DaS6dzomvqS3MpKcKgxz54GgEJje5Y11L1PHjyeMVniBrEM`

*Note: The Substrate node template uses a proof of authority consensus model also referred to as authority round or Aura consensus. The **Aura consensus protocol** limits block production to a rotating list of authorized accounts. The authorized accounts—authorities—create blocks in a round robin fashion and are generally considered to be trusted participants in the network.*

Since `grandpa` uses **Ed25519** as its key format, we will also derive the public key using the following command:

Use the secret phrase that was generated for you in the previous command.

`./target/debug/node-template key inspect --password-interactive --scheme Ed25519 "hen corn install jaguar spring pink neck squeeze account enough ahead bounce"`

Output: 
```
Secret phrase:       hen corn install jaguar spring pink neck squeeze account enough ahead bounce
  Network ID:        substrate
  Secret seed:       0xd4883e547610a9543e1f68db1100833f3f57586b0e7a70437c84cb558ecd7cbe
  Public key (hex):  0x128ea392292f8be6682543ee87e4b595e23c72015e848205f986e2d714fd68bf
  Account ID:        0x128ea392292f8be6682543ee87e4b595e23c72015e848205f986e2d714fd68bf
  Public key (SS58): 5CV36Gk8ckF66wjQCdZshY7wzJyZ84MZso6DmTJWYcriCzoG
  SS58 Address:      5CV36Gk8ckF66wjQCdZshY7wzJyZ84MZso6DmTJWYcriCzoG
```

We have now the `ed25519` public key `5CV36Gk8ckF66wjQCdZshY7wzJyZ84MZso6DmTJWYcriCzoG` from the output.

Make sure to save the output somewhere for later use from both commands.

*Repeat this process for each node we would like to add to our network.*

Now to trust these accounts as **validators** we need to create our [chain specification](https://docs.substrate.io/build/chain-spec/). Instead of creating one from scratch, we will modify the existing one.

Generate the chain specification using the following command:

`./target/debug/node-template build-spec --disable-default-bootnode --chain local > customSpec.json`

Let's open up our chain specification and add our nodes as trusted participants for the network.

We need to modify the `aura` configuration to have our `sr25519` keys to specify that these nodes are block producers.

```json
"aura": {
  "authorities": [
    "5DaS6dzomvqS3MpKcKgxz54GgEJje5Y11L1PHjyeMVniBrEM",
    "5E4pr85gYVTc6kk4fQTa9keXaPh3Gnj5y9MWHQ4FN5ubxUv4"
  ]
},
```

Now we need to modify the `grandpa` configuration to have our `ed25519` keys to specify that these nodes have the authority to finalize blocks.

```json
"grandpa": {
  "authorities": [
    ["5CV36Gk8ckF66wjQCdZshY7wzJyZ84MZso6DmTJWYcriCzoG", 1],
    ["5CCr8YMJercfhvFaQ2z9pS3r6Pyf48mx9XFbuvFDamkfG524", 1]
  ]
},
```

The second value `1` we precise for each node is the **vote weight**. Each validator in this example has a weight of 1 vote.

## Convert the chain specification to raw format

The raw chain specification includes the same information as the unconverted specification. However, the raw chain specification also contains encoded storage keys that the node uses to reference the data in its local storage. Distributing a raw chain specification ensures that each node stores the data using the proper storage keys.

`./target/debug/node-template build-spec --chain=customSpec.json --raw --disable-default-bootnode > customSpecRaw.json`

When creating a private blockchain network, only one person should be generating and sharing the raw chain specification file so all nodes are running using the same wasm.

## Preparing to launch the private network

To continue, verify the following:

- You have generated or collected the account keys for at least two authority nodes/accounts.
- You have updated your custom chain specification to include the keys for block production (aura) and block finalization (grandpa).
- You have converted your custom chain specification to raw format and distributed the raw chain specification to the nodes participating in the private network.

## Starting the first node

We need to begin by starting the first node otherwise known as the **bootnode**.

Start the first node using the custom raw chain specification we generated earlier:

```shell
./target/debug/node-template \
  --base-path /tmp/node01 \
  --chain ./customSpecRaw.json \
  --port 30333 \
  --ws-port 9945 \
  --rpc-port 9933 \
  --telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
  --validator \
  --rpc-methods Unsafe \
  --name MyNode01 \
  --password-interactive
```

Output:
```
2023-01-09 23:06:50 Substrate Node    
2023-01-09 23:06:50 ✌️  version 4.0.0-dev-4ae6e26d2fc    
2023-01-09 23:06:50 ❤️  by Substrate DevHub <https://github.com/substrate-developer-hub>, 2017-2023    
2023-01-09 23:06:50 📋 Chain specification: iam Local Testnet    
2023-01-09 23:06:50 🏷  Node name: MyNode01    
2023-01-09 23:06:50 👤 Role: AUTHORITY    
2023-01-09 23:06:50 💾 Database: RocksDb at /tmp/node01/chains/local_testnet/db/full    
2023-01-09 23:06:50 ⛓  Native runtime: node-template-100 (node-template-1.tx1.au1)    
2023-01-09 23:06:51 🔨 Initializing Genesis block/state (state: 0x0e5a…205a, header-hash: 0xd977…d9a1)    
2023-01-09 23:06:51 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.    
2023-01-09 23:06:52 Using default protocol ID "sup" because none is configured in the chain specs    
2023-01-09 23:06:52 🏷  Local node identity is: 12D3KooWDFcrrRui3J9JJGXX92dBtUqqFhZZzViDJy4QJD6DCJPG    
2023-01-09 23:06:52 💻 Operating system: macos    
2023-01-09 23:06:52 💻 CPU architecture: aarch64    
2023-01-09 23:06:52 📦 Highest known block at #0    
2023-01-09 23:06:52 〽️ Prometheus exporter started at 127.0.0.1:9615    
2023-01-09 23:06:52 Running JSON-RPC HTTP server: addr=127.0.0.1:9933, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]    
2023-01-09 23:06:52 Running JSON-RPC WS server: addr=127.0.0.1:9945, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]    
2023-01-09 23:06:58 💤 Idle (0 peers), best: #0 (0xd977…d9a1), finalized #0 (0xd977…d9a1), ⬇ 0 ⬆ 0
```

Some notable observations from the output: 

- the chain specification being used is the custom chain specification you created and specified using the `--chain` command-line option.
- the node is an authority because you started the node using the `--validator` command-line option.
- the genesis block being initialized with the block hash `(state: 0x0e5a…205a, header-hash: 0xd977…d9a1)`.
- the Local node identity for your node. In this example, the node identity is `12D3KooWDFcrrRui3J9JJGXX92dBtUqqFhZZzViDJy4QJD6DCJPG`.

### Insert keys in node keystore

The node will not produce any blocks after starting the first node. We need to two types of keys to each of our nodes in the network.

For each node:

- Add the `aura` authority keys to enable [block production](https://docs.substrate.io/reference/glossary/#author).
- Add the `grandpa` authority keys to enable [block finalization](https://docs.substrate.io/reference/glossary/#finality).

Insert the `aura` and `grandpa` secret keys into the nodes keystore:

Make sure:

- `--base-path` matches the same path used for starting the node. In this example, the path is `/tmp/node01`
- `--chain` points to the raw chain specification file we generated earlier
- `--suri` value can be either the secret phrase or the secret seed created for each node

```shell
./target/debug/node-template key insert \
  --base-path /tmp/node01 \ 
  --chain customSpecRaw.json \
  --scheme Sr25519 \
  --suri 0xd4883e547610a9543e1f68db1100833f3f57586b0e7a70437c84cb558ecd7cbe \
  --password-interactive \
  --key-type aura
```

```shell
./target/debug/node-template key insert \
  --base-path /tmp/node01 \
  --chain customSpecRaw.json \
  --scheme Ed25519 \
  --suri 0xd4883e547610a9543e1f68db1100833f3f57586b0e7a70437c84cb558ecd7cbe \
  --password-interactive \
  --key-type gran
```

Verify that the keys are in the keystore for `node01`

`ls /tmp/node01/chains/local_testnet/keystore`

Output:
```
6175726142e88babfc903a7f3c12e576f52288144487f019ff9d2605df0f558c617a6909
6772616e128ea392292f8be6682543ee87e4b595e23c72015e848205f986e2d714fd68bf
```

Now restart the node.

## Start the second node

Run the following command to start the second node using the same raw chain specification:

```shell
./target/debug/node-template \
  --base-path /tmp/node02 \
  --chain ./customSpecRaw.json \
  --port 30334 \
  --ws-port 9946 \
  --rpc-port 9934 \
  --telemetry-url "wss://telemetry.polkadot.io/submit/ 0" \
  --validator \
  --rpc-methods Unsafe \
  --name MyNode02 \
  --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWDFcrrRui3J9JJGXX92dBtUqqFhZZzViDJy4QJD6DCJPG \
  --password-interactive
```

*Make sure to replace the `--bootnodes` node identity with the one you have running*

Insert the secret keys like we did with the first node but this time in `/tmp/node02`. 

*Follow the same steps [here](#insert-keys-in-node-keystore) to configure the second node*

Finally, Substrate nodes require a restart after inserting a `grandpa` key, so you must shut down and restart nodes before you see blocks being finalized.
Restart both nodes in the right order and you should also see that each node has one peer `(1 peers)`, and they have produced a block proposal `(best: #2 (0xe111…c084))`. After a few seconds, you should see new blocks being finalized on both nodes `finalized #1 (0x45a4…52d1)`

Congratulations, you made it to the end!