Upgrades (cosmovisor)
Safrochain follows the standard Cosmos SDK upgrade pattern: an on-chain
MsgSoftwareUpgrade proposal targets a future block height, and every node
must run the new binary at exactly that height. The simplest way to do this
safely is cosmovisor, a thin process supervisor that watches for the
upgrade plan, halts safrochaind at the target height, swaps the binary
symlink, and restarts.
1 · Install cosmovisor
Linux / macOS
go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@latest
cosmovisor version
If ~/go/bin is not in your $PATH:
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.bashrc
source ~/.bashrc
2 · Lay out the cosmovisor directory
~/.safrochain/cosmovisor/
current -> upgrades/v1.0.0 # symlink, cosmovisor manages it
genesis/bin/safrochaind # the binary you launched the chain with
upgrades/v1.0.0/bin/safrochaind # current release
upgrades/v1.1.0/bin/safrochaind # staged for the next upgrade
Bootstrap with the binary you have today:
mkdir -p ~/.safrochain/cosmovisor/genesis/bin
cp "$(command -v safrochaind)" ~/.safrochain/cosmovisor/genesis/bin/
3 · Run cosmovisor under systemd
Create /etc/systemd/system/safrochaind.service:
[Unit]
Description=Safrochain (cosmovisor)
After=network-online.target
[Service]
User=safrochain
Environment="DAEMON_HOME=/home/safrochain/.safrochain"
Environment="DAEMON_NAME=safrochaind"
Environment="DAEMON_RESTART_AFTER_UPGRADE=true"
Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false"
ExecStart=/home/safrochain/go/bin/cosmovisor run start
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now safrochaind
sudo journalctl -u safrochaind -f
4 · Stage a new release before the upgrade height
When the foundation announces a release tag (for example v1.1.0):
RELEASE=v1.1.0
# verify the binary against the published checksum
URL="https://github.com/Safrochain-Org/safrochain-node/releases/download/${RELEASE}/safrochaind-${RELEASE}-linux-amd64.tar.gz"
curl -fsSL "$URL" -o /tmp/safrochaind.tar.gz
curl -fsSL "${URL}.sha256" -o /tmp/safrochaind.tar.gz.sha256
( cd /tmp && shasum -a 256 -c safrochaind.tar.gz.sha256 )
# extract and install under cosmovisor
mkdir -p ~/.safrochain/cosmovisor/upgrades/${RELEASE}/bin
tar -xzf /tmp/safrochaind.tar.gz -C ~/.safrochain/cosmovisor/upgrades/${RELEASE}/bin
~/.safrochain/cosmovisor/upgrades/${RELEASE}/bin/safrochaind version --long | head -2
cosmovisor will pick up the new binary automatically when it sees the matching upgrade plan on chain.
5 · Watch the upgrade height
# the active proposal (height + name)
safrochaind query upgrade applied $RELEASE
safrochaind query upgrade plan
# tail logs through the upgrade
sudo journalctl -u safrochaind -f
At the upgrade height, cosmovisor will halt the running binary, switch
the current symlink, and restart. After restart, confirm:
safrochaind status \
| jq '.node_info.version, .sync_info.latest_block_height'
6 · If something goes wrong
If a validator does not come back within ~5 minutes:
sudo journalctl -u safrochaind -n 500 --no-pager
If cosmovisor flipped the symlink but the new binary panics, flip it back to the previous version manually and coordinate with other validators in the operator channel:
sudo systemctl stop safrochaind
cd ~/.safrochain/cosmovisor
ln -sfn upgrades/<previous-version> current
sudo systemctl start safrochaind
7 · Coordinated chain restart (no governance)
Used only in emergencies (state corruption, panic loop). The foundation will publish:
- a new
genesis.json(export-genesis from a healthy archive) + sha256 - a new chain id, if any
Each operator:
sudo systemctl stop safrochaind
# replace genesis
sudo cp genesis-...json ~/.safrochain/config/genesis.json
# wipe local state but keep node_key.json + priv_validator_key.json
safrochaind comet unsafe-reset-all --keep-addr-book
sudo systemctl start safrochaind
Watch peers reconnect and consensus form. Coordinate timing in the operator channel before doing this.