1. Install Cabal, GHC and Set PATH
Update packages and install Ubuntu dependencies:
Copy sudo apt-get update -y
sudo apt-get upgrade -y
GETPKG_LIST="aptitude autoconf bc build-essential curl g++ git gnupg htop jq libffi-dev libgmp-dev libncursesw5 libpq-dev libsystemd-dev libssl-dev libtinfo-dev libtinfo-dev libtool make pkg-config rsync secure-delete tcptraceroute tmux wget zlib1g-dev"
sudo apt-get -y install ${GETPKG_LIST}
Install Libsodium:
Copy mkdir $HOME /git
cd $HOME /git
git clone https://github.com/input-output-hk/libsodium
cd libsodium
git checkout 66f017f1
./autogen.sh
./configure
make
sudo make install
Install Cabal:
Copy cd
wget https://downloads.haskell.org/~cabal/cabal-install-3.2.0.0/cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz
tar -xf cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz
rm cabal-install-3.2.0.0-x86_64-unknown-linux.tar.xz cabal.sig
mkdir -p $HOME /.local/bin
mv cabal $HOME /.local/bin/
Install GHC:
Copy wget https://downloads.haskell.org/~ghc/8.6.5/ghc-8.6.5-x86_64-deb9-linux.tar.xz
tar -xf ghc-8.6.5-x86_64-deb9-linux.tar.xz
rm ghc-8.6.5-x86_64-deb9-linux.tar.xz
cd ghc-8.6.5
./configure
sudo make install
Update PATH to include Cabal and GHC and add exports. Your node's location will be in $NODE_HOME. The cluster configuration is set by $NODE_CONFIG and $NODE_BUILD_NUM.
Copy echo PATH= "$HOME/.local/bin:$PATH" >> $HOME /.bashrc
echo export LD_LIBRARY_PATH= "/usr/local/lib:$LD_LIBRARY_PATH" >> $HOME /.bashrc
echo export NODE_HOME= $HOME /cardano-my-node >> $HOME /.bashrc
echo export NODE_CONFIG=testne t >> $HOME /.bashrc
echo export NODE_BUILD_NUM=$(curl https://hydra.iohk.io/job/Cardano/iohk-nix/cardano-deployment/latest-finished/download/1/index.html | grep -e "build" | sed 's/.*build\/\([0-9]*\)\/download.*/\1/g') >> $HOME/.bashrc
source $HOME /.bashrc
Update cabal and verify the correct versions were installed successfully.
Copy cabal update
cabal -V
ghc -V
9. Generate block producer keys
Testnet ADA do not have value and to ease the build all commands are assumed to be run on BP (Block Producer) node. Do not do this on your production stake pool.
The block-producer node requires you to create 3 keys as defined in the Shelley ledger specs :
stake pool cold key (node.cert
)
stake pool hot key (kes.skey
)
stake pool VRF key (vrf.skey
)
First, make a KES key pair.
Copy cd $NODE_HOME
cardano-cli shelley node key-gen-KES \
--verification-key-file kes.vkey \
--signing-key-file kes.skey
KES (key evolving signature) keys are created to secure your stake pool against hackers who might compromise your keys.
On mainnet, you will need to regenerate the KES key every 90 days.
Cold keys must be generated and stored on your air-gapped offline machine. The cold keys are the files stored in $HOME/cold-keys.
Copy mkdir $HOME /cold-keys
pushd $HOME/cold-keys
Make a set of cold keys and create the cold counter file.
on Airgap
Copy cardano-cli shelley node key-gen \
--cold-verification-key-file node.vkey \
--cold-signing-key-file node.skey \
--operational-certificate-issue-counter node.counter
Be sure to back up your all your keys to another secure storage device. Make multiple copies.
BP
Copy pushd +1
slotsPerKESPeriod=$(cat $NODE_HOME/${NODE_CONFIG}-shelley-genesis.json | jq -r '.slotsPerKESPeriod')
echo slotsPerKESPeriod: ${slotsPerKESPeriod}
Copy slotNo=$(cardano-cli shelley query tip --testnet-magic 1097911063| jq -r '.slotNo')
echo slotNo: ${slotNo}
Find the kesPeriod by dividing the slot tip number by the slotsPerKESPeriod.
Copy kesPeriod=$((${slotNo} / ${slotsPerKESPeriod}))
echo kesPeriod: ${kesPeriod}
startKesPeriod=$(( ${kesPeriod} - 1 ))
echo startKesPeriod: ${startKesPeriod}
With this calculation, you can generate a operational certificate for your pool.
Copy kes.vkey to your cold environment .
Change the startKesPeriod value accordingly.
Stake pool operators must provide an operational certificate to verify that the pool has the authority to run. The certificate includes the operator’s signature, and includes key information about the pool (addresses, keys, etc.). Operational certificates represent the link between the operator’s offline key and their operational key.
Copy cardano-cli shelley node issue-op-cert \
--kes-verification-key-file kes.vkey \
--cold-signing-key-file $HOME/cold-keys/node.skey \
--operational-certificate-issue-counter $HOME/cold-keys/node.counter \
--kes-period $startKesPeriod \
--out-file node.cert
Copy node.cert to your hot environment .
Make a VRF key pair
Open a new terminal window and stop your BP node by running the following:
Update your BP startup script with the new KES, VRF and Operation Certificate.
Copy cat > $NODE_HOME/startBlockProducingNode.sh << EOF
DIRECTORY=\$NODE_HOME
PORT=9000
HOSTADDR=0.0.0.0
TOPOLOGY=\${DIRECTORY}/${NODE_CONFIG}-topology.json
DB_PATH=\${DIRECTORY}/db
SOCKET_PATH=\${DIRECTORY}/db/socket
CONFIG=\${DIRECTORY}/${NODE_CONFIG}-config.json
KES=\${DIRECTORY}/kes.skey
VRF=\${DIRECTORY}/vrf.skey
CERT=\${DIRECTORY}/node.cert
cardano-node run --topology \${TOPOLOGY} --database-path \${DB_PATH} --socket-path \${SOCKET_PATH} --host-addr \${HOSTADDR} --port \${PORT} --config \${CONFIG} --shelley-kes-key \${KES} --shelley-vrf-key \${VRF} --shelley-operational-certificate \${CERT}
EOF
To operate a stake pool, you need the KES, VRF key and Operational Certificate. Cold keys generate new operational certificates periodically.
Now start your block producer node.
Copy cd $NODE_HOME
./startBlockProducingNode.sh
10. Setup payment and stake keys
To create our transaction we will need the protocol parameters, so let’s query the parameters and save them in params.json
Copy cardano-cli shelley query protocol-parameters \
--testnet-magic 1097911063 \
--out-file params.json
Payment keys are used to send and receive payments and stake keys are used to manage stake delegations.
Create a new payment key pair: payment.skey & payment.vkey
Copy ###
### On BP node machine,
###
cd $NODE_HOME
cardano-cli shelley address key-gen \
--verification-key-file payment.vkey \
--signing-key-file payment.skey
Create a new stake address key pair: stake.skey & stake.vkey.
Copy ###
### On air-gapped offline machine,
###
cardano-cli shelley stake-address key-gen \
--verification-key-file stake.vkey \
--signing-key-file stake.skey
Create your stake address from the stake address verification key and store it in stake.addr
Copy ###
### On air-gapped offline machine,
###
cardano-cli shelley stake-address build \
--stake-verification-key-file stake.vkey \
--out-file stake.addr \
--testnet-magic 1097911063
Build a payment address for the payment key payment.vkey which will delegate to the stake address, stake.vkey
Copy ###
### On air-gapped offline machine,
###
cardano-cli shelley address build \
--payment-verification-key-file payment.vkey \
--stake-verification-key-file stake.vkey \
--out-file payment.addr \
--testnet-magic 1097911063
Next step is to fund your payment address. Fill in the form below with your payment.addr
https://docs.google.com/forms/d/1BmPI3PsBChSIrpKBgroOjscRXe1vI7iQDFLNGVR6y2o/
Before continuing, your nodes must be fully synchronized to the blockchain. Otherwise, you won't see your funds.
After funding your account, check your payment address balance.
Copy cardano-cli shelley query utxo \
--address $(cat payment.addr) \
--testnet-magic 1097911063
You should see output similar to this. This is your unspent transaction output (UXTO).
Copy TxHash TxIx Lovelace
----------------------------------------------------------------------------------------
c69b3e652fa237875a2c13593c3585dcd87f29233d746dd6697159c4fba17e83 0 997820683
11. Register your stake address
Create a certificate, stake.cert
, using the stake.vkey
Copy cardano-cli shelley stake-address registration-certificate \
--stake-verification-key-file stake.vkey \
--out-file stake.cert
You need to find the tip of the blockchain to set the ttl parameter properly.
Copy currentSlot = $( cardano-cli shelley query tip --testnet-magic 1097911063 | jq -r '.slotNo' )
echo Current Slot: $currentSlot
Find your balance and UTXOs .
Copy cardano-cli shelley query utxo \
--address $( cat payment.addr ) \
--testnet-magic 1097911063 > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in = ""
total_balance = 0
while read -r utxo ; do
in_addr = $( awk '{ print $1 }' <<< "${utxo}" )
idx = $( awk '{ print $2 }' <<< "${utxo}" )
utxo_balance = $( awk '{ print $3 }' <<< "${utxo}" )
total_balance = $((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr} # ${idx}
echo ADA: ${utxo_balance}
tx_in = "${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt = $( cat balance.out | wc -l )
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}
Find the keyDeposit value.
Copy keyDeposit = $( cat $NODE_HOME /params.json | jq -r '.keyDeposit' )
echo keyDeposit: $keyDeposit
Registration of a stake address certificate (keyDeposit) costs 2000000 lovelace.
Run the build-raw transaction command
The ttl value must be greater than the current tip. In this example, we use current slot + 10000.
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $( cat payment.addr ) +0 \
--ttl $(( ${currentSlot} + 10000 )) \
--fee 0 \
--out-file tx.tmp \
--certificate stake.cert
Calculate the current minimum fee:
Copy fee = $( cardano-cli shelley transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 1 \
--testnet-magic 1097911063 \
--witness-count 2 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }' )
echo fee: $fee
Ensure your balance is greater than cost of fee + keyDeposit or this will not work.
Calculate your change output.
Copy txOut = $((${total_balance}-${keyDeposit}-${fee}))
echo Change Output: ${txOut}
Build your transaction which will register your stake address.
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $( cat payment.addr ) + ${txOut} \
--ttl $(( ${currentSlot} + 10000 )) \
--fee ${fee} \
--certificate-file stake.cert \
--out-file tx.raw
Sign the transaction with both the payment and stake secret keys.
Copy cardano-cli shelley transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file stake.skey \
--testnet-magic 1097911063 \
--out-file tx.signed
Sign transaction.
Copy cardano-cli shelley transaction submit \
--tx-file tx.signed \
--testnet-magic 1097911063
12. Register your stakepool
Create your pool's metadata with a JSON file. Update with your pool information.
ticker must be between 3-5 characters in length. Characters must be A-Z and 0-9 only. description cannot exceed 255 characters in length.
Copy cat > poolMetaData.json << EOF
{
"name": "MyPoolName",
"description": "My pool description",
"ticker": "MPN",
"homepage": "https://myadapoolnamerocks.com"
}
EOF
Calculate the hash of your metadata file.
Copy cardano-cli shelley stake-pool metadata-hash --pool-metadata-file poolMetaData.json > poolMetaDataHash.txt
Now upload your poolMetaData.json to your website or a public website such as https://pages.github.com/
Find the minimum pool cost.
Copy minPoolCost = $( cat $NODE_HOME /params.json | jq -r .minPoolCost )
echo minPoolCost: ${minPoolCost}
minPoolCost is 340000000 lovelace or 340 ADA. Therefore, your --pool-cost
must be at a minimum this amount.
Copy cardano-cli shelley stake-pool registration-certificate \
--cold-verification-key-file $HOME /cold-keys/node.vkey \
--vrf-verification-key-file vrf.vkey \
--pool-pledge 100000000000 \
--pool-cost 340000000 \
--pool-margin 0.01 \
--pool-reward-account-verification-key-file stake.vkey \
--pool-owner-stake-verification-key-file stake.vkey \
--testnet-magic 1097911063 \
--pool-relay-ipv4 81.108.149.100 \
--pool-relay-port 9001 \
--metadata-url < url where you uplaoded poolMetaData.jso n > \
--metadata-hash $( cat poolMetaDataHash.txt ) \
--out-file pool.cert
Pledge stake to your stake pool.
Copy cardano-cli shelley stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-file $HOME /cold-keys/node.vkey \
--out-file deleg.cert
You need to find the tip of the blockchain to set the ttl parameter properly.
Copy currentSlot = $( cardano-cli shelley query tip --testnet-magic 1097911063 | jq -r '.slotNo' )
echo Current Slot: $currentSlot
Find your balance and UTXOs .
Copy cardano-cli shelley query utxo \
--address $( cat payment.addr ) \
--testnet-magic 1097911063 > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in = ""
total_balance = 0
while read -r utxo ; do
in_addr = $( awk '{ print $1 }' <<< "${utxo}" )
idx = $( awk '{ print $2 }' <<< "${utxo}" )
utxo_balance = $( awk '{ print $3 }' <<< "${utxo}" )
total_balance = $((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr} # ${idx}
echo ADA: ${utxo_balance}
tx_in = "${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt = $( cat balance.out | wc -l )
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}
Find the keyDeposit value.
Copy poolDeposit = $( cat $NODE_HOME /params.json | jq -r '.poolDeposit' )
echo poolDeposit: $poolDeposit
Registration of a stake address certificate (keyDeposit) costs 500000000 lovelace.
Run the build-raw transaction command
The ttl value must be greater than the current tip. In this example, we use current slot + 10000.
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $( cat payment.addr ) + $(( ${total_balance} - ${poolDeposit})) \
--ttl $(( ${currentSlot} + 10000 )) \
--fee 0 \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--out-file tx.tmp
Calculate the current minimum fee:
Copy fee = $( cardano-cli shelley transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 1 \
--testnet-magic 1097911063 \
--witness-count 3 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }' )
echo fee: $fee
Ensure your balance is greater than cost of fee + minPoolCost or this will not work.
Calculate your change output.
Copy txOut = $((${total_balance}-${poolDeposit}-${fee}))
echo txOut: ${txOut}
Build your transaction:
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $( cat payment.addr ) + ${txOut} \
--ttl $(( ${currentSlot} + 10000 )) \
--fee ${fee} \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--out-file tx.raw
Sign the transaction with both the payment and stake secret keys.
Copy cardano-cli shelley transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file $HOME /cold-keys/node.skey \
--signing-key-file stake.skey \
--testnet-magic 1097911063 \
--out-file tx.signed
Sign transaction.
Copy cardano-cli shelley transaction submit \
--tx-file tx.signed \
--testnet-magic 1097911063
14. Configure your topology files
Shelley has been launched without peer-to-peer (p2p) node discovery so that means we will need to manually add trusted nodes in order to configure our topology. This is a critical step as skipping this step will result in your minted blocks being orphaned by the rest of the network.
Publishing your Relay Node with topologyUpdater.sh
Create the topologyUpdater.sh script which publishes your node information to a topology fetch list.
Copy ###
### On relaynode1
###
cat > $NODE_HOME/topologyUpdater.sh << EOF
#!/bin/bash
# shellcheck disable=SC2086,SC2034
USERNAME=$(whoami)
CNODE_PORT=9001 # must match your relay node port as set in the startup command
CNODE_HOSTNAME="CHANGE ME" # optional. must resolve to the IP you are requesting from
CNODE_BIN="/usr/local/bin"
CNODE_HOME=$NODE_HOME
CNODE_LOG_DIR="\${CNODE_HOME}/logs"
GENESIS_JSON="\${CNODE_HOME}/${NODE_CONFIG}-shelley-genesis.json"
###########################################
NETWORKID=\$(jq -r .networkId \$GENESIS_JSON)
CNODE_VALENCY=1 # optional for multi-IP hostnames
NWMAGIC=\$(jq -r .networkMagic < \$GENESIS_JSON)
[[ "\${NETWORKID}" = "Mainnet" ]] && HASH_IDENTIFIER="--mainnet" || HASH_IDENTIFIER="--testnet-magic \${NWMAGIC}"
[[ "\${NWMAGIC}" = "764824073" ]] && NETWORK_IDENTIFIER="--mainnet" || NETWORK_IDENTIFIER="--testnet-magic \${NWMAGIC}"
export PATH="\${CNODE_BIN}:\${PATH}"
export CARDANO_NODE_SOCKET_PATH="\${CNODE_HOME}/db/socket"
blockNo=\$(cardano-cli shelley query tip \${NETWORK_IDENTIFIER} | jq -r .blockNo )
# Note:
# if you run your node in IPv4/IPv6 dual stack network configuration and want announced the
# IPv4 address only please add the -4 parameter to the curl command below (curl -4 -s ...)
if [ "\${CNODE_HOSTNAME}" != "CHANGE ME" ]; then
T_HOSTNAME="&hostname=\${CNODE_HOSTNAME}"
else
T_HOSTNAME=''
fi
if [ ! -d \${CNODE_LOG_DIR} ]; then
mkdir -p \${CNODE_LOG_DIR};
fi
curl -s "https://api.clio.one/htopology/v1/?port=\${CNODE_PORT}&blockNo=\${blockNo}&valency=\${CNODE_VALENCY}&magic=\${NWMAGIC}\${T_HOSTNAME}" | tee -a \$CNODE_LOG_DIR/topologyUpdater_lastresult.json
EOF
Add permissions and run the updater script.
Copy ###
### On relaynode1
###
cd $NODE_HOME
chmod +x topologyUpdater.sh
./topologyUpdater.sh
Update your relay node topology files
Create relay-topology_pull.sh script which fetches your relay node buddies and updates your topology file. Update with your block producer's public IP address.
Copy ###
### On relaynode1
###
cat > $NODE_HOME/relay-topology_pull.sh << EOF
#!/bin/bash
BLOCKPRODUCING_IP=<BLOCK PRODUCERS PUBLIC IP ADDRESS>
BLOCKPRODUCING_PORT=6000
curl -s -o /home/test/cardano-my-node/testnet-topology.json "https://api.clio.one/htopology/v1/fetch/?max=15&magic=1097911063&customPeers=${BLOCKPRODUCING_IP}:${BLOCKPRODUCING_PORT}:1|relays-new.cardano-testnet.iohkdev.io:3001:2"
EOF
Add permissions and pull new topology files.
Copy ###
### On relaynode1
###
chmod +x relay-topology_pull.sh
./relay-topology_pull.sh
18.4 Changing the pledge, fee, margin, etc.
Find the minimum pool cost.
block producer node
Copy minPoolCost=$(cat $NODE_HOME/params.json | jq -r .minPoolCost)
echo minPoolCost: ${minPoolCost}
minPoolCost is 340000000 lovelace or 340 ADA. Therefore, your --pool-cost
must be at a minimum this amount.
If you're changing your poolMetaData.json, remember to calculate the hash of your metadata file and re-upload the updated poolMetaData.json file.
block producer node
Copy cardano-cli shelley stake-pool metadata-hash --pool-metadata-file poolMetaData.json > poolMetaDataHash.txt
Update the below registration-certificate transaction with your desired settings.
If you have multiple relay nodes, refer to section 12 and change your parameters appropriately.
metadata-url must be no longer than 64 characters.
air-gapped offline machine
Copy cardano-cli shelley stake-pool registration-certificate \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--vrf-verification-key-file vrf.vkey \
--pool-pledge 100000000000 \
--pool-cost 340000000 \
--pool-margin 0.01 \
--pool-reward-account-verification-key-file stake.vkey \
--pool-owner-stake-verification-key-file stake.vkey \
--testnet-magic 1097911063 \
--pool-relay-ipv4 81.108.149.100 \
--pool-relay-port 9001 \
--metadata-url <url where you uplaoded poolMetaData.json> \
--metadata-hash $(cat poolMetaDataHash.txt) \
--out-file pool.cert
Here we are pledging 1000 ADA with a fixed pool cost of 345 ADA and a pool margin of 20%.
Pledge stake to your stake pool.
air-gapped offline machine
Copy cardano-cli shelley stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-file $HOME/cold-keys/node.vkey \
--out-file deleg.cert
Copy deleg.cert to your hot environment.
You need to find the tip of the blockchain to set the ttl parameter properly.
block producer node
Copy currentSlot=$(cardano-cli shelley query tip --testnet-magic 1097911063 | jq -r '.slotNo')
echo Current Slot: $currentSlot
Find your balance and UTXOs .
block producer node
Copy cardano-cli shelley query utxo \
--address $(cat payment.addr) \
--testnet-magic 1097911063 > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in=""
total_balance=0
while read -r utxo; do
in_addr=$(awk '{ print $1 }' <<< "${utxo}")
idx=$(awk '{ print $2 }' <<< "${utxo}")
utxo_balance=$(awk '{ print $3 }' <<< "${utxo}")
total_balance=$((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr}#${idx}
echo ADA: ${utxo_balance}
tx_in="${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt=$(cat balance.out | wc -l)
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}
Run the build-raw transaction command.
The ttl value must be greater than the current tip. In this example, we use current slot + 10000.
block producer node
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${total_balance} \
--ttl $(( ${currentSlot} + 10000)) \
--fee 0 \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--out-file tx.tmp
Calculate the minimum fee:
block producer node
Copy fee=$(cardano-cli shelley transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 1 \
--testnet-magic 1097911063 \
--witness-count 3 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }')
echo fee: $fee
Calculate your change output.
block producer node
Copy txOut=$((${total_balance}-${fee}))
echo txOut: ${txOut}
Build the transaction.
block producer node
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${txOut} \
--ttl $(( ${currentSlot} + 10000)) \
--fee ${fee} \
--certificate-file pool.cert \
--certificate-file deleg.cert \
--out-file tx.raw
Copy tx.raw to your cold environment.
Sign the transaction.
air-gapped offline machine
Copy cardano-cli shelley transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file $HOME/cold-keys/node.skey \
--signing-key-file stake.skey \
--testnet-magic 1097911063 \
--out-file tx.signed
Copy tx.signed to your hot environment.
Send the transaction.
block producer node
Copy cardano-cli shelley transaction submit \
--tx-file tx.signed \
--testnet-magic 1097911063
Changes take effect next epoch. After the next epoch transition, verify that your pool settings are correct.
block producer node
Copy cardano-cli shelley query ledger-state --testnet-magic 1097911063 --out-file ledger-state.json
jq -r '.esLState._delegationState._pstate._pParams."'"$(cat stakepoolid.txt)"'" //
18.9 Send a simple transaction example
If you have not downloaded and install bech32 from https://github.com/input-output-hk/bech32/releases
Copy mkdir $HOME/bech32
cd $HOME/bech32
wget https://github.com/input-output-hk/bech32/releases/download/v1.1.0/bech32-v1.1.0-linux64.tar.gz
tar -xzvf bech32-v1.1.0-linux64.tar.gz
chmod +x $HOME/bech32/bin/bech32
cd $NODE_HOME
Example sends 1000 ADA to Love2Stake address
First, find the tip of the blockchain to set the ttl parameter properly.
block producer node
Copy currentSlot=$(cardano-cli shelley query tip --testnet-magic 1097911063 | jq -r '.slotNo')
echo Current Slot: $currentSlot
block producer node
Copy amountToSend=99000000000000
echo amountToSend: $amountToSend
cho "daedalus-address" | bech32 addr_test
Set the destination address which is where you're sending funds to.
block producer node
Copy testnetDaedalusAddress=addr1qzgc2yx9p55x50ggc3jvr8tfmahx23fvj2zqmqrvyg3he0z89uja3cpcdnpstavx5f37md2xuc03v84zkphz23djd62qdyu0u5
echo ${testnetDaedalusAddress} | destinationAddress=$HOME/bech32/bin/bech32
echo destinationAddress: $destinationAddress
Find your balance and UTXOs .
block producer node
Copy cardano-cli shelley query utxo \
--address $(cat payment.addr) \
--testnet-magic 1097911063 > fullUtxo.out
tail -n +3 fullUtxo.out | sort -k3 -nr > balance.out
cat balance.out
tx_in=""
total_balance=0
while read -r utxo; do
in_addr=$(awk '{ print $1 }' <<< "${utxo}")
idx=$(awk '{ print $2 }' <<< "${utxo}")
utxo_balance=$(awk '{ print $3 }' <<< "${utxo}")
total_balance=$((${total_balance}+${utxo_balance}))
echo TxHash: ${in_addr}#${idx}
echo ADA: ${utxo_balance}
tx_in="${tx_in} --tx-in ${in_addr}#${idx}"
done < balance.out
txcnt=$(cat balance.out | wc -l)
echo Total ADA balance: ${total_balance}
echo Number of UTXOs: ${txcnt}
Run the build-raw transaction command.
block producer node
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+0 \
--tx-out ${destinationAddress}+0 \
--ttl $(( ${currentSlot} + 10000)) \
--fee 0 \
--out-file tx.tmp
Calculate the current minimum fee:
block producer node
Copy fee=$(cardano-cli shelley transaction calculate-min-fee \
--tx-body-file tx.tmp \
--tx-in-count ${txcnt} \
--tx-out-count 2 \
--testnet-magic 1097911063 \
--witness-count 1 \
--byron-witness-count 0 \
--protocol-params-file params.json | awk '{ print $1 }')
echo fee: $fee
Calculate your change output.
block producer node
Copy txOut=$((${total_balance}-${fee}-${amountToSend}))
echo Change Output: ${txOut}
Build your transaction.
block producer node
Copy cardano-cli shelley transaction build-raw \
${tx_in} \
--tx-out $(cat payment.addr)+${txOut} \
--tx-out ${destinationAddress}+${amountToSend} \
--ttl $(( ${currentSlot} + 10000)) \
--fee ${fee} \
--out-file tx.raw
Copy tx.raw to your cold environment.
Sign the transaction with both the payment and stake secret keys.
air-gapped offline machine
Copy cardano-cli shelley transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--testnet-magic 1097911063 \
--out-file tx.signed
Copy tx.signed to your hot environment.
Send the signed transaction.
block producer node
Copy cardano-cli shelley transaction submit \
--tx-file tx.signed \
--testnet-magic 1097911063
Check if the funds arrived.
block producer node
Copy cardano-cli shelley query utxo \
--address ${destinationAddress} \
--testnet-magic 1097911063
You should see output similar to this showing the funds you sent.
Copy TxHash TxIx Lovelace
----------------------------------------------------------------------------------------
100322a39d02c2ead.... 0 1000000