The purpose of this paper is to understand what blockchain is through Java practical development tutorial. We will develop a very basic blockchain by self-study in Java through practical learning, and on this basis, we can expand such as web framework applications. This basic Java blockchain also implements a simple workload proving system. This paper uses a java example to demonstrate the process of developing a blockchain application, involving the concept and basic implementation methods of all blockchains. This article is mainly for project architects who want to be engaged in blockchain development. It should be noted that the blockchain we built with 150 lines of Java code can not reach the production level. It is just to help you better understand the concept of blockchain.
Java source code is saved in Github
Create blockchain
Blockchain is a collection of a series or a series of blocks, similar to the concept of chain list. Each block points to the next block, and then connects them in order. So what is the content of each block? Each block in the blockchain stores a lot of valuable information, mainly including three parts: its own digital signature, the digital signature of the previous block, and all the data that needs to be encrypted (these data in bitcoin are equivalent to transaction information, which is the essence of cryptocurrency). Each digital signature not only proves that it is a unique block, but also points to the source of the previous block, so that all blocks can be linked in the chain, and the data is some specific information, you can save the business data according to the business logic.
hash here refers to digital signature
Therefore, each block contains not only the hash value of the previous block, but also its own hash value. Its hash value is calculated by the previous hash value and data through hash. If the data of the previous block is tampered with, the hash value of the previous block will also change (because the data is also calculated), which leads to the hash value of all subsequent blocks. So calculating and comparing the hash value will let us check whether the current blockchain is effective, and avoid the possibility of data being tampered with maliciously, because tampering with the data will change the hash value and destroy the entire blockchain.
Define the blockchain class Block:
import java.util.Date; public class Block { public String hash; public String previousHash; private String data; //our data will be a simple message. private long timeStamp; //as number of milliseconds since 1/1/1970. //Block Constructor. public Block(String data,String previousHash ) { this.data = data; this.previousHash = previousHash; this.timeStamp = new Date().getTime(); } }
As you can see our basic block contains String hash, which will hold our digital signature. The variable previoushash saves the hash and String data of the previous block to save our block data
Create a digital signature
Friends who are familiar with the encryption algorithm, there are many encryption methods that can be implemented in Java, such as BASE, MD, RSA, SHA, etc. I choose SHA256 encryption method here. SHA (Secure Hash Algorithm) security hash algorithm is characterized by that a small amount of data change will produce a large number of unpredictable changes in hash value, hash value is used to represent a large number of data The unique value of fixed size, while the hash value of SHA256 algorithm is 256 bits. The reason why SHA256 is chosen is that its size is just right. On the one hand, it is very unlikely to generate duplicate hash values. On the other hand, in the practical application process of blockchain, it is likely to generate a large number of blocks, which makes the amount of information large, so the size of 256 bits is more appropriate.
Now I create a StringUtil method to call SHA256 algorithm conveniently
import java.security.MessageDigest; public class StringUtil { //Applies Sha256 to a string and returns the result. 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")); StringBuffer hexString = new StringBuffer(); // This will contain hash as hexidecimal 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); } } }
You may not fully understand the meaning of the above code, but you only need to understand that all the input calls this method will generate a unique hash value (digital signature), which is very important in the blockchain.
Next, let's apply the method applySha256 in the Block class. Its main purpose is to calculate the hash value. The hash value we calculate should include all the data in the Block that we don't want to be tampered with maliciously. The Block class we listed above must include previousHash, data and timeStamp,
public String calculateHash() { String calculatedhash = StringUtil.applySha256( previousHash + Long.toString(timeStamp) + data ); return calculatedhash; }
Then add this method to the Block constructor
public Block(String data,String previousHash ) { this.data = data; this.previousHash = previousHash; this.timeStamp = new Date().getTime(); this.hash = calculateHash(); //Making sure we do this after we set the other values. }
test
In the main method, let's create some blocks and print out their hash values to see if everything is under our control.
The first block is called the creation block, because it is the head block, so we only need to enter "0" as the previous hash of the previous block.
public class NoobChain { public static void main(String[] args) { Block genesisBlock = new Block("Hi im the first block", "0"); System.out.println("Hash for block 1 : " + genesisBlock.hash); Block secondBlock = new Block("Yo im the second block",genesisBlock.hash); System.out.println("Hash for block 2 : " + secondBlock.hash); Block thirdBlock = new Block("Hey im the third block",secondBlock.hash); System.out.println("Hash for block 3 : " + thirdBlock.hash); } }
Printout results:
Hash for block 1: f6d1bc5f7b0016eab53ec022db9a5d9e1873ee78513b1c666696e66777fe55fb Hash for block 2: 6936612b3380660840f22ee6cb8b72ffc01dbca5369f305b92018321d883f4a3 Hash for block 3: f3e58f74b5adbd59a7a1fc68c97055d42e94d33f6c322d87b29ab20d3c959b8f
Each block must have its own data signature, i.e. hash value. This hash value depends on its own information (data) and the previous block's digital signature (previousHash), but this is not a blockchain. Let's store the block into an array. Here I will introduce the gson package, so that we can view the entire blockchain structure in the json mode.
import java.util.ArrayList; import com.google.gson.GsonBuilder; public class NoobChain { public static ArrayList<Block> blockchain = new ArrayList<Block>(); public static void main(String[] args) { //add our blocks to the blockchain ArrayList: blockchain.add(new Block("Hi im the first block", "0")); blockchain.add(new Block("Yo im the second block",blockchain.get(blockchain.size()-1).hash)); blockchain.add(new Block("Hey im the third block",blockchain.get(blockchain.size()-1).hash)); String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain); System.out.println(blockchainJson); } }
Such an output structure is more similar to the blockchain we expect.
Check the integrity of blockchain
Add an isChainValid() method in the main method to cycle all blocks in the blockchain and compare the hash value. This method is used to check whether the hash value is equal to the calculated hash value, and whether the previousHash value is equal to the hash value of the previous block. You may have the following questions: we are creating blocks in the blockchain in a main function, so there is no possibility of modification. But you should note that one of the core concepts in the blockchain is decentralization. Each block may be generated in a node in the network, so it is likely that a node will modify the data in its own node Well, according to the above theoretical data changes, the whole blockchain will be broken, that is, the blockchain will be invalid.
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.hash.equals(currentBlock.calculateHash()) ){ System.out.println("Current Hashes not equal"); return false; } //compare previous hash and registered previous hash if(!previousBlock.hash.equals(currentBlock.previousHash) ) { System.out.println("Previous Hashes not equal"); return false; } } return true; }
Any slight change of the block in the blockchain will cause this function to return false, which proves that the blockchain is invalid.
All network nodes in bitcoin network share their own blockchain, but the longest effective blockchain is recognized by the whole network. If someone tampers with the previous data maliciously, then creates a longer blockchain and publishes it in the network, what should we do? This involves another important proof of concept workload in blockchain. We have to mention hashcash. This concept originated from a paper of Adam Back, which is mainly applied to email filtering and bitcoin to prevent double payment.
mining
Here we ask the miner to prove the workload. The specific way is to try different parameter values in the block until its hash value starts from a series of zeros. Let's add an int type called nonce to include in our calculatehash () method, as well as the mineblock () method we need.
import java.util.Date; public class Block { public String hash; public String previousHash; private String data; //our data will be a simple message. private long timeStamp; //as number of milliseconds since 1/1/1970. private int nonce; //Block Constructor. public Block(String data,String previousHash ) { this.data = data; this.previousHash = previousHash; this.timeStamp = new Date().getTime(); this.hash = calculateHash(); //Making sure we do this after we set the other values. } //Calculate new hash based on blocks contents public String calculateHash() { String calculatedhash = StringUtil.applySha256( previousHash + Long.toString(timeStamp) + Integer.toString(nonce) + data ); return calculatedhash; } public void mineBlock(int difficulty) { String target = new String(new char[difficulty]).replace('\0', '0'); //Create a string with difficulty * "0" while(!hash.substring( 0, difficulty).equals(target)) { nonce ++; hash = calculateHash(); } System.out.println("Block Mined!!! : " + hash); } }
In the mineBlock() method, an int value called difficultly is introduced. For example, 1 and 2 are low difficulties, which can be calculated by ordinary computers at once. My suggestion is to test between 4 and 6. Ordinary computers will take about 3 seconds. In litecoin, the difficulty is around 442592, while in bitcoin, each mining requires about 10 minutes. When However, according to the computing power of all networks, the difficulty will be constantly modified.
We add the static variable "difficultly" to the NoobChain class.
public static int difficulty = 5;
In this way, we must modify the main method to trigger the mineBlock() method when creating each new block, and the isChainValid() method is used to check whether the hash value of each block is correct and whether the whole blockchain is valid.
import java.util.ArrayList; import com.google.gson.GsonBuilder; public class NoobChain { 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).hash)); 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).hash)); System.out.println("Trying to Mine block 3... "); blockchain.get(2).mineBlock(difficulty); System.out.println("\nBlockchain is Valid: " + isChainValid()); String blockchainJson = new GsonBuilder().setPrettyPrinting().create().toJson(blockchain); System.out.println("\nThe block chain: "); System.out.println(blockchainJson); } 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.hash.equals(currentBlock.calculateHash()) ){ System.out.println("Current Hashes not equal"); return false; } //compare previous hash and registered previous hash if(!previousBlock.hash.equals(currentBlock.previousHash) ) { System.out.println("Previous Hashes not equal"); return false; } //check if hash is solved if(!currentBlock.hash.substring( 0, difficulty).equals(hashTarget)) { System.out.println("This block hasn't been mined"); return false; } } return true; } }
Print:
Connected to the target VM, address: '127.0.0.1:61863', transport: 'socket' Trying to Mine block 1... Block Mined!!! : 0000016667d4240e9c30f53015310b0ec6ce99032d7e1d66d670afc509cab082 Trying to Mine block 2... Block Mined!!! : 000002ea55735bea4cac7e358c7b0d8d81e8ca24021f5f85211bf54fd4ac795a Trying to Mine block 3... Block Mined!!! : 000000576987e5e9afbdf19b512b2b7d0c56db0e6ca49b3a7e638177f617994b Blockchain is Valid: true [ { "hash": "0000016667d4240e9c30f53015310b0ec6ce99032d7e1d66d670afc509cab082", "previousHash": "0", "data": "first", "timeStamp": 1520659506042, "nonce": 618139 }, { "hash": "000002ea55735bea4cac7e358c7b0d8d81e8ca24021f5f85211bf54fd4ac795a", "previousHash": "0000016667d4240e9c30f53015310b0ec6ce99032d7e1d66d670afc509cab082", "data": "second", "timeStamp": 1520659508825, "nonce": 1819877 }, { "hash": "000000576987e5e9afbdf19b512b2b7d0c56db0e6ca49b3a7e638177f617994b", "previousHash": "000002ea55735bea4cac7e358c7b0d8d81e8ca24021f5f85211bf54fd4ac795a", "data": "third", "timeStamp": 1520659515910, "nonce": 1404341 } ]
After testing, adding a new block, that is, mining must take a certain time, about 3 seconds. You can increase the difficulty of difficultly to see how it affects the time spent on data problems. If someone tampers with data maliciously in your blockchain system:
- Their blockchain is invalid.
- They can't create a longer blockchain
- Honest blockchain in the network will have more time advantage in the long chain
Because the tampered blockchain will not be able to catch up with the long chain and the effective chain, unless they have a faster computing speed than all the nodes in your network, maybe the future quantum computer or something.
You have completed your basic blockchain!
In addition, Amway:
1.Introduction to DApp development of Ethereum
2.DApp practice of Ethereum blockchain E-commerce
3.java development of Ethereum blockchain tutorial, web3j development details: http://t.cn/RrpULLJ