How to launch a private local substrate blockchain

michaelassaf

Michael Assaf

Posted on January 10, 2023

How to launch a private local substrate blockchain

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:

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:

./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
Enter fullscreen mode Exit fullscreen mode

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

./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
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Polkadot uses sr25519 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
Enter fullscreen mode Exit fullscreen mode

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. 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.

"aura": {
  "authorities": [
    "5DaS6dzomvqS3MpKcKgxz54GgEJje5Y11L1PHjyeMVniBrEM",
    "5E4pr85gYVTc6kk4fQTa9keXaPh3Gnj5y9MWHQ4FN5ubxUv4"
  ]
},
Enter fullscreen mode Exit fullscreen mode

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

"grandpa": {
  "authorities": [
    ["5CV36Gk8ckF66wjQCdZshY7wzJyZ84MZso6DmTJWYcriCzoG", 1],
    ["5CCr8YMJercfhvFaQ2z9pS3r6Pyf48mx9XFbuvFDamkfG524", 1]
  ]
},
Enter fullscreen mode Exit fullscreen mode

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:

./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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

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
./target/debug/node-template key insert \
  --base-path /tmp/node01 \ 
  --chain customSpecRaw.json \
  --scheme Sr25519 \
  --suri 0xd4883e547610a9543e1f68db1100833f3f57586b0e7a70437c84cb558ecd7cbe \
  --password-interactive \
  --key-type aura
Enter fullscreen mode Exit fullscreen mode
./target/debug/node-template key insert \
  --base-path /tmp/node01 \
  --chain customSpecRaw.json \
  --scheme Ed25519 \
  --suri 0xd4883e547610a9543e1f68db1100833f3f57586b0e7a70437c84cb558ecd7cbe \
  --password-interactive \
  --key-type gran
Enter fullscreen mode Exit fullscreen mode

Verify that the keys are in the keystore for node01

ls /tmp/node01/chains/local_testnet/keystore

Output:

6175726142e88babfc903a7f3c12e576f52288144487f019ff9d2605df0f558c617a6909
6772616e128ea392292f8be6682543ee87e4b595e23c72015e848205f986e2d714fd68bf
Enter fullscreen mode Exit fullscreen mode

Now restart the node.

Start the second node

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

./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
Enter fullscreen mode Exit fullscreen mode

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 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!

💖 💪 🙅 🚩
michaelassaf
Michael Assaf

Posted on January 10, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related