Năm 2021 chắc hẳn là một năm bùng nổ của Blockchain, khi người người nhà nhà làm Blockchain, game NFT, Token…. Vậy nếu Blockchain được phát triển trên ngôn ngữ PHP thì sao?

Blockchain là gì?

Blockchain (hay gọi là cuốn sổ cái) là hệ thống cơ sở dữ liệu cho phép lưu trữ và truyền tải các khối thông tin (block). Chúng được liên kết với nhau nhờ mã hóa. Các khối thông tin này hoạt động độc lập và có thể mở rộng theo thời gian. Chúng được quản lý bởi những người tham gia hệ thống chứ không thông qua đơn vị trung gian. Nghĩa là khi một khối thông tin được ghi vào hệ thống Blockchain thì không có cách nào thay đổi được. Chỉ có thể bổ sung thêm khi đạt được sự đồng thuận của tất cả mọi người.

Đang xem: Lập trình blockchain php

Tạo một block

Chúng ta sẽ khởi tạo 1 class có tên là Block, Class này sẽ làm nhiệm vụ mã hóa toàn bộ dữ liệu vào thành 1 chuỗi khóa

class Block{ public $index; //index là key của 1 block public $previousHash; // đây là hash của block trước public $timeHash; // là thời gian mã hóa của block public $data; // data là của block ( nội dung transaction chẳng hạn ) public $hash; // hash của block này public function __construct($index = 0, $previousHash = “”, $timeHash = “”, $data = “”) { $this->index = $index; $this->previousHash = $previousHash; $this->timeHash = $timeHash; $this->data = $data; $this->hash = $this->execHash(); } public function execHash() { if(is_array($this->data)) { $dataContent = json_encode($this->data); } else { $dataContent = $this->data; } return hash(“sha256”, $this->index . $this->previousHash . $dataContent . $this->timeHash); }}Tiếp đến chúng ta tạo một class Blockchain

namespace AppServices;use CarbonCarbon;class BlockChain extends Block{ public $chain = array(); public function __construct() { $this->chain<> = $this->createGenesisBlock(); parent::__construct(); } public function createGenesisBlock() { return new Block(0000,”the first”, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd”, “to” => “hunghd2”, “amount”=> 3000>); } private function getLatestBlock() { return $this->chain<(count($this->chain) – 1)>; } public function addBlock($index, $timeHash, $data) { $previousHash = $this->getLatestBlock()->hash; $newBlock = new Block($index, $previousHash, $timeHash, $data); $this->chain<> = $newBlock; }}Ở đây mình sẽ tạo 1 block khi có 1 data truyền vào. Giả dụ data là 1 transaction hunghd gửi tiền cho hunghd2 thì lúc này mình sẽ tạo ra 1 Block mới. Block này là block đầu tiên thế nên index = 0 , previousHash = “the first”.

Xem thêm:

Và khi có thêm transaction hunghd2 gửi cho hunghd3 thì block tiếp theo sẽ có previousHash = mã hash của block trước đó. Từ đó cứ thêm transaction mới được thêm vào sẽ tạo ra thêm 1 block mới nối với các trước đó. Từ đó chúng ta có một blockchain cơ bản.Đây là code kết quả khi mình chạy thêm block:

public function inValidBlock() { for ($i = 1; $i count($this->chain); $i++) { $currentBlock = $this->chain<$i>; $previousBlock = $this->chain<$i - 1>; if ($currentBlock->hash !== $currentBlock->execHash()) { return false; } if ($currentBlock->previousHash !== $previousBlock->hash) { return false; } } return true; }Giờ mình sẽ thử thay đổi 1 block ( thay đổi data hoặc hash ) trong chain sẽ có kết quả như sau:

$bl = new AppServicesBlockChain();$bl->addBlock(1, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd2”, “to” => “hunghd3”, “amount”=> 4000>);$bl->addBlock(2, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd3”, “to” => “hunghd4”, “amount”=> 5000>);$bl->addBlock(3, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd4”, “to” => “hunghd”, “amount”=> 6000>);$bl->chain<2>->data = < "from" => “hunghd3”, “to” => “hunghd”, “amount” => 5000>;$bl->chain<2>->hash = $bl->chain<2>->execHash();$bl->invalid = $bl->inValidBlock();Ở đây thấy mã hash của block thứ 2 đã bị thay đổi mà block thứ 3 đã lưu lại mã hash của block thứ 2 trước khi thay đổi. Nên kết quả kiểm tra là false

*

Proof-of-work

Nhưng thực tế, hash và previousHash khi mọi người có thể thay đổi dữ liệu 1 block rồi thay previousHash và hash của các block sau là vẫn tạo được một chain hợp lệ và chúng ta cũng muốn người dùng cùng phải đồng thuận (consensus) về một lịch sử duy nhất của chain. Và proof-of-work ra đời để giải quyết vấn đề này.

Xem thêm:

Nếu bạn muốn sửa đổi 1 block trước đó, bạn sẽ phải mine lại toàn bộ các block sau nó. Nó yêu cầu quét một giá trị bắt đầu bằng một số số 0 nhất định khi được hash. Giá trị được gọi là giá trị nonce, số bit 0 đứng đầu được gọi là difficulty. Bằng cách tăng độ khó việc khai thác, đồng nghĩa rằng việc mine sẽ ngày càng khó hơn.Chúng ta có thể làm hệ thống này bằng cách tạo method mine

Giờ class Block mình sẽ code cuối cùng như này:

class Block{ public $index; public $previousHash; public $timeHash; public $data; public $hash; public $mineVar; public function __construct($index = 0, $previousHash = “”, $timeHash = “”, $data = “”) { $this->index = $index; $this->previousHash = $previousHash; $this->timeHash = $timeHash; $this->data = $data; $this->hash = $this->execHash(); $this->mineVar = 0; } public function execHash() { if(is_array($this->data)) { $dataContent = json_encode($this->data); } else { $dataContent = $this->data; } return hash(“sha256”, $this->index . $this->previousHash . $dataContent . $this->timeHash . $this->mineVar ); } public function mine($difficulty) { while (!str_starts_with($this->execHash(), str_repeat(“0”, $difficulty))) { $this->mineVar++; $this->hash = $this->execHash(); } return $this->mineVar; }}Trong class Blockchain cũng cần bổ sung code như này:

use CarbonCarbon;class BlockChain extends Block{ public $chain = array(); public $difficulty; public function __construct($difficulty) { $this->chain<> = $this->createGenesisBlock(); $this->difficulty = $difficulty; parent::__construct(); } public function createGenesisBlock() { return new Block(0000,”the first”, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd”, “to” => “hunghd2”, “amount”=> 3000>); } private function getLatestBlock() { return $this->chain<(count($this->chain) – 1)>; } public function addBlock($index, $timeHash, $data) { $previousHash = $this->getLatestBlock()->hash; $newBlock = new Block($index, $previousHash, $timeHash, $data); $newBlock->mine($this->difficulty); $this->chain<> = $newBlock; } public function inValidBlock() { for ($i = 1; $i count($this->chain); $i++) { $currentBlock = $this->chain<$i>; $previousBlock = $this->chain<$i - 1>; if ($currentBlock->hash !== $currentBlock->execHash()) { return false; } if ($currentBlock->previousHash !== $previousBlock->hash) { return false; } } return true; }}Ok!! Giờ chúng ta sẽ thử chạy xem sao

$bl = new AppServicesBlockChain(4);$bl->addBlock(1, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd2”, “to” => “hunghd3”, “amount”=> 4000>);$bl->addBlock(2, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd3”, “to” => “hunghd4”, “amount”=> 5000>);$bl->addBlock(3, Carbon::now()->format(“d/m/Y H:i:s”), <"from" => “hunghd4”, “to” => “hunghd”, “amount”=> 6000>);Kết quả chúng ta sẽ có các block có số nonce như mong muốn. Để tăng độ khó là 5 số 0 thì mình chỉ cần thay đổi difficulty = 5.

Đây là bài viết dựa trên sự tìm hiểu của cá nhân mình nên có nhiều sai sót mong được mọi người đóng góp thêm!!!

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *