This document is my summary of:
- (outdated) https://iohk.zendesk.com/hc/en-us/articles/900001951646-Building-a-node-from-source
- https://developers.cardano.org/docs/get-started/installing-cardano-node
- https://github.com/mallapurbharat/cardano-tx-sample/blob/main/exercise1-simpletxfer.md
- https://github.com/mallapurbharat/cardano-tx-sample/blob/main/multutxo/multiutxo.md
sudo apt-get update -y
sudo apt-get install automake build-essential curl pkg-config libffi-dev libgmp-dev libssl-dev libtinfo-dev libsystemd-dev zlib1g-dev make g++ tmux git jq wget libncursesw5 libtool autoconfcurl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | shghcup install ghc 8.10.7
ghcup set ghc 8.10.7
ghc --versionghcup install cabal 3.6.2.0
ghcup set cabal 3.6.2.0
cabal --versionmkdir ~/cardano-srccd ~/cardano-src
git clone https://github.com/input-output-hk/libsodium
cd ~/cardano-src/libsodium
git checkout 66f017f1
./autogen.sh
./configure
make
sudo make installcd ~/cardano-src
git clone https://github.com/bitcoin-core/secp256k1
cd ~/cardano-src/secp256k1
git checkout ac83be33
./autogen.sh
./configure --enable-module-schnorrsig --enable-experimental
make
sudo make installAppend these exports to your ~/.bashrc file.
export LD_LIBRARY_PATH="/usr/local/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"Logout and login again.
The steps below are to be used ONLY THE FIRST TIME that you are building cardano-node and cardano-cli.
cd ~/cardano-src
git clone https://github.com/input-output-hk/cardano-node.git
cd ~/cardano-src/cardano-node
git fetch --all --recurse-submodules --tags
# Checks out the release/version of cardano-node that is considered official (latest) for mainnet.
git checkout $(curl -s https://api.github.com/repos/input-output-hk/cardano-node/releases/latest | jq -r .tag_name)
# If you would like to check out a different release/version then use the following command instead.
# git checkout MAJOR.MINOR.PATCH
# Example: git checkout 1.35.2
cabal update
cabal configure --with-compiler=ghc-8.10.7
cabal build allThe steps below are to be used ONLY FOR UPGRADE/REBUILD of an existing cardano-node and cardano-cli build.
It is assumed that a build (including steps of all sections above and below) was done once.
cd ~/cardano-src/cardano-node
git checkout master
git pull
git fetch --all --recurse-submodules --tags
# Checks out the release/version of cardano-node that is considered official (latest) for mainnet.
git checkout $(curl -s https://api.github.com/repos/input-output-hk/cardano-node/releases/latest | jq -r .tag_name)
# If you would like to check out a different release/version then use the following command instead.
# git checkout MAJOR.MINOR.PATCH
# Example: git checkout 1.35.2
cabal update
cabal configure --with-compiler=ghc-8.10.7
cabal build allDO NOT FORGET to run these steps if you upgraded (or rebuilt) your cardano-node.
cd ~/cardano-src/cardano-node
mkdir -p ~/.local/bin
rm -f ~/.local/bin/cardano-node
rm -f ~/.local/bin/cardano-cli
ln -s "$(./scripts/bin-path.sh cardano-node)" ~/.local/bin/cardano-node
ln -s "$(./scripts/bin-path.sh cardano-cli)" ~/.local/bin/cardano-cli
cardano-cli --version
cardano-node --versionVersions should be equal to the version/tag (e.g.
1.35.3) that was built previously.
Due to Vasil, testnet network is going to be deprecated.
To continue using it, cardano-node and cardano-cli must be on version 1.35.2 or lower.
Starting on version 1.35.3, test networks are preview and preprod.
Follow the instructions below according to the testing network you intend to use.
Before running Cardano node for the first time, you need to download the relevant configuration files.
mkdir -p "${HOME}/cardano-src/configuration/testnet"
cd "${HOME}/cardano-src/configuration/testnet"
curl -O 'https://book.world.dev.cardano.org/environments/testnet/config.json'
curl -O 'https://book.world.dev.cardano.org/environments/testnet/topology.json'
curl -O 'https://book.world.dev.cardano.org/environments/testnet/byron-genesis.json'
curl -O 'https://book.world.dev.cardano.org/environments/testnet/shelley-genesis.json'
curl -O 'https://book.world.dev.cardano.org/environments/testnet/alonzo-genesis.json'
mkdir -p "${HOME}/cardano-src/configuration/preview"
cd "${HOME}/cardano-src/configuration/preview"
curl -O 'https://book.world.dev.cardano.org/environments/preview/config.json'
curl -O 'https://book.world.dev.cardano.org/environments/preview/db-sync-config.json'
curl -O 'https://book.world.dev.cardano.org/environments/preview/submit-api-config.json'
curl -O 'https://book.world.dev.cardano.org/environments/preview/topology.json'
curl -O 'https://book.world.dev.cardano.org/environments/preview/byron-genesis.json'
curl -O 'https://book.world.dev.cardano.org/environments/preview/shelley-genesis.json'
curl -O 'https://book.world.dev.cardano.org/environments/preview/alonzo-genesis.json'
mkdir -p "${HOME}/cardano-src/configuration/preprod"
cd "${HOME}/cardano-src/configuration/preprod"
curl -O 'https://book.world.dev.cardano.org/environments/preprod/config.json'
curl -O 'https://book.world.dev.cardano.org/environments/preprod/db-sync-config.json'
curl -O 'https://book.world.dev.cardano.org/environments/preprod/submit-api-config.json'
curl -O 'https://book.world.dev.cardano.org/environments/preprod/topology.json'
curl -O 'https://book.world.dev.cardano.org/environments/preprod/byron-genesis.json'
curl -O 'https://book.world.dev.cardano.org/environments/preprod/shelley-genesis.json'
curl -O 'https://book.world.dev.cardano.org/environments/preprod/alonzo-genesis.json'
cd "${HOME}/cardano-src/cardano-node"Append these exports to your ~/.bashrc file.
Do not forget to replace API_KEY by the actual API key after registering on Blockfrost.
export CARDANO_HOME="${HOME}/cardano-src/cardano-node"
export CARDANO_CONFIG="${HOME}/cardano-src/configuration/testnet"
export CARDANO_DB="${CARDANO_HOME}/db-testnet"
export CARDANO_NODE_SOCKET_PATH="${CARDANO_DB}/node.socket"
export CARDANO_MAGIC='--testnet-magic=1097911063'
export CARDANO_ERA='--alonzo-era'
export BLOCKFROST_API_KEY='project_id: API_KEY'
export BLOCKFROST_API_URL='https://cardano-testnet.blockfrost.io/api/v0'Logout and login again.
Append these exports to your ~/.bashrc file.
Do not forget to replace API_KEY by the actual API key after registering on Blockfrost.
export CARDANO_HOME="${HOME}/cardano-src/cardano-node"
export CARDANO_CONFIG="${HOME}/cardano-src/configuration/preview"
export CARDANO_DB="${CARDANO_HOME}/db-preview"
export CARDANO_NODE_SOCKET_PATH="${CARDANO_DB}/node.socket"
export CARDANO_MAGIC='--testnet-magic=2'
export CARDANO_ERA='--babbage-era'
export BLOCKFROST_API_KEY='project_id: API_KEY'
export BLOCKFROST_API_URL='https://cardano-preview.blockfrost.io/api/v0' # Not available yetLogout and login again.
Append these exports to your ~/.bashrc file.
Do not forget to replace API_KEY by the actual API key after registering on Blockfrost.
export CARDANO_HOME="${HOME}/cardano-src/cardano-node"
export CARDANO_CONFIG="${HOME}/cardano-src/configuration/preprod"
export CARDANO_DB="${CARDANO_HOME}/db-preprod"
export CARDANO_NODE_SOCKET_PATH="${CARDANO_DB}/node.socket"
export CARDANO_MAGIC='--testnet-magic=1'
export CARDANO_ERA='--alonzo-era'
export BLOCKFROST_API_KEY='project_id: API_KEY'
export BLOCKFROST_API_URL='https://cardano-preprod.blockfrost.io/api/v0' # Not available yetLogout and login again.
cardano-node run \
--topology="${CARDANO_CONFIG}/topology.json" \
--database-path="${CARDANO_DB}" \
--socket-path="${CARDANO_NODE_SOCKET_PATH}" \
--port=3001 \
--config="${CARDANO_CONFIG}/config.json"Depending on the network, sync can take hours!
Usectrl-cto stop it.
Next time you run this command, it will continue syncing, from where you left before.
While sync is running, run this command on another terminal window.
cardano-cli query tip ${CARDANO_MAGIC}It returns a JSON object like the one below.
{
"era": "Alonzo",
"syncProgress": "100.00",
"hash": "5bb51f52da93020adefe04bb8447a394ab6670528b62d9bb01649d62d9538da8",
"epoch": 212,
"slot": 61276634,
"block": 3643388
}Pay attention to the
syncProgressattribute.
It indicates the percentage of the synchronization process.
Only when100.00it means that your copy of the blockchain is up-to-date.
Append these bash-completion commands to your ~/.bashrc file.
source <(cardano-node --bash-completion-script `which cardano-node`)
source <(cardano-cli --bash-completion-script `which cardano-cli`)Logout and login again.
The naming convention for the files below is my choice.
Actually, you can name them the way you prefer.
Nevertheless, all examples below follow this convention for order and brevity.
cardano-cli address key-gen \
--verification-key-file=addr1.payment.vk.json \
--signing-key-file=addr1.payment.sk.jsoncardano-cli stake-address key-gen \
--verification-key-file=addr1.staking.vk.json \
--signing-key-file=addr1.staking.sk.jsoncardano-cli address build ${CARDANO_MAGIC} \
--payment-verification-key-file=addr1.payment.vk.json \
--stake-verification-key-file=addr1.staking.vk.json \
--out-file=addr1.addr1.shelleycardano-cli query utxo ${CARDANO_MAGIC} --address="$(cat addr1.addr1.shelley)"The naming convention for the files below is my choice.
Actually, you can name them the way you prefer.
Nevertheless, all examples below follow this convention for order and brevity.
- Transaction input is a concatenation of
TxHash, number sign (#) andTxIx, obtained from query UTXO. - Transaction output is a concatenation of recipient address, sign (
+) and transaction amount in Lovelace. - Change address receives the remaining balance of the input UTXO(s) after deducting the transaction amount plus fees.
cardano-cli transaction build ${CARDANO_MAGIC} ${CARDANO_ERA} \
--out-file="tx$(date '+%s').raw.json" \
--tx-in='43ea8c25dd5e0c3ab33437e09642167729ce40fd1ae724ad1bd3db4d64075d5c#0' \
--tx-out="$(cat addr2.addr1.shelley)+250000000" \
--change-address="$(cat addr1.addr1.shelley)"cardano-cli transaction sign ${CARDANO_MAGIC} \
--signing-key-file=addr1.payment.sk.json \
--tx-body-file=tx1.raw.json \
--out-file=tx1.signed.json cardano-cli transaction submit ${CARDANO_MAGIC} --tx-file=tx1.signed.jsoncardano-cli transaction txid --tx-file=tx1.signed.jsonAppend these functions to your ~/.bash_aliases file (check that .bashrc loads it).
#########################
### CARDANO ALIASES ###
#########################
### GENERAL
function cardanosymlink() { cd "${CARDANO_HOME}" || exit; mkdir -p ~/.local/bin; rm -f ~/.local/bin/cardano-node; rm -f ~/.local/bin/cardano-cli; ln -s "$(./scripts/bin-path.sh cardano-node)" ~/.local/bin/cardano-node; ln -s "$(./scripts/bin-path.sh cardano-cli)" ~/.local/bin/cardano-cli; cardano-node --version; cardano-cli --version; }
function viewcbor() { local p1 p2; p1="${1:?Missing file name}"; shift; p2="${1:-.cborHex}"; shift; jq -c -r -M "${p2}" "${p1}" | cbor-diag --from=hex --to=diag; }
### NODE
function noderun() { cardano-node run --topology="${CARDANO_CONFIG}/topology.json" --database-path="${CARDANO_DB}" --socket-path="${CARDANO_NODE_SOCKET_PATH}" --port=3001 --config="${CARDANO_CONFIG}/config.json" "$@"; }
function nodetip() { cardano-cli query tip "${CARDANO_MAGIC}" "$@"; }
function getparams() { cardano-cli query protocol-parameters "${CARDANO_MAGIC}" --out-file=network.params.json; }
### ADDRESS
function genpaymentkeypair() { local p1; p1="${1:-addr$(date '+%s')}"; shift; cardano-cli address key-gen --verification-key-file="${p1}.payment.vk.json" --signing-key-file="${p1}.payment.sk.json" "$@"; }
function genstakingkeypair() { local p1; p1="${1:-addr$(date '+%s')}"; shift; cardano-cli stake-address key-gen --verification-key-file="${p1}.staking.vk.json" --signing-key-file="${p1}.staking.sk.json" "$@"; }
function genshelleyaddress() { local p1 p2 p3; p1="${1:?Missing address file prefix}"; shift; p2="${1:-${p1}}"; shift; if [ "${p2}" == "NONE" ]; then p2=''; p3=(); else p3=("--stake-verification-key-file" "${p2}.staking.vk.json"); fi; cardano-cli address build "${CARDANO_MAGIC}" --payment-verification-key-file="${p1}.payment.vk.json" ${p3[@]} --out-file="${p1}${p2:+.$p2}.shelley" "$@"; }
function getpaymenthash() { local p1; p1="${1:?Missing address file prefix}"; shift; cardano-cli address key-hash --payment-verification-key-file="${p1}.payment.vk.json" "$@"; }
### ADDRESS DETAILS
function getutxo() { local p1; p1="${1:?Missing address file name}"; shift; cardano-cli query utxo "${CARDANO_MAGIC}" --address="$(cat "${p1}")" "$@"; }
function getallutxo() { local p1; for p1 in addr*.shelley; do printf '>>> %s\n' "${p1}"; getutxo "${p1}"; echo; done; }
### TRANSACTION
function buildtx() { local p1 id; p1="${1:?Missing change address file name}"; shift; id="tx$(date '+%s')"; cardano-cli transaction build "${CARDANO_MAGIC}" "${CARDANO_ERA}" --out-file="${id}.raw.json" --change-address="$(cat "${p1}")" "$@"; printf '%s' "${id}"; }
function signtx() { local p1 p2; p1="${1:?Missing address file prefix}"; shift; p2="${1:?Missing transaction file prefix}"; shift; cardano-cli transaction sign "${CARDANO_MAGIC}" --signing-key-file="${p1}.payment.sk.json" --tx-body-file="${p2}.raw.json" --out-file="${p2}.signed.json" "$@"; }
function submittx() { local p1; p1="${1:?Missing transaction file prefix}"; shift; cardano-cli transaction submit "${CARDANO_MAGIC}" --tx-file="${p1}.signed.json" "$@"; gettxid "${p1}"; }
function witnesstx() { local p1 p2; p1="${1:?Missing address file prefix}"; shift; p2="${1:?Missing transaction file prefix}"; shift; cardano-cli transaction witness "${CARDANO_MAGIC}" --signing-key-file="${p1}.payment.sk.json" --tx-body-file="${p2}.raw.json" --out-file="${p2}.witness.${p1}.json" "$@"; }
function assembletx() { local p1 args w; p1="${1:?Missing transaction file prefix}"; shift; args=""; for w in "${p1}".witness.*.json; do args+='--witness-file='${w}' '; done; cardano-cli transaction assemble --tx-body-file="${p1}.raw.json" --out-file="${p1}.signed.json" ${args} "$@"; gettxid "${p1}"; }
function calctxfee() { local p1 p2 p3 p4; p1="${1:?Missing transaction file prefix}"; shift; p2="${1:?Missing # of input TXs}"; shift; p3="${1:?Missing # of output TXs}"; shift; p4="${1:?Missing # of witnesses}"; shift; getparams; cardano-cli transaction calculate-min-fee "${CARDANO_MAGIC}" --protocol-params-file="network.params.json" --tx-body-file="${p1}.raw.json" --tx-in-count="${p2}" --tx-out-count="${p3}" --witness-count="${p4}" "$@"; }
### TRANSACTION DETAILS
function gettxid() { local p1; p1="${1:?Missing transaction file prefix}"; shift; cardano-cli transaction txid --tx-file="${p1}.signed.json" "$@"; }
function viewrawtx() { local p1; p1="${1:?Missing transaction file prefix}"; shift; cardano-cli transaction view --tx-body-file="${p1}.raw.json" "$@"; }
function viewsignedtx() { local p1; p1="${1:?Missing transaction file prefix}"; shift; cardano-cli transaction view --tx-file="${p1}.signed.json" "$@"; }
function gettxmeta() { local p1; p1="${1:?Missing transaction file prefix}"; shift; curl -s -H "${BLOCKFROST_API_KEY}" "${BLOCKFROST_API_URL}/txs/$(gettxid "${p1}")/metadata" | jq; }
###Logout and login again.
Most aliases/functions below accepts extra parameters after the expected ones.
noderunruns cardano-node for the network of choice. It expects no input arguments.nodetipreturns the tip of the local blockchain. It expects no input arguments.genpaymentkeypairgenerates a payment address. It expects an address prefix (e.g.addr1) otherwise it will generate it, based on the current Unix epoch (e.g.addr1655650712).genstakingkeypairgenerates a staking address. It expects an address prefix (e.g.addr1) otherwise it will generate it, based on the current Unix epoch (e.g.addr1655650712).genshelleyaddressgenerates a Shelley address out of payment and staking addresses. It expects two address prefixes, first for the payment address, second for the staking address. If second is not provided, it assumes that it is equal to the first one.getutxogets the list of UTXOs of an address. It expects a Shelley address file name.getallutxogets the list of UTXOs of all Shelley addresses found in the current directory.getparamsgets current protocol params and store it onnetwork.params.json. Used mostly for estimating transaction fee.buildtxbuilds a raw transaction. It expects a Shelley address file name for being the change address. Transaction inputs, outputs and witnesses must be provided.calctxfeecalculates the minimum fee of a raw transaction. It expects the transaction (raw) file prefix, the count of transaction inputs, the count of transaction outputs and the count of transaction witnesses.signtxsigns the raw transaction. It expects a payment address (i.e. skey) file prefix and the transaction (raw) file prefix.submittxsubmits the signed transaction to the network. It expects the transaction (signed) file prefix.witnesstxsigns the raw transaction by a witness. It expects a payment address (i.e. skey of the witness) file prefix and the transaction (raw) file prefix.assembletxassembles and sign a transaction based on its witnesses. It expects the transaction (raw) file prefix.gettxidgets the id of a submitted transaction. It expects the transaction (signed) file prefix.viewrawtxshows details of a raw transaction. It expects the transaction (raw) file prefix.viewsignedtxshows details of a signed transaction. It expects the transaction (signed) file prefix.viewcbordisplays the content of a CBOR hex string from a JSON file. It expects a JSON file name (e.g. transaction files) and the JSON-Path to the property that holds the CBOR hex string (.cborHexif JSON-Path is not provided).
$ genpaymentkeypair addr1
$ genstakingkeypair addr1
$ genshelleyaddress addr1
$ ls -l addr1.*
-rw------- 1 feamcor feamcor 108 Jun 19 08:13 addr1.addr1.shelley
-rw------- 1 feamcor feamcor 180 Jun 19 08:03 addr1.payment.sk.json
-rw------- 1 feamcor feamcor 190 Jun 19 08:03 addr1.payment.vk.json
-rw------- 1 feamcor feamcor 176 Jun 19 08:04 addr1.staking.sk.json
-rw------- 1 feamcor feamcor 186 Jun 19 08:04 addr1.staking.vk.json$ genpaymentkeypair addr2
$ genshelleyaddress addr2 addr1
$ ls -l addr2.*
-rw------- 1 feamcor feamcor 108 Jun 19 08:29 addr2.addr1.shelley
-rw------- 1 feamcor feamcor 180 Jun 19 08:29 addr2.payment.sk.json
-rw------- 1 feamcor feamcor 190 Jun 19 08:29 addr2.payment.vk.json$ getutxo addr1.addr1.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
7156c3e8675fac899ae8ff63f86029b77598b4762c7ba0f35ad11060d93daa5d 1 100000000 lovelace + TxOutDatumNone
$ getutxo addr2.addr1.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
3fa42233914558204a72eba6230938a5ec6a6faf9aa417148a0fc416f042ab20 0 499312344 lovelace + TxOutDatumNone
$ getutxo addr3.addr3.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
3fa42233914558204a72eba6230938a5ec6a6faf9aa417148a0fc416f042ab20 1 200000000 lovelace + TxOutDatumNone
$ getutxo addr4.addr4.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
3fa42233914558204a72eba6230938a5ec6a6faf9aa417148a0fc416f042ab20 2 200000000 lovelace + TxOutDatumNone$ buildtx addr2.addr1.shelley \
--witness-override=3 \
--tx-in='3fa42233914558204a72eba6230938a5ec6a6faf9aa417148a0fc416f042ab20#0' \
--tx-in='3fa42233914558204a72eba6230938a5ec6a6faf9aa417148a0fc416f042ab20#1' \
--tx-in='3fa42233914558204a72eba6230938a5ec6a6faf9aa417148a0fc416f042ab20#2' \
--tx-out="$(cat addr1.addr1.shelley)+150000000" \
--tx-out="$(cat addr3.addr3.shelley)+150000000" \
--tx-out="$(cat addr4.addr4.shelley)+150000000"
Estimated transaction fee: Lovelace 185961
$ witnesstx addr2 tx1656248482
$ witnesstx addr3 tx1656248482
$ witnesstx addr4 tx1656248482
$ assembletx tx1656248482
$ submittx tx1656248482
Transaction successfully submitted.$ getutxo addr1.addr1.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
7156c3e8675fac899ae8ff63f86029b77598b4762c7ba0f35ad11060d93daa5d 1 100000000 lovelace + TxOutDatumNone
907e746cc8d743b68b8c833ea0bb4aa2705149bcd642120125116c7cfc29033c 1 150000000 lovelace + TxOutDatumNone
$ getutxo addr2.addr1.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
907e746cc8d743b68b8c833ea0bb4aa2705149bcd642120125116c7cfc29033c 0 449126383 lovelace + TxOutDatumNone
$ getutxo addr3.addr3.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
907e746cc8d743b68b8c833ea0bb4aa2705149bcd642120125116c7cfc29033c 2 150000000 lovelace + TxOutDatumNone
$ getutxo addr4.addr4.shelley
TxHash TxIx Amount
--------------------------------------------------------------------------------------
907e746cc8d743b68b8c833ea0bb4aa2705149bcd642120125116c7cfc29033c 3 150000000 lovelace + TxOutDatumNone
Very helpful, thanks @feamcor