Difference between revisions of "Set up a Cardano staking pool"
m (→Sending Tip to PoolTool) |
m (→Sending Tip to PoolTool) |
||
Line 355: | Line 355: | ||
You need to ensure minSeverity [https://docs.cardano.org/projects/cardano-node/en/latest/logging-monitoring/logging.html logging] is set to '''Notice'''! | You need to ensure minSeverity [https://docs.cardano.org/projects/cardano-node/en/latest/logging-monitoring/logging.html logging] is set to '''Notice'''! | ||
− | You may also need to | + | |
+ | You may also need to modify the '''cadano-node''' and '''cardano-cli''' if the script is running from systemd: | ||
<source lang="shell"> | <source lang="shell"> | ||
# CARDANO BINARIES | # CARDANO BINARIES |
Revision as of 04:28, 3 May 2021
The official documentation for setting up a node and configuring it as a stake pool on the mainnet is mostly very clear and complete. I was able to get my node compiled, installed and running pretty easily. But configuring the node to run as a stake pool is more complicated and the documentation seems to have some missing bits, so I'm documenting here just the specific parts that I had trouble with.
Contents
Prerequisites
You will need to have two servers (but three service is ideal so you can run two relays so one can be restarted to update topology without interrupting the service) and one offline machine, all running the node, so the first part of the procedure for compiling, installing and running is done on all three of the machines.
Procedure
First ensure that cardano-node is installed on the pool server, the relay server and a local machine (didn't have much luck with docker images).
Install cardano-addresses on the local machine.
Create a file called generate-keys.sh on the local machine with these contents (Note, the first line generates a phrase - remove it if you want to use an existing one.):
# Remove this line if you want to use an existing phrase stored in phrase.prv
cardano-address recovery-phrase generate > phrase.prv
# generate root keys
cat phrase.prv | cardano-address key from-recovery-phrase Shelley > rootkey.prv
cat rootkey.prv | cardano-address key public --with-chain-code > rootkey.pub
cat rootkey.prv | cardano-address key child 1852H/1815H/0H/0/0 > addr.prv
cat addr.prv | cardano-address key public --with-chain-code | cardano-address address payment --network-tag mainnet > payment.addr
cat rootkey.prv | cardano-address key child 1852H/1815H/0H/2/0 > stake.prv
cat stake.prv | cardano-address key public --with-chain-code | cardano-address address stake --network-tag mainnet > stake.addr
# Create payment and stake vkey/skey files
cardano-cli key convert-cardano-address-key --signing-key-file stake.prv --shelley-stake-key --out-file ShelleyStake.skey
cardano-cli key convert-cardano-address-key --signing-key-file addr.prv --shelley-payment-key --out-file ShelleyPayment.skey
cardano-cli key verification-key --signing-key-file ShelleyStake.skey --verification-key-file Ext_ShelleyStake.vkey
cardano-cli key verification-key --signing-key-file ShelleyPayment.skey --verification-key-file Ext_ShelleyPayment.vkey
cardano-cli key non-extended-key --extended-verification-key-file Ext_ShelleyStake.vkey --verification-key-file ShelleyStake.vkey
cardano-cli key non-extended-key --extended-verification-key-file Ext_ShelleyPayment.vkey --verification-key-file ShelleyPayment.vkey
cardano-cli stake-address build --stake-verification-key-file ShelleyStake.vkey --out-file ShelleyStake.addr --mainnet
cardano-cli address build --payment-verification-key-file ShelleyPayment.vkey --stake-verification-key-file ShelleyStake.vkey --out-file ShelleyPayment.addr --mainnet
# Nicer formatting
mkdir out
cp ShelleyPayment.addr out/payment.addr
cp ShelleyPayment.skey out/payment.skey
cp ShelleyPayment.vkey out/payment.vkey
cp ShelleyStake.addr out/stake.addr
cp ShelleyStake.skey out/stake.skey
cp ShelleyStake.vkey out/stake.vkey
Once you have that script ready disconnect from the internet and insert a fresh usb create a directory on it called wallet-keys and go into that directory in the terminal and run the script (script will work in your current working directory).
The script will have generated the keys you want int the out/ directory, copy the two .addr files onto your machine since these are not secret, and remove the drive.
On the server run:
cardano-cli query protocol-parameters \
--mainnet \
--out-file protocol.json
Send the keyDeposit amount (2 Ada at time of writing) as defined in the protocol.json and 1.5 Ada (1 for minimum wallet amount and 0.5 for transaction fees) to the payment address contained in payment.addr that you copied of the usb.
You should then continue as per the documentation page 4 but on step 5 generate the pool keys offline on the usb. Note: you will need to run any queries on the server (which has the node running) and formulate the transactions locally - disconnecting from the net, generating certs and signing transactions - then copy the transaction to the server to get fee size and actually send the transaction.
Skip step 6. Key Evolving Signature and KES period as it is redundant because it is just reiterating over the commands done in step 5.
Note on step 8 you can add the pledge balance to the address at a later time but your node will not produce blocks until the pledge is met. Note: for some reason the pre-calculated fee is different than what it should be - you just have to fail and use the fee that it says you should have used. If you want to use DNS use --single-host-pool-relay instead of --pool-relay-ipv4.
Once you hit step 9. Start your nodes copy kes.skey and vrf.skey from the offline usb to the computer and upload them to the server when you reconnect.
I recommend to write some startup scripts (for the block producing server, the relay and Prometheus) that log to a file like this:
#!/bin/sh
/root/.local/bin/cardano-node run \
--topology /root/config/mainnet-topology.json \
--database-path /root/data \
--socket-path /root/data/node.socket \
--host-addr <IP> \
--port <PORT> \
--config /root/config/mainnet-config.json \
--shelley-kes-key /root/keys/kes.skey \
--shelley-vrf-key /root/keys/vrf.skey \
>> /root/debug.log
And a corresponding systemd service:
# /etc/systemd/system/cardano.service
########################################
[Unit]
Description=Starts the cardano node.
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
ExecStart=/root/start.sh
Restart=on-failure
RestartSec=5
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target
Start with service cardano start
Start on boot with systemctl enable cardano
I would recommend changing minSeverity in mainnet-config.json to Warning for efficiency and log readability.
Testnet Procedure
Everything went smoothly until I got to Register stake address on the blockchain. The main issue is that you need to have some balance in your payment.addr address, and the previous step of creating a sample transaction is not optional, things in that step such as protocol.json and the output hash are referred to in this step.
The Key Evolving Signature and KES period section is redundant because it is done already in the Generate your stake pool keys section, but it is explained better in the later one.
The Configure topology files for block-producing and relay nodes section requires that we have a relay node IP address.
Relay Quickstart
Copy the binaries to the relay in /root/.local/bin/.
cd ~
# packages
apt-get update
apt-get install -y jq curl libtool git automake build-essential bc man-db -y
# Libsodium
mkdir src
cd src
git clone https://github.com/input-output-hk/libsodium
cd libsodium
git checkout 66f017f1
./autogen.sh
./configure
make
make install
cd ~
# setup paths
echo "export PATH=\"/root/.local/bin:/root/.local/bin/cardano-node:/root/.local/bin/cardano-cli:$PATH\"" >> .bashrc
echo "export CARDANO_NODE_SOCKET_PATH=/root/data/node.socket" >> .bashrc
echo "export LD_LIBRARY_PATH=\"/usr/local/lib:$LD_LIBRARY_PATH\"" >> .bashrc
echo "export PKG_CONFIG_PATH=\"/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH\"" >> .bashrc
source .bashrc
# get config
mkdir config
cd config
wget https://hydra.iohk.io/job/Cardano/cardano-node/cardano-deployment/latest-finished/download/1/mainnet-config.json
wget https://hydra.iohk.io/job/Cardano/cardano-node/cardano-deployment/latest-finished/download/1/mainnet-byron-genesis.json
wget https://hydra.iohk.io/job/Cardano/cardano-node/cardano-deployment/latest-finished/download/1/mainnet-shelley-genesis.json
wget https://hydra.iohk.io/job/Cardano/cardano-node/cardano-deployment/latest-finished/download/1/mainnet-topology.json
cd ~
# topology updater
mkdir scripts
cd scripts
wget https://raw.githubusercontent.com/cardano-community/guild-operators/alpha/scripts/cnode-helper-scripts/env
wget https://raw.githubusercontent.com/cardano-community/guild-operators/alpha/scripts/cnode-helper-scripts/topologyUpdater.sh
wget https://raw.githubusercontent.com/cardano-community/guild-operators/master/scripts/cnode-helper-scripts/gLiveView.sh
chmod +x topologyUpdater.sh
chmod +x gLiveView.sh
cd ~
# startup script
echo "#!/bin/sh
export PATH=\"/root/.local/bin:/root/.local/bin/cardano-node:/root/.local/bin/cardano-cli:$PATH\"
export CARDANO_NODE_SOCKET_PATH=/root/data/node.socket
export LD_LIBRARY_PATH=\"/usr/local/lib:$LD_LIBRARY_PATH\"
export PKG_CONFIG_PATH=\"/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH\"
cardano-node run \
--topology /root/config/mainnet-topology.json \
--database-path /root/data \
--socket-path /root/data/node.socket \
--host-addr 0.0.0.0 \
--port 3002 \
--config /root/config/mainnet-config.json \
>> /root/debug.log" > /root/start.sh
chmod +x start.sh
# Restart script
echo "#!/bin/sh
/bin/systemctl restart cardano.service" > /root/reboot-relay.sh
chmod +x /root/reboot-relay.sh
# systemd script
echo "
# /etc/systemd/system/cardano.service
########################################
[Unit]
Description=Starts the cardano node.
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
ExecStart=/root/start.sh
Restart=on-failure
RestartSec=5
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target" >> /etc/systemd/system/cardano.service
# Set to start on boot.
systemctl enable cardano
Remember to edit the Prometheus IP in /root/config/mainnet-config.json to 0.0.0.0
Add relays to /root/config/mainet-topology.json
Edit your static IP address in /root/start.sh
Edit the /root/scripts/env file to have the following configuration:
CCLI="/root/.local/bin/cardano-cli"
CNODE_PORT=3002
CONFIG="/root/config/mainnet-config.json"
TOPOLOGY="/root/config/mainnet-topology.json"
Edit the /root/scripts/topologyUpdater.sh file to include your block producing node's ip in CUSTOM_PEERS (Don't change the CNODE_HOSTNAME variable to an ip address.) Also set BATCH_AUTO_UPDATE=Y
Test the topology updater script runs by running it: /root/scripts/topologyUpdater.sh
Add it as a cron job crontab -e
0 * * * * /root/scripts/topologyUpdater.sh >> /root/debug-topology-updater.log
30 0 * * * /root/reboot-relay.sh >> /root/debug.log
Note change the second 0 on the reboot-relay script to what hour of the day you want it to run - best space out the relay restarts as far as possible from the other relays, we run it on the half hour so that topology updater does not try to query it when it is restarting.
You will need wait until the second time it can execute the topology updater (1 hour after the first time) for it to update the providers.
Run /root/scripts/gLiveView.sh to get information on how the relay is running.
Once you are ready run service cardano start to start the relay.
Stopping
The Cardano node should always be stoped with the SIGINT signal (e.g. kill -SIGINT <PROCESS>) otherwise it might not shutdown cleanly, it is designed to recover after a messy shutdown but next startup might be 30-40 minutes instead of the usual 5 minutes.
Updating Pool Registration
Pool registrations can be updated by simply sending a new pool registration certificate - no need to de-register! Just follow the same process but don't worry about the pool deposit or adding a delegation certificate.
Delegation (Offline)
If you want to delegate to a pool without being required to be online first ensure that you have access to your payment/stake keys (see script under procedure).
Generate your stake address registration certificate and your delegation certificate:
cardano-cli stake-address registration-certificate \
--stake-verification-key-file stake.vkey \
--out-file stake.cert
# Delegate to PUDIM! (or use the pool id of the pool you wish to delegate to)
cardano-cli stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--stake-pool-id pool1ujcu3myfg9wwvdyh2ks653954lamtufy3lefjs73jrr327q53j4 \
--out-file delegation.cert
Then generate a raw transaction to calculate fees:
cardano-cli transaction build-raw \
--tx-in <TxHash>#<TxIx> \
--tx-out <PAYMENT ADDRESS>+0 \
--invalid-hereafter 0 \
--fee 0 \
--out-file tx.raw \
--certificate-file stake.cert \
--certificate-file delegation.cert
Upload tx.raw to an online machine that has cardano-node running to calculate fees.
Once you know how much fees will be calculate your change using BALANCE - KEYDEPOSIT - FEES (see procedure if you don't know what pool deposit is - probably 2 Ada).
The build the transaction for real - note the order of certificate is important!
cardano-cli transaction build-raw \
--tx-in <TxHash>#<TxIx> \
--tx-out <PAYMENT ADDRESS>+<CHANGE> \
--invalid-hereafter <SLOT NO> \
--fee <FEE> \
--out-file tx.raw \
--certificate-file stake.cert \
--certificate-file delegation.cert
Sign it:
cardano-cli transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file stake.skey \
--mainnet \
--out-file tx.signed
Upload the signed transaction tx.signed to your online machine and send it!
cardano-cli transaction submit \
--tx-file tx.signed \
--mainnet
De-registering Certificates
To register the stake key you create a registration certificate which requires a key deposit, to get that deposit back follow the same steps as registering a certificate but use deregistration-certificate instead of registration-certificate and add the key deposit to the change address.
Prometheus
The documentation has pretty good information on how to get this running but I had to change the ip (under Prometheus) in mainnet-config.json to 0.0.0.0.
You may want to setup Prometheus on two different servers for redundancy so if something goes wrong with one you can still get information from the other.
You need to set the data directory otherwise it defaults to ~/data what cardano-node is using --storage.tsdb.path /root/prometheus/data
My prometheus.yml config uses this config:
scrape_configs:
- job_name: 'cardano' # To scrape data from the block producing node
scrape_interval: 5s
static_configs:
- targets: ['<Block Producing Node IP>:12798']
- job_name: 'relay' # To scrape data from the relay node
scrape_interval: 5s
static_configs:
- targets: ['<Relay Node IP>:12798']
- job_name: 'node' # To scrape data from a node exporter to monitor your linux host metrics.
scrape_interval: 5s
static_configs:
- targets: ['<Block Producing Node IP>:9100']
- job_name: 'prometheus monitor (external)' # To watch relay monitor for problems
scrape_interval: 5s
static_configs:
- targets: ['<External Monitor IP>:9090']
- job_name: 'prometheus monitor (self)' # To watch self for completeness
scrape_interval: 5s
static_configs:
- targets: ['<Block Producing Node IP>:9090']
Sending Tip to PoolTool
If you have setup the node without all the extra tools sending your tip is easiest done through the shell/systemd script found here. You can send this info from your relays.
You need to ensure minSeverity logging is set to Notice!
You may also need to modify the cadano-node and cardano-cli if the script is running from systemd:
# CARDANO BINARIES
CNODE=$(command -v cardano-node)
CCLI=$(command -v cardano-cli)
Debugging
Era Mismatch
If you get errors running some commands saying there is an era mismatch like the following:
Shelley command failed: query utxo Error: A query from a certain era was applied to a ledger from a different era: EraMismatch {ledgerEraName = "Allegra", otherEraName = "Shelley"}
This is because the ledger is on the "Allegra" soft fork while the cli is running "Shelley", you need to either update the cli and/or add a parameter to the command specifying the era like so:
cardano-cli query utxo \
--address $(cat payment.addr) \
--mainnet \
--allegra-era
Cardano Node Socket
If you have issues with cli commands referencing the cardano node socket, first ensure that the node is running (it can take a minute to generate the node.socket file in the database, then ensure the environment variable has been set.
export CARDANO_NODE_SOCKET_PATH=path/to/db/node.socket
Transactions
If your transaction fails due to a input-output mismatch, you need to check that the inputs (--tx-in) values sum to the output values (--tx-out) plus the fee's (--fee).
If your transaction fails due to output too small, you need to check that all the outputs (including change addresses) have the minimum value as set in the "minUTxOValue" parameter in the genesis block config (1000000 Lovelace or 1 Ada at the time of writing).
Floating IP/DNS
Floating IP's for some reason will not work with cardano-node so if you want the flexibility of floating IP's use DNS instead (with --single-host-pool-relay).
Guild Live View
I had an issue where the gLiveView script suddenly failed to connect to a running instance with the following error message:
COULD NOT CONNECT TO A RUNNING INSTANCE, 3 FAILED ATTEMPTS IN A ROW!
This problem appears to be with how the monitor records uptime, this should be fixed when cardano-node version 1.26 is released. A temporary fix is to prevent it from throwing the error, to do this change line 468 from:
if [[ ${uptimens} -le 0 ]]; then
To:
if false; then
Staking from a paper wallet
todo... I'll document this properly after I've done it myself
The idea is to first temporarily install a Daedalus on an offline live booted Linux and then restore a paper wallet into it with the 24 word backup phrase. Then we should be able to interact with the running wallet's associated node from the CLI to create and sign a delegation transaction. That transaction can then be broadcast to the network using any online Cardano node. This Shelley exercise explains the process of CLI delegation.
First you'll need to find the port that your Daedalus is running on:
ps x | grep cardano-node
Then you'll need to create the key files:
cardano-cli shelley address key-gen \
--verification-key-file payment.vkey \
--signing-key-file payment.skey \
--host-addr 127.0.0.1 \
--port PORT
Todo: We need to use a registered stake address that we have the keys for.
Create a delegation certificate, here the pool is the characters after the 5820 in the cborHex of the target pool's cold.vkey file.
cardano-cli shelley stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-hash POOL \
--out-file delegation.cert \
--host-addr 127.0.0.1 \
--port PORT
Draft the transaction:
cardano-cli shelley transaction build-raw \
--tx-in <UTXO>#<TxIx> \
--tx-out $(cat payment.addr)+0 \
--ttl 0 \
--fee 0 \
--out-file tx.draft \
--certificate-file delegation.cert
Calculate the fees:
cardano-cli shelley transaction calculate-min-fee \
--tx-body-file tx.draft \
--tx-in-count 1 \
--tx-out-count 1 \
--mainnet \
--witness-count 1 \
--byron-witness-count 0 \
--protocol-params-file protocol.json
Build the transaction:
cardano-cli shelley transaction build-raw \
--tx-in <UTXO>#<TxIx> \
--tx-out $(cat payment.addr)+<CHANGE IN LOVELACE> \
--ttl <TTL> \
--fee <FEE> \
--out-file tx.raw \
--certificate-file pool-registration.cert \
--certificate-file delegation.cert
Sign the transaction:
cardano-cli shelley transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file stake.skey \
--signing-key-file cold.skey \
--mainnet \
--out-file tx.signed
Submit the transaction:
cardano-cli shelley transaction submit --tx-file tx.signed --mainnet
Resources
See also
- Guild Operators - Useful scripts for assisting with running a Cardano node.
- Set up a Cardano ITN staking pool - the procedure for the Rust staking pool on the ITN
- Cardano Cafe knowledge base - another guide underway
- Stake Pool Course - Note this is using testnet so some of the processes have changed slightly.
- https://www.coincashew.com/coins/overview-ada/guide-how-to-build-a-haskell-stakepool-node