Create your own Blockchain in 30 minutes

in #blockchain7 years ago (edited)

The Blockchain is a technological revolution at the heart of the success of Bitcoin and other crypto currencies. For some, the Blockchain is a revolution comparable to what the Internet was in its day. In this article, we propose you to create your own Blockchain in 30 minutes by using the Java programming language. It will allow you to better discover how the Blockchain works internally.

1-KDuhFa0w3kBjAqYHtLtjFg.png

This article is divided in 3 parts :

  1. Design and Create the Blocks for the Blockchain
  2. Creating the Blockchain by using the Blocks
  3. Put our Blockchain in action !

You can also discover this tutorial in video on YouTube

Design and Create the Blocks for the Blockchain

First, we are going to design the Blocks for the Blockchain. Basically, a block contains the following information :

  • Index
  • Timestamp to store the creation date of the Block
  • Hash of the previous Block
  • Data stored in the Block. For the Bitcoin and the other crypto currencies, data are transactions
  • Hash of the current Block to ensure integrity of its content

1-n2ihH0lARSTDSNesARhZ9w.png

This gives us the following code for the properties of the Block :

public class Block {

  private int index;
  private long timestamp;
  private String hash;
  private String previousHash;
  private String data;
  private int nonce;

  // ..
}

SHA-256 Cryptographic Hash Function

The hash of the blocks of our Blockchain will be calculated by relying on the cryptographic hashing algorithm SHA-256 which you will find all the details on wikipedia : https://en.wikipedia.org/wiki/SHA-2 . Luckily, the Java language SDK offers a standard implementation of this algorithm. It will not be necessary to code it ourselves. The cryptography algorithms offered by Java are recoverable via the MessageDigest class, which allows you to retrieve the instance of an algorithm by entering the name of the getInstance() method.

It then remains to enter in parameter of the digest() method a textual representation of the blocks’s content to hash for getting the result of its hashing via the SHA-256 algorithm in the form of an array of bytes. To finish, we transform this array of bytes into a string of characters and we return this last function output :

public static String calculateHash(Block block) {
  if (block != null) {
    MessageDigest digest = null;

    try {
      digest = MessageDigest.getInstance("SHA-256");
     } catch (NoSuchAlgorithmException e) {
      return null;
     }

     String txt = block.str();
     final byte bytes[] = digest.digest(txt.getBytes());
     final StringBuilder builder = new StringBuilder();

     for (final byte b : bytes) {
        String hex = Integer.toHexString(0xff & b);

        if (hex.length() == 1) {
           builder.append('0');
        }

        builder.append(hex);
      }

      return builder.toString();
   }

   return null;
}

Mining the Blocks

Our block is practically functional. It only remains to add a method to carry out its mining. The mining process will allow us to solve the enigma posed by the famous “Proof of Work”. Given some difficulty passed as input, we will have to find a hash for the block starting with a given number of zeros :

public void mineBlock(int difficulty) {
   nonce = 0;

   while (!getHash().substring(0,  difficulty).equals(Utils.zeros(difficulty))) {
      nonce++;
      hash = Block.calculateHash(this);
    }
}


The attentive reader will have noticed the presence of the static method zeros of the class Utils in this code. This method returns a string containing the number of zeros passed as an input parameter. As for the nonce property, it will contain the number of tests performed before solving the proof of work during the block mining.

Complete code for the Block class

To end this first part, you will find the complete code for the Block class just below :

package fr.toutsurlebitcoin.myblockchain;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

public class Block {

   private int index;
   private long timestamp;
   private String hash;
   private String previousHash;
   private String data;
   private int nonce;

   public Block(int index, long timestamp, String previousHash, String data) {
     this.index = index;
     this.timestamp = timestamp;
     this.previousHash = previousHash;
     this.data = data;
     nonce = 0;
     hash = Block.calculateHash(this);
   }

   public int getIndex() {
     return index;
   }

   public long getTimestamp() {
     return timestamp;
   }
 
   public String getHash() {
     return hash;
   }
 
   public String getPreviousHash() {
     return previousHash;
   }
 
   public String getData() {
     return data;
   }

   public String str() {
     return index + timestamp + previousHash + data + nonce;
   }

   public String toString() {
     StringBuilder builder = new StringBuilder();
     builder.append("Block #").append(index).append(" [previousHash : ").append(previousHash).append(", ").
     append("timestamp : ").append(new Date(timestamp)).append(", ").append("data : ").append(data).append(", ").
    append("hash : ").append(hash).append("]");
     return builder.toString();
   }
    
   public static String calculateHash(Block block) {
     if (block != null) {
       MessageDigest digest = null;
 
       try {
         digest = MessageDigest.getInstance("SHA-256");
       } catch (NoSuchAlgorithmException e) {
         return null;
       }
            
       String txt = block.str();
       final byte bytes[] = digest.digest(txt.getBytes());
       final StringBuilder builder = new StringBuilder();
            
       for (final byte b : bytes) {
         String hex = Integer.toHexString(0xff & b);
 
         if (hex.length() == 1) {
           builder.append('0');
         }
                
         builder.append(hex);
       }
            
       return builder.toString();
     }
      
     return null;
   }
 
    public void mineBlock(int difficulty) {
      nonce = 0;
        
      while (!getHash().substring(0,  difficulty).equals(Utils.zeros(difficulty))) {
        nonce++;
        hash = Block.calculateHash(this);
      }
   }
    
 }

Creating the Blockchain by using the Blocks

In this second part of the tutorial, we are going to create the Blockchain object by using the Block object created previously.

Designing the Blockchain

The Blockchain is a distributed database ensuring the integrity of its data. The Blockchain will have a property letting to define the level of difficulty for the mining of the blocks during the solving of the “Proof of Work”. Then, the Blockchain will store its blocks within a List object of the Java language which gives us the following declaration start for the Blockchain object :

public class Blockchain {

  private int difficulty;
  private List<Block> blocks;

}

Creating and Mining new Blocks

Our Blockchain must allow the creation of new blocks and their mining taking into account the difficulty associated with it. So, we add a newBlock method to generate a new block associated with the last block known of the Blockchain. The block’s mining is done while adding the block to the Blockchain within a dedicated method addBlock :

public Block latestBlock() {
  return blocks.get(blocks.size() - 1);
}

public Block newBlock(String data) {
  Block latestBlock = latestBlock();
  return new Block(latestBlock.getIndex() + 1, System.currentTimeMillis(),
      latestBlock.getHash(), data);
}

public void addBlock(Block b) {
  if (b != null) {
    b.mineBlock(difficulty);
    blocks.add(b);
  }
}

Checking the Blockchain’s validity

The Blockchain must guarantee the integrity of the block data within it in order to remain valid. To do this, we will add different methods within our Blockchain to verify that :

  • The first block is valid
  • A new block is valid with the previous Blockchain block
  • Blockchain is valid

In order to implement these methods, it is necessary to define the validity criteria that we must consider. Thus, the first block is valid if its index is equal to 0, it does not have a previous previousHash and finally if its hash is correct. A new block is valid next to the previous block of the Blockchain if its index is incremented by 1 compared to the index of the previous block, its previousHash field is filled with the hash of the previous block and finally if its hash is itself coherent. Finally, a Blockchain is valid and the integrity of its data is guaranteed when the first block is valid and each block that composes it is valid next to the block that precedes it. All this gives us the following code :

public boolean isFirstBlockValid() {
  Block firstBlock = blocks.get(0);

  if (firstBlock.getIndex() != 0) {
    return false;
  }

  if (firstBlock.getPreviousHash() != null) {
    return false;
  }

  if (firstBlock.getHash() == null || 
          !Block.calculateHash(firstBlock).equals(firstBlock.getHash())) {
        return false;
  }

 return true;
}

public boolean isValidNewBlock(Block newBlock, Block previousBlock) {
  if (newBlock != null  &&  previousBlock != null) {
    if (previousBlock.getIndex() + 1 != newBlock.getIndex()) {
      return false;
    }

    if (newBlock.getPreviousHash() == null  || 
            !newBlock.getPreviousHash().equals(previousBlock.getHash())) {
      return false;
    }

    if (newBlock.getHash() == null  ||  
        !Block.calculateHash(newBlock).equals(newBlock.getHash())) {
      return false;
    }

    return true;
  }

  return false;
}

public boolean isBlockChainValid() {
  if (!isFirstBlockValid()) {
    return false;
  }

  for (int i = 1; i < blocks.size(); i++) {
    Block currentBlock = blocks.get(i);
    Block previousBlock = blocks.get(i - 1);

    if (!isValidNewBlock(currentBlock, previousBlock)) {
      return false;
    }
  }

  return true;
}

Complete code of the Blockchain

Our Blockchain class is almost complete. All we have to do is to override its toString() method in order to be able to return a textual representation facilitating the visualization of its contents. We obtain the following Java code :

package fr.toutsurlebitcoin.myblockchain;

import java.util.ArrayList;
import java.util.List;

public class Blockchain {

  private int difficulty;
  private List<Block> blocks;

  public Blockchain(int difficulty) {
    this.difficulty = difficulty;
    blocks = new ArrayList<>();
    // create the first block
    Block b = new Block(0, System.currentTimeMillis(), null, "First Block");
    b.mineBlock(difficulty);
    blocks.add(b);
  }

  public int getDifficulty() {
    return difficulty;
  }

  public Block latestBlock() {
    return blocks.get(blocks.size() - 1);
  }

  public Block newBlock(String data) {
    Block latestBlock = latestBlock();
    return new Block(latestBlock.getIndex() + 1, System.currentTimeMillis(),
        latestBlock.getHash(), data);
  }

  public void addBlock(Block b) {
    if (b != null) {
      b.mineBlock(difficulty);
      blocks.add(b);
    }
  }

  public boolean isFirstBlockValid() {
    Block firstBlock = blocks.get(0);

    if (firstBlock.getIndex() != 0) {
      return false;
    }

    if (firstBlock.getPreviousHash() != null) {
      return false;
    }

    if (firstBlock.getHash() == null || 
          !Block.calculateHash(firstBlock).equals(firstBlock.getHash())) {
      return false;
    }

    return true;
  }

  public boolean isValidNewBlock(Block newBlock, Block previousBlock) {
    if (newBlock != null  &&  previousBlock != null) {
      if (previousBlock.getIndex() + 1 != newBlock.getIndex()) {
        return false;
      }

      if (newBlock.getPreviousHash() == null  ||  
        !newBlock.getPreviousHash().equals(previousBlock.getHash())) {
        return false;
      }

      if (newBlock.getHash() == null  ||  
        !Block.calculateHash(newBlock).equals(newBlock.getHash())) {
        return false;
      }

      return true;
    }

    return false;
  }

  public boolean isBlockChainValid() {
    if (!isFirstBlockValid()) {
      return false;
    }

    for (int i = 1; i < blocks.size(); i++) {
      Block currentBlock = blocks.get(i);
      Block previousBlock = blocks.get(i - 1);

      if (!isValidNewBlock(currentBlock, previousBlock)) {
        return false;
      }
    }

    return true;
  }

  public String toString() {
    StringBuilder builder = new StringBuilder();

    for (Block block : blocks) {
      builder.append(block).append("\n");
    }

    return builder.toString();
  }

}

Put our Blockchain in action !

In this last part, we are going to put our Blockchain in action ! We are going to create some blocks for our Blockchain and then checking its validity.

1-Tsta--i1uxSem0VD-uCUJQ.png

Adding some blocks and checking the Blockchain’s integrity

We create our Blockchain by instantiating the Blockchain object and specifying in input a difficulty of 4 for the block mining. Next, we will add three blocks before checking the validity of the Blockchain and displaying the data it contains on the screen. This is done with the following Java code :

package fr.toutsurlebitcoin.myblockchain;

public class Main1 {

  public static void main(String[] args) {
    Blockchain blockchain = new Blockchain(4);
    blockchain.addBlock(blockchain.newBlock("Tout sur le Bitcoin"));
    blockchain.addBlock(blockchain.newBlock("Sylvain Saurel"));
    blockchain.addBlock(blockchain.newBlock("https://www.toutsurlebitcoin.fr"));

    System.out.println("Blockchain valid ? " + blockchain.isBlockChainValid());
    System.out.println(blockchain);
  }

}


Executing this code using the Java virtual machine will give us the following console output on which we can visually see the validity of our Blockchain :

1-Q8N-c7lbyop1TpgEi4aOzQ.png

Corruption of our Blockchain

In order to verify that our method of validating the Blockchain is working properly, it may be interesting to try to corrupt it by integrating a corrupted block. Once this addition is done, we will be able to verify that our method detects that the Blockchain is not valid :

package fr.toutsurlebitcoin.myblockchain;

public class Main {

  public static void main(String[] args) {
    Blockchain blockchain = new Blockchain(4);
    blockchain.addBlock(blockchain.newBlock("Tout sur le Bitcoin"));
    blockchain.addBlock(blockchain.newBlock("Sylvain Saurel"));
    blockchain.addBlock(blockchain.newBlock("https://www.toutsurlebitcoin.fr"));

    System.out.println("Blockchain valid ? " + blockchain.isBlockChainValid());
    System.out.println(blockchain);

    // add an invalid block to corrupt Blockchain
    blockchain.addBlock(new Block(15, System.currentTimeMillis(), "aaaabbb", "Block invalid"));

    System.out.println("Blockchain valid ? " + blockchain.isBlockChainValid());
  }

}


Executing this code using the Java virtual machine will give us the following console output on which we can see that our Blockchain detects a problem of validity with the corrupted block we added :

1-wcnJc1k0FgctoR43g97zqw.png

Go further

Our implementation of a basic Blockchain in Java is fully functional. It will have allowed us to highlight the internal functioning of a Blockchain and especially the part related to block mining that will be even faster than the computer or computers realizing it are powerful.

To go further, we should now implement features to peer-to-peer (P2P) our Blockchain. This could be done in a future tutorial if the subject seems interesting to you. Feel free to leave me your comments if you want to see these P2P features implemented in a future article.

To discover more tutorials on Java development, you can visit the SSaurel’s Blog.

Sort:  

Congratulations @sylvain.saurel, you have decided to take the next big step with your first post! The Steem Network Team wishes you a great time among this awesome community.


Thumbs up for Steem Network´s strategy

The proven road to boost your personal success in this amazing Steem Network

Do you already know that awesome content will get great profits by following these simple steps, that have been worked out by experts?

Coin Marketplace

STEEM 0.19
TRX 0.15
JST 0.029
BTC 63287.47
ETH 2569.39
USDT 1.00
SBD 2.81