Phần 2: Tạo công nghệ đào tiền ảo

Sơ hở của Blockchain hiện tại

Tiếp nối phần một, ta đã tìm hiểu về công nghệ Blockchain, về tính phân tán và minh bạch của nó.

Ta cũng thấy là công nghệ vừa tạo ra có nhược điểm là rất dễ bị hack. Bởi vì ta có được giao dịch cuối cùng trong chuỗi, thì lần theo dấu vết lần lượt các Hash của từng phần tử, ta sẽ xâu chuỗi lại được toàn bộ mảng Blockchain. Việc chỉnh sửa bằng cách tính toán lại toàn bộ Hash cho khớp và đồng bộ lúc này chỉ cần vài động tác và data sẽ nghiễm nhiên là toàn vẹn ở tất cả các máy trong mạng ngang hàng.

Có bạn sẽ bảo là có thuật toán để check MangBlock ở máy mình và MangBlock được tải về từ mạng P2P để xem sự khác nhau trước khi đồng bộ. Đúng là có thuật toán đó. Nhưng thuật toán này lại ưu tiên mảng nào “dài hơn” lại là mảng được cân nhắc là mảng đúng. Do đó nó không đủ mạnh để giải quyết vấn nạn hack.

Có một cách hay hơn để ngăn chặn việc này. Đó là giới hạn thời gian Hash được một Blockchain. Ta phải tăng độ khó của thuật toán Hash lên để Hash được một chuỗi sẽ cần rất nhiều thời gian. Điều này cũng có nghĩa là phải sau một thời gian nhất định mới có thể thêm mới 1 Block vào hệ thống. Ví dụ đồng tiền BitCoin thì quy định, sau mỗi 10 phút mới cho phép một bản ghi mới được thêm vào.

Làm điều này để làm gì?

1) Ngăn chặn hệ thống Blockchain bị SPAM, liên tục có người thêm mới giao dịch giả vào hệ thống. Dẫn đến 
Blockchain bị DDOS, và có thể sập. Dữ liệu thật thì bị lấy đi.

2) Ngăn chặn việc làm giả hệ thống, vì thời gian hacker Hash được 100 bản ghi sẽ bằng 100x10 phút = 1000 
phút. Do đó hắn sẽ không dễ dàng clone toàn bộ hệ thống và Hash ra mã mới.

Khi một người dùng muốn thêm mới một bản ghi vào hệ thống, người đó phải chứng tỏ mình thực sự muốn giao dịch. Và để chứng minh điều đó anh ta cần bỏ tài nguyên của máy ra để tính toán Hash, và sau một thời gian nhất định, anh ta sẽ đăng ký thành công bản ghi nối tiếp (chain) vào Blockchain. Quá trình này người ta gọi là Proof-Of-Work.

Proof of Work

Ta hãy thử minh họa bằng cách sửa đổi file Class Block như sau:

/*=== ĐÂY LÀ CLASS MÔ TẢ CẤU TRÚC CỦA MỘT BLOCK. MỘT PHẦN TỬ CỦA BLOCKCHAIN ===*/ 
class Block { 
    constructor(NgayGioTao, DuLieu, HashTruocDo = '') { //Để tạo ra một Block chúng ta cần truyền vào các tham số như sau: 
    this.NgayGioTao = NgayGioTao; //Ngày tháng hiện tại tạo ra Block này
    this.DuLieu = DuLieu; //Dữ liệu sẽ được lưu trong BLock này. Nó có thể là bất cứ cái gì, từ String, Array, Object JSON... 
    this.HashTruocDo = HashTruocDo; //Lưu trữ Hash của Block ngay trước Block này. Vì các Block sẽ được nối lại thành chuỗi (mảng). 
    this.Hash = this.TinhToanHash(); //Mã hóa toàn bộ nội dung của BLock này theo thuật toán SHA256 và lưu lại vào chính Block này.
    this.GiaTriTuTang = 0; //THÊM VÀO Giá trị tự tăng của Block  
 } 
 TinhToanHash() { //Hàm mã hóa nội dung của toàn bộ Block. Do đó ta cần lấy toàn bộ các thuộc tính của Block đưa vào SHA256 để mã hóa ra một chuỗi. 
     return CryptoJS.SHA256(this.HashTruocDo + this.NgayTao + JSON.stringify(this.DuLieu) + this.GiaTriTuTang) //Chỗ này có thêm GiaTriTuTang .toString(); //chú ý: JSON.stringify(this.DuLieu) sẽ convert biến Object this.DuLieu thành chuỗi 
 } 

//thay đổi hàm TaoBlock thành hàm DaoBlock 
 DaoBlock(DoKho) { 
     while (this.Hash.substring(0, DoKho) !== Array(DoKho + 1).join("0")) { //Kiểm tra xem giá trị Hash hiện tại đã đạt đủ số 0 ở đầu tiên như yêu vầu về độ khó đặt ra chưa. Lặp đi lặp lại hàm cho đến khi tìm được giá trị Hash đáp ứng yêu cầu.
        this.GiaTriTuTang++; //Tăng giá trị trong Block lên, để Hash mỗi lần sẽ nhận được một giá trị khác nhau. Nếu Hash không có 2 hoặc n số 0 ở đầu thì sẽ không đạt yêu cầu và phải tiếp tục Hash cái khác. 
        this.Hash = this.TinhToanHash(); //Tính toán lại Hash của toàn bộ Block ứng với lần tăng này. 
     } 
     console.log("Đã đào xong Block: " + this.Hash); //Nếu đã tìm được Hash thì ta coi đấy là một lần "đào" (hashing) thành công.
   } 
}

Trong class Block ta thêm vào một GiaTriTuTang, đây là một biến được dùng khi tính toán Hash.

Vì ta cần phải tăng độ khó mỗi khi Hash, hàm TinhToanHash vẫn không đổi, tuy nhiên ta tạo ra một thuật toán đơn giản, đó là không chấp nhận mã Hash tạo ra không đáp ứng yêu cầu. Yêu cầu của ta ở đây là mã Hash phải bắt đầu bằng 2 hoặc 3 hoặc 4 thậm chí 5 số “0” liên tiếp ở đầu.

Vì thuật toán SHA256 không bao giờ thay đổi đầu ra đối với 1 chuỗi đầu vào, bắt buộc phải thay đổi chuỗi đầu vào để tìm ra được Hash ở đầu ra thỏa mãn.

Do đó ta viết một hàm gọi là DaoBlock để lặp đi lặp lại quá trình “đào” cái mã Hash cho Block hiện tại. Và việc đào này có độ khó phụ thuộc vào biến DoKho. Nếu tăng số chữ số 0 liên tiếp lên thì cần lặp khá lâu mới tìm được chuỗi Hash ưng ý.

Giờ ta sửa lại class Blockchain để đưa thuật toán “Đào’ Block vào:

/*=== ĐÂY LÀ CLASS MÔ TẢ CẤU TRÚC CỦA MỘT BLOCKCHAIN. LÀ MỘT MẢNG CÁC BLOCK ===*/ 
class Blockchain { 
      constructor() { //Cấu trúc của Blockchain như sau
          this.MangBlock = []; //Tạo ra một mảng rỗng để chứa các Block.  
          this.MangBlock.push(new Block("01/01/2018", "Genesis Block", "0")); //Tạo phần tử đầu tiên của Blockchain. Đây thường được gọi là Genesis Block, hay chính là "phần tử khởi tạo". Các phần tử tiếp theo sẽ nối tiếp vào phần tử này. 
         this.DoKho = 5; //Thêm độ khó cho Blockchain; 
 } 

 PhanTuCuoiCung() { 
     return this.MangBlock[this.MangBlock.length - 1]; //Lấy ra phần tử cuối cùng của Blockchain 
 } 

 TaoMoiBlock(newBlock) { //Hàm dùng để thêm mới một Block vào Blockchain. 
    newBlock.HashTruocDo = this.PhanTuCuoiCung().Hash; //Lấy Hash của phần tử cuối cùng của mảng và lưu vào HasTruocDo của phần tử này //newBlock.Hash = newBlock.TinhToanHash(); //Lúc này ta không tính toán Hash đơn thuần nữa mà phải "đào" thì mới có Hash cho Block mới. 
    newBlock.DaoBlock(this.DoKho); 
    this.MangBlock.push(newBlock); //Nối phần tử newBlock vào làm phần tử cuối cùng của mảng Blockchain sau khi đã "đào" được. 
 } 

 KiemTraTinhToanVen() { 
     for (let i = 1; i < this.MangBlock.length; i++) { 
         const BlockHienTai = this.MangBlock[i]; //Lấy ra phần tử ở vị trí hiện tại 
         const BlockTruocDo = this.MangBlock[i - 1]; //Lấy ra phần tử ở ngay trước vị trí hiện tại 
         if (BlockHienTai.Hash !== BlockHienTai.TinhToanHash()) { //Kiểm tra lại Hash của toàn bộ Block hiện tại và Hash đã lưu xem có trùng nhau không. 
             return false; //Nếu không trùng tức là Dữ liệu trong Block hiện tạiđã bị chỉnh sửa, hàm KiemTraToanVen sẽ trả về false luôn. 
         } 
         if (BlockHienTai.HashTruocDo !== BlockTruocDo.Hash) { //Lấy Hash hiện tại và Hash phần tử trước đó đã lưu xem có trùng nhau không. 
            return false; //Nếu không trùng tức là Hash của Block hiện tại đã bị chỉnh sửa, hàm KiemTraToanVen sẽ trả về false luôn.
         } 
     } 
     return true; //Nếu kiểm tra hết toàn bộ trong vòng For mà không vấn đề gì thì tức là Blockchain vẫn toàn vẹn, chưa bị sửa đổi. 
  } 
}

Ta cần tạo một biến this.DoKho trong Blockchain. Sau đó ta gọi newBlock.DaoBlock(this.DoKho); để mỗi khi tạo mới Block, ta phải đào mới có mã Hash cho nó.

Blockchain không thể sống thiếu Cryptocurrency và Cryptocurrency cũng không thể sống mà không có Blockchain, như thể sinh ra đã là của nhau vậy. Blockchain nếu không có quá trình đào tiền ảo bằng các thuật toán Proof-Of-Work thì sẽ không có gì hấp dẫn người dùng, và quá ít người dùng trong hệ thống cùng đào sẽ dẫn đến 1 Hacker có máy tính đủ mạnh có thể đánh bại tất cả. Do đó một công ty nào đó muốn sử dụng Blockchain để làm cơ sở dữ liệu lưu trữ, họ phải liên tục tạo ra sự cạnh tranh và sự hấp dẫn cho những người tham gia xây dựng CSDL Blockchain đó.

Tuy nhiên nhiều đồng tiền ảo hiện nay đã có sự lo ngại là đến một giai đoạn thoái trào, phong trào đào tiền ảo sẽ nguội bớt, và người ta không cắm máy để đào nữa vì phần thưởng ít dần. Lúc này Proof-Of-Work không còn là liều thuốc mạnh. Người ta đang thay thế bằng một thứ mới, đó là Proof-Of-Stake.

Kết luận

Như vậy ta đã áp dụng thành công thuật toán ĐÀO cho Blockchain của mình. Tuy nhiên đây không phải Đào BitCoin mà chỉ là Đào BLock.

Để có thể ứng dụng Blockchain này và tạo ra một đồng tiền ảo BitCoin của riêng mình, ta cần phải tạo ra được “Phần Thưởng” cho người đào Hash. Đó chính là tiền ảo, một dạng tiền thưởng cho người bỏ công ra đào Hash.

Vì mã Hash là giới hạn bởi độ dài số ký tự. Do đó đến một lúc nào đó sẽ không còn tìm được mã Hash nào thỏa mãn yêu cầu đặt ra nữa. Đó chính là điểm mấu chốt tạo ra giá trị của đồng tiền ảo. Người nào bỏ công ra tìm Hash, sẽ nhận được Tiền ảo. Và chúng ta cũng sẽ tạo ra một Ví tiền ảo để có thể gửi và nhận BitCoin sau khi đã đào xong.

Để tự mình tạo ra một đồng tiền ảo của riêng mình, sử dụng HTML và Javascript, mời các bạn đón đọc phần 3 của Series này nhé.

Ghi chú: Các thuật ngữ chuyên ngành tiếng Anh các bạn có thể biết để tham khảo và đọc tài liệu cho rõ hơn như sau:

  • DaoBlock trong blockchain thì hàm này thường có tên là Mining hoặc MineBlock
  • GiaTriTuTang trong blockchain thì biến này thường có tên là nonce
  • NgayGioTao trong blockchain thì biến này thường có tên là timestamp
  • KiemTraTinhToanVen trong blockchain thì hàm này thường có tên là Validate hoặc Accept

 

Leave a reply:

Your email address will not be published.

Site Footer