All articles
รวมเอกสาร CSJan 06, 20240 min read

Lab1 Setup private blockchain

Learned to create private blockchain network, create multiple node, mining, and create transactions

A

Athicha Leksansern

Full-stack Engineer

Install on MacOS

  1. Download geth 1.8.27

    $ wget https://gethstore.blob.core.windows.net/builds/geth-alltools-darwin-amd64-1.8.27-4bcc0a37.tar.gz
    --2025-01-06 19:15:45--  https://gethstore.blob.core.windows.net/builds/geth-alltools-darwin-amd64-1.8.27-4bcc0a37.tar.gz
    Resolving gethstore.blob.core.windows.net (gethstore.blob.core.windows.net)... 20.60.40.164
    Connecting to gethstore.blob.core.windows.net (gethstore.blob.core.windows.net)|20.60.40.164|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 39639257 (38M) [application/octet-stream]
    Saving to: ‘geth-alltools-darwin-amd64-1.8.27-4bcc0a37.tar.gz’
    
    geth-alltools-darwin-amd64-1.8.27-4bcc0a37.tar.gz                      100%[=========================================================================================================================================================================>]  37.80M  3.00MB/s    in 15s     
    
    2025-01-06 19:16:02 (2.44 MB/s) - ‘geth-alltools-darwin-amd64-1.8.27-4bcc0a37.tar.gz’ saved [39639257/39639257]
    
  2. Extract .tar.gz

    $ tar -xvzf geth-alltools-darwin-amd64-1.8.27-4bcc0a37.tar.gz 
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/COPYING
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/abigen
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/bootnode
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/evm
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/geth
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/puppeth
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/rlpdump
    x geth-alltools-darwin-amd64-1.8.27-4bcc0a37/wnode
    
  3. Rename geth-alltools-darwin-amd64-1.8.27-4bcc0a37 to geth

    mv geth-alltools-darwin-amd64-1.8.27-4bcc0a37 geth
    

Setup private blockchain

For node1

  1. Create genesis.json

    {
     "config": {
       "chainId": 100,
       "homesteadBlock": 0,
       "eip155Block": 0,
       "eip158Block": 0,
       "byzantiumBlock": 0
     },
     "nonce": "0x0000000000000042",
     "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
     "difficulty": "0x400",
     "coinbase": "0x0000000000000000000000000000000000000000",
     "timestamp": "0x00",
     "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
     "gasLimit": "0xffffffff",
     "alloc": {}
    }
    
  2. Create node1

    $ ./geth/geth --networkid 100 \
        --identity node1 \
        --verbosity 3 \
        --nodiscover \
        --nat none \
        --datadir node1 \
        init genesis.json
    INFO [01-06|19:21:50.015] Maximum peer count                       ETH=25 LES=0 total=25
    INFO [01-06|19:21:50.089] Allocated cache and file handles         database=/Users/athicha/Desktop/งาน/CsCourse65/BlockChain/Lab1/node1/geth/chaindata cache=16 handles=16
    INFO [01-06|19:21:50.101] Writing custom genesis block 
    INFO [01-06|19:21:50.102] Persisted trie from memory database      nodes=0 size=0.00B time=15.5µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
    INFO [01-06|19:21:50.105] Successfully wrote genesis state         database=chaindata                                                                  hash=272003…b62890
    INFO [01-06|19:21:50.105] Allocated cache and file handles         database=/Users/athicha/Desktop/งาน/CsCourse65/BlockChain/Lab1/node1/geth/lightchaindata cache=16 handles=16
    INFO [01-06|19:21:50.107] Writing custom genesis block 
    INFO [01-06|19:21:50.107] Persisted trie from memory database      nodes=0 size=0.00B time=2.333µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
    INFO [01-06|19:21:50.108] Successfully wrote genesis state         database=lightchaindata                                                                  hash=272003…b62890
    
  3. Connect to node1 console

    $ ./geth/geth --networkid 100 \
        --identity node1 \
        --verbosity 3 \
        --nodiscover \
        --nat none \
        --datadir node1 \
        --rpc --rpcapi "web3, eth, personal" --rpccorsdomain "*" \
        --ipcpath node1/geth.ipc \
        console
    INFO [01-06|19:23:44.984] Maximum peer count                       ETH=25 LES=0 total=25
    INFO [01-06|19:23:45.005] Starting peer-to-peer node               instance=Geth/node1/v1.8.27-stable-4bcc0a37/darwin-amd64/go1.11.9
    INFO [01-06|19:23:45.005] Allocated cache and file handles         database=/Users/athicha/Desktop/งาน/CsCourse65/BlockChain/Lab1/node1/geth/chaindata cache=512 handles=5120
    INFO [01-06|19:23:45.032] Initialised chain configuration          config="{ChainID: 100 Homestead: 0 DAO: <nil> DAOSupport: false EIP150: <nil> EIP155: 0 EIP158: 0 Byzantium: 0 Constantinople: <nil>  ConstantinopleFix: <nil> Engine: unknown}"
    INFO [01-06|19:23:45.032] Disk storage enabled for ethash caches   dir=/Users/athicha/Desktop/งาน/CsCourse65/BlockChain/Lab1/node1/geth/ethash count=3
    INFO [01-06|19:23:45.032] Disk storage enabled for ethash DAGs     dir=/Users/athicha/.ethash                                                  count=2
    INFO [01-06|19:23:45.033] Initialising Ethereum protocol           versions="[63 62]" network=100
    INFO [01-06|19:23:45.077] Loaded most recent local header          number=0 hash=272003…b62890 td=1024 age=55y9mo3w
    INFO [01-06|19:23:45.077] Loaded most recent local full block      number=0 hash=272003…b62890 td=1024 age=55y9mo3w
    INFO [01-06|19:23:45.077] Loaded most recent local fast block      number=0 hash=272003…b62890 td=1024 age=55y9mo3w
    INFO [01-06|19:23:45.081] Regenerated local transaction journal    transactions=0 accounts=0
    INFO [01-06|19:23:45.096] New local node record                    seq=1 id=6ddaad509c2c3832 ip=127.0.0.1 udp=0 tcp=30303
    INFO [01-06|19:23:45.097] Started P2P networking                   self="enode://3263a6d420648480a4fa6cd95d8ab6f18ed2caec2cf77212b3d2cb21d3a70203ac2baa8dbf0bf641209063c2ca21d42154622662da1265a0a95b00132813c8eb@127.0.0.1:30303?discport=0"
    INFO [01-06|19:23:45.102] IPC endpoint opened                      url=node1/geth.ipc
    INFO [01-06|19:23:45.103] HTTP endpoint opened                     url=http://127.0.0.1:8545 cors=* vhosts=localhost
    Welcome to the Geth JavaScript console!
    
    instance: Geth/node1/v1.8.27-stable-4bcc0a37/darwin-amd64/go1.11.9
     modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
    
    >
    
  4. Create new account

    > personal.newAccount("password1")
    "0x5b7604b47e9a16f62a1e8da369a3f963535b0d8c"
    

To disconnect from console press Ctrl + D

For node2

  1. Open new terminal, and create node2

    $ ./geth/geth --networkid 100 \
       --identity node2 \
       --verbosity 3 \
       --nodiscover \
       --nat none \
       --datadir node2 \
       init genesis.json
    
  2. Connect to node2 console

    $ ./geth/geth --networkid 100 \
       --identity node2 \
       --verbosity 3 \
       --nodiscover \
       --nat none \
       --datadir node2 \
       --rpc --rpcapi "web3, eth, personal" --rpccorsdomain "*" \
       --rpcport 2222 --port 2 \
       --ipcpath node2/geth.ipc \
       console
    
  3. Create new account

    > personal.newAccount("password2")
    "0x5b7a42191f1e47f03bdfa45ec2ecd182dc0803b6"
    

Connect node1 and node2 together

  1. Inside node1 console, get connection information

    > admin.nodeInfo.enode
    "enode://3263a6d420648480a4fa6cd95d8ab6f18ed2caec2cf77212b3d2cb21d3a70203ac2baa8dbf0bf641209063c2ca21d42154622662da1265a0a95b00132813c8eb@127.0.0.1:30303?discport=0"
    
  2. Inside node2 console, add pear to node1 using above connection info

    > admin.addPeer("enode://3263a6d420648480a4fa6cd95d8ab6f18ed2caec2cf77212b3d2cb21d3a70203ac2baa8dbf0bf641209063c2ca21d42154622662da1265a0a95b00132813c8eb@127.0.0.1:30303?discport=0")
    true
    

For node3

  1. Open new terminal, and create node3

    $ ./geth/geth --networkid 100 \
       --identity node3 \
       --verbosity 3 \
       --nodiscover \
       --nat none \
       --datadir node3 \
       init genesis.json
    
  2. Connect to node3 console

    $ ./geth/geth --networkid 100 \
       --identity node3 \
       --verbosity 3 \
       --nodiscover \
       --nat none \
       --datadir node3 \
       --rpc --rpcapi "web3, eth, personal" --rpccorsdomain "*" \
       --rpcport 3333 --port 3 \
       --ipcpath node3/geth.ipc \
       console
    
  3. Create new account

    > personal.newAccount("password3")
    "0x7d87ec7bb1b0bd9437aeb8e644177dee10ea67de"
    
  4. Connect to node1 using the same connection info from node1

    > admin.addPeer("enode://3263a6d420648480a4fa6cd95d8ab6f18ed2caec2cf77212b3d2cb21d3a70203ac2baa8dbf0bf641209063c2ca21d42154622662da1265a0a95b00132813c8eb@127.0.0.1:30303?discport=0")
    true
    

Checking account balance

  1. From any node console, check account balance in Wei

    > eth.getBalance(eth.accounts[0])
    0
    
  2. Check account balance in Ether

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

Mining for money ⛏️

  1. Inside node1 console, start mining

    > miner.start()
    
  2. To stop mining use (THIS WILL NOT STOP MINING IMMEDIATELY PLEASE BE PATIENT)

    > miner.stop()
    null
    
  3. Check account balance (13,493,018 THB)

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

Transfer money between account

AccountAddress
node10x5b7604b47e9a16f62a1e8da369a3f963535b0d8c
node20x5b7a42191f1e47f03bdfa45ec2ecd182dc0803b6
node30x7d87ec7bb1b0bd9437aeb8e644177dee10ea67de
  1. From node1 console

    > personal.unlockAccount(eth.accounts[0])
    Unlock account 0x5b7604b47e9a16f62a1e8da369a3f963535b0d8c
    Passphrase: password1
    true
    
  2. Transfer 10 ether from node1 account to node2 account

    > eth.sendTransaction({from:eth.accounts[0], to:"0x5b7a42191f1e47f03bdfa45ec2ecd182dc0803b6", value:web3.toWei(10,"ether")})
    INFO [01-06|20:18:23.267] Setting new local account                address=0x5B7604B47e9A16F62A1e8da369A3F963535b0D8c
    INFO [01-06|20:18:23.270] Submitted transaction                    fullhash=0x2c6cd53554202cbbd18a4706afbf145aa7b74751827307db49d7fa504f6d76cf recipient=0x5b7a42191f1E47f03BdFa45Ec2ecD182dC0803b6
    "0x2c6cd53554202cbbd18a4706afbf145aa7b74751827307db49d7fa504f6d76cf"
    
  3. Check transaction

    > eth.getTransaction("0x2c6cd53554202cbbd18a4706afbf145aa7b74751827307db49d7fa504f6d76cf")
    {
      blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
      blockNumber: null,
      from: "0x5b7604b47e9a16f62a1e8da369a3f963535b0d8c",
      gas: 90000,
      gasPrice: 1000000000,
      hash: "0x2c6cd53554202cbbd18a4706afbf145aa7b74751827307db49d7fa504f6d76cf",
      input: "0x",
      nonce: 0,
      r: "0x94a65b13cf56a00d904b11f7cbada96c9a014c980493533370c0cb36c0858def",
      s: "0x3443c4f3ea2d91cb21b2c5698d24416c1539af2af6cb0d3dbf71e7c025f56103",
      to: "0x5b7a42191f1e47f03bdfa45ec2ecd182dc0803b6",
      transactionIndex: 0,
      v: "0xeb",
      value: 10000000000000000000
    }
    
  4. See pending transaction

    > eth.pendingTransactions
    [{
        blockHash: null,
        blockNumber: null,
        from: "0x5b7604b47e9a16f62a1e8da369a3f963535b0d8c",
        gas: 90000,
        gasPrice: 1000000000,
        hash: "0x2c6cd53554202cbbd18a4706afbf145aa7b74751827307db49d7fa504f6d76cf",
        input: "0x",
        nonce: 0,
        r: "0x94a65b13cf56a00d904b11f7cbada96c9a014c980493533370c0cb36c0858def",
        s: "0x3443c4f3ea2d91cb21b2c5698d24416c1539af2af6cb0d3dbf71e7c025f56103",
        to: "0x5b7a42191f1e47f03bdfa45ec2ecd182dc0803b6",
        transactionIndex: 0,
        v: "0xeb",
        value: 10000000000000000000
    }]
    
  5. To process transaction, you can continue mining

    > miner.start()
    > miner.stop()
    
  6. Verify that node2 account have 10 ether

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

For node4

  1. Open new terminal, and create node4
  2. Connect to node4 console
  3. Create new account
  4. Connect to node1 using the same connection info from node1