Setting up your own Private Dune Network

DUNE network
Dune Network
Published in
7 min readDec 6, 2019

When developing a blockchain project, a frequent question that arises is whether to use a public blockchain or a private blockchain. On one hand, public blockchains have the benefit that the infrastructure is already in place, it is often self-administrated, and the project only needs to deploy its smart contract on top of it. On another hand, private blockchains have the benefit of privacy/confidentiality, control of validation/baking, higher throughput and no fees for operations. Being able to switch from one setup to another is an important criteria to choose the blockchain a project will target.

Early in the Dune Network development, we made sure it would be easy for projects to deploy their own private instance of the Dune Network. The following features are available:

  • Configuration of the network through a specific configuration file and an environment variable
  • Administration operations, to change the protocol or just its constants

In this post, we will explain step by step how to deploy your private network and administrate it.

Private Network Configuration

In this post, we will use the next branch of the GIT repository of Dune Network. It is usually the most advanced branch, though less tested. We will suppose it has been compiled before.

First, we will need to create a configuration for our private network. This configuration will mainly differ from the public network by three parts:

  • The Genesis block will differ by its hash and its initial date. That date should be as recent as possible, as the initial baker will have to create all the blocks from that time.
  • The P2P handshake will also differ to prevent our nodes from connecting with public nodes.
  • Finally, we will need our own key pair for administration operations

All these values should be provided in a JSON file (we will see later how to hardcode them in the code, if you want to distribute your own code). dune-client can create such a file that we will modify for our purpose (here, we call it network-config.json):

> ./dune-client -p PsB dune output network config -o network-config.json> cat network-config.json            
{ "network": "Testnet",
"genesis_key": "edpkvNMEhZWPeARxBoBHVxzkPAgHJHcNKdFXCgwZBYQGc2XGExW3K5",
"p2p_version": "DUNE_TESTNET_2019-09-11T15:07:53Z",
"max_operation_data_length": 64000, "encoding_version": 2,
"prefix_dir": "dune-testnet", "p2p_port": 9734, "rpc_port": 8734,
"bootstrap_peers": [ "boot1.testnet.dune.network" ],
"genesis_time": "2019-09-11T15:07:53Z",
"genesis_block": "BLockGenesisGenesisGenesisGenesisGenesis59cdfbfK2jQ",
"genesis_protocol": "Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P",
"forced_protocol_upgrades": [], "cursym": "đ", "discovery_port": 10734,
"signer_tcp_port": 7734, "signer_http_port": 6734, "protocol_revision": 0,
"only_foundation_bakers": false }

Let’s start modifying this file:

  • "network" is the name of the network, let’s replace "Testnet" by "Appnet"
  • "prefix_dir" is the prefix used to create the node and client default directories. We can use "dune-appnet" so that the node files will be stored in $HOME/.dune-appnet-node/.
  • "genesis_key" is the public key for administrative operations. For now, we can generate a simple key pair and print the public key:
> DUNE_CONFIG=network-config.json ./dune-client gen keys appnet-adminEnter password to encrypt your key: 
Confirm password:
Key appnet-admin registered
> DUNE_CONFIG=network-config.json ./dune-client show address appnet-adminHash: dn1WLLWBERK56a9n4xdPJupf8qZsvCiNamNA
Public Key: edpkuszp8nzpTWUQAfrtXK8n9MyK3u7eHVxgb3f4CyDFdWPc3itrEg
  • "p2p_version" is the string used for the handshake with other nodes. We can replace it by "DUNE_APPNET_2019_12_04T14:00:00Z"for example.
  • "bootstrap_peers" should be the list of the initial nodes. For our test, we can use the empty list [] .
  • "genesis_time" the time at which the network will start. For example: "2019-12-04T14:00:00Z".
  • "genesis_block" is the hash of the Genesis block. We can use dune-client to generate it:
> ./dune-client dune generate genesis hash -d 2019-12-04T14:00:00ZDate: 2019-12-04T14:00:00Z
Hash: BLockGenesisGenesisGenesisGenesisGenesis689U3ubs3zP

For now, we don’t need to modify any other value.

Let’s start the node:

> DUNE_CONFIG=network-config.json ./dune-node identity generateDUNE_CONFIG="network-config.json"
Config: Appnet. Revision: 2
Generating a new identity... (level: 26.00)
Stored the new identity (idsd4LT1VK8fEFeKtfBKDkvovpGd18) into '/home/user/.dune-appnet-node/identity.json'.
> DUNE_CONFIG=network-config.json ./dune-node run --rpc-addr 127.0.0.1[...]
Dec 4 14:14:26 - node.main: The Dune node is now running!

The node is now running, but it is not yet running a useful protocol, we will need to “activate” such a protocol in the next section.

In the rest of this post, we will always use the DUNE_CONFIG variable:

export DUNE_CONFIG=network-config.json

(you may want to specify the absolute path if you want to be able to change directories)

Private Network Activation

To activate the network, we need to take a few decisions:

  • Which protocol to activate ? In the following, we will use the new Babylon+ protocol.
  • What will be the protocol parameters ?
  • What will be the first accounts and the total supply of coins ?

To choose the protocol, we can start by listing all the available protocols:

> DUNE_CONFIG=network-config.json ./dune-client list understood protocols -LThis client understands commands for:
Ps9mPmXaRzmzk35gbAYNCAw6UXdE2qoABTHbN2oEEc1qM7CwT9P
Pt24m4xiPbLDhVgVfABUjirbmda3yohdN82Sp9FeuAXJ4eV9otd
PsBabyM1eUXZseaJdmXFApDSBqj8YBfwELoxZHHW77EMcAbbwAS

For Babylon+, we will use the last one, which is usually always a good idea.

For the protocol parameters, we can start with the default ones:

> DUNE_CONFIG=network-config.json ./dune-client -p PsBaby dune output protocol parameters -o protocol_parameters.jsonWarning:
The protocol provided via `--protocol` (PsBabyM1eUXZ)
is not the one retrieved from the node (Pt24m4xiPbLD).
Node: http://testnet-node.dunscan.io:8733
Warning: could not retrieve constants, printing defaults
> cat protocol_parameters.jon{ "preserved_cycles": 5, "blocks_per_cycle": 4096,
"blocks_per_commitment": 32, "blocks_per_roll_snapshot": 256,
"blocks_per_voting_period": 32768, "time_between_blocks": [ "60", "40" ],
"endorsers_per_block": 32, "hard_gas_limit_per_operation": "1040000",
"hard_gas_limit_per_block": "10400000",
"hard_gas_limit_to_pay_fees": "40000", "max_operation_ttl": 16,
"frozen_account_cycles": 60, "allow_collect_call": true,
"proof_of_work_threshold": "70368744177663",
"tokens_per_roll": "10000000000", "michelson_maximum_type_size": 1000,
"seed_nonce_revelation_tip": "125000", "origination_size": 257,
"block_security_deposit": "512000000",
"endorsement_security_deposit": "64000000", "block_reward": "16000000",
"endorsement_reward": "2000000", "cost_per_byte": "1000",
"hard_storage_limit_per_operation": "60000",
"test_chain_duration": "1966080", "quorum_min": 2000, "quorum_max": 7000,
"min_proposal_quorum": 500, "initial_endorsers": 24,
"delay_per_missing_endorsement": "8" }

Note that, since we requested the protocol parameters for a protocol that is not the currently running one on the node to which we are connected, the client decided to print the default ones.

In this example, we will bake with only one account. This account will have to deposit during 7 cycles for 4096 blocks. With the default values, it requires 7 * 4096 * (32 * 64 + 512) tokens, i.e. 73,400,320 duns. Since we don’t want to give the baker so many tokens, we will just put the deposits to 0, by setting "block_security_deposit" and "endorsement_security_deposit" to "0". Similarly, we don’t want to receive rewards in this example, so we can set "block_reward", "endorsement_reward" and "seed_nonce_revelation_tip" also to "0".

There is not much more that you want to change here, except maybe the time_between_blocks constants that you reduce to speed up the network during testing.

Yet, we will need to add a new field "bootstrap_accounts" in the file protocol_parameters.json to create the first accounts on the network.

Before, we create two new addresses:

  • appnet-baker will be the initial baker on the network. We will give it only one roll (10,000 dun) to be able bake, plus 1 dun for a few transfer operations in the future.
  • appnet-supply will be an account owning all the remaining tokens. We decide to create a supply of 10,000,000 dun.
> DUNE_CONFIG=network-config.json ./dune-client gen keys appnet-bakerEnter password to encrypt your key:
Confirm password:
Key appnet-baker registered
> DUNE_CONFIG=network-config.json ./dune-client gen keys appnet-supplyEnter password to encrypt your key:
Confirm password:
Key appnet-supply registered
> DUNE_CONFIG=network-config.json ./dune-client show address appnet-bakerHash: dn1GzpD9araZ7cjWCTBMMHunhhR3WtgmBQVo
Public Key: edpku7wmQb6EU84bWJESQS6xLxopoEhWQ1SM6wuMYuPWAgs2mE92um
> DUNE_CONFIG=network-config.json ./dune-client show address appnet-supply Hash: dn1N7crmAkgmPKPRcwsC3FYDACgH85W29D6R
Public Key: edpkuLqnDJm63Ht2zxjSYx4W4k1pdchetWGSUbLpfHoFeQBM4CQtg8

So, we modify protocol_parameters.json to have:

{
"bootstrap_accounts": [
[ "dn1N7crmAkgmPKPRcwsC3FYDACgH85W29D6R", "10000000000000" ],
[ "edpku7wmQb6EU84bWJESQS6xLxopoEhWQ1SM6wuMYuPWAgs2mE92um",
"10001000000" ],
[ "dn1WLLWBERK56a9n4xdPJupf8qZsvCiNamNA", "10000000" ]
],
[...other fields...]
}

For each account, we specify its address (dn1) and its supply, in mudun. Here, we have also added some tokens to the appnet-admin address, so that we have enough tokens to pay fees for administration operations, and to the baker too.

As an exception, we specify the public key (edpk) of the baker instead of its address: as part of the bootstrap code, the node will register such accounts as delegates (bakers) and reveal their public keys. If we don’t specify such an account, no baker will be able to create the first block of the new protocol!

We can now issue the activation command (the node must be running):

> DUNE_CONFIG=network-config.json ./dune-client -block genesis activate protocol PsBabyM1eUXZseaJdmXFApDSBqj8YBfwELoxZHHW77EMcAbbwAS with fitness 1 and key appnet-admin and parameters protocol_parameters.jsonDUNE_CONFIG="network-config.json"
Config: Appnet. Revision: 2
Node: http://localhost:8734
Enter password for encrypted key:
Injected BKxEi63v1JVQ

The new protocol is now activated, we can start the baker and endorser:

> DUNE_CONFIG=network-config.json ./dune-baker-005-PsBabyM1 run with local node ~/.dune-appnet-node appnet-bakerDUNE_CONFIG="network-config.json"
Config: Appnet. Revision: 2
Node: http://localhost:8734
Enter password for encrypted key "appnet-baker":
Waiting for the node to be synchronized with its peers...
Node synchronized.
Baker started.
Dec 4 14:50:53 - 005-PsBabyM1.baking.forge: New baking slot found (level 1, priority 0) at 2019-12-04T17:45:00-00:00 for appnet-baker after BKxEi63v1JVQ.
[...]

and endorse:

> DUNE_CONFIG=network-config.json ./dune-endorser-005-PsBabyM1 run appnet-bakerDUNE_CONFIG="network-config.json"
Config: Appnet. Revision: 2
Node: http://localhost:8734
Enter password for encrypted key "appnet-baker":
Enter password for encrypted key "appnet-baker":
Waiting for the node to be synchronized with its peers...
Node synchronized.
Endorser started.
Dec 4 18:52:33 - 005-PsBabyM1.baking.endorsement: Received new block BMWLADNDVHM9
Dec 4 18:52:33 - 005-PsBabyM1.baking.endorsement: Found slots for BMWLADNDVHM9/appnet-baker (32)
[...]

We have now the network running, with both the baker and endorser.

Distributing your Private Network Sources

It is sometimes easier to directly distribute the sources of the server with a modified configuration. Dune Network also makes this process easy:

  • In the sources, go to src/lib_config
  • Copy the file set_config_testnet.ml to another name set_config_appnet.ml (don’t forget to commit this new file):
cp set_config_testnet.ml set_config_appnet.ml
git add set_config_appnet.ml
  • Modify the link set_config.ml:
ln -sf set_config_appnet.ml set_config.ml
  • Edit the file set_config_appnet.ml. It has the same structure as the network configuration JSON file, so it should be easy to adapt.
  • Clean and rebuild:
make clean
make

Now, you don’t need to use DUNE_CONFIG anymore!

Conclusion

We have shown how to easily deploy a private Dune Network with both a specific network configuration and a specific protocol parameters.

If you need helps, do not hesitate to contact us on Discord!

In a forthcoming post, we will show how to use Proof-of-Authority in your private network to prevent other accounts from baking/endorsing.

--

--

DUNE network
Dune Network

A secured Web 3.0 platform designed for enterprise-grade decentralized applications.