Introduction to Ethereum - Part 1


Bhaskar S 12/18/2017


Overview

In the article Introduction to Blockchain, we introduced the concept of Blockchain at a very high-level.

In this article, we introduced Ethereum, an open-source, decentralized, distributed, public, blockchain-based computing platform.

Ethereum provides support for:

In this article, we will setup a private Ethereum blockchain cluster consisting of a single node to demonstrate the basic capabilities of Ethereum.

Installation

The installation is on a Ubuntu 16.04 LTS (and above) based Linux desktop.

We will assume a hypothetical user called polarsparc with the home directory located at /home/polarsparc.

Assuming that we are logged in as polarsparc and the current working directory is the home directory /home/polarsparc, we will setup a directory structure by executing the following commands:

$ mkdir -p Ethereum/conf

$ mkdir -p Ethereum/data/test

Now, change the current working directory to the directory /home/polarsparc/Ethereum.

To install the most popular Ethereum platform implemented using the Go language, execute the following commands:

$ sudo apt-get install software-properties-common

$ sudo add-apt-repository -y ppa:ethereum/ethereum

$ sudo apt-get update

$ sudo apt-get install ethereum

Once the installation complete, execute the following command to check everything was ok:

$ geth version

The following would be the typical output:

Output.1

Geth
Version: 1.7.3-stable
Git Commit: 4bb3c89d44e372e6a9ab85a8be0c9345265c763a
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.9
Operating System: linux
GOPATH=
GOROOT=/usr/lib/go-1.9

Hands-on with Ethereum

In order to interact with Ethereum, we will need some accounts. We will need atleast two accounts to perform transactions such as transferring ethers from one account to another.

Every account in Ethereum has associated with it some state, which is in the form of a balance. In other words, Ethereum is basically a state machine and transactions between any two accounts change their state (which is the balance in this case).

For our setup, we will start with 4 accounts. To create an account to represent the bank, execute the following command:

$ geth --datadir ./data/test account new

As part of the account creation process, the command will prompt for a secret passphrase. The following would be the typical output:

Output.2

Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase: bank
Repeat passphrase: bank
Address: {ef17ec5df3116dea3b7abaf1ff3045639453cc76}

The following is the repetition of the above command to create the remaining 3 accounts for our setup.

Account #2 (to represent the buyer):

$ geth --datadir ./data/test account new

Account #2 output:

Output.3

Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase: buyer
Repeat passphrase: buyer
Address: {35ddac855e0029676f489dafca9ab405a348317c}

Account #3 (to represent the dealer):

$ geth --datadir ./data/test account new

Account #3 output:

Output.4

Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase: dealer
Repeat passphrase: dealer
Address: {46bf8994c8702919434271d89bcad8abec915612}

Account #4 (to represent the dmv):

$ geth --datadir ./data/test account new

Account #4 output:

Output.5

Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase: dmv
Repeat passphrase: dmv
Address: {518a6377a3863201aef3310da41f3448d959a310}

When an account is created, it has an associated key file that is named using the following format and is located under a directory called keystore:

    UTC--{timestamp}--{address}

Execute the following command to list all the account key files:

$ ls -l data/test/keystore/

The following would be the typical output:

Output.6

total 16
-rw------- 1 polarsparc polarsparc 491 Dec 17 12:45 UTC--2017-12-17T17-45-27.423606627Z--ef17ec5df3116dea3b7abaf1ff3045639453cc76
-rw------- 1 polarsparc polarsparc 491 Dec 17 12:45 UTC--2017-12-17T17-45-38.439797664Z--35ddac855e0029676f489dafca9ab405a348317c
-rw------- 1 polarsparc polarsparc 491 Dec 17 12:45 UTC--2017-12-17T17-45-47.535855157Z--46bf8994c8702919434271d89bcad8abec915612
-rw------- 1 polarsparc polarsparc 491 Dec 17 12:45 UTC--2017-12-17T17-45-56.439705978Z--518a6377a3863201aef3310da41f3448d959a310

As can be seen from the Output.6 above, we have the 4 key files starting with UTC and ending with the account address.

Each account has two parts to it - a private key and a public key. Also, each account is indexed by its associated address, which is formed by taking the last 20 bytes of the public key. The private key is encrypted using the passphrase that was entered during the account creation process.

To list all the accounts currently stored in our setup, execute the following command:

$ geth --datadir ./data/test account list

The following would be the typical output:

Output.7

Account #0: {ef17ec5df3116dea3b7abaf1ff3045639453cc76} keystore:///home/polarsparc/Ethereum/data/test/keystore/UTC--2017-12-17T17-45-27.423606627Z--ef17ec5df3116dea3b7abaf1ff3045639453cc76
Account #1: {35ddac855e0029676f489dafca9ab405a348317c} keystore:///home/polarsparc/Ethereum/data/test/keystore/UTC--2017-12-17T17-45-38.439797664Z--35ddac855e0029676f489dafca9ab405a348317c
Account #2: {46bf8994c8702919434271d89bcad8abec915612} keystore:///home/polarsparc/Ethereum/data/test/keystore/UTC--2017-12-17T17-45-47.535855157Z--46bf8994c8702919434271d89bcad8abec915612
Account #3: {518a6377a3863201aef3310da41f3448d959a310} keystore:///home/polarsparc/Ethereum/data/test/keystore/UTC--2017-12-17T17-45-56.439705978Z--518a6377a3863201aef3310da41f3448d959a310

In order to setup a private Ethereum blockchain network (consisting of a single node), we need to initialize and create the Genesis block. The Genesis block is the first block of the blockchain that has no previous block.

We will create an initialization file called genesis.json that will be located in the directory conf, with the following contents:

genesis.json
{
    "config": {
        "chainId": 21,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
    "nonce": "0x0000000000000000",
    "timestamp": "0x0",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "extraData": "0x00",
    "gasLimit": "0x80000000",
    "difficulty": "0x400",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "coinbase": "0xef17ec5df3116dea3b7abaf1ff3045639453cc76",
    "alloc": {
        "ef17ec5df3116dea3b7abaf1ff3045639453cc76": {
            "balance": "20000000000000000000"
        },
        "35ddac855e0029676f489dafca9ab405a348317c": {
            "balance": "10000000000000000000"
        },
        "46bf8994c8702919434271d89bcad8abec915612": {
            "balance": "5000000000000000000"
        },
        "518a6377a3863201aef3310da41f3448d959a310": {
            "balance": "3000000000000000000"
        }        
    }
}

Let us explain and understand some of the important parameters used in the JSON file shown above.

The parameter config describes this private blockchain in terms of the network identifier, the consensus engine used, and the block number of the hard forks. The parameter chainId is the blockchain network identifier. A value of 1, 2, or 3 refer to the real-world public Ethereum networks currently in use. Since we desire a private network, we decide to choose an arbitrary value of 21 for our network. The parameter homesteadBlock with a value of 0 (zero) indicates we want to use the homestead consensus engine, which is the current version of Ethereum.

The parameter nonce is the 64-bit hash corresponding to amount of mining computation effort (Proof-of-Work) performed on this block.

The parameter timestamp indicates the time this block was created. It's value is the amount of time in seconds since epoch.

The parameter parentHash indicates the hash value of the parent block. Since this is the first block, we set it to 0 (zero).

The parameter gasLimit indicates the limit of the gas fees that will be charged for processing a block. Before a transaction is processed, a small processing fee is collected from the initiator by the miner(s). That fees is referred to as gas (also referred to as crypto-fuel) in Ethereum.

The parameter difficulty indicates level of effort for performing the proof-of-work processing. Higher value indicates more effort on the part of the miner nodes. For our private network, we will keep this value low.

The parameter mixhash is the 256-bit hash, that combined with nonce, indicates the amount of computation performed to solve a mathematical puzzle (proof-of-work).

The parameter coinbase (also referred to as etherbase) indicates the address of the account that will receive the rewards for successful mining of a block. Notice that we have selected the first address of the 4 accounts we created for this parameter.

The parameter alloc pre-allocates ethers to the accounts in our private network.

To initialize our private Ethereum network with the Genesis block, execute the following command:

$ geth --datadir ./data/test init ./conf/genesis.json

The following would be the typical output:

Output.8

INFO [12-17|13:13:50] Allocated cache and file handles         database=/home/polarsparc/Ethereum/data/test/geth/chaindata cache=16 handles=16
INFO [12-17|13:13:50] Writing custom genesis block 
INFO [12-17|13:13:50] Successfully wrote genesis state         database=chaindata                                                   hash=1bb226…2fa09e
INFO [12-17|13:13:50] Allocated cache and file handles         database=/home/polarsparc/Ethereum/data/test/geth/lightchaindata cache=16 handles=16
INFO [12-17|13:13:50] Writing custom genesis block 
INFO [12-17|13:13:50] Successfully wrote genesis state         database=lightchaindata                                                   hash=1bb226…2fa09e

To start a single node in our private Ethereum network, execute the following command:

$ geth --identity "test" --datadir ./data/test --ethash.dagdir ./data/test --networkid "21" --maxpeers 0 --nodiscover --ipcdisable --rpc --rpcaddr 127.0.0.1 --rpcport 8081 --rpccorsdomain "*" --port 30001 --verbosity 2 console

The following would be the typical output:

Output.9

WARN [12-18|11:03:24] Upgrading database to use lookup entries 
Welcome to the Geth JavaScript console!

instance: Geth/test/v1.7.3-stable-4bb3c89d/linux-amd64/go1.9
coinbase: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76
at block: 0 (Wed, 31 Dec 1969 19:00:00 EST)
 datadir: /home/polarsparc/Ethereum/data/test
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

>

Let us explain some of the options used in the command above.

The option --identity assigns an identity for our node in the private network.

The option --datadir specifies the location of the directory where the chain data for our private network will be stored.

The option --ethash.dagdir specifies the location of the directory where the mined proof-of-work data is stored.

The option --networkid specifies the network identifier and this value needs to match the value we specified in the genesis.json file.

The option --maxpeers indicates how many nodes (peers) will be connecting to this node in our private network. Since we are starting with a single node, we set it to 0 (zero) indicating no peers.

The option --nodiscover indicates our private network is not discoverable by any other nodes (peers) in the network.

The option --ipcdisable will disable the ability to connect to this node via ipc.

The option --rpc will enable access to this node via rpc.

The option --rpcaddr specifies the interface to use for the rpc connection. For our setup, we choose the localhost (127.0.0.1) interface.

The option --rpcport specifies the listening port for the rpc connection.

The option --rpccorsdomain specifies the CORS domain from which rpc connections will be accepted. In our case, we have accept all domains by specifying asterisk (*).

The option --port specifies the network port for connecting with other nodes (peers).

The console option enables the built-in Javascript runtime environment to be activated and we are presented with an REPL shell for interacting with this node.

The node exposes various commands (often referred to as APIs) that can be executed via the Javascript shell and are grouped under different namespaces as listed below:

To get information on the networking details of this node in our private network, execute the following command in the Javascript shell prompt:

> admin.nodeInfo

The following would be the typical output:

Output.10

{
  enode: "enode://ae00af23967b3a32b00b5666b63859d0db69f1fb450cb15346df54e1d53f9298adc054399dd42e521d33b7759b0ae9fa19f33f7b06ba0411cb1465ccafdc9b6c@[::]:30001?discport=0",
  id: "ae00af23967b3a32b00b5666b63859d0db69f1fb450cb15346df54e1d53f9298adc054399dd42e521d33b7759b0ae9fa19f33f7b06ba0411cb1465ccafdc9b6c",
  ip: "::",
  listenAddr: "[::]:30001",
  name: "Geth/test/v1.7.3-stable-4bb3c89d/linux-amd64/go1.9",
  ports: {
    discovery: 0,
    listener: 30001
  },
  protocols: {
    eth: {
      difficulty: 1024,
      genesis: "0x1bb226f9e281ee44981ef5668004142012e0e56ebc6b70b8bf759cece82fa09e",
      head: "0x1bb226f9e281ee44981ef5668004142012e0e56ebc6b70b8bf759cece82fa09e",
      network: 21
    }
  }
}

To get the list of peers connected to this node in our private network, execute the following command in the Javascript shell prompt:

> admin.peers

The following would be the typical output:

Output.11

[]

The Output.11 above indicates that there are no other nodes (peers) connected to this node in our private network.

We have not performed any transactions with any of our 4 accounts and only have the initial genesis block in the chain. The genesis block is the first block with the block number '0x0' (in hex).

To retrieve the state of the accounts corresponding to block '0x0', execute the following command in the Javascript shell prompt:

> debug.dumpBlock('0x0')

The following would be the typical output:

Output.12

{
  accounts: {
    35ddac855e0029676f489dafca9ab405a348317c: {
      balance: "10000000000000000000",
      code: "",
      codeHash: "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      nonce: 0,
      root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
      storage: {}
    },
    46bf8994c8702919434271d89bcad8abec915612: {
      balance: "2500000000000000000",
      code: "",
      codeHash: "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      nonce: 0,
      root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
      storage: {}
    },
    518a6377a3863201aef3310da41f3448d959a310: {
      balance: "1500000000000000000",
      code: "",
      codeHash: "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      nonce: 0,
      root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
      storage: {}
    },
    ef17ec5df3116dea3b7abaf1ff3045639453cc76: {
      balance: "20000000000000000000",
      code: "",
      codeHash: "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
      nonce: 0,
      root: "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
      storage: {}
    }
  },
  root: "bd6d8e14d71964cbd6d1a254f4c7c6c4fdca38f7a4dec177faa9ba9b6690fd1b"
}

To list all the account addresses in this node of our private network, execute the following command in the Javascript shell prompt:

> personal.listAccounts

The following would be the typical output:

Output.13

["0xef17ec5df3116dea3b7abaf1ff3045639453cc76", "0x35ddac855e0029676f489dafca9ab405a348317c", "0x46bf8994c8702919434271d89bcad8abec915612", "0x518a6377a3863201aef3310da41f3448d959a310"]

To retrieve the details of a block by block number, execute the following command in the Javascript shell prompt:

> eth.getBlock(0)

The following would be the typical output:

Output.14

{
  difficulty: 1024,
  extraData: "0x00",
  gasLimit: 2147483648,
  gasUsed: 0,
  hash: "0x1bb226f9e281ee44981ef5668004142012e0e56ebc6b70b8bf759cece82fa09e",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xef17ec5df3116dea3b7abaf1ff3045639453cc76",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000000",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 507,
  stateRoot: "0xbd6d8e14d71964cbd6d1a254f4c7c6c4fdca38f7a4dec177faa9ba9b6690fd1b",
  timestamp: 0,
  totalDifficulty: 1024,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

Now we are at a point ready to send a transaction, transfering some cryptocurrency from one account to another.

As we indicated at the beginning, the cryptocurrency used in Ethereum is known as ether. Just like with any currency, there are various demoninations of the cryptocurrency in Ethereum, which is as follows:

For convenience and ease of use, let us assign the addresses of the 2nd and 3rd accounts to variables named buyer and dealer using the Javascript shell as shown below:

> buyer = "0x35ddac855e0029676f489dafca9ab405a348317c"

> dealer = "0x46bf8994c8702919434271d89bcad8abec915612"

When a transaction is sent for transferring some cryptocurrencies from one account address to another, they need to be sent in the denominations of wei. So if we want to transfer one ether from the buyer to the dealer, we will need to convert the unit from ethers to wei using the utility function web3.toWei().

To send a transaction to transfer 1 ether from the buyer to the dealer, execute the following command in the Javascript shell prompt:

> eth.sendTransaction({from: buyer, to: dealer, value: web3.toWei(1, "ether")})

The following would be the typical output:

Output.15

Error: authentication needed: password or unlock
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at <anonymous>:1:1

OOPS !!! What happened here ???

By default, all accounts are in a locked state and need to be unlocked before performing transactions. Since the transaction transfers from the buyer to the dealer, we need to unlock the buyer account.

To unlock the buyer account, execute the following command in the Javascript shell prompt:

> personal.unlockAccount(buyer)

This will prompt us for the password for the buyer account. The following would be the typical output:

Output.16

Unlock account 0x35ddac855e0029676f489dafca9ab405a348317c
Passphrase: buyer
true

To re-send the transaction, transfering 1 ether from the buyer to the dealer, execute the following command in the Javascript shell prompt:

> eth.sendTransaction({from: buyer, to: dealer, value: web3.toWei(1, "ether")})

The following would be the typical output:

Output.17

"0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db"

The big hex value in Output.17 above is the transaction number for the just sent transaction.

Remember, we have not started any miner on this network yet and hence the just sent transaction will be in a pending state.

To display all the pending transactions on this network, execute the following command in the Javascript shell prompt:

> eth.pendingTransactions

The following would be the typical output:

Output.18

[{
    blockHash: null,
    blockNumber: null,
    from: "0x35ddac855e0029676f489dafca9ab405a348317c",
    gas: 90000,
    gasPrice: 18000000000,
    hash: "0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db",
    input: "0x",
    nonce: 0,
    r: "0xc512c5265a533abcfcf04f7ce0c2478495bf44ddc95125bd1923f3fa459340ad",
    s: "0x3e72713f8be93a0b8f28c77d2abccaafd74f6e48ffca6175748dc9a5d7595a47",
    to: "0x46bf8994c8702919434271d89bcad8abec915612",
    transactionIndex: 0,
    v: "0x4d",
    value: 1000000000000000000
}]

To display information about the pending transaction(s) in the transaction pool, execute the following command in the Javascript shell prompt:

> txpool.inspect

The following would be the typical output:

Output.19

{
  pending: {
    0x35DdaC855e0029676f489daFca9AB405A348317C: {
      0: "0x46bF8994C8702919434271D89bcad8ABeC915612: 1000000000000000000 wei + 90000 gas × 18000000000 wei"
    }
  },
  queued: {}
}

For convenience, one can create custom Javascript utility functions to extract and display information. The following is a custom Javascript utility function to display account balances (in ethers):

showBalances
function showBalances() {
  var i = 0;
  eth.accounts.forEach(function(e) {
     console.log("---> eth.accounts["+i+"]: " + e + " \tbalance: " + web3.fromWei(eth.getBalance(e), "ether") + " ether");
     i++;
  })
};

Paste the above Javascript code in the shell prompt and the following would be the typical output:

Output.20

undefined

To display account balances using the Javascript utility function showBalances, execute the following command in the Javascript shell prompt:

> showBalances()

The following would be the typical output:

Output.21

---> eth.accounts[0]: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76 	balance: 20 ether
---> eth.accounts[1]: 0x35ddac855e0029676f489dafca9ab405a348317c 	balance: 10 ether
---> eth.accounts[2]: 0x46bf8994c8702919434271d89bcad8abec915612 	balance: 5 ether
---> eth.accounts[3]: 0x518a6377a3863201aef3310da41f3448d959a310 	balance: 3 ether
undefined

Now we are ready to start a miner for this network.

To start the miner with one mining thread, execute the following command in the Javascript shell prompt:

> miner.start(1)

The following would be the typical output:

Output.22

null

Now, let us check the status of the transaction pool by executing the following command in the Javascript shell prompt:

> txpool.inspect

The following would be the typical output:

Output.23

{
  pending: {},
  queued: {}
}

To stop the miner, execute the following command in the Javascript shell prompt:

> miner.stop()

The following would be the typical output:

Output.24

true

To retrieve the transaction details of the just sent transaction 0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db, execute the following command in the Javascript shell prompt:

> eth.getTransaction("0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db")

The following would be the typical output:

Output.25

{
  blockHash: "0x99cbf1020c5b46e0a6594f14a9808b476a2371bb66a7d18affc7156e4160d477",
  blockNumber: 1,
  from: "0x35ddac855e0029676f489dafca9ab405a348317c",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db",
  input: "0x",
  nonce: 0,
  r: "0xc512c5265a533abcfcf04f7ce0c2478495bf44ddc95125bd1923f3fa459340ad",
  s: "0x3e72713f8be93a0b8f28c77d2abccaafd74f6e48ffca6175748dc9a5d7595a47",
  to: "0x46bf8994c8702919434271d89bcad8abec915612",
  transactionIndex: 0,
  v: "0x4d",
  value: 1000000000000000000
}

To retrieve the details of the latest block, execute the following command in the Javascript shell prompt:

> eth.getBlock('latest')

The following would be the typical output:

Output.26

{
  difficulty: 136322,
  extraData: "0xd583010703846765746885676f312e39856c696e7578",
  gasLimit: 1980209296,
  gasUsed: 0,
  hash: "0xb64ad7568b60fe0d98385502473e764229545bd0a1ae80957605d6f25c62a804",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xef17ec5df3116dea3b7abaf1ff3045639453cc76",
  mixHash: "0x038871d3e962edbb4df995d7dd645d3dd4a18e2a1c58d82c817ca35117f1edbe",
  nonce: "0x46843562ace0073d",
  number: 83,
  parentHash: "0x4f660077db95f0a8105f39ffa6b3b8955d2dcb86daea807b38b3b9a2482560e9",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 534,
  stateRoot: "0xe44b4636b8d46c3b8f3894473528d779340cc828089be8e46d66119f9bea50bf",
  timestamp: 1513629672,
  totalDifficulty: 11093922,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

Now, we check the account balances using the Javascript utility function showBalances by executing the following command in the Javascript shell prompt:

> showBalances()

The following would be the typical output:

Output.27

---> eth.accounts[0]: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76 	balance: 435.000378 ether
---> eth.accounts[1]: 0x35ddac855e0029676f489dafca9ab405a348317c 	balance: 8.999622 ether
---> eth.accounts[2]: 0x46bf8994c8702919434271d89bcad8abec915612 	balance: 6 ether
---> eth.accounts[3]: 0x518a6377a3863201aef3310da41f3448d959a310 	balance: 3 ether
undefined

As is evident from the Output.27 above, the account balance for the buyer (2nd account) has decreased, while the account balance for the dealer (3rd account) has increased.

Hmm !!! Something is odd about the balances for the first two accounts above. Let us try and break it down as follows:

From the Output.25 above, we see that the transaction was processed in block number 1. To find the processing fees (gas) charged for the transaction, we need two pieces of information - the gasUsed (amount of processing done - similar to hours of work done) and the gasPrice (cost for unit of processing - similar to wages per hour). The processing fees (gas) is then computed as (gasUsed * gasPrice).

To retrive the value for gasUsed for the transaction, execute the following command in the Javascript shell prompt:

> eth.getBlock(1)

The following would be the typical output:

Output.28

{
  difficulty: 131072,
  extraData: "0xd583010703846765746885676f312e39856c696e7578",
  gasLimit: 2145386497,
  gasUsed: 21000,
  hash: "0x99cbf1020c5b46e0a6594f14a9808b476a2371bb66a7d18affc7156e4160d477",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0xef17ec5df3116dea3b7abaf1ff3045639453cc76",
  mixHash: "0xb7c4819bd25d949099f9e91820a5bd5fa86c474f989542cce2a42fd83a9ff98a",
  nonce: "0x413d27030b1878ee",
  number: 1,
  parentHash: "0x1bb226f9e281ee44981ef5668004142012e0e56ebc6b70b8bf759cece82fa09e",
  receiptsRoot: "0x19a2e3d54c3ae29d6ec9783441fe274609835f0eafeef24f23045c6522ec2e87",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 648,
  stateRoot: "0x1a2345d1d056090f46967c5d9db6ada58280715426c1aa592420e53fbc9981bc",
  timestamp: 1513629452,
  totalDifficulty: 132096,
  transactions: ["0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db"],
  transactionsRoot: "0x87676e8a360ffc4fc58149e9f139e7721d46a04e916b8561834aca7c2aaad8b3",
  uncles: []
}

Next, to retrive the value for gasPrice for the transaction, execute the following command in the Javascript shell prompt:

> eth.getTransactionFromBlock(1)

The following would be the typical output:

Output.29

{
  blockHash: "0x99cbf1020c5b46e0a6594f14a9808b476a2371bb66a7d18affc7156e4160d477",
  blockNumber: 1,
  from: "0x35ddac855e0029676f489dafca9ab405a348317c",
  gas: 90000,
  gasPrice: 18000000000,
  hash: "0x22f09fd982cd6404dfc3c388c3af86fa12eae56c5198d80f00af9a0c981907db",
  input: "0x",
  nonce: 0,
  r: "0xc512c5265a533abcfcf04f7ce0c2478495bf44ddc95125bd1923f3fa459340ad",
  s: "0x3e72713f8be93a0b8f28c77d2abccaafd74f6e48ffca6175748dc9a5d7595a47",
  to: "0x46bf8994c8702919434271d89bcad8abec915612",
  transactionIndex: 0,
  v: "0x4d",
  value: 1000000000000000000
}

From the Output.28 above, we see that the gasUsed is 21000 and from the Output.29 above, the gasPrice is 18000000000. The processing fees (gas) is then (21000 * 18000000000) which equals 378000000000000 wei's.

Execute the following expression in the Javascript shell prompt:

> 9 - web3.fromWei(378000000000000)

The following would be the typical output:

Output.30

8.999622

This is the remaining balance in the account of the buyer.

To exit the Javascript shell as well as the node, execute the following command in the Javascript shell prompt:

> exit

References

Official Ethereum Documentation

Command-line options for the geth client

Ethereum Management APIs

web3.js Ethereum JavaScript API