This is a basic way to setup Ethereum light client with private network. I will talk about 3 things.

What is Ethereum light client? How to setup server How to setup client

What is light client?

Light client is an ethereum client which keeps only keys. You can check accurate definition here. Traditionally in blockchain world, everyone keep same databases. That’s why we can trust entire system. I mean we can trust at least our own data. But light client don’t keep data.

Why do light client matter?

But problem is keeping entire database is tough. When I created an ethereum wallet first time I needed to download entire ethereum database. That syncing process took almost whole day and the file size was huge. A web site said the storage size was more than 75GB in 2016 and was growing 1GB per month. This is insane and only blockchain enthusiast can keep it.

You can not run ethereum full node on mobile devices. Or normal users don’t want to keep full node on their devices anyway.

That’s why we need light clients. With light clients, user don’t need to keep ethereum node. They can just enjoy decentralized services. This is pretty cool.

How do we setup light client?

I experimented light client with my private network. Because we can develop dapps for mobile, this has a huge potential.

1. Prepare private network

You need at least 1 ethereum node. Since light client don’t run ethereum node, we need to run nodes for clients to connect.

I installed geth which is Go implementation of the Ethereum protocol. I think geth is most popular. You can check how to install geth here.

Once you install geth, you can setup private network.

First, you have to prepare genesis block.

You can easily create new genesis block with a command line tool called puppeth which is installed with geth. Here’s my example. I choose proof of authorization as my consensus algorithm because I don’t want heavy computation for my experiment.

{

"config": {

"chainId": <Your ChainID>,

"homesteadBlock": 1,

"eip150Block": 2,

"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",

"eip155Block": 3,

"eip158Block": 3,

"byzantiumBlock": 4,

"clique": {

"period": 10,

"epoch": 30000

}

},

"nonce": "0x0",

"timestamp": "0x5a00bccf",

"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000<Your address 1>0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

"gasLimit": "0x47b760",

"difficulty": "0x1",

"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",

"coinbase": "0x0000000000000000000000000000000000000000",

"alloc": {

"<Your address 1>": {

"balance": "0x200000000000000000000000000000000000000000000000000000000000000"

},

"<Your address 2>": {

"balance": "0x100000000000000000000000000000000000000000000000000000000000000"

}

},

"number": "0x0",

"gasUsed": "0x0",

"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"

}

I saved this json file as genesis_poa.json.

You can initialize your network with command like this.

geth --datadir <Your data directory> init genesis_poa.json

Now you can start your private network with command like this.

geth --datadir /mnt/privatenet/data_poa



--nodiscover --networkid <Your networkID>



--rpc --rpcapi db,eth,net,web3,personal,miner,admin



--cache=128



--rpcport 8545 --rpcaddr 127.0.0.1 --rpccorsdomain "*"

That’s it. Your geth node is ready.

2. Use Haproxy to make rpc service public

Now your node (rpc service) is running at 127.0.0.1.

But since light clients are not on your server, we need to make this rpc service public.

To do that, I use Haproxy. Haproxy is stable and easy to use load balancer.

I use Haproxy just as a proxy this time.

And we can use https which I think is very important for security.

Here’s an example of /etc/haproxy/haproxy.cfg



log /dev/log local0

log /dev/log local1 notice

chroot /var/lib/haproxy

stats socket /run/haproxy/admin.sock mode 660 level admin

stats timeout 30s

user haproxy

group haproxy

daemon



# Default SSL material locations

ca-base /etc/ssl/certs

crt-base /etc/ssl/private



# Default ciphers to use on SSL-enabled listening sockets.

# For more information, see ciphers(1SSL). This list is from:

# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/

ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

ssl-default-bind-options no-sslv3

tune.ssl.default-dh-param 2048 globallog /dev/log local0log /dev/log local1 noticechroot /var/lib/haproxystats socket /run/haproxy/admin.sock mode 660 level adminstats timeout 30suser haproxygroup haproxydaemon# Default SSL material locationsca-base /etc/ssl/certscrt-base /etc/ssl/private# Default ciphers to use on SSL-enabled listening sockets.# For more information, see ciphers(1SSL). This list is from:ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSSssl-default-bind-options no-sslv3tune.ssl.default-dh-param 2048 defaults

log global

mode http

option httplog

option dontlognull

timeout connect 5000

timeout client 50000

timeout server 50000

errorfile 400 /etc/haproxy/errors/400.http

errorfile 403 /etc/haproxy/errors/403.http

errorfile 408 /etc/haproxy/errors/408.http

errorfile 500 /etc/haproxy/errors/500.http

errorfile 502 /etc/haproxy/errors/502.http

errorfile 503 /etc/haproxy/errors/503.http

errorfile 504 /etc/haproxy/errors/504.http frontend www

bind 0.0.0.0:80

mode http

timeout client 5s

redirect scheme https code 301 if !{ ssl_fc } frontend wwws

mode http

bind :443 ssl crt /etc/haproxy/certs/<You Cert>.pem

timeout client 1h



tcp-request inspect-delay 500ms

tcp-request content accept if HTTP



default_backend privatenetwork_backend

acl is_privatenetwork hdr_end(host) -i <Your domain>

use_backend privatenetwork_backend if is_privatenetwork backend privatenetwork_backend

mode http

option forwardfor

option http-server-close

option forceclose

no option httpclose

balance roundrobin

option forwardfor

timeout server 86400000

timeout connect 4000

server API.js1 127.0.0.1:8545 weight 1 maxconn 10000 check

Now your light client can access to your node (rpc server) through https .

Let’s prepare client.

React web app with ethereum light client

First, we create React app and prepare modules

I used create-react-app to create React starter project.

create-react-app is a cool tool to create React app quickly.

create-react-app sample_lightclient_app

Install eth-lightwallet, hooked-web3-provider and web3 modules.

eth-lightwallet does the most of magic. eth-lightwallet is developed by ConsenSys and you can use the library to develop light client easily.

we also need hooked-web3-provider which work with eth-lightwallet.

And let’s install web3 too. web3 is official Javascript library for ethereum.

npm install --save eth-lightwallet

npm install --save hooked-web3-provider

npm install --save web3 # Or you may do just npm install

A bit of hack

In your Javascript file,

// step 1: import web3, eth-lightwallet, and hooked-web3-provider

import Web3 from 'web3'

import lightwallet from 'eth-lightwallet'

import HookedWeb3Provider from 'hooked-web3-provider' // step 2: you may need to tweak crypto module

// THIS IS A BIT OF HACK

import crypto from 'crypto'

const sourceCreateHash = crypto.createHash

crypto.createHash = function createHash(alg) {

if (alg === 'ripemd160') {

alg = 'rmd160'

}

return sourceCreateHash(alg)

}

As of 11/10/2017, you man encounter an error relating to bitcore-lib.

Error: More than one instance of bitcore-lib found

It looks like eth-lightwallet version 2.5.6 has dependancy of bitcore-lib version 0.14.0 because we can find bitcore-lib version 0.14.0 in node_module/eth-lightwallet/package.json.

But bitcore-lib version 0.15.0 seems to be used somewhere else.

So you have to …

1. cd node_modules/eth-lightwallet 2. vi package.json to modify bitcore-lib's version number

# from ^0.14.0 to: ^0.15.0 3. npm install at node_modules/eth-lightwallet directory

I’m not sure whether that change has side effect or not. But for me it’s working. It’s a bit troublesome though because every time I add new module, I need to do “npm install” at eth-lightwallet directory.

Now you are ready to create UI

First step is creating keystore or wallet with keystore.

I call it wallet.

# step.1: generate seed text



let randomSeed = lightwallet.keystore.generateRandomSeed();

const password = "password" # This is equivalent to keystore in the document of

# eth-lightwallet github page.

# I pick the name wallet because in the original document, the term keystore is used both medhod name and generated wallet with keystore and bit confusing. let wallet # get pwDerivedKey <

lightwallet.keystore.deriveKeyFromPassword(

password, (err, pwDerivedKey) => { if (err){

console.log("err 1:", err)

}



# goto step.2

Step 2 is generate address.

It was interesting to me first time that we can generate same address from same seed text. So you don’t need server or other network services to generate an address.

# step.2: add new address

wallet.generateNewAddress(pwDerivedKey);

Step 3 connect to our node (rpc server) with hooked-web3-provider

# step.3: prepare provider

var web3Provider = new HookedWeb3Provider({

host: "https://<your rpc server>",

transaction_signer: wallet

}); const web3 = new Web3(web3Provider);

Here you need hooked-web3-provider.

That’s it.

From here you can check balance and transfer eth or even execute smart contract.

This is an example of checking balances.

web3.eth.getBalance(address, (err, data) => {

if (err) {

console.log(err);

} else {

let balance = web3.utils.fromWei( data, 'ether');

eth_balance[address] = balance

}

})

And you can save wallet (keystore ) locally.

const serialized_keystore = wallet.serialize()

localStorage.setItem("local storage key", serialized_keystore )

Problem?

That’s it. we can develop dapps for normal users now. I think it’s a big deal because there is a chance for mass adoption!

But is there any problem of light client?

Actually there are a few concerns.

As far as I understand, light client need to connect to a node. And this part is not actually a decentralized network but rather distributed network. Light client may be a way for free ride. Philosophically blockchain world is a ideal democracy. We expect everyone contribute something. Security

Security could be the biggest.

Number 1 and 2 are not real problems but philosophical ones.

I think this is a sign of blockchain becoming a main stream service.

Software versions.

eth-lightwallet: 2.5.6

hooked-web3-provider: 1.0.0

web3: 1.0.0-beta.24

node: 8.9.1

haproxy: 1.6.3

geth: 1.6.3

Some software and some technique may be depreciated. Sorry about that.

Here is source code.

Since I added uPort login feature, the codes are slightly different but still it’s simple and easy.

And oops. I have to say this source code is not production ready…

Conclusion

Light client is a huge step for ethereum/blockchain to go to main stream. I think we can even develop React native apps with ethereum light client feature.

* I have not tested it yet.

Thanks for reading.