PHP從零實(shí)現(xiàn)區(qū)塊鏈(一)基本原型

前言

學(xué)習(xí)區(qū)塊鏈有些時(shí)間了,根據(jù)大佬的文章用Go也實(shí)現(xiàn)了一遍,但作用一名web碼農(nóng),平時(shí)用的最多的還是PHP,所以打算用PHP再搞一搞,當(dāng)是復(fù)習(xí)了。本教程基于LaravelZero(因?yàn)闃?gòu)建命令行省事兒)簡單構(gòu)建一個(gè)屬于你的區(qū)塊鏈,如果你有一些區(qū)塊鏈的前置知識那就最好不過啦。

參考文章:

初始化

  1. 根據(jù) LaravelZero 文檔,先創(chuàng)建一個(gè)項(xiàng)目,確保能順利跑起來。
  2. 在app目錄下創(chuàng)建 Services 文件夾,咱們的代碼都寫在這里面。

區(qū)塊鏈?zhǔn)鞘裁?/h1>

簡單來說,區(qū)塊鏈?zhǔn)且粋€(gè)提供了拜占庭容錯、并保證了最終一致性的分布式數(shù)據(jù)庫;從數(shù)據(jù)結(jié)構(gòu)上看,它是基于時(shí)間序列的鏈?zhǔn)綌?shù)據(jù)塊結(jié)構(gòu);從節(jié)點(diǎn)拓?fù)渖峡矗械墓?jié)點(diǎn)互為冗余備份;從操作上看,它提供了基于密碼學(xué)的公私鑰管理體系來管理賬戶。

組成區(qū)塊鏈的核心技術(shù)主要有

  1. P2P 網(wǎng)絡(luò)協(xié)議
  2. 分布式一致性算法
  3. 加密簽名算法
  4. 賬戶與存儲模型

在本文中,我們將利用數(shù)組來存儲區(qū)塊,來實(shí)現(xiàn)區(qū)塊鏈的基本原型。

區(qū)塊

在區(qū)塊鏈中,真正存儲有效信息的是區(qū)塊(block)。

那就創(chuàng)建一個(gè)區(qū)塊,在 App/Services 目錄新建一個(gè) Block.php。

<?php

namespace App\Services;

use Carbon\Carbon;

class Block
{
    /**
     * 當(dāng)前時(shí)間戳,也就是區(qū)塊創(chuàng)建的時(shí)間
     * @var int $timestamp
     */
    public $timestamp;

    /**
     * 區(qū)塊存儲的信息,也就是交易
     * @var string $data
     */
    public $data;

    /**
     * 前一個(gè)塊的哈希,即父哈希
     * @var string $prevBlockHash
     */
    public $prevBlockHash;

    /**
     * 當(dāng)前塊的哈希 
     * @var string $hash
     */
    public $hash;
}

在比特幣中,區(qū)塊的結(jié)構(gòu)主要有如下信息:

Field Purpose Size(Bytes)
Block Size 區(qū)塊大小 4
Block Header 區(qū)塊頭 80
Transaction Counter 交易計(jì)數(shù)器 1~9
Transactions 交易 -

區(qū)塊頭的主要結(jié)構(gòu):

字段 描述 大小
Version Block version number 4
hashPrevBlock 256-bit hash of the previous block header 32
hashMerkleRoot 256-bit hash based on all of the transactions in the block 32
Time Current timestamp as seconds since 1970-01-01T00:00 UTC 4
Bits Current target in compact format 4
Nonce 32-bit number (starts at 0) 4

其中交易(Transactions)也就是我們創(chuàng)建的 data 字段;而其他字段(prevBlockHash,timestamp)在比特幣中由專門的數(shù)據(jù)結(jié)構(gòu),即區(qū)塊頭存儲;另外為了方便,我們還加上了當(dāng)前塊的 hash 字段,在比特幣中是沒有直接存儲當(dāng)前塊的哈希的。

為了方便,我們就不單獨(dú)實(shí)現(xiàn)區(qū)塊頭了,而是所有數(shù)據(jù)都放在一起,這樣我們就創(chuàng)建了一個(gè)簡單的區(qū)塊。

下面我們來完善區(qū)塊的創(chuàng)建:
Block.php


    public function __construct(string $data, string $prevBlockHash)
    {
        $this->prevBlockHash = $prevBlockHash;
        $this->data = $data;
        $this->timestamp = time();
        $this->hash = $this->setHash();
    }

    public function setHash(): string
    {
        return hash('sha256', implode('', [$this->timestamp, $this->prevBlockHash, $this->data]));
    }

區(qū)塊鏈

本質(zhì)上,區(qū)塊鏈就是一個(gè)有著特定結(jié)構(gòu)的數(shù)據(jù)庫,是一個(gè)有序,每一個(gè)塊都連接到前一個(gè)塊的鏈表。也就是說,區(qū)塊按照插入的順序進(jìn)行存儲,每個(gè)塊都與前一個(gè)塊相連。這樣的結(jié)構(gòu),能夠讓我們快速地獲取鏈上的最新塊,并且高效地通過哈希來檢索一個(gè)塊。

有了區(qū)塊,下面讓我們來實(shí)現(xiàn)區(qū)塊鏈。在基本原型階段,我們用數(shù)組來存放區(qū)塊結(jié)構(gòu)。新建一個(gè)文件 BlockChain.php

<?php
namespace App\Services;

class BlockChain
{
    /**
     * @var Block[] $blocks
     */
    public $blocks;

    public function __construct(Block $block)
    {
        $this->blocks[] = $block;
    }

    // 加入一個(gè)塊到區(qū)塊鏈中
    public function addBlock(string $data)
    {
        $prevBlock = $this->blocks[count($this->blocks) - 1];
        $newBlock = new Block($data, $prevBlock->hash);
        $this->blocks[] = $newBlock;
    }
}

addBlock() 方法使我們有了向鏈中添加區(qū)塊的能力,但是還沒完,在添加區(qū)塊以前,區(qū)塊鏈中應(yīng)該存在一個(gè)創(chuàng)世區(qū)塊。

    // 初始化創(chuàng)世區(qū)塊
    public static function NewGenesisBlock()
    {
        $block = new Block('Genesis Block', '');

        return new BlockChain($block);
    }

大功告成,下面讓我們來測試一下!

$bc = BlockChain::NewGenesisBlock();
$bc->addBlock('i am 2 block');
$bc->addBlock('i am 3 block');
dd($bc->blocks);

結(jié)果如下:

array:3 [
  0 => App\Services\Block {#155
    +timestamp: 1587700797
    +data: "Genesis Block"
    +prevBlockHash: ""
    +hash: "e0ecf169c2ea5143743438fd91778ca6cdff1c870120c784f836650cfaaaff38"
  }
  1 => App\Services\Block {#153
    +timestamp: 1587700797
    +data: "i am 2 block"
    +prevBlockHash: "e0ecf169c2ea5143743438fd91778ca6cdff1c870120c784f836650cfaaaff38"
    +hash: "c33a37e9708a2871c6b03fd2f6468081edb4e96d911c7227ad84271d9c4f8b6d"
  }
  2 => App\Services\Block {#160
    +timestamp: 1587700797
    +data: "i am 3 block"
    +prevBlockHash: "c33a37e9708a2871c6b03fd2f6468081edb4e96d911c7227ad84271d9c4f8b6d"
    +hash: "de300a998179bfeeb3ea60be3f49e205f8552b8ab9d506a76d847f0ba9d93646"
  }
]

NICE!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 8.1 簡介 挖礦是增加比特幣貨幣供應(yīng)的一個(gè)過程。挖礦同時(shí)還保護(hù)著比特幣系統(tǒng)的安全,防止欺詐交易,避免“雙重支付”...
    冉冉升起的沙丁魚閱讀 1,826評論 0 1
  • AS 有一項(xiàng)極其便利的重構(gòu)操作,稱為 Refactor | Refactor this可以進(jìn)行如下操作: 重命名類...
    菜鳥沖沖沖閱讀 642評論 0 0
  • 今天是來到長春的第四天,依舊是磨蹭到了下午1點(diǎn)多才開始收拾出門,今天的目的地是在大眾點(diǎn)評上享譽(yù)盛名的磨時(shí)光咖啡館。...
    軟小圓0720閱讀 1,228評論 0 0
  • 下午看著群里有人發(fā)了求助的信息,說的是同事的孩子生下來重度窒息,現(xiàn)在還沒脫離危險(xiǎn),可是治療需要的龐大費(fèi)用不是他們普...
    檐下閱讀 516評論 2 1
  • 夏天, 艷陽高照, 五彩繽紛, ...
    覓音少女閱讀 83評論 0 0

友情鏈接更多精彩內(nèi)容