Running your own Private Network

This tutorial shows you how to create your own private network if you want more freedom to develop your dapp or to test your baking infrastructure locally. We will suppose that you want your network to be called APPNET.

Building a new Branch appnet

First, clone the sources of Dune Network from https://gitlab.com/dune-network/dune-network, and checkout either the testnet branch (current Testnet) or the next branch (development branch). Then, build it (see how to build Dune Network binaries here).

Now, create your own branch (it will make it easier for other devs to use your network):

$ git checkout -b appnet

You will need to modify the file src/lib_config/set_config_testnet.ml under a new name, and make it available as set_config.ml. For that, follow these steps:

$ cd src/lib_config
$ cp set_config_testnet.ml set_config_appnet.ml
$ ln -sf set_config_appnet.ml set_config.ml
$ git add set_config.ml set_config_appnet.ml

Now, you can edit the content of set_config_appnet.ml, and:

  • Change the name of the network network to "Appnet"

  • Change the genesis_time to the current date (it will prevent your network from connecting to the official Testnet)

  • Create a new genesis initial block. For that, run the following command with the date that you have chosen:

    $ dune-client dune generate genesis hash -d 2019-06-24T12:00:00Z
    Date: 2019-06-24T12:00:00Z
    Hash: BLockGenesisGenesisGenesisGenesisGenesis5e671cK5Xad
    

    Use the hash in genesis_block.

  • Change bootstrap_peers with the address:port of the first node of your network (other nodes will try to connect to it automatically)

  • Change prefix_dir if you don’t want to conflict with Dune’s configuration file. For example, if you set prefix_dir to app, the dune-node command will look for its files in $HOME/.app-node and the dune-client in $HOME/.app-client.

  • Change the genesis_key to the public key (edpk) of an account that you will use to activate the network. If you want to create such a key, you can use:

    $ dune-client gen keys app-activator
    Key app-activator registered
    
    $dune-client show address app-activator
    Hash: dn1XA5ieuGaBfFRTBY5bR3VUT8LHV2Q5CSK2
    Public Key: edpkvMberySJBQ71TdWo7Fg4bryxNX72JBLjwM8N9WcX9cNPnYdAtU
    

Now, you can clean and rebuild:

make clean
make

Normally, you should see messages like Network Config: Appnet in the build log.

Starting the Network

If you have not changed the prefix_dir in the previous stage, beware that you will need to specify your own directory for the node (using --data-dir) or you need to remove the files/directories context and store in $HOME/.dune-node.

If you start the node now, the node will start in the genesis protocol, called Ps9mPmXa, from where the only block you can create is to activate a new protocol.

To simplify these steps, you can use the scripts available in the run-scripts directory of Dune Network.

The scripts in run-scripts use a configuration script called $HOME/dune-env.sh. Let’s create it:

#!/bin/sh

DUNE_EXECDIR=$HOME/dune-appnet-2019-06-24
DUNE_NET_PORT=9733
DUNE_RPC_ADDR=127.0.0.1
DUNE_RPC_PORT=8733
GENESIS_DIR=$HOME/genesis-appnet
DUNE_BOOTSTRAP_THRESHOLD=0

The first variable DUNE_EXECDIR is used to set a top directory where all executable ran by run-scripts are executed. For example, dune-node will have its data directory in $HOME/dune-appnet-2019-06-24/dune, whereas the logs will be in $HOME/dune-appnet-2019-06-24/logs.

The variable GENESIS_DIR is where the scripts will expect to find the configuration to activate the network. The variable DUNE_BOOTSTRAP_THRESHOLD is set to 0 to allow the client to inject transactions without requiring the node to be connected to others.

For now, let’s start the node:

$ ./run-scripts/01-dune-node.sh start
Executing $HOME/dune-env.sh
[Dune Node] == Starting ==
dune-node is not running
Initializing Dune node
Network Config: Appnet
Generating a new identity... (level: 26.00)
Stored the new identity (idtkDumzLmYsQG7kQC4BwapiGG7Fvv) into '$HOME/dune-appnet-2019-06-24/dune/identity.json'.
Dune node started...
dune-node is running ! (pid=9425)
You can watch the log:
tail -f $HOME/dune-appnet-2019-06-24/log/dune-node.log

As you can see, the node has been started after generating a new identity. If you stop and restart the node, the identity will be kept between runs. You can stop the node (later, not now !), if you want, using:

$ ./run-scripts/01-dune-node.sh stop
Executing $HOME/dune-env.sh
[Dune Node] == Stoping ==
dune-node is running ! (pid=9425)
dune-node is running (pid=9425)...
Process received signal INTR. Waiting 5 seconds...
./run-scripts/stop-process.sh: 33: kill: No such process
dune-node is down. Removing pid file.

Activating the new Protocol

To activate the new protocol, the scripts in run-scripts expect two files in $HOME/genesis-appnet. So, let’s start by creating a directory to store these new files:

mkdir $HOME/genesis-appnet

Then, we create a script genesis-env.sh in this directory with the new protocol, the activator key and the initial baker key:

#!/bin/sh

PROTO_NUM=004
PROTO_HASH=Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd

ACTIVATOR_KEYHASH=dn1XA5ieuGaBfFRTBY5bR3VUT8LHV2Q5CSK2
ACTIVATOR_PUBKEY=edpkvMberySJBQ71TdWo7Fg4bryxNX72JBLjwM8N9WcX9cNPnYdAtU
ACTIVATOR_PRIVKEY=edsk3WcShEmqBWT6TpC5JGCvZTDQiMtcQJUdEgT6Rk88LMCitHFW4z

BAKER_KEYHASH=dn1b2TKR532nymdE4tAkGDbJoc34PZb677x9
BAKER_PUBKEY=edpktpwqiAh3AKnrM6GVYhXtrSRYwRAuMdd7o748LHCQpUcTYSvhz2
BAKER_PRIVKEY=edsk4CKXSgR4DSasxGjCDjxjaHNG2BnGABjzHkurzfRiHijTatmYbN
  • The PROTO_NUM and PROTO_HASH are used to specify the protocol to activate. You will find these values by looking into Dune Network sources. There should be a directory src/proto_???_????????, indicating the value for PROTO_NUM, and you can then check the first line of lib_protocol/TEZOS_PROTOCOL in that directory for the value of PROTO_HASH.

  • For the ACTIVATOR variables, you must use the same key as we used in set_config_appnet.ml:

    $ dune-client show address  app-activator -S
    Hash: dn1XA5ieuGaBfFRTBY5bR3VUT8LHV2Q5CSK2
    Public Key: edpkvMberySJBQ71TdWo7Fg4bryxNX72JBLjwM8N9WcX9cNPnYdAtU
    Secret Key: unencrypted:edsk3WcShEmqBWT6TpC5JGCvZTDQiMtcQJUdEgT6Rk88LMCitHFW4z
    

    You need to specify the Hash, the Public Key and the Secret Key (without the unencrypted: prefix.

  • Finally, for the BAKER variables, you can create a specific key:

    $ dune-client gen keys app-baker
    Key app-baker registered
    $ dune-client show address  app-baker -S
    Hash: dn1b2TKR532nymdE4tAkGDbJoc34PZb677x9
    Public Key: edpktpwqiAh3AKnrM6GVYhXtrSRYwRAuMdd7o748LHCQpUcTYSvhz2
    Secret Key: unencrypted:edsk4CKXSgR4DSasxGjCDjxjaHNG2BnGABjzHkurzfRiHijTatmYbN
    

We can now move to the protocol_parameters.json that allows to initialize the protocol (for example, with a supply of tokens, the number of blocks per cycle, …). Here is a minimal example:

{ "bootstrap_accounts":
  [
    [ "dn1XA5ieuGaBfFRTBY5bR3VUT8LHV2Q5CSK2",
            "1000000000000" ],
    [ "edpktpwqiAh3AKnrM6GVYhXtrSRYwRAuMdd7o748LHCQpUcTYSvhz2",
              "10000000000" ]
  ],
  "time_between_blocks" : [ "30" ],
  "preserved_cycles":2,
  "blocks_per_cycle":4,
  "blocks_per_roll_snapshot":2,
  "hard_gas_limit_per_operation":"400000",
  "hard_gas_limit_per_block":"4000000",
  "michelson_maximum_type_size":1000,
  "seed_nonce_revelation_tip":"0",
  "origination_size":0,
  "block_security_deposit":"0",
  "endorsement_security_deposit":"0",
  "block_reward":"0",
  "endorsement_reward":"0",
  "cost_per_byte":"0",
  "hard_storage_limit_per_operation":"60000"
}

In this file, we have set several things:

  • We gave our two initial keys some tokens (in nano tokens units). You can of course add more keys, and not give the app-activator any tokens (it does not need them). Here, we gave app-activator 1,000,000 tokens, and app-baker 10,000 tokens (one roll, the minimum for him to bake).

    We used the public key (edpk) of app-baker instead of its key hash because we want it to be set as a delegate immediately to be able to bake.

  • We also set some parameters. For example, 30 seconds between blocks (it can be useful), no rewards/no deposits, only two preserved cycles, and each cycle has only 4 blocks. There are also other constants for running contracts.

We can now activate this protocol. If the network is not aleady running, start by running:

$ ./run-scripts/01-dune-node.sh start

Then, activate the protocol with:

$ ./run-scripts/01-dune-node.sh activate

This command should end up injecting the new protocol.

We can then start the initial bakers and endorsers for this network:

$ ./run-scripts/02-dune-baker.sh start
$ ./run-scripts/03-dune-endorser.sh start

At this point, you should be able to check in the logs that the baker and endorsers are working. You can also use ./run-scripts/01-dune-node.sh head to check that new blocks are being added. Note that, you can also execute client-related commands via ./run-scripts/01-dune-node.sh client <client command>.

We are done ! You can now publish your appnet branch to other developers or start it on other computers for them to use your private network.

Resetting the new private network

Now that you have done it once, you may want at some point to reset a new private network, while keeping the former configuration. It is now much easier:

  • Edit set/lib_config/set_config_appnet.ml, but just modify the genesis_time and genesis_block. Clean (make clean) and rebuild (make).

  • Change the DUNE_EXECDIR in $HOME/dune-env.sh for a new directory. Stop any previous node, start the new one and activate it:

    $ ./run-scripts/01-dune-node.sh stop
    $ ./run-scripts/01-dune-node.sh start
    $ ./run-scripts/01-dune-node.sh activate
    $ ./run-scripts/02-dune-baker.sh start
    $ ./run-scripts/03-dune-endorser.sh start
    

    Your new private network should be up and ready for other nodes.