This is a step-by-step guide on how to set up your Tendermint validator with SignCTRL.
In order to set up your node, you can follow Tendermint's official documentation.
Each validator node runs in tandem with its own SignCTRL daemon, so each and every validator in the set needs to have its own configuration.
SignCTRL needs to be configured in order to be able to talk to a validator. The configuration directory defaults to $HOME/.signctrl
- it can be set to a custom directory, though, via the environment variable $SIGNCTRL_CONFIG_DIR
.
First thing we're going to do is initialize SignCTRL via
$ signctrl init
This will create the following files in your configuration directory:
$HOME/.mintctrl/
├── config.toml
└── conn.key
The config.toml
is the configuration file for SignCTRL. We will be taking a look at it in great detail in the Configuration section.
The conn.key
file is a secret key that is used to establish an encrypted connection between SignCTRL and the validator.
The last thing we need to do is import the validator node's priv_validator_key.json
and priv_validator_state.json
into the configuration directory. Your directory should now look like this:
$HOME/.mintctrl/
├── config.toml
├── conn.key
├── priv_validator_key.json
└── priv_validator_state.json
ℹ️ If you don't already have a key and state file, or want to use new ones, you can use
signctrl init --keypair
.
In the previous section, we've created a config.toml
file in our configuration directory.
[init]
# Minimum log level for SignCTRL logs.
# Must be either DEBUG, INFO, WARN or ERR.
log_level = ""
# Number of SignCTRL validator nodes running in parallel.
# This number cannot be changed during operation anymore.
# If you want to change this value you need to stop all
# nodes, modify the configuration on each node and start
# them up again.
# Must be 2 or higher.
set_size = 0
# Number of missed blocks in a row that triggers a rank
# update in the set.
# Must be 1 or higher.
threshold = 0
# SignCTRL node's rank on startup. It is used to determine
# which node in the set is currently signing (rank 1) and
# which nodes line up as backups (ranks 2-n).
# Must be 1 or higher.
rank = 0
# TCP socket address the validator listens on for an external
# PrivValidator process. SignCTRL dials this address to
# establish a connection to the validator.
# Must be in host:port format.
validator_laddr = ""
# TCP socket address the validator's RPC server listens on.
# Must be in host:port format.
validator_laddr_rpc = ""
[file_pv]
# The chain ID the signer should sign for.
chain_id = ""
# The path to the priv_validator_key.json file.
# Defaults to $SIGNCTRL_CONFIG_DIR/priv_validator_key.json if left empty.
key_file_path = ""
# The path to the priv_validator_state.json file.
# Defaults to $SIGNCTRL_CONFIG_DIR/priv_validator_state.json if left empty.
state_file_path = ""
The initial config.toml
is merely a template and needs customization. There are a couple of things to consider:
set_size
,threshold
andchain_id
must be shared values across all validators in the setrank
must be unique, so no two validators in the set can have the same rank
The following two configurations are an example for a SignCTRL set of two validators.
Validator #1 | Validator #2 |
---|---|
[init]
log_level = "INFO"
set_size = 2 # Shared value
threshold = 5 # Shared value
rank = 1 # Unique
validator_laddr = "127.0.0.1:3000"
validator_laddr_rpc = "127.0.0.1:26657"
[privval]
chain_id = "testchain" # Shared value
key_file_path = "/Users/myuser/.signctrl/priv_validator_key.json"
state_file_path = "/Users/myuser/.signctrl/priv_validator_state.json" |
[init]
log_level = "INFO"
set_size = 2 # Shared value
threshold = 5 # Shared value
rank = 2 # Unique
validator_laddr = "127.0.0.1:3000"
validator_laddr_rpc = "127.0.0.1:26657"
[privval]
chain_id = "testchain" # Shared value
key_file_path = "/Users/myuser/.signctrl/priv_validator_key.json"
state_file_path = "/Users/myuser/.signctrl/priv_validator_state.json" |
It is recommended to use systemctl
to run SignCTRL. Here's an example of a signctrl.service
unit file:
[Unit]
Description=signctrl
Requires=network-online.target
After=network-online.target
[Service]
User=ec2-user
Group=ec2-user
PermissionsStartOnly=true
ExecStart=/home/<user>/go/bin/signctrl start
KillSignal=SIGTERM
LimitNOFILE=4096
Environment=SIGNCTRL_CONFIG_DIR=/Users/<user>/.signctrl
[Install]
WantedBy=multi-user.target
⚠️ Do under no circumstances use any restart options in your SignCTRL unit file, as they currently carry the risk of double-signing.
ℹ️ Replace all occurrences of
simd
with the name of your binary.
Once all the nodes are configured, start the SignCTRL service first via
$ sudo systemctl start signctrl
and then, start your validator via
$ sudo systemctl simd start
For convenience, you can also chain the commands above with small delays in between:
$ sudo systemctl start signctrl; sleep 0.5s; sudo systemctl start simd
ℹ️ It doesn't matter which order you start your validators in. Ranks 2..n will always wait for a signature from rank 1 before they start counting missed blocks in a row and consequently updating their ranks.