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 autoconf
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
ghcup install ghc 8.10.7
ghcup set ghc 8.10.7
ghc --version
ghcup install cabal 3.6.2.0
ghcup set cabal 3.6.2.0
cabal --version
mkdir ~/cardano-src
cd ~/cardano-src
git clone https://github.com/input-output-hk/libsodium
cd ~/cardano-src/libsodium
git checkout 66f017f1
./autogen.sh
./configure
make
sudo make install
cd ~/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 install
Append 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 all
The 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 all
DO 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 --version
Versions 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 yet
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/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 yet
Logout 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-c
to 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
syncProgress
attribute.
It indicates the percentage of the synchronization process.
Only when100.00
it 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.json
cardano-cli stake-address key-gen \
--verification-key-file=addr1.staking.vk.json \
--signing-key-file=addr1.staking.sk.json
cardano-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.shelley
cardano-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.json
cardano-cli transaction txid --tx-file=tx1.signed.json
Append 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.
noderun
runs cardano-node for the network of choice. It expects no input arguments.nodetip
returns the tip of the local blockchain. It expects no input arguments.genpaymentkeypair
generates 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
).genstakingkeypair
generates 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
).genshelleyaddress
generates 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.getutxo
gets the list of UTXOs of an address. It expects a Shelley address file name.getallutxo
gets the list of UTXOs of all Shelley addresses found in the current directory.getparams
gets current protocol params and store it onnetwork.params.json
. Used mostly for estimating transaction fee.buildtx
builds a raw transaction. It expects a Shelley address file name for being the change address. Transaction inputs, outputs and witnesses must be provided.calctxfee
calculates 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.signtx
signs the raw transaction. It expects a payment address (i.e. skey) file prefix and the transaction (raw) file prefix.submittx
submits the signed transaction to the network. It expects the transaction (signed) file prefix.witnesstx
signs 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.assembletx
assembles and sign a transaction based on its witnesses. It expects the transaction (raw) file prefix.gettxid
gets the id of a submitted transaction. It expects the transaction (signed) file prefix.viewrawtx
shows details of a raw transaction. It expects the transaction (raw) file prefix.viewsignedtx
shows details of a signed transaction. It expects the transaction (signed) file prefix.viewcbor
displays 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 (.cborHex
if 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