Tutorial: Deploy your own ICO token using Geth (Part I)

HaloBlock Official
HaloBlock
Published in
6 min readJul 30, 2018

Hey, guys! We’re so excited to share this tutorial with you. Since the past several weeks, we have published a series of blogs related to smart contract development, like Remix, Truffle and many testing tools. This time, as usual, we decide to write a beginner’s tutorial about using Geth, the official golang implementation of the Ethereum protocol. With this tool, we can deploy our own smart contracts to any network supported by powerful functions. So, let’s just get started!

Install Geth

On Linux

sudo apt-get install software-properties-common
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum

On OSX

brew update
brew upgrade
brew tap ethereum/ethereum
brew install ethereum

After that, you can type geth --help to check whether geth has been successfully installed. If it shows help information, then you are good to go.

Create a new account

Now, we have our Geth ready and in order to make transactions, we need an account. If we already have our own account, then we can import the private key file into Geth with the following command:

$ geth account import 

Then we just need to follow its instructions.

But, if we don’t have one, we can create a new account with Geth. Simply type:

$ geth account new

After that, Geth will store your private key file in a global manner. We can check that in these locations per your operating system.

  • Linux: ~/.ethereum
  • OSX: ~/Library/Ethereum

For example, we create a new account and its public address is

0x2f5e0ff2c960852e76be73b7cff8ea20d42d2ec

And if we type:

$ geth account list

We will find out that we have one account currently. If we forget the newly created public address, don’t worry. We can check it in this way.

Create genesis.json

Now, we can first create our initial block using genesis.json.

Basically, genesis.json is a file which specifies a series of rules and configurations for the entire blockchain, including chainID, difficulty, gasLimit and so on. Each transaction made will follow these rules. For now, we just need to change our account address here, and leave all the other stuffs alone.

We can store this file anywhere we like. It will not affect the following steps to initialize a blockchain.

{
"config": {
"chainID": 1234,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc": {
// Remember to change your address here
"<Your account address>": {
"balance": "1000000000000000000000000000"
}
},
"difficulty": "0x4000",
"gasLimit": "0xffffffff",
"nonce": "0x0000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x123458db4e347b1234537c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"timestamp": "0x00"
}

Create blockchain

As we all know, every block of the blockchain will be stored in each node’s local disk if the node is fully synchronized. Thus, we should also specify a folder to store the entire blockchain. In order to achieve that, we can use this command:

$ geth --datadir "./LocalNode1/" init genesis.json

It will first create a folder named LocalNode1 in the current folder, then initialize the blockchain with genesis.json and store the data files into LocalNode1. Here the path of genesis.json should be given correctly, otherwise it won’t work.

We will get a “Successfully wrote genesis state” message if everything goes well. And look into the LocalNode1 folder, we can find there are two folders geth and keystore, and one file geth.ipc.

Files under LocalNode1

Interact with blockchain

To interact with the blockchain we just created, simply type:

$ geth --datadir "./LocalNode1" --networkid 1234 --port 10000 --nodiscover console

This command specifies several things:

  • datadir: data folder to store blocks
  • networkid: has to match the chainID in genesis.json
  • port: occupy a given port
  • nodiscover: make our node not automatically interact with others

Add existing account

For now, we don’t have any account inside LocalNode1. Though we created a new account previously, it couldn’t be found by Geth because we are currently running data from LocalNode1. In order to add existing account to LocalNode1, we need to open a new terminal and type the following:

$ cp ~/.ethereum/keystore/UTC--<rest of account file's name> pathbeforelocalnode1/LocalNode1/keystore/

All right. Check the account inside LocalNode1 by:

> personal.listWallets

We can also check the balance of our account.

> web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");

Remember, we specify 10¹¹ in genesis.json for the balance of our account.

Connect to other nodes

Now, we open a new terminal and create a new folder named LocalNode2 under the same folder of LocalNode1. We do the same process as the old node because, in order to make two nodes connected, we need to have the exact same blockchain information. That being said, the new node should initialize all the information with genesis.json and synchronize all the past transactions within this blockchain.

Create a new data folder and initialize with genesis.json:

$ geth --datadir "./LocalNode2/" init genesis.json

Open Geth console:

$ geth --datadir "./LocalNode2" --networkid 1234 --port 10001 --nodiscover console

Note that the port number should be different from the previous one.

Create a new account for node2:

> personal.newAccount()

OK. Now, we can start with our connecting process. If you follow our tutorial carefully, you will find out that we set nodiscover previously, and you might be confused. Yes, nodiscover property will prevent our node automatically interact with the other nodes, which means if we actively add a node, it will be fine.

First, in the node2’s terminal, get the node2's information by:

> admin.nodeInfo.enode

Second, in the node1’s terminal, add the node2’s information by:

> admin.addPeer("enode://123456789...")
Successfully connected

Then check the connection by:

> admin.peers

or

> net.peerCount

Set the miner

A miner is a node who provides computation power to gain rewards. Every transaction must be mined to put on a block. So, there are thousands of miners out there to compete with each other to execute the transaction. Sometimes, the higher the amount of gas the transaction provides, the more intense the competition is.

To set the miner, simply type the following in the node1’s terminal:

> miner.setEtherbase(eth.accounts[0])

This means eth.accounts[0] not only plays the part of a caller, but also plays the part of a miner. We can definitely set other accounts as the miner.

Also, in the node2’s terminal, set the miner:

> miner.setEtherbase(eth.accounts[0])

Conclusion

That’s it! Playing around these tools will help us have a deeper understanding of how the blockchain actually works, how nodes interact with each other and so on. Next time, we will share more details about how to compile a contract, make a contract creation transaction and start the miner to mine the transaction. See you next week!

By Zhiyuan Li and Quan Sun, Security Researchers from HaloBlock.io

--

--

HaloBlock Official
HaloBlock

Security Audits for Smart Contracts and Crypto Exchanges