Blockchain and Ethereum for JavaScript and React developers

Blockchain is a technology for building decentralized apps. We are used to storing data in centralised databases. For the sake of fault tolerance, we may have clusters of databases distributed geographically. But that does not make traditional databases decentralized. All of the databases are controlled by a single company. Blockchain makes the data politically decentralized. There is no single authority that controls all of data. Instead, a group of distributed servers (also called nodes) have a copy of the actual data. Even if one node goes down, no problem. The rest of the nodes can continue to process the transactions. How is it possible?

How does Blockchain work?

I am going to present a simplified version of how the Blockchain works. My explanation is very similar to how a physicist explains Quantum theory to you.

Any transaction on the Blockchain is broadcast to the entire network. One of the node prepares a block, transactions which happened around the same time. The block is sent to the whole network along with a puzzle. The puzzle is figuring out the order in which the transactions appear in the block. It is difficult to solve the puzzle by a single computer and requires trial and error or brute force solution. One of the computers in the network will figure out the puzzle in a short span of time. And that block becomes confirmed. There may be occasions when two computers in the network solve the puzzle at the same time (with a different order of blocks). In that case, both blocks are transmitted to the network.

Each confirmed block in the network is chained to the previous block in the network. There may be times when these chains may diverge in individual nodes. Again by consensus, over time, the longer chain wins. And hence a single blockchain appears as source of truth.

Due to these complex computations, any transaction on the Blockchain will take some amount of time to be confirmed. If the transaction is confirmed by 6 or 12 subsequent blocks, then it is permanently part of the blockchain. Though Blockchain is a technology, there are different platforms which implement the technology in different ways. Bitcoin and Ethereum are two popular implementations of the Blockchain. In the Bitcoin network, a transaction takes 15 minutes to confirm. Whereas the Ethereum protocol has a simple puzzle and so a transaction takes only a few seconds to confirm.

More on Ethereum and Geth

Ethereum protocol is quite popular these days. It was announced to the world in 2013. It has a good developer ecosystem. Ethereum protocol is implemented by many programs. One of the popular program that implements Ethereum is Geth. It is implemented using Go language. If you run geth on your system, it will download the entire public blockchain. But for practice, we like to create our own private blockchain, running just only on our system. Download Geth from the official source. Install in any folder on your Mac. And add the folder to the $PATH variable.

To create a private blockchain, we need to initialise Geth with a genesis block (or the first block).

{
    "coinbase"   : "0x0000000000000000000000000000000000000001",
    "difficulty" : "0x20000",
    "extraData"  : "",
    "gasLimit"   : "0x8000000",
    "nonce"      : "0x0000000000000042",
    "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
    "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
    "timestamp"  : "0x00",
    "alloc": {},
    "config": {
          "chainId": 15,
          "homesteadBlock": 0,
          "eip155Block": 0,
          "eip158Block": 0
      }
  }

Use the above file contents in a genesis.json file. Also create another folder called chaindata where Geth will store all the blocks. And do a init.

geth --datadir=./chaindata/ init ./genesis.json

After Geth initialises, run Geth to start your private blockchain.

geth --datadir=./chaindata/

Right now, geth is running in only your computer. But with ethereum public chain, geth will run on a lot of computers. You are free to start and stop geth any time. If geth is started, it will download the latest chain data from other nodes in the network. In that way, blockchain is truly decentralized with no single node controlling the network.

Blockchain terminology

I like to explain the terminology involved in Blockchain by showing you transactions and blocks in etherchain. Consider a single transaction.

Transaction in EtherChain

The properties of transactions has a lot of detail. From and To are two accounts in the public chain. These accounts may represent two real people, Joe and Mike. In this transaction, Joe is transferring 7.53 Ether or $ 3501.45 to Mike. When you create an account in any Blockchain, you create a private key and public key pair. I won’t explain how cryptography works. But at high level, you share your public key with others. And keep your private key with you. A sender can encrypt data with your public key. And you can decrypt the data with your private key. Private key is kept secure. And if you lose your private key, you lose access to your Blockchain account. It is that important. The From and To properties in the transaction details represent public key hash of two accounts (Joe and Mike) in the Blockchain.

The transaction also has a hash. And it is part of a block (4642361). There is two confirmations. This means that there are two more confirmed blocks in the blockchain following the block. Then down below, the Amount property, we have a few more properties related to transaction price. Every transaction requires computations or processing power. And so, it has a charge. When you are sending a transaction, we can also send two additional parameters, gas price and gas limit. Gas limit indicates the maximum computation. And gas price indicates the price for each computation. The product of gas price and total gas used is the transaction price.

You might notice that gas price (or the price for each computation) is denoted by 10 GWei. Wei is an ether denomination.

Ether denominations

One ether is 10^18 Wei and 10^9 GWei. Transaction amount is 10 GWei multiplied by 21,000 which is 210,000 GWei or 0.00021 Ether.

Now, that you understood the transaction properties, let us look into block properties. Consider a block.

Block in Etherchain

I won’t discuss each property of the block. But I want to point out three properties: difficulty, miner and reward. When preparing a block, there is a difficulty associated with the block. The difficulty indicates how difficult it is to mine the block. The miner is the node (Geth node) which solved the puzzle for the block. And it gets the reward which is the sum of all transaction charges in the block.

Mining in action

When we start Geth, it opens an IPC endpoint. Retrieve the IPC endpoint using the last line of the log.

INFO [11-29|13:12:06] IPC endpoint opened: /Users/vijayst/documents/react/vijay/blockchain/assignment_2/chaindata/geth.ipc

Start a Geth Javascript console using the following command.

geth attach /Users/vijayst/documents/react/vijay/blockchain/assignment_2/chaindata/geth.ipc

Within the JavaScript console, we can execute JavaScript methods to start and stop mining.

miner.start(1);

The above command starts the miner in one thread. Now, our node participates in a mining process. Mining is what confirms transactions. In addition, mining generates ether out of thin air and adds it to primary account of the node (also known as coinbase).

We create the primary account using a wallet program called Mist. Mist is a Meteor app based on electron. Download and install it from the official source. Add the installation folder to the $PATH variable. Usually it is /Applications/Mist.app/Contents/MacOS. Start Mist using the following command. (Supply the IPC endpoint of Geth)

mist --rpc /Users/vijayst/documents/react/vijay/blockchain/assignment_2/chaindata/geth.ipc

Create an account in Mist. This will create the private / public key pair. And now when you start miner, your account will generate ether in your account.

Mist with primary account

My account has 1,245 Ether. It is the reward for running Geth in my system and using it for mining. Not bad, right? (This Ether is useful only for your private network!)

Stop the miner by issuing miner.stop() in the JavaScript console.

React app for interacting with Blockchain

We are all set to write our React app which will interact with the Blockchain. We will continue to use our private network. Create a new react app using create-react-app.

create-react-app blockchaindemo
cd blockchaindemo
yarn start

The local server starts at port 3000. If we navigate to http://localhost:3000, we should see our React app.

Next, we want to start the Ethereum node on a private blockchain. I mentioned Ethereum node because we are not going to use Geth for our development. Geth has a mining component which is processor intensive. Thankfully, developers at ethereum have built a simple ethereum node for testing called testrpc.

yarn global add ethereumjs-testrpc

Start testrpc using testrpc --secure. By default, testrpc creates 10 accounts in a sandboxed environment. It runs as a http server in port 8545.

Now that we have set our node, we are all set to interact with it from our React app. Web3 is a package that allows us to interact with the blockchain.

yarn add web3

At the time of writing the blog post, the above command throws an error. The issue is documented in web3 repo. As a workaround, use the following command.

yarn add web3@^0.19.0

Let us start working on the App component. Import web3.

import Web3 from "web3";

Web3 behaves more like an API. We interact with API in componentDidMount lifecycle method. Let us connect to testrpc first.

componentDidMount() {
    const provider = new Web3.providers.HttpProvider("http://localhost:8545");
    const web3 = new Web3(provider);
}

Next, let us iterate through each account and find the balances.

componentDidMount() {
    const provider = new Web3.providers.HttpProvider("http://localhost:8545");
    const web3 = new Web3(provider);
    const accounts = web3.eth.accounts.map(account => {
        let balance = web3.eth.getBalance(account);
        balance = web3.fromWei(balance, 'ether').toNumber();
        return { account, balance };
    });
    this.setState({ accounts });
}

Accounts collection has an address. If we use the getBalance function, we get the balance in Wei. fromWei function converts it to ether. The balance is still in an object format. The toNumber function converts it into a decimal.

Finally, we display the account balances in our component.

render() {
    return (
        <div className="App">
            <header className="App-header">
                <h1 className="App-title">Blockchain Demo</h1>
            </header>
            <table border="1" cellpadding="8" cellspacing="0" style={{ border: '1px solid black', margin: 30 }}>
                <thead>
                    <tr>
                        <th>Account</th>
                        <th>Balance</th>
                    </tr>
                </thead>
                <tbody>
                    {this.state.accounts.map(accountItem => (
                        <tr key={accountItem.account}>
                            <td>{accountItem.account}</td>
                            <td>{accountItem.balance}</td>
                        </tr>
                    ))}
                </tbody>
            </table>
        </div>
    );
}

As you can see from the below screenshot, each account has 100 ether.

Account balances in testrpc

Let us take our example a bit further. We will add a button. On clicking the button, let us transfer 10 ether from the first account to the second.

handleTransfer() {
    const from = this.web3.eth.accounts[0];
    const to = this.web3.eth.accounts[1];
    const value = this.web3.toWei(10, "ether");
    this.web3.eth.sendTransaction({ from, to, value });
}

sendTransaction function does the transfer. I have deliberately simplified it.

Usually, an account is in locked state. We have to unlock it using web3.personal.unlockAccount function. Running testrpc with –secure flag locks all the accounts. At the time of writing the blog, unlockAccount is not working due to a bug.

Confirming a transaction in blockchain takes some time. Usually a few seconds. With testrpc, there is no mining. But we can simulate mining using –blocktime flag. After we confirm our transaction, we usually want to refresh the UI. But, how do we know the transaction is confirmed. We poll the blockchain periodically for a transaction object. When we get it, we refresh the UI.

handleTransfer() {
    const from = this.web3.eth.accounts[0];
    const to = this.web3.eth.accounts[1];
    const value = this.web3.toWei(10, "ether");
    const txnHash = this.web3.eth.sendTransaction({ from, to, value });
    const handle = setInterval(() => {
        const txn = this.web3.eth.getTransaction(txnHash);
        if (txn) {
            clearInterval(handle);
            this.refreshUI();
        }
    }, 100);
}

The entire source code for App.js is available in a gist.

Contracts and much more

We have scratched the surface of Blockchain development. There is much more to Ethereum. We have something called Contract. A contract can be deployed on the blockchain. It will have its own address just like an account. A contract can also hold ether. And authorised accounts can use the contract to initiate transactions on the Blockchain.

Solidity is a programming language for creating new contracts on the blockchain. There are some tools to write Solidity code. Remix and Ethereum Studio are two popular tools for creating and deploying contracts.  For the JavaScript developer, truffle is a NPM package to manage contracts. truffle also lets us write test cases for testing contracts.

As a React developer, we may have to understand how contracts are created and deployed. And how to call functions on the contract to initiate transactions on the Blockchain. I won’t be covering contracts now. But, I am looking for a case study for using Blockchain in which I will explore contracts much more.

Related Posts

Leave a Reply

Your email address will not be published.