Running your own Testnet

This tutorial shows you how to create your own testnet 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, and checkout either the testnet branch (current Testnet) or the next branch (development branch). Build it.

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/ under a new name, and make it available as

cd src/lib_config
ln -sf
git add

Now, you can edit the content of

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

  • Change the genesis_time to the current date (it will prevent your network to connect 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

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.

To activate a new protocol, you will need some files, so let’s start by creating a directory to store these new files:

mkdir $HOME/genesis-appnet

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



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/ start
Executing $HOME/
[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/ stop
Executing $HOME/
[Dune Node] == Stoping ==
dune-node is running ! (pid=9425)
dune-node is running (pid=9425)...
Process received signal INTR. Waiting 5 seconds...
./run-scripts/ 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:

  • A script with the new protocol, the activator key and the initial baker key

  • A configuration file protocol_parameters.json to initialize the protocol (for example, with a supply of tokens)

Let’s start with It should look like:




  • 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

    $ 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 file. It should look like:

{ "bootstrap_accounts":
    [ "dn1XA5ieuGaBfFRTBY5bR3VUT8LHV2Q5CSK2",
            "1000000000000" ],
    [ "edpktpwqiAh3AKnrM6GVYhXtrSRYwRAuMdd7o748LHCQpUcTYSvhz2",
              "10000000000" ]
  "time_between_blocks" : [ "30" ],

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, 30s between blocks (it can be useful), and no rewards/no deposits. There are also other constants for running contracts.

We can now activate this protocol:

$ ./run-scripts/ activate

This command should end up injecting the new protocol.

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

$ ./run-scripts/ start
$ ./run-scripts/ 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/ head to check that new blocks are being added. Note that, you can also execute client-related commands via ./run-scripts/ 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 Appnet testnet.

Resetting the new Testnet

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

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

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

    $ ./run-scripts/ stop
    $ ./run-scripts/ start
    $ ./run-scripts/ activate
    $ ./run-scripts/ start
    $ ./run-scripts/ start

    Your new testnet should be up and ready for other nodes.