Transaction generator: Usage Guide - input-output-hk/iohk-monitoring-framework GitHub Wiki

This page describes how to build transaction generator, launch it and check the results.

Generator command

Currently transaction generator is a part of cardano-cli executable and corresponds to generate-txs subcommand.

Build generator

$ git clone [email protected]:input-output-hk/cardano-node.git
$ cd cardano-node
$ cabal new-update
$ cabal new-build all

Now cardano-cli executable is available via cabal new-run command.

Launch a Cluster

The purpose of transaction generator is to generate a lot amount of transactions, so we need a cluster from cardano-nodes to submit these transactions to. Currently we can run minimal local cluster (only 3 nodes) using scripts/shelley-testnet.sh from the root of cardano-node repository. Example of command:

$ tmux
$ ./scripts/shelley-testnet.sh

Please note that you have to launch this cluster in the tmux session. By default you will see 4 tmux panes with 3 running cardano-nodes.

Launch a Generator

To launch a generator use scripts/generator.sh script from the root of cardano-node repository. Example of command:

$ ./scripts/generator.sh --target-node-id 0

where -n 0 is an index of the node we're going to talk with. Since we already have a working cluster (see above) we have to choose some node to submit generated transactions to, by default we take the first node.

CLI arguments

There are following CLI arguments we use to set generator up:

  1. --target-node-id is an id of node we'll send transactions to. Can be specified multiple times.
  2. --sig-key is a path to .key-file (which contains signing key).
  3. --num-of-txs is a number of benchmarking transactions we'll generate.
  4. --inputs-per-tx is a number of inputs per 1 benchmarking transaction.
  5. --outputs-per-tx is a number of outputs per 1 benchmarking transaction.
  6. --tx-fee is a fee per transaction (in Lovelaces).
  7. --tps is a TPS (transactions per second) rate.
  8. --add-tx-size is an additional size of transaction, using TxAttributes (in bytes).

Please note that currently we have to provide at least 3 keys (using --sig-key argument): for genesis address, for source address and for recipient address.

To get help info about generator-related arguments use this command:

$ stack exec -- cardano-cli generate-txs --help

or this one:

$ cabal new-run -- cardano-cli generate-txs --help

Transactions

Transacrion generator generates 3 "kinds" of transactions:

  1. genesis transaction,
  2. splitting transactions,
  3. benchmarking transactions.

Genesis transaction is a very first transaction: we move huge amount of ADA from genesisAddress to sourceAddress. And sourceAddress will be used as a source for all further transactions.

The purpose of splitting transactions is to split huge amount of ADA on sourceAddress to sufficient number of "coins" we will use for further transactions. Technically we split initial amount of money M to N equal parts, as a result we'll have N UTxO entries, and alltogether these entries will contain the same amount M (e.g. 1 initial entry * 1000 ADA -> 10 entries * 100 ADA). These UTxO entries will be used as inputs for benchmarking transactions.

Benchmarking transactions are the main ones because they will be used for a system benchmarking. CLI arguments --num-of-txs and --outputs-per-tx specify total number of benchmarking transactions and number of outputs in each of them. Currently each benchmarking transaction has only 1 input and K outputs (corresponding to --outputs-per-tx value), each output sends fixed amount of money to recipientAddress.

Check blockchain: local Cardano Explorer

Since we have a local cluster we are sending transactions to, it is possible to launch cardano-explorer-node to check our local blockchain.

It is recommended to use nix to build cardano-explorer-node:

$ git clone [email protected]:input-output-hk/cardano-explorer.git
$ cd cardano-explorer
$ nix-build -A scripts.mainnet.exporter -o launch_mainnet_exporter

Then set CARDANO_NODE_SOCKET_PATH variable:

export CARDANO_NODE_SOCKET_PATH=/path/to/socket

where /path/to/socket is an absolute path to a socket of some node from our local cluster. For example, in my case it is:

export CARDANO_NODE_SOCKET_PATH=/home/shevchenko/cardano-node/socket/node1.socket

It will be used to connect to the node and listen to the blockchain.

Now explorer can be launched by launch_mainnet_exporter script. But please make sure it contains a valid genesis hash value! cardano-explorer-node executable has a CLI argument --genesis-hash, and this value should be equal to genesis hash of the node we are going to connect to. To get this hash use following commands:

$ cd cardano-node
$ cabal new-run -v0 -- cardano-cli --log-config configuration/log-configuration.yaml --real-pbft print-genesis-hash --genesis-json configuration/33873/genesis.json --socket-path socket/node1.socket

You will see something like this:

33873aeaf8a47fefc7c2ea3f72e98a04459e07ec3edfb63c9ca709f540f69503

This value should be provided to cardano-explorer-node via CLI argument --genesis-hash.

In case of success, right after launching you will see something like this:

$ ./launch_mainnet_exporter
/home/shevchenko/Code/cardano-explorer/pgpass
[iohk.cardano.explorer-db-node:Info:1] [2019-09-25 06:56:43.97 UTC] Initial genesis distribution present and correct
[iohk.cardano.explorer-db-node:Info:1] [2019-09-25 06:56:44.00 UTC] Total genesis supply of Ada: 7998949166.000000
[iohk.cardano.explorer-db-node:Info:1] [2019-09-25 06:56:44.00 UTC] Starting node client
[iohk.cardano.explorer-db-node:Info:1] [2019-09-25 06:56:44.00 UTC] localInitiatorNetworkApplication: connecting to node via "/home/shevchenko/Code/cardano-node/socket/node1.socket"
[iohk.cardano.explorer-db-node:Info:39] [2019-09-25 06:56:44.00 UTC] Starting chainSyncClient
[iohk.cardano.explorer-db-node:Info:39] [2019-09-25 06:56:44.01 UTC] Explorer DB tip is at slot 131826

Cardano Explorer DB

Since Cardano Explorer uses database to store an information, it is assumed that you have installed and configured PostgreSQL. You can find database schema here.

To drop Explorer's database completely:

postgres@linux:~$ dropdb cexplorer -U cexplorer

To create Explorer's database from scratch:

postgres@linux:~$ createdb cexplorer -U cexplorer

To work with this database:

postgres@linux:~$ psql cexplorer -U cexplorer

Current structure of this database is this one:

cexplorer=# \dt
              List of relations
 Schema |      Name      | Type  |   Owner
--------+----------------+-------+-----------
 public | block          | table | cexplorer
 public | meta           | table | cexplorer
 public | schema_version | table | cexplorer
 public | slot_leader    | table | cexplorer
 public | tx             | table | cexplorer
 public | tx_in          | table | cexplorer
 public | tx_out         | table | cexplorer
(7 rows)

To check blocks:

cexplorer=# SELECT * FROM block;

As you can see, hash of the first block is equal to --genesis-hash (see above).

Cardano Explorer DB: troubleshooting

If you stuck with an error psql: FATAL: Peer authentication failed for user "cexplorer", you probably need to change PostgreSQL configuration files. Examples:

$ cat /etc/postgresql/11/main/pg_hba.conf
local all all ident map=explorer-users
local all shevchenko trust
local all all ident

host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5
$ cat /etc/postgresql/11/main/pg_ident.conf
explorer-users /root cexplorer
explorer-users /postgres cexplorer
explorer-users /shevchenko cexplorer
$ cat /etc/postgresql/11/main/postgresql.conf
data_directory = '/var/lib/postgresql/11/main'          
hba_file = '/etc/postgresql/11/main/pg_hba.conf'        
ident_file = '/etc/postgresql/11/main/pg_ident.conf'    
log_destination = 'stderr'
listen_addresses = 'localhost'
port = 5432

Work with real (distributed) cluster

Running transaction generator on the local cluster (which is launched on the one computer) is the simplest possible way, but in this case we'll get "an ideal values" without any network latency. Real-life measurements can be obtained only from distributed cluster: nodes are working on the different computers in the different world regions.

Set up and run a cluster

There is no describing of this procedure in this document: it is assumed that such a cluster already exists and works, it is responsibility of DevOps team to do it.

As an example there is the simplest possible (physically distributed) cluster from 3 nodes working in three world regions.

Login to staging server

Since the servers (which host running nodes) exist in AWS environment, it is possible to get an access to them from staging server. Please make sure you have an access to it.

Login to cardano-deployer server as staging:

$ ssh [email protected]
Last login: Thu Oct  3 10:24:15 2019 from 37.252.89.158
staging@cardano-deployer:~$

Benchmarking directory structure

Currently, there's a directory dshevchenko in the root of cardano-deployer server with the following structure:

dshevchenko/
    cardano-node
        ... Code of the node, for cardano-cli
    cert/
        delegation-cert.000.json
        delegation-cert.001.json
        delegation-cert.002.json
    genesis.json
    keys/
        delegate-keys.000.key
        delegate-keys.001.key
        delegate-keys.002.key
    log-config/
        log-config-0.yaml
        log-config-1.yaml
        log-config-2.yaml
    topology/
        topology-node-1.json
        topology-node-2.json
        topology-node-3.json

cardano-node will be used to build cardano-cli, because transaction generator is a part of it.

Login to real node server

Now it is possible to login to server which hosts some of nodes. For example, there are 3 nodes in the current cluster: a1, b1, c1. To login to the server which hosts a1 node use this command:

staging@cardano-deployer:~$ nixops ssh -d shelley-aws a1

[root@a1:~]#

Check the node

Let's check if the node is running and what configuration it is running with:

[root@a1:~]# ps aux | grep cardano-node
cardano+ 23120  0.2 16.2 1074462292 80480 ?    Ssl  Nov07   3:19 /nix/store/aac92zm4jqy76vh626xzdfni9ndcd88a-cardano-node-exes/bin/cardano-node --genesis-file /nix/store/bpnvc57j8v5s3imc2yi7iy6050qnggbd-genesis.json --genesis-hash d3931233c9b1e22d18b94bed9713a929186ca0ef7e7a187fc2ab612a60a8e69a --log-config /nix/store/b4skln4dbvx0n4yi25khd3xl6mgzzm4i-log-config.json --database-path /var/lib/cardano-node/db-testnet --socket-dir /run/cardano-node --topology /nix/store/33mmhh97lfx7d1x70djg1ba46s6k25xh-topology.yaml --real-pbft --node-id 0 --host-addr 172.31.35.144 --port 3001 --pbft-signature-threshold 0.9 --signing-key /nix/store/y8k4ia7l4rk2caz3xlpby573a3bv3xy6-delegate-keys.000.key --delegation-certificate /nix/store/9yisxnpm6a4pva3gjv7w515nbsbv4y21-delegation-cert.000.json

Read the log

It is possible to read a log produced by a node:

[root@a1:~]# journalctl -f -u cardano-node

Drop the -f flag to get the full history. You can also add --since 2019-09-01 and --until 2019-10-01 to restrict it to a time-range, for example:

[root@a1:~]# journalctl -u cardano-node --since 2019-10-01 --until 2019-10-03 > sample.txt

and then read this file:

[root@a1:~]# vi sample.txt

Run transaction generator

Since transaction generator should submit transactions to the cluster, it must connect to some "target" node to submit transactions to. Currently the only way to do it is to launch transaction generator right on the server where "target" node is running.

IMPORTANT: this behavior is not the best one, because in this case we'll get unfair results. In the future cluster's configuration will be changed and transaction generator will be launched on another server.

To launch transaction generator we have to use parameters corresponding to the running node (and we already saw these parameters from ps aux | grep cardano-node command), so:

cabal new-run -- exe:cardano-cli --log-config ../log-config/log-config-0.yaml --signing-key ../keys/delegate-keys.000.key --delegation-certificate ../cert/delegation-cert.000.json --real-pbft --genesis-file ../genesis.json --genesis-hash d3931233c9b1e22d18b94bed9713a929186ca0ef7e7a187fc2ab612a60a8e69a generate-txs --topology ../topology/topology-node-1.json --num-of-txs 2 --inputs-per-tx 1 --outputs-per-tx 1 --tx-fee 1000000 --tps 10 --add-tx-size 100 --sig-key ../keys/delegate-keys.000.key --sig-key ../keys/delegate-keys.001.key --sig-key ../keys/delegate-keys.002.key --target-node-id 0 --node-id 0

IMPORTANT: Please note that currently --sig-keys are taken from the root of current server. This is because these keys were copied manually from cardano-deployer server. It is temporary solution!

Re-deploy a cluster

Go to cluster's subdirectory:

staging@cardano-deployer:~$ cd david/cardano-ops

Then:

staging@cardano-deployer:~$ nix-shell

Now update cardano-nodes using particular branch:

staging@cardano-deployer:~$ niv update cardano-node -b master

where master is the name of branch.

Before deploy please do this export:

export NIX_PATH="nixpkgs=$(nix eval '(import ./nix {}).path')"

Finally deploy it:

staging@cardano-deployer:~$ nixops deploy -d shelley-aws

In case of success you will see something like this:

...
shelley-aws> deployment finished successfully

Please note that servers are working on NixOS, so all the paths to executables are immutable by definition. Make sure that after re-deployment you check the new /nix/store-path to executables cardano-node and cardano-cli.

Misc

Copy delegate keys

To copy delegate key to particular server (for example, a1), use this command

staging@cardano-deployer:~$ nixops scp -d shelley-aws --to a1 dshevchenko/keys/delegate-keys.000.key /root

Clean nodes' databases

To clean up nodes' databases, use these commands. First of all, stop the nodes:

staging@cardano-deployer:~$ nixops ssh-for-each -d shelley-aws systemctl stop cardano-node

Then wipe the state:

staging@cardano-deployer:~$ nixops ssh-for-each -d shelley-aws -- rm -rf /var/lib/cardano-node/db-testnet-0

Now start nodes again:

staging@cardano-deployer:~$ nixops ssh-for-each -d shelley-aws systemctl start cardano-node

cardano-explorer without Nix

This is a temporary draft, devops will change it soon.

$ stack build
$ cat launch_mainnet_exporter.sh 
#!/bin/bash

mkdir -p log-dir

# work around a bug in cardano-node
mkdir -p configuration
cp -f /home/shevchenko/Code/cardano-node/configuration/log-configuration.yaml configuration/log-configuration.yaml
# end of work-around

stack exec -- cardano-explorer-node --log-config /home/shevchenko/Code/cardano-node/configuration/log-configuration.yaml \
  --genesis-hash db60f5877ac3032b401e53bf5c91d4fe84b6cb993582ffcf4c10828407127386 \
  --genesis-file /home/shevchenko/Code/cardano-node/configuration/b0109/genesis.json \
  --socket-path /home/shevchenko/Code/cardano-node/socket/node1.socket \
  --schema-dir /home/shevchenko/Code/cardano-explorer/schema
$ cat pgpass 
localhost:5432:cexplorer:cexplorer:cexplorer
$ PGUSER=cexplorer PGHOST=localhost PGPORT=5432 PGPASSFILE=pgpass ./launch_mainnet_exporter.sh
⚠️ **GitHub.com Fallback** ⚠️