Tạo 1 blockchain với Java (Part 1)

Mục đích của loạt bài hướng dẫn này là giúp bạn xây dựng một bức tranh về cách mà người ta có thể phát triển công nghệ blockchain.

Trong bài hướng dẫn này, chúng ta sẽ:

  • Tạo "blockchain" cơ bản đầu tiên của bạn

(Tôi sẽ giả sử bạn có một sự hiểu biết cơ bản về lập trình hướng đối tượng 😄)

Cần lưu ý rằng đây không phải là một dây chuyền sản xuất hoàn chỉnh, sẵn sàng cho production block chain. Thay vào đó, bài viết giúp bạn hiểu sơ lược blockchain là gì cho các hướng dẫn trong tương lai.

1. Chuẩn bị

Chúng ta sẽ sử dụng Java và Eclipse, hãy cài đặt Java(Java và JDK) và eclipse(hoặc bất kì IDE nào bạn cảm thấy quen thuộc) nếu bạn chưa sẵn sàng.

Chúng ta sẽ tạo 1 java project mới

2. Tạo ra blockchain

Một blockchain chỉ là một chuỗi / danh sách các khối. Mỗi khối trong blockchain sẽ có chữ ký số riêng của nó, chứa chữ ký số của khối trước và có một số dữ liệu (dữ liệu này có thể là các giao dịch chẳng hạn).

Hash = Digital Signature.

Mỗi khối không chỉ chứa hash của khối phía trước của nó, mà hash của khối đó còn được tính toán từ hash của khối phía trước. Nếu dữ liệu của khối dữ liệu trước đó được thay đổi thì hash của nó cũng sẽ thay đổi (vì nó được tính toán một phần theo dữ liệu) lần lượt ảnh hưởng đến tất cả các hash của các khối sau đó. Tính toán và so sánh các hash cho phép chúng ta xem nếu một blockchain là không hợp lệ.

Nào, cùng tạo đối tượng block, cái mà tạo ra blockchain

package vutachain;

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.

	public Block(String data, String previousHash) {
		this.data = data;
		this.previousHash = previousHash;
		this.timeStamp = new Date().getTime();
	}
}

Như bạn có thể thấy Block chứa một String hash sẽ giữ chữ ký số của block hiện tại. Biến previousHash để giữ hash của block trước đó và String data để giữ dữ liệu.

Tiếp theo cúng ta sẽ cần một cách để sinh ra chữ ký số (Digital signature)

Có rất nhiều thuật toán mã hóa bạn có thể lựa chọn, tuy nhiên SHA256 phù hợp tốt cho ví dụ này. Chúng ta có thể import java.security.MessageDigest; để có được quyền truy cập vào thuật toán SHA256.

Hãy tạo 1 class helper như sau

package vutachain;

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

Đừng lo lắng quá nhiều nếu bạn không hiểu nội dung của phương thức trợ giúp này, tất cả những gì bạn cần biết là đưa vào một string và áp dụng thuật toán SHA256 vào nó, và trả về chữ ký đã tạo là một string.

Bây giờ hãy sử dụng helper applySha256 của chúng ta, trong một phương thức mới trong lớp Block, để tính toán hash. Chúng ta phải tính toán hash từ tất cả các phần của khối mà chúng ta không muốn bị giả mạo. Vì vậy, hãy sử dụng đến previousHash, data và timeStamp.

public String calculateHash() {
		String calculatedhash = StringUtil.applySha256(previousHash + Long.toString(timeStamp) + data);
		return calculatedhash;
	}

và thêm phương thức tính hash đó vào constructor của class 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.
	}

Đến lúc test blockchain của chúng ta

Hãy cùng tạo 1 class chứa main method như sau và run

package vutachain;

public class VutaChain {

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

}

Kết quả như sau: Hash for block 1 : 54a132cabb5511cd43a81edae602467ecf490b22f7fa6fdf6a6745992c4e0097 Hash for block 2 : 7a958f8e988a50dcb88e798713ed7acb7959b19c08e42f8be1c8df98ae6ea75b Hash for block 3 : cefe2659cab699b1421ecdb5c1f85f56ea1668c6fef5e684700dc432ff3a5f77

Mỗi khối bây giờ có chữ ký số của riêng mình dựa trên thông tin của nó và chữ ký của khối trước đó Bây giờ cùng lưu các block của chúng ta vào 1 ArrayList và import gson để view nó dưới dạng Json

GSON là gì? Gson là 1 thư viện Java được tạo bởi google cho phép bạn có thể get 1 thể hiện JSON của Java Object.

Bạn có thể download thư viện này tại “gson-2.6.2.jar” và import vào eclipse như sau. Trong Eclipse mở Windows >preferences trên menu, chọn Java >Build path > User Libraries tab. Click new và nhập tên mới cho User Library: như “gson_lib” và click ok. Với “gson_lib” được chọn và click Add External JARs sau đó chọn đến file gson-2.6.2.jar bạn vừa download. Click Apply và Close. Right click your package in package explorer > Build path > Add Libraries. Chọn User libraries sau đó click next, giờ chỉ cần tick “gson_lib” và finish thế là xong.

Hãy cùng thay đổi class vừa tạo ở trên như sau và run

package vutachain;

import java.util.ArrayList;
import com.google.gson.GsonBuilder;

public class VutaChain {

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

}

Wow kết quả nhìn cũng ngon phải ko 😄? [ { "hash": "4a80241416aa0968a659f9e7998655e5e65f07da5f9e8ae75f93083f0bf3e2d7", "previousHash": "0", "data": "Hi im the first block", "timeStamp": 1517649052109 }, { "hash": "a3a9d837d91d2df9e86ac2c9e3f97f840db36bdf52d179bc0e6861d812f9d439", "previousHash": "4a80241416aa0968a659f9e7998655e5e65f07da5f9e8ae75f93083f0bf3e2d7", "data": "Yo im the second block", "timeStamp": 1517649052126 }, { "hash": "c97afb784558a3d664129de17a099b41c447ecd1776b5f9b2e5922d2ec11ca1b", "previousHash": "a3a9d837d91d2df9e86ac2c9e3f97f840db36bdf52d179bc0e6861d812f9d439", "data": "Hey im the third block", "timeStamp": 1517649052126 } ]

Bây giờ chúng ta cần một cách để kiểm tra tính toàn vẹn của blockchain.

Hãy tạo isChainValid() Boolean method, nó sẽ lặp qua tất cả các block trong chuỗi và so sánh tất cả các hash. Phương thức này sẽ cần thiết để kiểm tra tính toàn vẹn của blockchain

public static Boolean isChainValid() {
		Block currentBlock;
		Block previousBlock;

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

Vậy là sau bài này bạn đã có 1 blockchain đơn sơ nhất 😄, hẹn gặp lại trong bài tiếp theo.