Toggle Theme Editor
Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Charcoal

Hot! Lập Trình Blockchain Phần Với Ngôn Ngữ Lập Trình Java

Discussion in 'Xây dựng các ứng dụng Java khác, các vấn đề khác' started by ThanhNhan, 18/6/18.

  1. ThanhNhan

    ThanhNhan Active Member

    blockchain là công nghệ đang hot và sẽ được ứng dụng nhiều, anh em tham khảo nhé, cái này copy thôi :D

    Ngôn ngữ lập trình Java
    Trong hướng dẫn này, nhiệm vụ chính sẽ là:

    • Tạo 'blockchain' cơ bản (rất) cơ bản.
    • Thực hiện một proof of work đơn giản (khai thác hệ thống).
    • Tìm hiểu những khả năng của blockchain.
    (Với điều kiện 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 blockchain được tạo trong bài viết này chỉ đơn thuần giúp làm rõ các khái niệm và giúp bạn đọc hiểu thêm về blockchain.

    Cài đặt
    Bài viết sẽ sử dụng Java nhưng bạn sẽ có thể làm tương tự trong bất kỳ ngôn ngữ OOP nào. Bài viết sẽ sử dụng Eclipse nhưng bạn cũng có thể sử dụng bất kỳ trình soạn thảo văn bản ưa thích mới nào.

    Bạn sẽ cần:

    • Java và JDK.(duh) đã được cài đặt
    • Eclipse (hoặc một IDE/Trình soạn thảo văn bản khác).
    Tuy nhiên, bạn có thể dùng thư viện GSON của google. Điều này sẽ cho phép bạn biến một đối tượng thành Json \o/. Đó là một thư viện cực kỳ hữu ích mà sẽ tiếp tục được sử dụng như các công cụ tương tự khác. Nếu không muốn, bạn vui lòng sử dụng một phương pháp thay thế.

    Trong Eclipse, tạo một dự án Java (file> new>). Giả sử đặt tên dự án là “noobchain” và tạo một Class mới cùng tên (NoobChain).

    [​IMG]

    Bây giờ bạn đã sẵn sàng để tạo blockchain rồi!

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

    [​IMG]

    Hash = Digital Signature

    Mỗi khối không chỉ chứa hàm hash của khối trước đó, mà còn chứa hash của chính nó (được tính từ giá trị previous hash). Nếu dữ liệu của khối trước đó bị thay đổi thì giá trị hash của khối trước đó sẽ thay đổi (vì nó được tính toán một phần bởi dữ liệu) và sẽ ả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 ta biết liệu một blockchain có hợp lệ hay không.

    Điều đó có nghĩa là, thay đổi bất kỳ dữ liệu nào trong danh sách này, sẽ thay đổi chữ ký số và phá vỡ chuỗi.

    Vì vậy, Firsts cho phép tạo ra lớp Block tạo nên blockchain:
    PHP:
    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();
    }
    }
    Như bạn thấy, Block cơ bản chứa một String hash (giữ chữ ký số). Biến previousHashchứa dữ liệu hash và chuỗi của khối trước đó để giữ dữ liệu khối.

    Tiếp theo chúng ta sẽ cần tìm cách để tạo chữ ký số.

    Có rất nhiều thuật toán mã hóa mà bạn có thể chọn, tuy nhiên SHA256 là phù hợp nhất với ví dụ này. Chúng ta có thể nhập
    PHP:
    java.security.MessageDigest
    để truy cập thuật toán SHA256.

    Cần sử dụng SHA256 sau đó xuống dòng để cho phép tạo ra một phương thức trợ giúp tiện dụng trong một lớp 'tiện ích' StringUtil mới:
    PHP:
    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 0hash.lengthi++) {
    String hex Integer.toHexString(0xff hash[i]);
    if(
    hex.length() == 1hexString.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à nó lấy một chuỗi và áp dụng thuật toán SHA256, rồi trả về chữ ký được tạo ra dưới dạng một chuỗi.

    Bây giờ hãy sử dụng applySha256 helper, tại một phương thức mới trong lớp Block, để tính toán giá trị hash. Cần phải tính toán hash từ tất cả các phần của khối. Vì vậy, khối này sẽ bao gồm previousHash, datatimeStamp:
    PHP:
    public String calculateHash() {
    String calculatedhash StringUtil.applySha256(
    previousHash +
    Long.toString(timeStamp) +
    data
    );
    return 
    calculatedhash;
    }
    cũng như cho phép thêm phương thức này vào Block constructor:
    PHP:
    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.
    }
    Một số thử nghiệm
    Lớp NoobChain chính cho phép tạo ra một số khối và xuất các hash ra màn hình để thấy rằng mọi thứ đang hoạt động tốt.

    Khối đầu tiên được gọi là khối genesis, và bởi vì không có khối trước đó nên chúng ta sẽ chỉ nhập “0” làm previous hash.

    PHP:
    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);
    }
    }
    Kết quả sẽ trông giống như sau:

    [​IMG]

    Mỗi khối bây giờ có chữ ký số của riêng nó dựa trên thông tin và chữ ký của khối trước đó.

    Hiện tại, blockchain không có nhiều khối, vì vậy hãy lưu trữ các khối trong ArrayList và cũng nhập gson để coi nó như là Json.
    PHP:
    import java.util.ArrayList;
    import com.google.gson.GsonBuilder;
    public class 
    NoobChain {
    public static 
    ArrayList<Blockblockchain = 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);
    }
    }
    Bây giờ, kết quả hiển thị sẽ giống với những gì chúng ta mong đợi ở một blockchain.

    Tiếp theo, hãy tìm cách để kiểm tra tính toàn vẹn của blockchain.

    Tạo phương thức Boolean isChainValid() trong lớp NoobChain. Nó sẽ lặp qua tất cả các khối trong chuỗi và so sánh các hash. Phương pháp này sẽ cần phải kiểm tra biến hash thực tế có bằng với hash được tính toán và hash của khối trước có bằng với biến previousHash không.
    PHP:
    public static Boolean isChainValid() {
    Block currentBlock;
    Block previousBlock;
    //loop through blockchain to check hashes:
    for(int i=1blockchain.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;
    }
    Mọi thay đổi đối với các khối của blockchain sẽ khiến phương thức này trả về false.

    Các nút mạng bitcoin chia sẻ blockchain của chúng và chuỗi dài nhất hợp lệ sẽ được mạng chấp nhận. Vậy điều gì ngăn chặn ai đó giả mạo dữ liệu trong một khối cũ sau đó tạo ra một blockchain hoàn toàn mới? Proof of work (bằng chứng hoạt động). Hệ thống Proof of work Hashcash proof of work có nghĩa là phải mất nhiều thời gian và công sức tính toán để tạo ra các khối mới. Do đó kẻ tấn công sẽ tốn nhiều công sức tính toán khi kết hợp các khối.

    Khai thác các khối
    Bạn sẽ phải yêu cầu miner (người đào) thực hiện proof-of-work bằng cách thử các giá trị biến khác nhau trong khối cho đến khi giá trị hash bắt đầu bằng một số xác định, bắt đầu từ 0.

    Hãy thêm một int, gọi là nonce vào phương thức calculateHash() và phương thức mineBlock():

    PHP:
    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.substring0difficulty).equals(target)) {
    nonce ++;
    hash calculateHash();
    }
    System.out.println("Block Mined!!! : " hash);
    }
    }
    Trong thực tế mỗi miner sẽ bắt đầu lặp lại từ một điểm ngẫu nhiên, một số miner có thể thử số ngẫu nhiên cho nonce. Những giải pháp khó hơn sẽ yêu cầu integer.MAX_VALUE nhiều hơn, miner lúc này có thể thử thay đổi timestamp.

    Phương thức mineBlock() chứa int được đặt tên là difficulty, đây là số lượng số bắt đầu từ 0 mà chúng phải giải quyết. Độ khó thấp như 1 hoặc 2 có thể được giải quyết gần như ngay lập tức trên hầu hết các máy tính, nên hãy nâng lên mức khoảng 4-6 để thử nghiệm. Tại thời điểm bài viết, độ khó Litecoin là khoảng 442.592.

    Giờ ta thêm độ khó làm biến tĩnh vào lớp NoobChain:

    public static int difficulty = 5;
    Nên cập nhật lớp NoobChain để kích hoạt phương thức mineBlock() cho mỗi khối mới. Các Boolean isChainValid() cũng kiểm tra xem mỗi khối có một hash đã được giải quyết (bằng cách đào) hay không.
    PHP:
    import java.util.ArrayList;
    import com.google.gson.GsonBuilder;
    public class 
    NoobChain {
    public static 
    ArrayList<Blockblockchain = 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=1blockchain.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.substring0difficulty).equals(hashTarget)) {
    System.out.println("This block hasn't been mined");
    return 
    false;
    }
    }
    return 
    true;
    }
    }
    Kết quả hiển thị sẽ như sau:

    [​IMG]

    Đào mỗi khối sẽ mất một chút thời gian! (khoảng 3 giây). Bạn nên thử thay đổi các giá trị độ khó khác nhau để xem nó ảnh hưởng đến thời gian cần thiết để đào mỗi khối như thế nào.

    Nếu ai đó giả mạo dữ liệu trong hệ thống blockchain:

    • Blockchain sẽ không hợp lệ
    • Sẽ không thể tạo ra một blockchain dài hơn.
    • Các blockchain trung thực trong mạng sẽ có lợi thế về thời gian trong chuỗi dài nhất.
    Một blockchain giả mạo sẽ không thể bắt kịp chuỗi dài hơn và hợp lệ, trừ khi chúng có tốc độ tính toán lớn hơn tất cả các nút khác trong mạng kết hợp lại (có thể bằng một máy tính lượng tử trong tương lai hay gì đó).

    Blockchain cơ bản đã hoàn tất rồi! Hãy ghi nhớ những điều sau về Blockchain của bạn:

    • Được tạo thành từ các khối lưu trữ dữ liệu.
    • Có một chữ ký số kết nối các khối của bạn với nhau.
    • Yêu cầu bằng chứng proof of work để xác nhận các khối mới.
    • Có thể kiểm tra xem dữ liệu trong đó có hợp lệ và có bị thay đổi không.

    Nguồn: quantrimang.com
     
    D.A.N_3002 likes this.
  2. D.A.N_3002

    D.A.N_3002 Active Member

    WOW :) Giờ mới biết rằng Java cũng có thể làm công nghệ Blockchain :) Cảm ơn bạn đã chia sẻ :))
     
  3. JackV

    JackV Administrator Staff Member

    Mình không quan tâm tiền kỹ thuật số nên cũng chưa tìm hiểu nó là gì, nghe sơ sơ trên tivi thì nó là dạng tạo ra khối dữ liệu mang theo chữ ký số, ngày trước ta thấy dạng mã hóa Private & Public keys rồi, cái này không biết nó giống hay không, nghe bảo ví dụ như là nếu khách hàng chọn các report của mình rồi thì khi admin nhận được sẽ biết chính xác đó là report nguyên gốc hay không.
     

Chia sẻ trang này

Loading...