A simple java implementation of Blockchain

May 27, 2019 by Thibault Debatty - 523 views

https://cylab.be/blog/26/a-simple-java-implementation-of-blockchain

Blockchain is currently a very hot research topic. To understand how it works and what it can achieve, here is a simple java implementation.

The full source code is available at https://gitlab.cylab.be/cylab/simple-blockchain

Blocks

A blockchain is, as the name states, a chain of blocks: each block contains a link to its parent. Additionally, the blocks contain a timestamp, some data that is considered as the truth at that moment in time, and a hash computed using sha256 for example:

public class Block implements Serializable {
    public String parent;
    public String data;
    public long timestamp;

    public String hash = "";
    public int nonce;

    public String hash() {
        return sha256(parent
                + data
                + Long.toString(timestamp)
                + Integer.toString(nonce));
    }
}

Blocks also have a second characteristics: they should be hard to compute. This is called the proof-of-work. For example, the hash of each block must start with a sequence of 5 "0". This means multiple values of nonce have to be tried before the block is considered as valid:

    public void solve() {
        do {
            nonce++;
            hash = hash();
        } while (!hash.substring(0, 5).equals("00000"));
    }

Miners

The miners are responsible for creating the new blocks. Once a new block is ready (the correct hash was found). The miner will broadcast this block to all participants using some peer-to-peer (P2P) network:

public class SimpleChain {

    public void mine() {
        while (true) {
            Block block = new Block();
            block.data = getData();
            block.timestamp = new Date().getTime();
            block.parent = chain.head().block.hash;

            block.solve();
            p2p.broadcastBlock(block);
        }
    }

Branches and rogue miners

As all miners work in parallel, branches can appear when multiple miners create new blocks that have the same parent. This is normal, and the situation fixes itself as legitimate miners always try to create new blocks on top the of the current head (block.parent = chain.head().block.hash;).

As each block is linked to its parent and new blocks are costly to compute, this continuously reinforces the validity of the data saved in previous blocks.

To modify past data, a rogue miner has to create a new branch that is longer then all others. Hence the rogue miner has to be more powerful then all legitimate miners combined.

Hence the chain is actually implemented as a tree, to keep track of branches:

public class ChainLink implements Serializable {

    public Block block;
    public List<ChainLink> children = new LinkedList<>();

Peer-to-peer network

The main responsibility of the peer-to-peer network is to broadcast new blocks to all miners. In this simple implementation we use java Remote Method Invocation (RMI).

At the client side, we send the block to every client in turn (in RMIBasedP2P.java):

    @Override
    public void broadcastBlock(Block block) {

        List<String> participants = getParticipants();
        System.out.println("Broadcast <" + block + "> to " + participants);

        for (String participant : participants) {
            try {
                RemoteInterface remote = (RemoteInterface) Naming.lookup(
                        participant);
                remote.addBlock(block);
            } catch (RemoteException ex) {
                System.err.println("Failed to send to " + participant 
                    + " Moving on...");
            } catch (NotBoundException | MalformedURLException ex) {
                throw new RuntimeException(ex);
            }
        }
    }

At the server side, we start a RMI server on a provided port (also in RMIBasedP2P.java) that implements the addBlock method:

    private void startRMIHandler(final int port) throws RemoteException {
        RemoteHandler rh = new RemoteHandler(sc);
        Registry rgsty = LocateRegistry.createRegistry(port);
        rgsty.rebind("simplechain", rh);
    }

Code and demo

The full source code is available at https://gitlab.cylab.be/cylab/simple-blockchain. To run a simple demo:

git clone git@gitlab.cylab.be:cylab/simple-blockchain.git
cd simple-blockchain
mvn package
./demo.sh

This will open 4 terminals: three miners and one window to watch the evolution of the chain.

Simple java Blockchain