Skip to content

Instantly share code, notes, and snippets.

@dylanschultzie
Last active August 27, 2022 13:46
Show Gist options
  • Save dylanschultzie/0a0b10cf695749f9697197759e7b12ec to your computer and use it in GitHub Desktop.
Save dylanschultzie/0a0b10cf695749f9697197759e7b12ec to your computer and use it in GitHub Desktop.

Start Using Horcrux

The setup script below will require using 3 signers, and any number of full nodes.

Source: https://github.com/strangelove-ventures/horcrux

Official installation instructions: https://github.com/strangelove-ventures/horcrux/blob/main/docs/migrating.md

Warnings!

You'll be tempted to use AWS EC2 instances for this. Don't. We tried c6a.xl, c6i.xl, and t3a.xl, and all of them would run at ~20% or so usage (with ~25 networks connected, including tesnets) until suddenly they'd hit 100% CPU and disk usage and cause blocks to be missed. Don't get woken up multiple nights in a row - just go straight to bare metal. Horcrux is designed such that it can sit on the same servers as the nodes and still be secure.

Setup

Install Horcrux

When installing horcrux they recommend using the prebuilt binaries from the releases page. Pick the release corresponding to the tendermint dependancy for the go.mod of your chain binary. You should be able to get this with {binary} version --long.

If you don't want to do that work, the following instructions should work on any network updated since 2019.

Install like so:

wget https://github.com/strangelove-ventures/horcrux/releases/download/v2.0.0/horcrux_2.0.0_linux_amd64.tar.gz && \
tar -xzf horcrux_2.0.0_linux_amd64.tar.gz && sudo mv horcrux /usr/bin/horcrux && \
rm horcrux_2.0.0_linux_amd64.tar.gz README.md LICENSE.md

Setup Cross-signer SSHing

This will make it so signer 1 can scp the shared key to the other signers. This specific process will depend on what provider you use and your settings. We do not allow password login, so ssh keys must be copied manually. If you do allow password login, you can simply do an ssh-copy-id user@ip-of-cosigner.

On signer 1

  1. create an ssh key: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
  2. copy ssh pubkey
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcc77gKDU2ttbXv81oN2Mq6pqP9p/Cc6nf+//d+ddee ubuntu@my-ip

On signers 2/3

You'll need to manually copy signer 1's ssh pubkey.

# 1. open file
nano ~/.ssh/authorized_keys
# 2. create new line
# 3. paste in pubkey
# 4. save and close file

Setup Script

Copy the script from below. From EACH of your signers:

# 1. Open install_horcrux.sh
nano install_horcrux.sh

# 2. Paste in script, save, and exit
ctrl+v, ctrl+x, y

# 3. Make script executable
chmod +x install_horcrux.sh

Migrate priv_validator_key.json

Copy the priv_validator_key.json to ~/key.json on horcrux signer 1.

Execute install_horcrux.sh

Install_horcrux.sh will do the following:

  1. create the .horcrux dir if it does not exist
  2. create config for signer
  3. create the horcrux service file

You MUST run the script on signers 2 and 3 before signer 1 in order to correctly split up the key.

If it's horcrux signer 1, it'll also take the priv_validator_key.json and split it up.

The dir will be as follows:

ubuntu@horcrux1:~$ tree .horcrux/
.horcrux/
├── akash
│   ├── config.yaml
│   ├── raft
│   │   ├── logs.dat
│   │   ├── snapshots
│   │   └── stable.dat
│   ├── share.json
│   └── state
│       ├── akashnet-2_priv_validator_state.json
│       └── akashnet-2_share_sign_state.json
├── bitcanna
│   ├── config.yaml
│   ├── raft
│   │   ├── logs.dat
│   │   ├── snapshots
│   │   └── stable.dat
│   ├── share.json
│   └── state
│       ├── bitcanna-1_priv_validator_state.json
│       └── bitcanna-1_share_sign_state.json

Usage:

Helpful link for getting chain-ids: https://cosmos.directory/

./install_horcrux.sh <user> <node string> <chain_id> <network> <signer_1_ip> <signer_2_ip> <signer_3_ip> <signer_port> <signer_number> <path/to/key.json IF SIGNER 1>
# ./install_horcrux.sh ubuntu "tcp://131.148.169.128:26659,tcp://35.148.51.219:26659" dig-1 dig 1.25.215.77 14.214.21.26 3.138.24.17 2222 1 key.json

Follow the instructions from Step 4 onwards

https://github.com/strangelove-ventures/horcrux/blob/main/docs/migrating.md#4-halt-your-validator-node-and-supply-signer-state-data-horcrux-nodes

Script

#! /bin/bash

USER=$1
SENTRIES=$2
CHAIN_ID=$3
NETWORK=$4
SIGNER_1_IP=$5
SIGNER_2_IP=$6
SIGNER_3_IP=$7
SIGNER_PORT=$8
SIGNER_NODE=$9
KEY=${10}
PORT=${11}

SIGNER_1="tcp://${SIGNER_1_IP}:${SIGNER_PORT}"
SIGNER_2="tcp://${SIGNER_2_IP}:${SIGNER_PORT}"
SIGNER_3="tcp://${SIGNER_3_IP}:${SIGNER_PORT}"
HOME="/home/${USER}/.horcrux/${NETWORK}"

HORCRUX_DIR="/home/${USER}/.horcrux"
[ ! -d "$HORCRUX_DIR" ] && mkdir ${HORCRUX_DIR} && echo "[INFO] Creating .horcrux dir under ${HORCRUX_DIR}"

if [ $SIGNER_NODE -eq 1 ]
then
	echo "[INFO] Creating config for signer 1"
	horcrux config init ${CHAIN_ID} ${SENTRIES} -c -p "${SIGNER_2}|2,${SIGNER_3}|3" -l "${SIGNER_1}" -t 2 --timeout 1500ms --home ${HOME}
elif [ $SIGNER_NODE -eq 2 ]
then
	echo "[INFO] Creating config for signer 2"
	horcrux config init ${CHAIN_ID} ${SENTRIES} -c -p "${SIGNER_1}|1,${SIGNER_3}|3" -l "${SIGNER_2}" -t 2 --timeout 1500ms --home ${HOME}
elif [ $SIGNER_NODE -eq 3 ]
then
	echo "[INFO] Creating config for signer 3"
	horcrux config init ${CHAIN_ID} ${SENTRIES} -c -p "${SIGNER_1}|1,${SIGNER_2}|2" -l "${SIGNER_3}" -t 2 --timeout 1500ms --home ${HOME}
else
	echo "[ERROR] ERROR"
	exit
fi

if [ ! -z "$KEY" ] && [ $SIGNER_NODE -eq 1 ]
	then
		echo "[INFO] priv_validator_key.json supplied, splitting..."
		horcrux create-shares $KEY 2 3
		echo "[INFO] Deleting key..."
		rm ./$KEY
		echo "[INFO] Moving Node ${SIGNER_NODE} signer share to ${HOME}/share.json"
		mv private_share_1.json ${HOME}/share.json
		echo "[INFO] Moving private_share_2.json to ${USER}@${SIGNER_2_IP}:.horcrux/${NETWORK}/share.json"
		scp -P ${PORT} private_share_2.json ${USER}@${SIGNER_2_IP}:.horcrux/${NETWORK}/share.json && rm private_share_2.json
		echo "[INFO] Moving private_share_3.json to ${USER}@${SIGNER_3_IP}:.horcrux/${NETWORK}/share.json"
		scp -P ${PORT} private_share_3.json ${USER}@${SIGNER_3_IP}:.horcrux/${NETWORK}/share.json && rm private_share_3.json
fi

SERVICE_FILE=/etc/systemd/system/horcrux_${NETWORK}.service
echo "[INFO] Writing ${SERVICE_FILE}..."

sudo tee ${SERVICE_FILE} > /dev/null <<EOF
[Unit]
Description=${NETWORK} Horcrux Signer Node ${SIGNER_NODE}
After=network.target

[Service]
Type=simple
User=${USER}
WorkingDirectory=/home/${USER}
ExecStart=/usr/bin/horcrux cosigner start --home ${HOME}
Restart=on-failure
RestartSec=3
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload && sudo systemctl enable horcrux_${NETWORK}
echo "[INFO] Run sudo systemctl restart horcrux_${NETWORK} && sudo journalctl -fu horcrux_${NETWORK} to start the signer"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment