Skip to content
This repository has been archived by the owner on Mar 1, 2019. It is now read-only.

Building Running and Testing a Wallet Node

Jonathan Knowles edited this page Feb 4, 2019 · 2 revisions

Building, running and testing a wallet node connected to staging mainnet

Prerequisites

This guide assumes that you have clones of the cardano-sl and cardano-wallet repositories within a common parent directory:

$ git clone https://github.com/input-output-hk/cardano-sl
$ git clone https://github.com/input-output-hk/cardano-wallet

Build cardano-sl-tools

$ cd cardano-sl
# Linux:
$ stack build cardano-sl-tools 
# macOS:
$ stack build cardano-sl-tools --ghc-options=-optl-Wl,-dead_strip_dylibs

Generate new TLS certificates:

mkdir -p ../cardano-wallet/state-staging/tls/{client,server}
stack exec cardano-x509-certificates -- \
  --server-out-dir  ../cardano-wallet/state-staging/tls/server \
  --clients-out-dir ../cardano-wallet/state-staging/tls/client \
  -k default -c lib/configuration.yaml

Build the wallet server:

cd ../cardano-wallet
# Linux:
$ stack build cardano-wallet:cardano-wallet-server
# macOS:
$ stack build cardano-wallet:cardano-wallet-server --ghc-options=-optl-Wl,-dead_strip_dylibs

This step can take some time, especially if you've never built the wallet before.

Run a node:

If the above steps completed successfully, we should now be ready to run a node!

Issue the following command (from within the cardano-wallet directory):

stack exec -- cardano-wallet-server                               \
  --configuration-key       mainnet_dryrun_full                   \
  --configuration-file      ../cardano-sl/lib/configuration.yaml  \
  --db-path                 ./state-staging/db                    \
  --wallet-db-path          ./state-staging/wallet-db             \
  --tls-ca-cert             ./state-staging/tls/server/ca.crt     \
  --tls-node-client-cert    ./state-staging/tls/client/client.crt \
  --tls-node-client-key     ./state-staging/tls/client/client.key \
  --tls-wallet-server-cert  ./state-staging/tls/server/server.crt \
  --tls-wallet-server-key   ./state-staging/tls/server/server.key \
  --topology                ./topology-examples/testnet.yaml      \
  --system-start            $(($(date +%s) +10))                  \
  --node-id                 wallet-node                           \
  --node-api-address        127.0.0.1:8080                        \
  --wallet-api-address      127.0.0.1:8090                        \
  --wallet-doc-address      127.0.0.1:8100                        \
  --rebuild-db                                                    \
  --wallet-rebuild-db

Notes:

  • When running for the first time, we ask the server to build both the node and wallet databases (with the --rebuild-db and --wallet-rebuild-db options respectively). These options can be omitted on further runs, in which case the existing databases will be reused.

  • With the above command, the node API, wallet API and wallet documentation servers will listen on localhost (127.0.0.1) only. If instead you want to connect from another machine, change 127.0.0.1 to 0.0.0.0.

  • In the above example, we connect to the staging main net (configuration-key is set to mainnet_dryrun_full)

  • The --db-path and --wallet-db-path options can actually point to any directory of choice. By specifying them, we have required that both node and wallet DBs will use persistent storage.

Querying the wallet API

If all is well, we should now be able to query the wallet API:

$ curl https://127.0.0.1:8090/api/v1/wallets --cert ./state-staging/tls/edge/client.pem --cacert ./state-staging/tls/edge/ca.crt

Generating new mnemonics

Mnemonics (needed for example when creating wallet) can be generated using :

$ cd cardano-sl

# Linux:
$ stack build cardano-sl-tools
# macOS:
$ stack build cardano-sl-tools --ghc-options=-optl-Wl,-dead_strip_dylibs

$ stack exec cardano-generate-mnemonic

Testing wallet-node attached to mainnet setup

Push mechanism based on readerT, right now default one

Starting wallet and node attached to mainnet can be realized by calling :

$ cd cardano-wallet
$ stack exec -- cardano-wallet-server   \
    --configuration-file              ../cardano-sl/lib/configuration.yaml  \
    --configuration-key               mainnet_dryrun_full   \
    --db-path                         ../state-mainnet/db   \
    --node-id                         wallet-node   \
    --node-tls-ca-cert                ./state-staging/tls/edge/ca.crt   \
    --node-tls-client-cert            ./state-staging/tls/edge/server.crt   \
    --node-tls-key                    ./state-staging/tls/edge/server.key  \
    --system-start                    $(($(date +%s) +10))   \
    --topology                        ./topology-examples/testnet.yaml   \
    --wallet-address                  127.0.0.1:8090   \
    --wallet-db-path                  ../state-mainnet/wallet-db   \
    --wallet-node-api-address         127.0.0.1:8080 \
    --tlsca                           ./state-staging/tls/edge/ca.crt  \
    --tlskey                          ./state-staging/tls/edge/server.key \
    --tlscert                         ./state-staging/tls/edge/server.crt \
    --rebuild-db \
    --wallet-rebuild-db

Both node and wallet dbs are empty and the node starts from scratch to sync with mainnet (see Fig 1).

Fig. 1. The situation when the new node and wallet start from scratch

Fig. 1. The situation when the new node and wallet start from scratch

The node starts to build its database (persisted in directory indicated in --db-path and denoted here with cylinder symbol with block header range that represent the blocks consumed), wallet persists in directory pinpointed by --wallet-db-path and presented like for the node - although wallet does not store blocks but its state with sql db and respective checkpoints). In push mechanism, the node holds responsibility for block syncing to a wallet. The wallet subscribes for block syncing to the node. Hence, when the node downloads the batch of blocks the same batch is pushed to the wallet (Fig. 2).

Fig. 2. The first batch of blocks accommodated by the  node and pushed to the wallet

Fig. 2. The first batch of blocks accommodated by the node and pushed to the wallet

When the wallet-node pair is stopped and then restarted (notice the absence of --rebuild-db and --wallet-rebuild-db flags):

$ cd cardano-wallet
$ stack exec -- cardano-wallet-server   \
    --configuration-file              ../cardano-sl/lib/configuration.yaml  \
    --configuration-key               mainnet_dryrun_full   \
    --db-path                         ../state-mainnet/db   \
    --node-id                         wallet-node   \
    --node-tls-ca-cert                ./state-staging/tls/edge/ca.crt   \
    --node-tls-client-cert            ./state-staging/tls/edge/server.crt   \
    --node-tls-key                    ./state-staging/tls/edge/server.key  \
    --system-start                    $(($(date +%s) +10))   \
    --topology                        ./topology-examples/testnet.yaml   \
    --wallet-address                  127.0.0.1:8090   \
    --wallet-db-path                  ../state-mainnet/wallet-db   \
    --wallet-node-api-address         127.0.0.1:8080 \
    --tlsca                           ./state-staging/tls/edge/ca.crt  \
    --tlskey                          ./state-staging/tls/edge/server.key \
    --tlscert                         ./state-staging/tls/edge/server.crt

the node resumes downloading blocks from what it has in db. The Fig. 3 shows restarting result at time t2. db before restart had h1-h5 state (the wallet likewise) and restarted on top of that, ie., downloading the block with h6 header and as a consequence persisting h1-h6 state. The h6 block was also pushed to the wallet.

Fig. 3. The restart of the node without databases rebuilding

Fig. 3. The restart of the node without databases rebuilding

The node db persistence is closely connected with block listener capability and how push mechanism works. If we stop wallet-node pair and replace the node db with h1-h5 db with wallet db intact and restart wallet-node the node will resume operation as before. It will accomodate h6 block, persist h1-h6 state and push h6 block once again to the wallet. If the wallet is idempotent to apply blocks then this is ok, although superfluous.

The another behavior takes place when the contrary happens. The node has h1-h6 state persisted and the wallet has, for example, h1-h3 state persisted - and the wallet-node pair is restarted (Fig. 4).

Fig. 4. The states of the node and wallet before restart with backfilling

Fig. 4. The states of the node and wallet before restart with backfilling

In that case the node retrieves h6 block and pushes it to the block listener (ie., the wallet). The wallet tries to accommodate the block but detects discontinuity when looking at its persisted state (as the wallet does not persists the blocks, but checkpoints and metadata one has to make sure h1-h3 refers to other checkpoint than the checkpoint of h1-h5 to make it happen). The wallet starts-up backfilling which downloads backward blocks needed to recreate missing checkpoints (the one it would have when it was synchronized with the node persisted state), then resolves h6 block and continue operation.

Fig. 5. Restart with backfilling

Fig. 5. Restart with backfilling