Skip to main content

Add and remove QBFT validators

Prerequisites

A QBFT network as configured in the QBFT tutorial.

Add a validator

  1. Create a working directory for the new node that needs to be added:

    mkdir -p Node-5/data/keystore
  2. In the artifacts directory, generate one new validator using the Quorum Genesis Tool:

    npx quorum-genesis-tool \
    --validators 1 \
    --members 0 \
    --bootnodes 0 \
    --outputPath artifacts
  3. Copy the latest generated artifacts:

    cd artifacts/2022-04-21-08-10-29/validator0
    cp nodekey* address ../../../Node-5/data
    cp account* ../../../Node-5/data/keystore
  4. Copy the address of the validator and propose it from more than half the number of current validators.

    Attach a geth console to the node:

cd ..
geth attach node0/data/geth.ipc

Check existing validators:

istanbul.getValidators();

Propose the new validator using the command istanbul.propose(<address>, true) with <address> replaced by the new validator candidate node address:

istanbul.propose("0x2aabbc1bb9bacef60a09764d1a1f4f04a47885c1", true);

Exit the console:

exit;

Repeat the proposal process for this candidate node by connecting your geth console to node 1, node 2, and node 3.

note

To drop a currently running validator candidate and stop further votes from being cast either for or against it, use istanbul.discard.

:::

  1. Verify that the new validator is now in the list of validators by running istanbul.getValidators in a geth console attached to any of your nodes:
istanbul.getValidators();

The list of validators contains six addresses now.

  1. Copy static-nodes.json and genesis.json from the existing chain, placing static-nodes.json into the new node's data directory:

cd node5
cp ../node0/static-nodes.json data
cp ../node0/genesis.json data
  1. Edit static-nodes.json and add the new validator's node info to the end of the file.

The new validator's node info can be retrieved from the output of qbft setup --num 1 --verbose --quorum --save in step 2. Update the IP address and port of the node info to match the IP address of the validator and port you want to use.

[
"enode://dd333ec28f0a8910c92eb4d336461eea1c20803eed9cf2c056557f986e720f8e693605bba2f4e8f289b1162e5ac7c80c914c7178130711e393ca76abc1d92f57@127.0.0.1:30300?discport=0",
"enode://1bb6be462f27e56f901c3fcb2d53a9273565f48e5d354c08f0c044405b29291b405b9f5aa027f3a75f9b058cb43e2f54719f15316979a0e5a2b760fff4631998@127.0.0.1:30301?discport=0",
"enode://0df02e94a3befc0683780d898119d3b675e5942c1a2f9ad47d35b4e6ccaf395cd71ec089fcf1d616748bf9871f91e5e3d29c1cf6f8f81de1b279082a104f619d@127.0.0.1:30302?discport=0",
"enode://3fe0ff0dd2730eaac7b6b379bdb51215b5831f4f48fa54a24a0298ad5ba8c2a332442948d53f4cd4fd28f373089a35e806ef722eb045659910f96a1278120516@127.0.0.1:30303?discport=0",
"enode://e53e92e5a51ac2685b0406d0d3c62288b53831c3b0f492b9dc4bc40334783702cfa74c49b836efa2761edde33a3282704273b2453537b855e7a4aeadcccdb43e@127.0.0.1:30304?discport=0",
"enode://273eaf48591ce0e77c800b3e6465811d6d2f924c4dcaae016c2c7375256d17876c3e05f91839b741fe12350da0b5a741da4e30f39553fe8790f88503c64f6ef9@127.0.0.1:30305?discport=0"
]
  1. Initialize the new node with the following command:
geth --datadir data init data/genesis.json
  1. In the Node-5 directory, start the first node:

export ADDRESS=$(grep -o '"address": *"[^"]*"' ./data/keystore/accountKeystore | grep -o '"[^"]*"$' | sed 's/"//g')
export PRIVATE_CONFIG=ignore
geth --datadir data \
--networkid 1337 --nodiscover --verbosity 5 \
--syncmode full --nousb \
--istanbul.blockperiod 5 --mine --miner.threads 1 --miner.gasprice 0 --emitcheckpoints \
--http --http.addr 127.0.0.1 --http.port 22005 --http.corsdomain "*" --http.vhosts "*" \
--ws --ws.addr 127.0.0.1 --ws.port 32005 --ws.origins "*" \
--http.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft \
--ws.api admin,trace,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,istanbul,qbft \
--unlock ${ADDRESS} --allow-insecure-unlock --password ./data/keystore/accountPassword \
--port 30305
  1. Check that node 5 is validator:

geth attach http://localhost:22005
> istanbul.isValidator()
true

Remove a validator

  1. Attach a geth console to a running validator, run istanbul.getValidators, and identify the address of the validator that needs to be removed:
geth attach node0/data/geth.ipc

Run istanbul.getValidators:

istanbul.getValidators();

We will remove 0x2aabbc1bb9bacef60a09764d1a1f4f04a47885c1 from the validator list in this tutorial.

  1. Run istanbul.propose(<address>, false) by passing the address of the validator that needs to be removed from more than half of the current validators:
istanbul.propose("0x2aabbc1bb9bacef60a09764d1a1f4f04a47885c1", false);

Repeat istanbul.propose("0x2aabbc1bb9bacef60a09764d1a1f4f04a47885c1",false) for node 1, node 2, and node 3.

  1. Verify that the validator has been removed by running istanbul.getValidators in one of the nodes' attached geth console:
istanbul.getValidators();

The validator 0x2aabbc1bb9bacef60a09764d1a1f4f04a47885c1 was removed and the validators list now only has five addresses.

  1. Check that node 5 is not validator:

geth attach http://localhost:22005
> istanbul.isValidator()
false
  1. Stop the geth process corresponding to the validator that was removed:
ps

Kill the geth process that uses port 22005, corresponding to node 5 as indicated in start5.sh:

kill 36485

Add a non-validator node

Same instructions as adding a validator excluding step 4, which proposes the node as validator.

Remove a non-validator node

Just execute step 5 from removing a validator.