Getting started with Ethereum as a developer
As a developer, one of the first obstacles to overcome when starting a new platform is to understand the framework and how your projects are structured. This is followed by understanding how to deploy code and secure code in a test or production environment.
The goal of this article is to get your started as a developer on Ethereum. We will aim to familiarise you with the tools required to setup your development environment and to deploy a smart contract on Ethereum. You don’t need to have an understanding of Solidity or how to write a smart contract at this point. That is a topic for another day. We will show you how to:
- Setup a simulated environment
- Deploy and test your smart contracts
- Setup a private testnet for a more realistic environment for testing your smart contracts.
Setting up your first Ethereum project
Before we get started, let’s get an introduction to the terminology and the tools we are going to use.
Testnet — From ethereum.stackexchange.com
Testnets are “play money” so that you can try out applications without spending real money. Applications are typically deployed on testnets before eventually being deployed on the main network. Etherbase is the account that would get the mining reward if you were mining. It has little relevance if you are not mining.
Testrpc — from testrpc github
testrpc
is a Node.js based Ethereum client for testing and development. It uses ethereumjs to simulate full client behavior and make developing Ethereum applications much faster.
Truffle — refers to the Truffle Framework — this is the most popular framework for getting started with Ethereum development. It will make your life a lot easier by handling, compiling, linking, deployment and binary management. It also handles automated testing of your smart contracts among other things.
In order to create and deploy your smart contract, you need to have a blockchain to deploy and test your contract on. Here you have 4 options here:
- Use a dockerized testrpc image — arguably this was the easiest way to get started. However, as of writing this, the image seems to have been removed so this will not be covered.
- Use an simulated testnet — currently, the easiest way to get started
- Create your own private TestNet — arguably the hardest option. It provides you with a lot more control over your environment making running scenarios and debugging issues a lot easier.
- Connect to an existing TestNet — best option to see how your contract will behave in the real world and easier than setting up your own private TestNet.
We are going to cover the second and third points in this post. Future posts will cover connecting and deploying to a public testnet and to production, so keep an eye out.
Why test in a simulated or private testnet
However, it is recommended that you first, test in a simulated testnet, then in a private testnet, before going to a public testnet and then finally into production. There are a few reasons for this:
- Debugging tools are next to non-existent so you want to control the environment as much as possible till you are sure your contract works.
- You don’t want to spend all your ether on a testnet getting more ether even in the testnet will be a pain.
- You want to get an idea of the cost of storing your data on the blockchain, how much time it takes to execute your contracts and optimise them before going to a public testnet or production. Both the amount of data stored and the time it takes to execute contracts can significantly drive up the cost of using Ethereum.
- You may want control over the speed of mining during development or to visually inspect the whole blockchain.
Setting up your environment
Requirements:
- NodeJs 6.0+ — stick to the recommended version
- NPM — NPM comes with node, just make sure it’s installed with the
-g
option.npm install npm -g
- EthereumJs’s testrpc —
npm install -g ethereumjs-testrpc
- Truffle —
npm install -g truffle
Validate that you have installed truffle properly by running truffle version
on your console or command line. If you see an error something went wrong.
That’s it! You should have everything you need to get started as a smart contract developer.
Setting up your first project
Before we start we should take a moment to discuss the advantages and drawbacks of using the Truffle Framework. Drawbacks include not knowing what’s going on. Using Truffle is simple, it completely obfuscates what it takes to compile and deploy a contract from you. This may not work for some projects and will force you to have to learn the compile and deploy process yourself. Advantages include, not needing to know what’s going on 😀, checking dependencies before deploying and Truffle automatically remembers where the last deployment was made to.
Choose a folder for your new project. Choose a directory and path without any spaces in it. A space in the path will probably not cause any issues, but some scripts can have difficulty with it.
mkdir first-smart-contract
cd first-smart-contract
truffle init
truffle init
creates a truffle project that points to a blockchain on your computer. This project comes with a sample contract and some tests. If you wanted an empty project, you could run truffle init bare
.
After running truffle init
the project generated should look something like this:
➜ first-smart-contract tree
.
├── contracts
│ ├── ConvertLib.sol
│ ├── MetaCoin.sol
│ └── Migrations.sol
├── migrations
│ ├── 1_initial_migration.js
│ └── 2_deploy_contracts.js
├── test
│ ├── TestMetacoin.sol
│ └── metacoin.js
└── truffle.js
If you look inside truffle.js
you’ll see where a your project currently thinks an ethereum node to deploy to resides.
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*" // Match any network id
}
}
};
There is only one environment configured called development
which points to localhost
on port 8545
. You can create paths to other environments here if you want.
All the smart contract(s) reside under the contracts directory. Compiling and deploying the contracts is very straight forward.
truffle compile
truffle migrate
truffle compile
will work, however, truffle migrate
will error out since there is no blockchain running on localhost at present.
What are our options to deploy to the blockchain?
As mentioned earlier there are 3 main ways you can do this. Whichever way you choose the actual compile and deploy process will not change and you will still use truffle compile && truffle migrate
to deploy to the chain. You can just configure the environment you want to deploy in truffle.js
and then deploy to the environment using it’s name truffle migrate --network <network name>
. For example, our truffle.js
file reads:
module.exports = {
networks: {
"live": {
network_id: 10,
host: "192.168.1.15", // Point to live env
port: 8545
}
},
rpc: {
host: "localhost",
port: 8545
}
};
You can deploy to the live
environment using truffle migrate --network live
.
Running a simulated testnet using testrpc
This is by far the simplest way to get started.
Open a console separate from the one you have been working on so far and run the command testrpc -d
. The -d
flag makes your testrpc run in deterministic mode. This means that all mnemonic generated along with all the test wallets and private keys will be the same each time. You can try running testrpc
with and without the -d
flag to see this behaviour.
Once testrpc is running go back to your project directory and run truffle migrate
. You should see the console running testrpc
output a bunch of text showing that the contract was successfully deployed. Once the deployment is successful, you can confirm that your contract is working by running truffle test
which will execute the automated tests in your sample project.
That’s it!
Once you have done this the next step is to test your contracts in your own private testnet.
But before we setup our own private testnet, let’s talk about the benefits and drawback of using Truffle.
Setup your own private testnet
.
Setting up your own private testnet
Requirements
Note: if you’re using a Debian based Linux distribution, make it Ubuntu. I tried to setup Geth on Linux Mint and kept coming up against issues. Go1.7 is recommended, however, I was able to get things up and running with Go1.6, I would recommend taking the extra step to setup Go1.7 just to invite good tides.
Genesis file
Before we setup our own private testnet, we should create a genesis file. A genesis file is the starting block for your chain. As such, it contains the initial allocation and the configuration for your chain. A genesis file is not required and you can always use a predefined one which is provided if you run geth
with the --dev
option. More on geth
in a bit. For now, lets assume you want to use your own genesis.json
file.
Below is a sample genesis.json
file.
{
"difficulty": "1",
"gasLimit": "9999999",
"config": {
"chainId": 101,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
"7ccc413a6b51be178ae62c1bcd86e8c1217c40cb": {
"balance": "1000000"
},
"b73f3248a841d9bb6f01d256baa3f9bfcc6a0be8": {
"balance": "1000000"
}
}
}
Explaining the contents of the genesis.json file
difficulty
— this is the difficulty of the cryptographic function, set this to a low number to get the block to mine fast, set it to a larger number for a more realistic or slow mining result.
gasLimit
— this is the maximum possible cost of mining a block. Set this to a high number for testing or development purposes.
chainId
— this is the ID of the chain. In practice setting this can help provide simple validation and provide protection from playback attacks (simply put, this is when an unauthorized acts as the original sender).
homesteadBlock
— the second major release of Ethereum was named “Homestead”. The first release was called “Frontier”. Zero-value here means that you are using Homestead.
alloc
— as the name implies, this is the initial allocation of Ethereum (the cryptocurrency) to wallets. The 40-character hex string is the wallet address and the balance
is the amount of ether allocated to each of the wallets.
As mentioned, the genesis file is not required and you can always use a predefined one which is provided if you run geth
with the --dev
option.
It may be a good idea to familiarise yourself with the genesis file as the preallocated genesis file may not work for you, or just because you want more control over your project. Also, you probably want your initial wallets setup before you initialise your blockchain.
It’s also worth noting that as mentioned in this Ethereum blog post there is a python tool available for generating your own genesis.json file.
Initialize the blockchain and creating an account
The initial genesis file will have to have nothing under the alloc
section because we haven’t created any accounts yet. We’ll have to initialise the blockchain, then create a new account on it and then run the initialisation command again. The genesis.json
file I’ll be using is the one below.
mkdir myblockchain myblockchain/datadir
cd myblockchaingeth account new --datadir "$PWD/datadir"# outputs something like this:
Passphrase: ********
Repeat passphrase: ********
Address: {289a21e11cb10f77f7b17fa39a0f6613ec681293}cat > genesis.json <<EOF
{
"difficulty": "1",
"gasLimit": "9999999",
"config": {
"chainId": 101,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
"289a21e11cb10f77f7b17fa39a0f6613ec681293": {
"balance": "1000000"
}
}
}geth init --datadir "$PWD/datadir" genesis.json# Ctrl+D to exit the geth console
We have now created a chain and created an account.
Note that the balance amount is in quotes “1000000”
.
You should now have a new chain with pre-allocation to the account mentioned above. You should now check what accounts exist on your chain and assign a default one:
geth --datadir "$PWD/datadir" account list
# Outputs something like:
Account #0: {289a21e11cb10f77f7b17fa39a0f6613ec681293} keystore://..
We will now launch the geth console with proper configuration, assign the account shown above as our default account and check our Ethereum balance.
geth --identity "MyPrivateBC" --rpc --rpcport "8545" --rpccorsdomain "*" --datadir "$PWD/datadir" --port "30303" --nodiscover --rpcapi "db,eth,net,web3" --networkid 1900 --nat "any" console# Inside the console to get verify your account,
# set a primary account and check its balance, run:
> eth.accounts
["0x289a21e11cb10f77f7b17fa39a0f6613ec681293"]> primary = eth.accounts[0]
0x289a21e11cb10f77f7b17fa39a0f6613ec681293
> eth.getBalance("0x289a21e11cb10f77f7b17fa39a0f6613ec681293")
1000000
# Ctrl+D to exit the console
We have now successfully created a blockchain, created an account on the blockchain and assigned it a million Ethereum.
If you want to know more about the flags on the geth
command, take a look at this page. Just a word of caution that the commands shown on that page are outdated and may not work. --nodiscover
will make this blockchain a private one and the only way to for other nodes to connect to you is for them to add you manually.
Creating your blockchain: connecting static nodes
If you’re running the console, your node will automatically connect to nodes with the same genesis file and networkId. If you follow the same setup instructions on another machine or even in an other directory you should be able to create a second node.
Since your nodes are not discoverable, you need to define your static nodes. Static nodes are nodes that you always want to connect to. Your node will also automatically re-establish connection with these nodes if the connection is ever terminated.
Static nodes contain information such as IP address/domain and port to connect on as well as the public key of the node to connect to. You need to create <datadir>/static_nodes.json
file and add the enode URI to it. You can find your encode URI in the geth console after launching it:
geth console
WARN [10–16|14:51:10] No etherbase set and no accounts found as default
INFO [10–16|14:51:10] Starting peer-to-peer node instance=Geth/v1.6.7-stable-ab5646c5/darwin-amd64/go1.8.3
INFO [10–16|14:51:10] Allocated cache and file handles database="/Users/ali/Library/Ethereum/geth/chaindata" cache=128 handles=1024
INFO [10–16|14:51:10] Initialised chain configuration config="{ChainID: 1 Homestead: 1150000 DAO: 1920000 DAOSupport: true EIP150: 2463000 EIP155: 2675000 EIP158: 2675000 Metropolis: 9223372036854775807 Engine: ethash}”
INFO [10–16|14:51:10] Disk storage enabled for ethash caches dir="/Users/ali/Library/Ethereum/geth/ethash" count=3
INFO [10–16|14:51:10] Disk storage enabled for ethash DAGs dir="/Users/ali/.ethash" count=2
INFO [10–16|14:51:10] Initialising Ethereum protocol versions="[63 62] network=1
INFO [10–16|14:51:10] Loaded most recent local header number=1536 hash=b787b8…7d0da3 td=39056428498300
INFO [10–16|14:51:10] Loaded most recent local full block number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [10–16|14:51:10] Loaded most recent local fast block number=1136 hash=533e56…d0055d td=25929990157171
INFO [10–16|14:51:10] Starting P2P networking
INFO [10–16|14:51:12] UDP listener up self=enode://1a84136963764e37cdb5768c23335175b5861419b8d747964e050f06dbfb9349dee0cc4a6e4f0f36c9a312423234e386c32e82c774a0253335cf1f7f6baf70c8@[::]:30303
INFO [10–16|14:51:12] RLPx listener up self=enode://1a84136963764e37cdb5768c23335175b5861419b8d747964e050f06dbfb9349dee0cc4a6e4f0f36c9a312423234e386c32e82c774a0253335cf1f7f6baf70c8@[::]:30303
INFO [10–16|14:51:12] IPC endpoint opened: /Users/ali/Library/Ethereum/geth.ipc
Welcome to the Geth JavaScript console!
# Ctrl+D to exit
Exit the console and then, create a static_nodes.json
file — a sample file is shown below. Make sure to replace [::]
shown above with the IP address or domain name of your machine.
[
"enode://17acb9097df2ce730feb3148e21ab6346ffd21a2221c21094993e3eb6fee56cff1c576b447323d52feb79ecb10d303a1f8f4e68c64050b25e6e2840e55b22392@192.168.1.1:30303?discport=0", "enode://publickey@<ipaddress>:30303?discport=0",
"enode://publickey@<ipaddress>:30303?discport=0",
"enode://publickey@<ipaddress>:30303?discport=0",
]
Make sure to add the URI for all the nodes you want to connect to. This includes your own node. Copy this file to every node in your private network. Now when you run the geth
console your nodes should connect.
Since this is not a simulated environment, you will need to enable mining on your nodes, otherwise any contracts your deploy or Ethereum you exchange will stay in a pending state.
# In geth console
> miner.start(0)
> miner.stop()
Deploy your smart contract on your private testnet
Now that we have our own private testnet setup. We can compile our smart contract and deploy to it. With the geth
console running, navigate to your smart contract project directory. First, check the <smart contract project dir>/truffle.js
file to make sure you have an environment configured pointing to your private testnet and then compile and deploy with truffle
truffle compile
truffle migrate --network myPrivateTestNet
That it! You now have a private testnet setup to test your smart contracts.
Finally
Give us a 👏👏👏 if you enjoyed this post it will motivate us to put out more great content.
You made it to the end! You’re awesome! We should hang out more often! To learn how to build great app and dApps, follow BCG Digital Ventures Engineering, BCG Digital Ventures and the author of this post, Ali Muzaffar.