Programming Hotmoka
A tutorial on Hotmoka and smart contracts in Takamaka
Chapter 7 Hotmoka blockchains
The experiments of the previous chapters have been performed on a Hotmoka node already existing online, part of a blockchain installed by somebody else. Namely, we have used the Hotmoka node at \serverMokamint, that is part of a blockchain based on a proof of space consensus algorithm [28], and the Hotmoka node at \serverTendermint, that is part of another blockchain, this time based on a proof of stake consensus algorithm [12]. Both are able to execute Hotmoka transactions, store smart contracts and interact with them, but they are different for the way they create new blocks and synchronize their state among all the nodes of the blockchain they belong to. Namely, in the case of proof of space, each node of the blockchain increases the likelihood of winning the right to create a new block if it allocates a larger data structure on disk (typically, on SSD) than the other nodes of the same blockchain. Instead, in the case of proof of stake, only a restricted, modifiable set of nodes (called validators) has the right to create new blocks, in a round-robin way, and the prize earned for the creation of a new block is proportional to the shares of validation power owned by each validator. Other nodes can just verify the transactions. We do not enter into the (sometime religious) discussion about which consensus algorithm is the best. Probably none of them, as each of them (and others, that we do not even speak about here) has its advantages and drawbacks. What is important to highlight is that Hotmoka is not bound to a specific consensus algorithm, but is rather a software layer for the execution of smart contract transactions, that can be plugged on top of different consensus engines, giving rise to distinct blockchains with distinct consensus algorithms.
This chapter shows how to build new blockchains or connect to existing blockchains, both for proof of space and for proof of stake consensus. It will present this by using docker, so that you do not need to install anything on your machine beyond docker itself. Namely, there exist preconfigured docker images that allow one to run Hotmoka nodes of a blockchain without preliminary, complex configuration. They are meant to simplify the life of users who just want to install nodes with a standard procedure that should cover most typical use cases. For less standard use cases, such docker images can be partially configured or Hotmoka nodes can be installed with Java code, as it will be shown later in Ch. 8.
7.1 Hotmoka blockchains based on Mokamint (proof of space)
Hotmoka can run on top of a generic engine for proof of space consensus, called Mokamint [16]. The latter implements the networking and consensus layers of a blockchain, leaving the application layer generic, so that it can be plugged on top of it. Hotmoka is one such application layer, but others may exist as well. Mokamint implements a consensus algorithm based on proof of space, derived from that of Burstcoin/Signum [28]. In such algorithm, the creation of a new block required to identification of a data structure, called nonce, from a set of nonces precomputed on disk, in order to minimize the waiting time for the creation of the next block. The more nonces are precomputed on disk, the higher the likelihood of winning the competition for the creation of the next blocks. Nonces could in principle be recomputed on the fly at each block creation, but their computation is so complex that it becomes impossible to perform it in the short time between the creaton of successive blocks. From this point of view, proof of space is similar to Bitcoin’s proof of work [19], but the resource used for the competition is different: SSD instead of CPU. Consequently, proof of space has a minimal energy cost and can be run a cheap hardware as well. In particular, you can mine for Mokamint-based blockchains with a desktop machine or even with a mobile phone or tablet (see the Mokaminter Android app [15]). This becomes possible for Hotmoka as well, if run on top of Mokamint, as shown in this section.
Fig. 7.1 shows the network architecture of a couple of Hotmoka nodes based on Mokamint, that are two peers of the same blockchain. The two Mokamint instantiations communicate between each other, in order to exchange blocks and synchronize their copy of the blockchain. Each Mokamint instantiation runs an instance of Hotmoka, that specifies the semantics of the transactions that can be executed on the blockchain. Each peer exports the node interface (Fig. 8.1), respectively, in this example, at port 80 and 8001. Remote clients, such as moka or Mokito, can connect to such ports and run transactions on the nodes, that will be automatically executed in all peers. Fig. 7.1 shows that each peer runs a local miner, that is, a software tool that finds nonces on disk in order to create the next blocks. It is well possible to have peers without any miner, in which case they just synchronize their copy of the blockchain but do not contribute new blocks. However, for simplicity, our docker images will always provide a local miner to a node. As the same figure shows, some peer might allow the connection of remote miners, that is, miners, identical to the local ones, but running as a remote network service. This allows peers to exploit the willingness of remote users to provide mining power to them by just plugging remote miners, without running a full node. If such remote miners contribute to the creation of new blocks, the prize for this creation will be shared between the peer and the remote miners.
7.1.1 Start a remote miner for an existing node
The simplest scenario is that of a user who wants to provide mining power to an existing node of a blockchain based on Mokamint, such as \serverMokamint. This user does not want to run a full node of the blockchain, for instance because he does not want to perfom a long synchronization, nor hold a copy of the full blockchain in his machine, or maybe because his internet connection is not stable enough for running a full node, or just because he does not want to keep his machine always on, day and night. This user can contribute to the creation of new blocks, and earn crypto for this, by running a remote miner for an existing Hotmoka node based on Mokamint (Fig. 7.1), which can be done in two ways. The simplest is to run the Mokaminter Android app [15] on a mobile phone or tablet. This should be so simple that we do not really describe it here: just install the app and try starting mining. The other possibility is to mine on a local machine, and we describe it here. In both cases, the miner is identified by a key pair, that is where the crypto earned for mining gets sent. The key is created automatically by Mokaminter, while it must be created manually when mining on a local machine.
There is a docker image for running a remote miner for Mokamint [14]. You first need to create a key pair that will identify you as a miner of the blockchain, then create a mining configuration, compatible with the Mokamint node that you are going to mine for, that includes a plot file for mining. The larger this plot file, the more likely it is that the miner will be selected for creating the next blocks of the blockchain and more coins will be earned by your miner, on average. For instance, in order to mine for the Mokamint node running the Hotmoka testnet and published at \serverMokamintMining, you start with the creation of the key pair that will identify you as a miner:
docker run --name temp -it mokamint/mokamint:1.6.4 mokamint-node keys create --name miner.pem --password; docker cp temp:/home/mokamint/miner.pem .; docker rm temp
Enter value for --password (the password that will be needed later to use the key pair): sun The new key pair has been written into "miner.pem": * public key: DsTMjsEZZpA5UeN55KvhCMQsEQQgKEyVAAUfVthoGR1d (ed25519, base58) * public key: vzkWDzX/NaDv4mdiOUAax/sPI+RE8WZCYCeGQGsLknw= (ed25519, base64) * Tendermint-like address: 17AD1E4397E40BE1DE46B05E743BC1BE16DA50D4
The command above asks for a password, that you will use to control the key pair, it creates the key pair in your local file system, named miner.pem, and prints its public key. Write down the password on paper, since it is not possible to recover it if lost. Save miner.pem in a safe place as well.
You can create the mining configuration now:
docker run --log-driver local --rm -it -e MINER_PUBLIC_SERVICE_URI=ws://panarea.hotmoka.io:8025 -e PUBLIC_KEY_MINER_BASE58=DsTMjsEZZpA5UeN55KvhCMQsEQQgKEyVAAUfVthoGR1d -e PLOT_SIZE="5000" -v miner_configuration:/home/mokamint/ miner_configuration mokamint/mokamint:1.6.4 config-miner
You can replace 5000 with any other positive number of nonces in order to increase or decrease the size of the plot file.
After a mining configuration has been created, you can start mining:
docker run --log-driver local --name miner --rm -it -e MINER_PUBLIC_SERVICE_URI=ws://panarea.hotmoka.io:8025 -v miner_configuration:/home/mokamint/miner_configuration mokamint/mokamint:1.6.4 mine
You should see on the screen the flow of the logs of the miner. You can terminate the miner by pressing the ENTER key. Or you can leave the miner working in the background by pressing CTRL+p followed by CTRL-q, as always with docker.
You can stop an already running miner by simply stopping its docker container (docker stop miner). You can restart a stopped miner by running the above mine command again. You normally do not recreate the mining configuration when you restart a miner: its creation is a one-shot action. Nevertheless, you can recreate the configuration if, for instance, you want to change the size of the plot file. For that, stop your miner (if running) and just rerun the docker command for config-miner. Once the mining configuration has been recreated, you can restart your miner with mine.
Your miner will earn coins for the mining activity. You can check the current balance of the public key that identifies your miner, as follows:
docker run --rm -it mokamint/mokamint:1.6.4 mokamint-miner balance DsTMjsEZZpA5UeN55KvhCMQsEQQgKEyVAAUfVthoGR1d --uri ws://panarea.hotmoka.io:8025
When the balance will finally be non-zero, you can bind the public key to the actual account that holds its crypto coins, with
moka keys bind miner.pem --password --uri=ws://panarea.hotmoka.io:8001
that requires you to have moka installed in your machine (Sec. 2.2.1) and to be run in the directory where you have saved the key pair file miner.pem.
7.1.2 Start a node of an existing blockchain
This is the most typical situation. Namely, this occurs if you want to join an existing blockchain, with a node that mines new blocks and receives blocks created by the other peers. This docker image provides a script for this situation. This script includes the creation of a local miner as well, or otherwise your node would not be able to mine new blocks. Because of this, the scripts deal with two key pairs: the former identifies the node, and is kept inside the machine running the script, and the latter identifies the miner, can be stored elsewhere and only its public key is needed here.
The process is consequently split in two:
-
• configure the node (config-clone);
-
• run the node (go).
Each phase is the execution of a script inside this docker image. The script config-clone is meant to be run only once, while go can be run, stopped and run again, whenever you want to start, stop and restart a node. You can also pause it and unpause it. The reason for splitting the process in two scripts is that it allows one to manually edit the configuration created by config-clone before running the node, although we will not show this here. Moreover, having distinct scripts allows go to be stopped and run again, repeatedly, whenever you want to stop and restart a node.
The following instructions assume that you have a reliable internet connection. If the connection is too slow, or flickering, or if it disconnects for some time, the synchronization of the node will likely fail. In that case, stop and restart go later, hoping to complete the synchronization, eventually. Please consider that the synchronization of the node requires to download all the history of the blockchain that you are joining, which might take time (hours, days, even weeks, depending on the age of the blockchain and the quality of the internet connection).
Configure the node (config-clone)
The config-clone script creates the configuration directory of a node that joins an existing Hotmoka blockchain based on the Mokamint proof of space engine. For that, you must specify the URI of a node of this blockchain, from where the configuration information will be fetched. This is important, since all nodes of the same blockchain must have the same consensus parameters.
The first thing to do is to create a key pair for the miner of the new node that you want to start. You can do this as in Sec. 7.1.1, hence generating miner.pem.
You can then run the script that configures the node. Use for it the base58-encoded public key of the key pair that you have created above. Specify \serverMokamintPublic as the URI of a node of the blockchain to join. Specify the size of the plot file to use for the proof of space: the larger, the more blocks will be created by your node, but also more disk space will be allocated for mining. We will use two volumes: chain will contain the actual blockchain data and hotmoka_mokamint will contain the configuration information created for the node. By using volumes, we can share that information across successive invocations of docker:
docker run -it --rm -e PUBLIC_KEY_MINER_BASE58=DsTMjsEZZpA5UeN55KvhCMQsEQQgKEyVAAUfVthoGR1d -e MOKAMINT_PUBLIC_SERVICE_URI=ws://panarea.hotmoka.io:8030 -e PLOT_SIZE=4000 -v chain:/home/hotmoka/chain -v hotmoka_mokamint:/home/hotmoka/ hotmoka_mokamint hotmoka/mokamint-node:1.11.5 config-clone
Note that the script above will create another key pair (and ask you about the relative password), that will be kept inside the container. This key pair identifies the node and will be used to sign the blocks that the node will create. It must remain inside the container, although you may want to extract a copy from the container to your local host.
Run the node (go)
After configuring the node, you can run it with the go script:
docker run -it --log-driver local --rm --name hotmoka -p 8001:8001 -p 8025:8025 -p 8030:8030 -p 127.0.0.1:8031:8031 -v chain:/home/hotmoka/chain -v hotmoka_mokamint:/home/hotmoka/hotmoka_mokamint hotmoka/mokamint-node:1.11.5 go
The command above will start a node of the same blockchain of \serverMokamint, that allows connections to the ports:
- 8001:
-
this is the port where the Hotmoka node is published by default; it can be used to contact the node, install and run smart contracts;
- 8025:
-
this is the port where mining services can connect by default; mining services help your node produce new blocks; note that this requires to open a remote miner in your node, listening at port 8025 (mokamint-node miners add);
- 8030:
-
this is the port where Mokamint can be reached for public queries, by default;
- 8031:
-
this is the port where Mokamint can be reached for restricted operations, by default; note the we have restricted its access to localhost only, since we do not want our Mokamint node to be freely reconfigured remotely.
After the command above, you should see that the node will start up and begin synchronizing from \serverMokamintPublic. This will take some time (hours, days, weeks…) depending on the age of the cloned blockchain and on the speed of your internet connection. You can leave the container in the backrground by entering CTRL+p, CTRL+q, as always in docker.
You can then monitor the progress of the synchronization by entering the running container and executing the mokamint-node command:
docker exec -it hotmoka /bin/bash
and then inside the container:
hotmoka@e41eda9afd3b: mokamint-node chain ls 10
You can also see the manifest of the node, that is identical to that of any other node of the joined blockchain:
hotmoka@e41eda9afd3b: moka nodes manifest show
Remember that you can always check the logs of a running docker container, for instance with:
docker logs -f hotmoka
7.1.3 Start the first node of a new blockchain
This situation is much rarer. It occurs when you want to start a brand new blockchain from scratch, by minting its genesis block and initializing its store. Later, other nodes can join the new blockchain with the technique described in Sec. 7.1.2.
The docker image of Hotmoka provides scripts for starting a brand new blockchain. These scripts include the creation of a local miner as well, or otherwise your node would not be able to mine new blocks. Because of this, the scripts deal with two key pairs: the first identifies the node, and is kept inside the machine running the script, and the second identifies the miner, can be stored elsewhere and only its public key is needed for starting the node.
The process is consequently split in three:
-
• configure the node (config-new)
-
• initialize the node (init)
-
• run the node (go)
Each phase is the execution of a script inside the docker image. The scripts config-new and init are meant to be run only once, while go can be run, stopped and run again, whenever you want to start or stop a node. You can also pause it and unpause it. The reason for splitting the process in three scripts is that it allows one to manually edit the configuration created by config-new before initializing and running the node, although we will not show this here. Moreover, having distinct scripts allows go to be stopped and run again, repeatedly, whenever you want to stop and restart a node.
Configure the node (config-new)
The configuration requires the creation of a brand new key pair that will identify the miner of the node. You can do this as in Sec. 7.1.1, hence generating miner.pem. Moreover, you will need another key pair, for the gamete account. This is an account of Hotmoka that holds all cryptocurrency minted at start-up (if any). It can also be used as faucet of the node, if your node allows a free faucet. In any case, you need a key pair for the gamete account as well. Therefore, follow the instructions in Sec. 7.1.1 and create gamete.pem as well:
docker run --name temp -it hotmoka/mokamint-node:1.11.5 moka keys create --name gamete.pem --password; docker cp temp:/home/hotmoka/gamete.pem .; docker rm temp
Enter value for --password (the password that will be needed later to use the key pair): moon The new key pair has been written into "gamete.pem": * public key: D73ZxUhVrR6riCeHkDRNgj3UCGrVYxstvv5mTMpGmHah (ed25519, base58) * public key: s9ihwatVvAsS7EuYGP2QzaHhK0fKnu8HwSdqDalPoxI= (ed25519, base64) * Tendermint-like address: 5C31A3FF841CD5F35E81E819B96C76B6EF56396A
You can now configure the node, by specifying the public key of the miner and that of the gamete:
docker run -it --rm -e PUBLIC_KEY_MINER_BASE58=DsTMjsEZZpA5UeN55KvhCMQsEQQgKEyVAAUfVthoGR1d -e PUBLIC_KEY_GAMETE_BASE64="s9ihwatVvAsS7EuYGP2QzaHhK0fKnu8HwSdqDalPoxI=" -e PLOT_SIZE=5000 -e CHAIN_ID=whale -e TARGET_BLOCK_CREATION_TIME=10000 -v chain:/home/hotmoka/chain -v hotmoka_mokamint:/home/hotmoka/hotmoka_mokamint hotmoka/mokamint-node:1.11.5 config-new
Note that the public key of the miner is reported in base58, while that of the gamete is reported in base64, currently. The target block creation time, in milliseconds, is the average time between the creation of two successive blocks. The chain identifier identifies the new network and must be used, for instance, in the transaction requests sent to the Hotmoka nodes of the network. The script above will prompt for the password of the key pair used for signing the new blocks, that it creates. Enter your chosen password or leave it blank. The script will configure the node and create a plot file for its miner.
Initialize the node (init)
The initialization of the node consists in the execution of a few initial transactions that create the genesis block, the manifest and the gas station of the node. You can do this with:
docker run -it --rm -v chain:/home/hotmoka/chain -v hotmoka_mokamint:/home/hotmoka/hotmoka_mokamint hotmoka/mokamint-node:1.11.5 init
This will take a few seconds. You should see the logs of the executed transactions, until the script terminates.
Run the node (go)
Once the node has been configured and initialized, you can run it. Follow for this the instructions reported in Sec. 7.1.2 for the go script.

We create the key pair inside a docker container above and then export it outside. Thus is because, in this chapter, we perform everything with the docker tool only. You can of course do the same by invoking moka keys create directly if you have installed on your local machine (Sec. 2.2.1).