Blockchain Validation and Mining!
Ok, I changed my mind. I was going to go over, line for line, Part 3 and discuss all that code. Did you really want me to do that? How boring right? Well in Part 4, we are going to discuss the final two important pieces of the blockchain puzzle. How to validate the blockchain to ensure it is a valid chain and mining! Let's start will validation of the chain.
First, understand that everyone in the network share the longest blockchain. The longest valid blockchain is the accepted blockchain on the network. If two blockchains exist on the network, the group considers the longest one valid. This is why validation and mining produce the security of the blockchain. The time required to validate an existing chain and mining the next block requires computational power. Therefore, anyone trying to replace a valid blockchain with a blockchain of their own, would need more computational power then the honest members of the network. This is the wonderful security of blockchain.
Validation is simple. The program will look at every block in the blockchain and ensure that all the digital signatures are correct and that the chain is indeed valid. As the chain grows, so does the time to validate the chain, computational power security is born.
Mining is the cool part. To add more computation power to the security of the chain, they use a system that requires a digital signature to have a difficulty value based on the number of leading zero's in the digital signature. For example, it would be easier to find a digital signature for the next block if it only needed one leading zero in the digital signature versus five leading zero's in the digital signature. If you are confused, think of it this way. The miner's must produce a specific digital signature based on the validity of the blockchain and a specific amount of leading zero's in the digital signature. Ok, maybe that's still confusing. Let's get to some code.
This example code is not meant to be used. Just to show you what it looks like. At the end of this tutorial, all the changes to the code will be presented in two classes, ExampleChain and Block.
Validation of a blockchain
public static Boolean isChainValid()
{
Block currentBlock;
Block previousBlock;
//loop through blockchain to check hashes:
for(int i=1; i < blockchain.size(); i++) {
currentBlock = blockchain.get(i);
previousBlock = blockchain.get(i-1);
//compare registered hash and calculated hash:
if(!currentBlock.getHash().equals(currentBlock.calculateHash()) ){
System.out.println("Current Hashes not equal");
return false;
}
//compare previous hash and registered previous hash
if(!previousBlock.getHash().equals(currentBlock.getPreviousHash()) ) {
System.out.println("Previous Hashes not equal");
return false;
}
}
return true;
}
This static method would be added to our ExampleChain class. When we call the method isChainValid() we loop through our blockchain and test the digital signatures of the previous and current block. If any signatures are invalid, it returns false. Meaning the chain is an invalid. As you will notice, the longer the chain, the more computational power will be needed to validate the chain.
Next for the mining.
public void mineBlock(int difficulty)
{
//Create a string with difficulty * "0"
String target = new String(new char[difficulty]).replace('\0', '0');
while(!hash.substring( 0, difficulty).equals(target))
{
nonce ++;
hash = calculateHash();
}
System.out.println("Block Mined!!! : " + hash);
}
The mine block method is pretty simple as well. It takes a value of difficulty. It runs the calculateHash() method and evaluates the results based on the number of leading zero's in the hash. If the resulting hash has the number of leading zero's in it's digital signature, it considers the block mined.
You will notice there is a variable in the mineBlock() method called nonce. This variable will be added to the Block class. The variable will also be added to the calculateHash() method. This is what will change the digital signature each loop of calculation. As the nonce increases, the possibility of getting the correct digital signature with the proper number of leading zero's increase.
Since everyone is on the network mining. It is like a lottery system as to who will discover the correct digital signature for the next valid block. Mining software will have many strategies as to how to calculate and win the race. Ultimately, the miners must create a digital signature based on the number of leading zero's required in the hash and be the first to submit their valid block upon the blockchain to win. Winning means a payout of currency. As soon as someone wins, a new race for the next block begins.
Due to the complexity and computational power needed to produce a valid block, honest members of the network will always be able to out build dishonest members of the network. An attacker would have to have more computational power then the honest members combined.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This code is example code only. True mining software and computers are meant to handle situation's with very large difficulty values. The code has been wrote to keep the difficulty between 1 and 7.
Compiling and using the following example code is at your own risk. It is meant for educational purposes only.
Block Class
import java.util.Date;
import java.security.MessageDigest;
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
// AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
// BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// This software is for educational purposes only.
public class Block
{
// The variables we need to create a block.
private String data;
private String hash;
private String previousHash;
private long timeStamp;
private int nonce;
// The constructor of a block. We need to give it data and a previous block's hash.
public Block(String data, String previousHash)
{
// Initialize all the variables so the block is built correctly.
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
//Making sure we do this after we set the other values.
this.hash = calculateHash();
}
// Getter method to return the value of the block's private hash.
public String getHash()
{
return this.hash;
}
// Getter method to return the value of the block's previous hash.
public String getPreviousHash()
{
return this.previousHash;
}
// Getter method to return the value of the block's data.
public String getData()
{
return this.data;
}
// Getter method to return the value of the block's timestamp
public long getTimeStamp()
{
return this.timeStamp;
}
// Getter method to return the value of the block's nonce
public int getNonce()
{
return this.nonce;
}
// This is a method to calculate the hash code for this block.
// Note we add everything that we want to protect from tampering into the hash
// in this situation we added data, timeStamp, and previousHash.
public String calculateHash()
{
String calculatedhash = Block.applySha256(
previousHash +
Long.toString(timeStamp) +
Integer.toString(nonce) +
data);
return calculatedhash;
}
public void mineBlock(int difficulty)
{
// Added this code to keep the difficulty between 1 and 7
// The bigger the difficulty the longer it takes your computer to calculate the results
// To ensure that it doesn't take too long we keep it within an easy setting.
if ( difficulty < 1 )
{
difficulty = 1;
}
else if ( difficulty > 7 )
{
difficulty = 7;
}
//Create a string with difficulty * "0"
String target = new String(new char[difficulty]).replace('\0', '0');
while(!hash.substring( 0, difficulty).equals(target))
{
nonce ++;
hash = calculateHash();
}
System.out.println("Block Mined!!! : " + hash);
}
// This is the SHA-256 algorithm.
public static String applySha256(String input)
{
try
{
MessageDigest digest = MessageDigest.getInstance("SHA-256");
//Applies sha256 to our input,
byte[] hash = digest.digest(input.getBytes("UTF-8"));
// This will contain hash as hexidecimal
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
String hex = Integer.toHexString(0xff & hash[i]);
if(hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
}
ExampleChain Class
import java.util.ArrayList;
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
// AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
// BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// This software is for educational purposes only.
public class ExampleChain
{
public static ArrayList<Block> blockchain = new ArrayList<Block>();
public static int difficulty = 5;
public static void main(String[] args)
{
//add our blocks to the blockchain ArrayList:
blockchain.add(new Block("Hi im the first block", "0"));
System.out.println("Trying to Mine block 1... ");
blockchain.get(0).mineBlock(difficulty);
blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).getHash()));
System.out.println("Trying to Mine block 2... ");
blockchain.get(1).mineBlock(difficulty);
blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).getHash()));
System.out.println("Trying to Mine block 3... ");
blockchain.get(2).mineBlock(difficulty);
System.out.println("\nBlockchain is Valid: " + isChainValid());
System.out.println("\nThe block chain: ");
for(int i=0; i < blockchain.size(); i++)
{
System.out.println("Block: " + (i+1) );
System.out.println(" Hash: " + blockchain.get(i).getHash() );
System.out.println("PreviousHash: " + blockchain.get(i).getPreviousHash() );
System.out.println(" Data: " + blockchain.get(i).getData() );
System.out.println(" Time Stamp: " + blockchain.get(i).getTimeStamp() );
System.out.println(" Nonce: " + blockchain.get(i).getNonce() );
System.out.println();
}
}
public static Boolean isChainValid()
{
Block currentBlock;
Block previousBlock;
String hashTarget = new String(new char[difficulty]).replace('\0', '0');
//loop through blockchain to check hashes:
for(int i=1; i < blockchain.size(); i++)
{
currentBlock = blockchain.get(i);
previousBlock = blockchain.get(i-1);
//compare registered hash and calculated hash:
if(!currentBlock.getHash().equals(currentBlock.calculateHash()) )
{
System.out.println("Current Hashes not equal");
return false;
}
//compare previous hash and registered previous hash
if(!previousBlock.getHash().equals(currentBlock.getPreviousHash()) )
{
System.out.println("Previous Hashes not equal");
return false;
}
//check if hash is solved
if(!currentBlock.getHash().substring( 0, difficulty).equals(hashTarget)) {
System.out.println("This block hasn't been mined");
return false;
}
}
return true;
}
}
At this point, we have a blockchain of blocks that store data, digital signatures that chain our blocks together, a proof of work mining system to validate new blocks, and a system to ensure that our blockchain is valid and the data is unchanged.
Hope you enjoyed this tutorial!