What is blockchain? Only 150 lines of java code to fully understand!

The purpose of this article is to help you really understand what a blockchain is. We will create a very basic blockchain in Java, implement a simple proof-of-work system, and extend it on this basis. Java source code is kept on Github .

It should be pointed out that the blockchain we built with 150 lines of code is not production-level, it is just to help you better understand the concept of blockchain.

If you want to start learning Ethereum blockchain application development right away, you can visit Huizhi.com's excellent online interactive tutorial:

Create a blockchain

A blockchain is a collection of a series or a series of blocks, similar to the concept of a linked list, each block points to the next block, and then connected together in sequence. So what's in 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 are in In Bitcoin, it is equivalent to the information of the transaction, which is the essence of the 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 together in the chain, and data is some specific information, you can follow the business logic to store business data.

Enter image description

The hash here refers to the digital signature

Therefore, each block not only contains the hash value of the previous block, but also contains its own hash value. Its own hash value is calculated by hashing the previous hash value and data data. 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 counted), which will result in the hash value of all subsequent blocks. Therefore, calculating and comparing the hash value will allow us to check whether the current blockchain is valid, which also avoids the possibility of malicious tampering of the data, because tampering with the data will change the hash value and destroy the entire blockchain.

The class Block that defines the blockchain:

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 holds the hash of the previous block and String data to hold our block data

Create a digital signature

Friends who are familiar with encryption algorithms, there are many encryption methods that can be implemented in Java, such as BASE, MD, RSA, SHA, etc. I chose the encryption method SHA256 here, SHA (Secure Hash Algorithm) secure hash algorithm, The characteristic of this algorithm is that a small change of data will produce an unpredictable large number of changes in the hash value, which is used as a unique value of a fixed size to represent a large amount of data, while the hash value of the SHA256 algorithm has a size of 256 bits. The reason why SHA256 is chosen is because its size is just right. On the one hand, the possibility of generating repeated hash values ​​is very small. On the other hand, in the actual application process of the blockchain, a large number of blocks may be generated, which makes the amount of information very large. large, then the size of 256 bits is more appropriate.

Below I created a StringUtil method to facilitate calling the SHA256 algorithm

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);
        }
    }   
}

Maybe you don't fully understand the meaning of the above code, but you only need to understand that all inputs will generate a unique hash value (digital signature) after calling this method, and this hash value is very important in the blockchain.

Next, let us apply the method applySha256 method 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 do not want to be maliciously tampered with. In our Block class 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 constructor of Block

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 their hash to see if everything is under our control.

The first block is called the genesis block, because it is the header block, so we just 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);

    }
}

Print out the result:

Hash for block 1: f6d1bc5f7b0016eab53ec022db9a5d9e1873ee78513b1c666696e66777fe55fb
Hash for block 2: 6936612b3380660840f22ee6cb8b72ffc01dbca5369f305b92018321d883f4a3
Hash for block 3: f3e58f74b5adbd59a7a1fc68c97055d42e94d33f6c322d87b29ab20d3c959b8f

Each block must have its own data signature, that is, a hash value. This hash value depends on its own information (data) and the digital signature (previousHash) of the previous block, but this is not a blockchain. Let's Store blocks in an array, here I will introduce the gson package, the purpose is to view the entire blockchain structure in 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 what we expect from a blockchain.

Check the integrity of the blockchain

Add an isChainValid() method to the main method, the purpose is 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 the same as the previous hash value. The hash value of a block is equal. Maybe you will have the following questions, we create the blocks in the blockchain in a main function, so there is no possibility of modification, but you should pay attention to that, a core concept in the blockchain is to go to Centralization, each block may be generated in a certain node in the network, so it is very likely that a node has modified the data in its own node, then according to the above theoretical data changes will lead to the entire blockchain. When it breaks, the blockchain becomes 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;
}

The slightest change in any block in the blockchain will cause this function to return false, which proves that the blockchain is invalid.

All network nodes in the Bitcoin network share their respective blockchains. However, the longest valid blockchain is uniformly recognized by the entire network. If someone maliciously tampers with the previous data, and then creates a longer one The blockchain and the whole network are published and presented in the network, what should we do? This involves another important concept workload proof in the blockchain. Here we have to mention hashcash. This concept first came from a paper by Adam Back. It is mainly used in email filtering and preventing double payments in Bitcoin. .

mining

Here we ask miners to do proof-of-work by trying different parameter values ​​in a block until its hash starts with a series of zeros. Let's add an int type called nonce to include in our calculatehash() method, and the required mineblock() method

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);
    }
}

The mineBlock() method introduces an int value called difficulty. For low difficulties such as 1 and 2, ordinary computers can basically calculate them immediately. My suggestion is to test between 4-6. Ordinary computers will probably It takes 3 seconds, and the difficulty in Litecoin is about 442592, while in Bitcoin, each mining requires about 10 minutes. Of course, according to the computing power of all networks, the difficulty will be constantly modified.

We add the static variable difficulty in the NoobChain class.

public static int difficulty = 5;

In this way, we must modify the main method so that the mineBlock() method must be triggered when each new block is created, and the isChainValid() method is used to check whether the hash value of each block is correct and whether the entire block chain 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 to see how it affects the time spent on data problems

If someone maliciously tampered with data in your blockchain system:

  • Their blockchain is invalid.
  • They cannot create longer blockchains
  • An honest blockchain in the network will have more time advantage in long chains

Because tampered blockchains won't be able to keep up with long and valid chains unless they have greater computational speed than all the nodes in your network, maybe a future quantum computer or something.

You have completed your basic blockchain!

Original: 150 lines of java code let you thoroughly understand what the blockchain is

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325474358&siteId=291194637