To develop a smart contract on the ethereum blockchain we need a local environment to work in. Obviously we don't want to test on the main network where we take on actual financial costs and risks so instead we need to setup a test network. We could use one of the public test networks but this takes a lot of time and memory to sync with. Instead it will often be sufficient to create a personal, private test network with multiple accounts to interact with. This post shows how such a network can be created locally using geth.

Setting up geth

geth is a node environment for interacting with the network, for making transactions, mining and creating contracts. There are many methods for installing geth that can be found here https://github.com/ethereum/go-ethereum/wiki/Installing-Geth but to keep my development environment clean I use the official docker image creating an alias so that the container behaves identically to a natively installed executable:

$ alias geth='docker run -w /src --rm -it -v `realpath .`:/src -v ${ETHEREUM_DATA_DIR}:/root/.ethereum ethereum/client-go:stable'

This will mount the current working directory into the containers working directory so that all files can be accessed by their relative paths and stores the network data in ${ETHEREUM_DATA_DIR}

Setting up the network

To interact with the network we will first need to create it. This is done using geth init:

$ geth --datadir /root/.ethereum/test --networkid 123 --nodiscover --maxpeers 0 init genesis.json

Where genesis.json looks like:

{
    "nonce": "0x0000000000000042",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "difficulty": "0x4000",
    "alloc": {},
    "coinbase": "0x0000000000000000000000000000000000000000",
    "timestamp": "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "extraData": "0x",
    "gasLimit": "0xffffffff",
    "config": {}
}

Note: The --datadir parameter points to /root/.etherium/test, this is the absolute path in the container where the data should be stored.

Next we need to create an account for our miner to use. To do this we need to create our first account using geth account new:

$ geth --datadir /root/.ethereum/test --networkid 123 account new

This will prompt for a passphrase to use for the account. Once this is complete the signature of the account will be stored as the default coinbase for geth and we can start a miner by running:

$ geth --datadir /root/.ethereum/test --networkid 123 --mine --minerthreads 1

Since this is the only miner on the network we only need to specify one miner thread as mining will be very easy.

Testing our setup

To make sure we have setup out chain correctly we will try and transfer some funds between accounts on our network. Firstly we need to start an interactive geth session running on our network, to do this we attach to the currently running network using:

$ geth --datadir /root/.ethereum/test --networkid 123 attach

If you do not have the miner (or any other instance of geth) running you can instead use geth console:

$ geth --datadir /root/.ethereum/test --networkid 123 console

Once the session has started we can check that our miner is mining happily and gaining funds using:

> eth.getBalance(eth.coinbase)
1.77e+21

Assuming the balance is not zero we can start transferring funds. First we create a new account:

> personal.newAccount()
Passphrase: <new account passphrase>
Repeat passphrase: <new account passphrase>

After creating the account, transfer funds to it using:

> personal.unlockAccount(eth.coinbase)> personal.unlockAccount(eth.coinbase)
Unlock account <account signature>
Passphrase: <miner passphrase>
true

> eth.sendTransaction({from: eth.coinbase, to: eth.accounts[1], amount: 1000})
"<transaction address>"

Once the transaction block has been mined we can then check the funds in our second account using:

> eth.getBalance(eth.accounts[1])
1000

And we are done!

A few notes:

  1. eth.coinbase is an alias to whichever account has been set as the coinbase. If no option is set this defaults to accounts[0] so in our example eth.coinbase == eth.accounts[0].
  2. The full documentation for geth can be found here https://github.com/ethereum/go-ethereum/wiki
comments powered by Disqus

Pingbacks

Pingbacks are open.