How to run a private network of the NEO blockchain

Running a private network of the NEO blockchain is an integral part of working with the blockchain, in particular for writing and testing dApps and smart contracts. A private network is a complete NEO blockchain for yourself, isolated from the public networks. You can spin it up quickly, claim the initial 100 million NEO, and experiment with all aspects of it.

This post is a step-by-step guide on setting up a private chain with Docker and Python on Mac, Linux and Windows, and an introduction to neo-python and neo-privatenet-docker.

Update 2017–11–20: There is now a turnkey Docker image with a pre-build private network and a wallet with 100m NEO and 16.6k GAS ready-to-go, available here: https://hub.docker.com/r/metachris/neo-privnet-with-gas/


Note for Windows users:

  • neo-python currently has no documented support for Windows, because getting LevelDB only works easily on OSX and Linux. You can still run the private network with the Docker container, but to create wallets and extract NEO and GAS you’ll need to follow the official NEO private chain docs beginning with step 5.
  • Docker does not work with Windows 10 Home Edition, you’ll need at least Pro.

NEO itself and the native tooling is primarily developed with C# using Windows. The official NEO documentation on private chains gives a good overview how to setup a private network with a Windows toolchain and 4 Windows virtual machines as consensus nodes.

Thanks to the monumental efforts of the City of Zion community (CoZ), running a private chain is possible on any platform with Docker and Python, with minimal system requirements. The two specific projects we are going to use are neo-python and neo-privatenet-docker:

  • neo-python — allows us to run a full NEO node and to interact with the blockchain with Python 3.
  • neo-privatenet-docker — allows us to run a whole NEO blockchain with 4 consensus nodes in a single, lightweight Docker container

At this point I also want to mention neo-js, a NEO node implementation in JavaScript, with several features in the pipeline. neo-js is not quite as mature as neo-python, but already supports all RPC calls, and you can run a full local node, saving the blockchain data into a MongoDB database.


Setting up a private NEO chain, step-by-step

The steps are the following: Docker setup → neo-privatenet-dockerneo-python → connect to the private net and create a wallet → claim the initial 100,000,000 NEO.

Docker Setup

Run the private chain Docker container

  • Clone neo-privatenet-docker, then build and run the Docker container with the four initial consensus nodes:
$ git clone https://github.com/Splyse/neo-privatenet-docker.git
$ cd neo-privatenet-docker
$ ./docker_build.sh
$ ./docker_run.sh
  • At this point, the Docker container running the consensus nodes is running in the background. You can see it with $ docker ps:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f7ed0d4ae3a neo-privnet "/bin/bash /opt/pr..." 2 hours ago Up 2 hours 0.0.0.0:20333-20336->20333-20336/tcp neo-privnet
  • If you encounter an error like Get https://registry-1.docker.io/v2/library/ubuntu/manifests/16.04: unauthorized: incorrect username or password, you may need to login to Docker hub $ docker login with your user-id (not email).
  • When the Docker container stops or restarts, all state is deleted (the whole ‘old’ blockchain will be gone), and you should also remove Chains/privnet from neo-python and any privnet wallets you created.

neo-python

Now we can connect to the private network with neo-python, create a wallet and claim the initial NEO:

$ python prompt.py -c protocol.privnet.json
NEO cli. Type 'help' to get started
neo>
  • The number of blocks should be increasing continuously (eg. ‘Progress 0/1’)
  • Create a wallet:
neo> create wallet privnet
password> ************
password> ************
Script hash b"'\xbaI\xf7H\x13\x1d \x7fC5\xf1\x1d\x04!a\xb5\xce-\xb4" <class 'bytes'>
Wallet {
"percent_synced": 0,
"path": "privnet",
"addresses": [
"AKPwAZWyBWMdUe8NtoSYMeTmwCxrP4e2KB"
],
"public_keys": [
{
"Public Key": "02ddeee35542a7e390395b0cca3a493ee001fee35b7710846b5b73bf0d888c133b",
"Address": "AKPwAZWyBWMdUe8NtoSYMeTmwCxrP4e2KB"
}
],
"synced_balances": [],
"height": 0
}
pubkey b'02ddeee35542a7e390395b0cca3a493ee001fee35b7710846b5b73bf0d888c133b'
  • Make a note of the address, in this case AKPwAZWyBWMdUe8NtoSYMeTmwCxrP4e2KB
  • Close prompt.py (type exit or press CTRL+D)
  • Claim the initial 100,000,000 NEO:
$ python contrib/privnet-claimall.py -c protocol.privnet.json -a {your-address}
  • This creates a transaction signed by 3 of the 4 consensus nodes, and waits for the blockchain to confirm the transaction.
  • Be patient, this may take a minute or two.

At this point, you have 100m NEO in your wallet and you can do as you please. Check the balance with neo-python:

neo> open wallet privnet
password> ************
Opened wallet at privnet
neo> wallet
Script hash b'i\xd5r\xef\\\xf2=\xb32\xb7\xffe\xa4\t@6\xdbM\x1b\xb7' <class 'bytes'>
Wallet {
"percent_synced": 100,
"path": "privnet",
"addresses": [
{
"votes": [],
"balances": {
"c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b": "100000000.0"
},
"version": 0,
"is_watch_only": false,
"frozen": false,
"script_hash": "ARRUJLMrTipDfvzUGHNJ3qAAcQRSdtUcEX"
}
],
"public_keys": [
{
"Public Key": "02c017615119d81f4b3ab7ddb016e22e3313cacb6ab5cf2ef38addd752ac1b3d9f",
"Address": "ARRUJLMrTipDfvzUGHNJ3qAAcQRSdtUcEX"
}
],
"synced_balances": [
"[NEO]: 100000000.0 "
],
"height": 402
}

At this point you now have a private NEO chain up and running and full control over the initial funds. Happy hacking!

How to restart and reset the private network

The Docker container does not persist any state. If it stops or restarts, all state is lost and the whole blockchain will be newly created at the next start.

It’s important to remove the old chain files from neo-python (Chains/privnet), else you’ll run into problems running the old database against another chain.

neo-python$ rm -rf Chains/privnet/

You can manually restart the private-net container by running ./docker_run.sh. This stops the neo-privnet container if it is running, and starts a fresh one:

$ ./docker_run.sh
Stopping container named neo-privnet
Removing container named neo-privnet
Starting container...
7e23e2fe1475489503f4d6b6a619275d806043dbeb0672e981ec3938c875167f

Claiming the initial GAS

neo-python does not yet support claiming GAS. You can claim it with the official NEO tools as described in the NEO private chain docs beginning with step 5.

Docker Tips & Tricks

Here are a few often-used Docker commands:

  • docker ps lists all running instances, docker ps -a also all stopped ones - docs
  • docker images lists all your local images from which a container can start from - docs
  • docker exec -it {container-id} /bin/bash opens a bash interface into the running container - docs
  • docker stop {container-id} stops the container - docs
  • docker rm -f {container-id} stops and deletes the container - docs
  • docker run to start a new container - docs

NEO TestNet

The NEO project also provides a running TestNet, but this should be only used in the final stages of development (for a variety of reasons).


neo-python

neo-python is an amazing project, a community effort to re-implement the original C# NEO project in Python! It has come a long way and already supports the following functionality:

  • Running a Python based NEO P2P node
  • Interactive CLI for configuring node as well as inspecting and interacting with the blockchain
  • Executing smart contracts on the blockchain in a Python virtual machine
  • Very basic Wallet functionality (not fully tested, please do not use on mainnet)

neo-python has been forked from a “very” preliminary Python SDK, but development really started in July 2017, with constant contributions since then:

As of November 3, 2017, neo-python has 18 contributors, and is spearheaded by localhuman.

If you want to work with the NEO blockchain on a platform other than Windows, you’ll most certainly interact with neo-python in one way or the other. It’s an integral part of the cross-platform development toolchain, actively developed, and just overall a great project.

I just want to send a big thank-you to all the individuals who contributed to making this possible! ♥️ I’m excited about the bright future of this project and it’s further development.


neo-privatenet-docker

Let’s take a closer look at neo-privatenet-docker, which allows us to easily run a private NEO blockchain within an Ubuntu Docker image. A private chain requires at least 4 consensus nodes, which are all running inside this single Docker container. The main contributors are hal0x2328 and phetter.

Let’s start with the Dockerfile:

FROM ubuntu:16.04
MAINTAINER hal0x2328
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y apt-utils
RUN apt-get install -y mininet netcat curl wget unzip less python screen
RUN apt-get install -y ca-certificates apt-transport-https
RUN apt-get install -y libleveldb-dev sqlite3 libsqlite3-dev
RUN apt-get install -y expect
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg
RUN echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list
RUN apt-get update && apt-get install -y dotnet-sdk-2.0.0
RUN wget -O /opt/neo-cli.zip https://github.com/neo-project/neo-cli/releases/download/v2.3.2/neo-cli-ubuntu.16.04-x64.zip
  • The image is based on Ubuntu 16:04
  • Various system utilities are installed, including LevelDB, a fast key-value storage from Google, and sqlite3, a self-contained, serverless, zero-configuration, transactional SQL database engine.
  • The Microsoft apt repositories are setup, and the dotnet-sdk-2.0.0 is installed. Remember, the original NEO project is implemented in C# and runs on .NET Core.
  • The the neo-cli Ubuntu release is downloaded

That’s pretty much the whole setup. After this, neo-cli is extracted 4 times (once for each consensus node), and the private chain startup files are copied:

RUN unzip -d /opt/node1 /opt/neo-cli.zip
RUN unzip -d /opt/node2 /opt/neo-cli.zip
RUN unzip -d /opt/node3 /opt/neo-cli.zip
RUN unzip -d /opt/node4 /opt/neo-cli.zip
ADD ./scripts/private_chain_start.sh /opt/
ADD ./scripts/start_cli.sh /opt/

When you run the Docker container with docker_run.sh, it starts the container with 4 open ports (20333-20336, mapped to the host), and invokes the private_chain_start.sh script:

docker run -d --name neo-privnet -p 20333-20336:20333-20336/tcp -h neo-privnet neo-privnet /bin/bash /opt/private_chain_start.sh /opt/

private_chain_start.sh in turn starts 4 NEO nodes by executing start_cli.sh four times:

#!/usr/bin/expect -f
set dnpath [lindex $argv 0]
set wallet [lindex $argv 1]
set password [lindex $argv 2]
set timeout -1
cd $dnpath
spawn dotnet neo-cli.dll
expect "neo>"
send "open wallet $wallet\n"
expect "password:"
send "$password\n"
expect "neo>"
send "start consensus\n"
expect "OnStart"
#expect "LIVEFOREVER"
interact

This code sets a few variables from the arguments (dnpath, wallet, password), runs dotnet neo-cli.dll, opens the initial node wallet and calls start consensus in order for the nodes to start working. At this point, blocks in the private chain are being created.


That’s pretty much it! And even though it doesn’t look like much code, it’s a life-saver for getting started with NEO blockchain development and running a private chain, because it makes it just so easy and accessible. Again a big thank-you to the developers driving this project!


I would suggest that you try it out right now! Just follow the getting started guide above and you will have your own private NEO chain running in no time.

Feel free to join the NEO Slack and say hi, it’s an open and welcoming community! You can also find links to various other resources on the official NEO homepage at neo.org.


If you have feedback or comments regarding this post, please reach out to the author via @metachris.