Skip to main content

Tutorial: Creating and Joining a Network

In this tutorial, we will:

  1. Create a node and start a new network.
  2. Create a second node and configure it to join the network.
  3. Add the second node to the network as a non-validating peer.
  4. Upgrade the second node to a validator.
tip

In order to do this tutorial, you will need to install the kwild binary, as well as have docker installed.

Creating The First Node

Creating The Node's Files

To create the node's configuration files, a new genesis.json, and a new key pairs, we will use the kwild setup command:

kwild setup init --root ./testnet/node0 --db-owner <YOUR_ETHEREUM_ADDRESS>

The ./testnet/node0 folder will be the "root" directory for kwild that contains the configuration files, including genesis.json and config.toml.

Running The Node

To run the first node, we will need to start a properly configured PostgreSQL instance. We will use a default pre-configured image provided by Kwil. For information on how this can be configured manually, see the node's PostgreSQL configuration section. Once the PostgreSQL instance is running, we can start the node using the kwild binary:

# Run Postgres
docker run -d -p 5432:5432 --name kwil-postgres -e "POSTGRES_HOST_AUTH_METHOD=trust" \
kwildb/postgres:latest

# Run the node
kwild start --root ./testnet/node0 --admin.listen /tmp/node0.sock --db.port 5432

The command then runs the local Kwil network, and begins producing blocks.

note

We override the default admin.listen because in this tutorial, we will be running two nodes on the same machine. To allow us to interact with both nodes' admin RPCs, we will make them listen on different UNIX sockets.

Getting The Node's Info

In order to allow other nodes to join, we will need to expose our node's information publicly. Other operators can then set us as a peer, and request to join the network as a validator.

To get our node's information, we can use the kwild node tool, specifying the UNIX socket that our admin RPC is listening on:

$ kwild admin status --rpcserver /tmp/node0.sock
{
"node": {
"chain_id": "kwil-test-chain",
"node_id": "02e804dfd8e28cbd791fd3439149b909e5300d7b7cc6cbd0e94e2178e7ed21e120#secp256k1", # node ID
"app_ver": 1,
"listen_addr": "127.0.0.1:6600", # p2p address
"role": "leader",
"rpc_addr": "/tmp/kwild.socket"
},
"sync": {
"app_hash": "2d8f3ceeff2c836527da823d7b654d33d3e44b6159b172235c160001e0c9b4db",
"best_block_hash": "3e044fb509b9e55c70f127ccae7884916a668ea389b71ee88a088cf172dd46a9",
"best_block_height": 1,
"best_block_time": "2025-01-27T11:28:02.336-06:00",
"syncing": false
},
"validator": {
"pubkey": "02e804dfd8e28cbd791fd3439149b909e5300d7b7cc6cbd0e94e2178e7ed21e120",
"type": "secp256k1",
"power": 1
}
}

The node.node_id and node.listen_addr fields can be given to the second node as a persistent peer, in the format: node-id@p2p-address. For the above node, we would have 02e804dfd8e28cbd791fd3439149b909e5300d7b7cc6cbd0e94e2178e7ed21e120#[email protected]:26656.

Creating A Second Peer Node

Using kwild to create the second node's directories and configs, we can specify where to find the genesis file and any peers that it should try to connect to when starting up. Since both nodes are running locally, we need to specify new addresses for the different endpoints, so that the second node does not conflict with the first node:

Ensure that you replace 02e804dfd8e28cbd791fd3439149b909e5300d7b7cc6cbd0e94e2178e7ed21e120 with your own node's ID obtained from the kwild admin status command above.

kwild setup init --root ./testnet/node1 --genesis ./testnet/node0/genesis.json \
--p2p.bootnodes 02e804dfd8e28cbd791fd3439149b909e5300d7b7cc6cbd0e94e2178e7ed21e120#[email protected]:6600 \
--rpc.listen=localhost:8485 --admin.listen=/tmp/node1.sock \
--p2p.listen=127.0.0.1:6601

Start the second node to verify that it was created correctly:

# Run Postgres
docker run -d -p 5431:5432 --name kwil-postgres-1 -e "POSTGRES_HOST_AUTH_METHOD=trust" \
kwildb/postgres:latest

# Run the node
kwild start --root=./testnet/node1 --db.port 5431

If done correctly, you should be able to see the second node's logs, where it will have completed block synchronization with the first node. The first node's logs should also show that it has a new peer.

Upgrading The Second Node To A Validator

To upgrade the second node to a validator, we will use the kwild validators command to:

  1. Request to join the network as a validator, from the second node
  2. Approve the request, from the first node

We will use the configured UNIX socket to communicate with the nodes.

Requesting To Upgrade

To request to join from the second node:

kwild validators join --rpcserver /tmp/node1.sock

To check that the request was successful, we can get a list of pending join requests:

$ kwild validators list-join-requests --rpcserver /tmp/node0.sock
Pending join requests (1 approval needed):
| Candidate | Power | Approvals | Expiration |
+--------------------------------------------------------------------------------+-------+-----------+-------------------------------+
| '0385480e6c66e9c98e05a4d7dd597a096058b918a0bac4e337c25363be649e484b#secp256k1' | 1 | 0 | 2025-01-28 14:42:10 -0600 CST |

Approving The Request

The first node can vote to approve the second node by running the kwild validators approve command and passing the second node's public key:

kwild validators approve <node_pubkey> --rpcserver /tmp/node0.sock

For example, with second node above, <node_pubkey> would be 0385480e6c66e9c98e05a4d7dd597a096058b918a0bac4e337c25363be649e484b#secp256k1.

tip

If the requesting node's public key is unknown, all pending requests and their public keys can be retrieved with the kwild validators list-join-requests command.

The validators approve command will return a transaction hash of the approval transaction. When the transaction is included in a block, the second node will be promoted to a validator.

And that's it! The second node should now be a validator on the network. To verify this, we can use kwild validators list to get the list of validators:

$ kwild validators list --rpcserver /tmp/node0.sock
| Identifier | Power |
+------------------------------------------------------------------------------+-------+
| '02e804dfd8e28cbd791fd3439149b909e5300d7b7cc6cbd0e94e2178e7ed21e120#secp256k1' | 1 |
| '0385480e6c66e9c98e05a4d7dd597a096058b918a0bac4e337c25363be649e484b#secp256k1' | 1 |

The logs for the second node should also show that it has been promoted to a validator: [INF] CONS: Role updated {from=sentry to=validator}.

Cleanup

If you wish to reset this tutorial, you will need to stop the nodes and Postgres containers, remove the testnet directory, and remove the Postgres container:

# Stop the nodes using Ctrl+C

# Stop and remove the Postgres containers and their volumes
docker rm -f -v kwil-postgres kwil-postgres-1

# Remove the testnet directory
rm -rf ./testnet

Conclusion

In this tutorial, we have:

  1. Created a node and started a network.
  2. Created a second node and configured it to join the network.
  3. Added the second node to the network as a non-validating peer.
  4. Promoted the second node to a validator.