Deploy Private IBFT 2.0 Network

Deploy Private Network Node

In this tutorial we will use the following private keys and their corresponding addresses.

DON'T use these keys in production.

AddressPrivate Key

0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa

fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d

153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b

0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a

89b03c4de62d61be16d22e09c8a48929a9bccd11fa6b37809cfef290292bcba3

Let's describe an Ethereum Node that uses a custom genesis block to join a private Proof of Authority network using ibft2 consensus configuration in the genesis block.

besu-ibft2-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: besu-ibft2-node
spec:
  client: besu
  nodePrivateKeySecretName: besu-ibft2-nodekey
  rpc: true
  genesis:
    chainId: 4444
    networkId: 4444
    ibft2:
      validators:
        - "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
        - "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
        - "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"

In this node, we're using Hyperledger besu client client: besu, enabling JSON-RPC server rpc: true so we can query number of peers later in this tutorial, and we're loading the node private key from Kubernetes secretd called besu-ibft2-nodekey.

The node private key will give the node a unique identity and node URL, and will allow the node to generate blocks, because the address 0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa that's corresponding to the node private key is in the initial block validators.

We're defining a genesis block that uses the value 4444 as network and chain identifier, and we start the chain with 3 validators as defined by spec.genesis.ibft2.validators.

This node private key secret can be created by:

kubectl create secret generic besu-ibft2-nodekey --from-literal=key=fb5411342ae51291447515c89bcf6a057e3dbd0b51e060c45cb73406c38f851d

Private key must not start with 0x, and must be stored in secret data field called key.

Let's deploy the node:

kubectl apply -f besu-ibft2-node.yaml

Kotal operator will notice your besu-ibft2-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Node using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-ibft2-node      besu     ibft2       private

Fetch Node Logs

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-ibft2-node-0     1/1     Running   0          1m

Get the logs of the running node:

kubectl logs -f besu-ibft2-node-0

Deploy a Second Node

Let's deploy another go-ethereum node, and connect it to the previous node in our private proof of authority network.

Genesis block must be the same in both nodes, or they will fork at genesis block, and won't reach consensus.

geth-ibft2-node.yaml
apiVersion: ethereum.kotal.io/v1alpha1
kind: Node
metadata:
  name: geth-ibft2-node
spec:
  client: geth
  miner: true
  coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
  import:
    privateKeySecretName: geth-ibft2-account-key
    passwordSecretName: geth-ibft2-account-password
  staticNodes:
    - besu-ibft2-node
  genesis:
    chainId: 4444
    networkId: 4444
    ibft2:
      validators:
        - "0xbAa5f05af4A67A467cEcA89085f162aFb4206Aaa"
        - "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d"
        - "0x7DE985E2f878c83C4e91b6B1312c0f63A56C844a"

In this node, we're using go-ethereum client client: geth, starting the PoA consensus engine miner: true, setting the second address in the genesis validators list spec.genesis.ibft2.validators as the coinbase coinbase: "0xc1381ED43B327e3C7A1ADb21285f1e9cB82Bc00d", and loading the validator account private key and password from kubernetes secrets privateKeySecretName: ... and passwordSecretName: .... We're connecting to the first node using staticNodes option which accepts Node name or enode url.

staticNodes accept Node name or enode URL. Node name has the format of name.namespace, namespace is optional if Node is in the same namespace. If the node doesn't exist, or is not up and running yet, Kotal will not raise an error.

You can create the private key and password secrets using:

kubectl create secret generic geth-ibft2-account-key --from-literal=key=153b174f5e9948ae4678baed54f88244cc9c39d56b9f17ecef93d7ede633f56b
kubectl create secret generic geth-ibft2-account-password --from-literal=password=s3cr3t

Deploy the second node using:

kubectl apply -f geth-ibft2-node.yaml

Kotal operator will notice your second geth-ibft2-node and will create all the necessary pods, persistent volumes, services, configmaps, and secrets.

You can fetch the deployed Ethereum Nodes using:

kubectl get nodes.ethereum

It will return an output similar to the following:

NAME                 CLIENT   Consensus   Network
besu-ibft2-node      besu     poa         private
geth-ibft2-node      geth     poa         private

Call JSON-RPC Method net_peerCount

Get the pods that has been created by Kotal for the node:

kubectl get pods

It will return an output similar to the following:

NAME                  READY   STATUS    RESTARTS   AGE
besu-ibft2-node-0     1/1     Running   0          1m
geth-ibft2-node-0     1/1     Running   0          1m

Forward localhost:8545 calls to the node pod:

kubectl port-forward besu-ibft2-node-0 8545

In another terminal window call net_peerCount JSON-RPC method

curl -X POST -H 'content-type: application/json' --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":32}' http://127.0.0.1:8545

You will get JSON result similar to the following:

{
  "jsonrpc" : "2.0",
  "id" : 32,
  "result" : "0x1"
}

Homework

Deploy a third node that uses Nethermind client, and signing blocks using the third key in the validators list spec.genesis.ibft2.validators. Nethermind client is similar to geth, you will import validator account private key and password from kubernetes secrets, and use the same genesis as the other nodes.

Finally you can delete all the nodes by:

kubectl delete nodes.ethereum --all

Kubernetes garbage collector will delete all the resources that has been created by Kotal Ethereum Node controller.

Last updated