Building a Multi-Node Ethereum Private Chain with Geth: Mining and Smart Contract Deployment

·

Geth is an Ethereum client written in Go that interacts with the Ethereum network.

1. Initializing the Genesis Block

Creating an Ethereum network starts with a genesis block. Create a file named genesis.json with the following content:

{
 "config": {
 "chainId": 666,
 "homesteadBlock": 0,
 "eip155Block": 0,
 "eip158Block": 0
 },
 "coinbase" : "0x0000000000000000000000000000000000000000",
 "difficulty" : "0x1",
 "extraData" : "",
 "gasLimit" : "0x2fefd8",
 "nonce" : "0x0000000000000042",
 "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
 "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
 "timestamp" : "0x00",
 "alloc" : {}
}

Parameter explanations:

ParameterDescription
configPrivate chain configuration
config.chainIdChain ID (must match --networkid in geth command)
coinbaseMiner account
difficultyMining difficulty (set low for private chains)
gasLimitGas consumption limit per block
nonce64-bit random number for mining
parentHashParent block hash (0 for genesis block)

2. Initializing the Genesis Block

Initialize using the init command:

geth --datadir /path/to/ehtdata/ init genesis.json

Parameter explanation:

3. Starting the Genesis Block

Start the node with console access:

geth --datadir /path/to/ehtdata/ \
--networkid 666 \
--identity "bootnode" \
--port 30303 \
--rpc \
--rpcport 8545 \
--rpccorsdomain "*" \
--nodiscover \
--verbosity 4 \
console 2>> eth.log

Key parameters:

4. Creating Accounts

Create new accounts within the Geth console:

> personal.newAccount() // Create account
> eth.accounts // List accounts
> eth.getBalance(eth.accounts[0]) // Check balance

5. Mining for ETH

Start mining to earn Ether:

> miner.start() // Start mining
> eth.getBalance(eth.accounts[0]) // Check balance
> eth.blockNumber // Check block height

6. Creating New Nodes and Joining the Network

To create additional nodes:

  1. Initialize with the same genesis block
  2. Start with different ports
  3. Connect nodes using one of these methods:

Method 1: Using admin.addPeer()

> admin.addPeer("enode://[email protected]:30303")

Method 2: Using static-nodes.json

[
 "enode://[email protected]:30303"
]

Method 3: Using --bootnodes parameter

geth ... --bootnodes "enode://[email protected]:30303"

7. Deploying Smart Contracts

Sample Contract

pragma solidity >=0.5.1;
contract Test {
 uint256 public A = 0;
 
 function set(uint256 a) public {
 A = a;
 }
 
 function get() view public returns(uint256) {
 return A;
 }
 
 function sum(uint256 b) view public returns(uint256) {
 return A + b;
 }
}

Deployment Steps

  1. Compile and get ABI/Bytecode
  2. Define contract in Geth console:
> var bytecode = "0x..."
> var abi = JSON.parse('[{\"constant\":...}]')
  1. Create contract instance:
> test = web3.eth.contract(abi)
  1. Estimate gas:
> web3.eth.estimateGas({data: bytecode})
  1. Unlock account:
> personal.unlockAccount(eth.accounts[0])
  1. Deploy contract:
> contractInstance = test.new({data: bytecode, gas: 1000000, from: eth.accounts[0]})
  1. Start mining to confirm deployment:
> miner.start()
  1. Interact with contract:
> contractInstance.get()
> contractInstance.set.sendTransaction(9, {from: eth.accounts[0]})
> contractInstance.sum(666)

👉 Learn more about Ethereum development

FAQ Section

Q1: What's the minimum difficulty setting for private chains?

A: You can set difficulty as low as "0x1" for private chains to enable fast block generation during testing.

Q2: How do I connect nodes running on different machines?

A: Replace "127.0.0.1" with the actual IP address in the enode URL and ensure firewalls allow the specified ports.

Q3: Why isn't my contract deployment completing?

A: You need to mine blocks to include your deployment transaction. Start mining with miner.start().

Q4: How can I check if my contract deployed successfully?

A: Use eth.getCode(contractAddress) - it should return non-zero bytecode if deployed.

Q5: What's the difference between test.new() and test.at()?

A: new() deploys a new contract while at() connects to an existing deployed contract.

👉 Explore advanced Ethereum features