天天看點

PHP 建立區塊鍊

雲栖号: https://yqh.aliyun.com 第一手的上雲資訊,不同行業精選的上雲企業案例庫,基于衆多成功案例萃取而成的最佳實踐,助力您上雲決策!

前話

提供一個思路幫助你了解區塊鍊基礎運作,文本并不是一個完整的區塊鍊,希望你能舉一反三

源碼: ar414-com/phpblock

記住

區塊鍊是一個 不可變的、有序的 被稱為塊的記錄鍊。它們可以包含交易、檔案或任何您喜歡的資料。但重要的是,他們用哈希 一起被連結在一起

需要準備什麼?

  • php5.6+

1、Block 區塊

塊是什麼樣的?

每個塊都有一個

索引

,一個

時間戳(Unix時間戳)

事務清單

, 一個

校驗(工作證明算法生成的證明)

前一個塊的哈希

block = {
    'index': 2,
    'timestamp': 1506057125,
    'transactions': [
        {
            'sender': "8527147fe1f5426f9dd545de4b27ee00",
            'recipient': "a77f5cdfa2934df3954a5c7c7da5df1f",
            'amount': 5,
        }
    ],  
    'proof': 324984774000,
    'previous_hash': "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
}           

在這一點上,一個 區塊鍊 的概念應該是明顯的 - 每個新塊都包含在其内的前一個塊的 哈希 。 這是至關重要的,因為這是 區塊鍊 不可改變的原因:如果攻擊者損壞 區塊鍊 中較早的塊,則所有後續塊将包含不正确的哈希值。

建立一個

Block

類,區塊鍊由N個區塊組成,在區塊鍊裡,價值資訊存儲在區塊之中。比如,比特币的區塊存儲交易記錄,而交易記錄是任何加密貨币的核心。除此之外,區塊裡還包含有技術資訊,比如它的版本号,目前的時間戳,以及上一個區塊的哈希(Hash)。

<?php
/**
 * Created by PhpStorm.
 * User: [email protected]
 * Date: 2020/2/2
 * Time: 18:42
 */

class Block
{
    /**
     * @var integer 索引
     */
    private $index;

    /**
     * @var integer 時間戳
     */
    private $timestamp;

    /**
     * @var array 事務清單
     */
    private $transactions;

    /**
     * @var string 上一塊的哈希值
     */
    private $previousHash;

    /**
     * @var integer 由工作證明算法生成的證明
     */
    private $proof;

    /**
     * @var string 目前塊的哈希值
     */
    private $hash;

    /**
     * 通過調用方法傳回新生成塊的哈希
     * 防止外界改動
     * @return string
     */
    public function getHash()
    {
        return $this->hash;
    }

    public function __construct($index,$timestamp,$transactions,$previousHash,$proof)
    {
        $this->index        = $index;
        $this->timestamp    = $timestamp;
        $this->transactions = $transactions;
        $this->previousHash = $previousHash;
        $this->proof        = $proof;
        $this->hash         = $this->blockHash();
    }

    /**
     * 目前塊簽名
     * @return string
     */
    private function blockHash()
    {
        //我們必須確定這個字典(區塊)是經過排序的,否則我們将會得到不一緻的哈希值
        $blockArray = [
            'index' => $this->index,
            'timestamp' => $this->timestamp,
            'transactions' => $this->transactions,
            'proof'        => $this->proof,
            'previous_hash' => $this->previousHash
        ];
        $blockString = json_encode($blockArray);
        return hash('sha256',$blockString);
    }
}           
  • index

    是目前塊的索引
  • timestamp

    是目前塊的生成時間
  • transactions

    是目前塊的交易事務清單(有多個或一個交易)
  • previousHash

    是上一個區塊的簽名哈希
  • hash

    是目前區塊的簽名哈希
  • proof

    是目前區塊的礦工工作量證明

proof

使用工作量證明(PoW)算法,來證明是如何在區塊鍊上建立或挖掘新的區塊。PoW 的目标是計算出一個符合特定條件的數字,這個數字對于所有人而言必須在計算上非常困難,但易于驗證。這是工作證明背後的核心思想。

在比特币中,工作量證明算法被稱為 Hashcash ,它和上面的問題很相似,隻不過計算難度非常大。這就是礦工們為了争奪建立區塊的權利而争相計算的問題。 通常,計算難度與目标字元串需要滿足的特定字元的數量成正比,礦工算出結果後,就會獲得一定數量的比特币獎勵(通過交易)

2、建立一個區塊鍊

我們要建立一個Blockchain類 ,他的構造函數建立了一個初始化的空清單(要存儲我們的區塊鍊)并且建立世紀快,以及初始化了事務清單。下面是我們這個類的執行個體:

Step 1:初始化區塊清單并且建立創世塊

/**
     * @var array 區塊清單
     */
    private $chain;

    /**
     * @var array 交易事務清單
     */
    private $currentTransactions;

    public function __construct()
    {
        $this->chain = [$this->createGenesisBlock()];
        $this->currentTransactions = [];
    }

     /**
     * 建立創世塊
     * @return array
     */
    private function createGenesisBlock()
    {
        $block = [
            'index' => 1,
            'timestamp' => time(),
            'transactions' => [

            ],
            'proof' => 100,
            'previous_hash' => '0000000000000000000000000000000000000000000000000000000000000000',//參考BTC的第一個創世塊
        ];
        $block['hash'] = (new Block($block['index'],$block['timestamp'],$block['transactions'],$block['previous_hash'],$block['proof']))->getHash();
        return $block;
    }           

Step 2:新增交易事務

建立一筆新的交易到交易事務清單中等待新區塊打包,每次生成新區塊後清空清單

/**
      * 新增交易事務
      * @param $senderPrivateKey
      * @param $senderAddress
      * @param $recipientAddress
      * @param $amount
      * @return bool
      */
     public function createTransaction($senderPrivateKey,$senderAddress,$recipientAddress,$amount)
     {
         $row = [
             'from'   => $senderAddress,
             'to'     => $recipientAddress,
             'amount' => $amount,
             'timestamp' => time()
         ];
         //TODO 私鑰簽名(就像支票簽名)
         //TODO 區塊鍊節點可以用發送者的簽名來推導出公鑰,再通過公鑰驗簽并對比資料
         $this->currentTransactions[] = $row;
         return true;
     }           

Step 3:建立新區塊

目前示例建立新區快操作隻能由挖礦成功的礦工操作,挖礦講解在Step4

/**
     * 增加新區塊
     * @param int $proof
     * @return bool
     */
    public function addBlock(int $proof)
    {
        //上一個區塊的資訊
        $preBlockInfo = $this->chain[count($this->chain)-1];
        //驗證工作證明
        if($this->checkProof($proof,$preBlockInfo['proof']) == false){
            return false;
        }
        //TODO 獎勵礦工(在交易事務中)
        $block = [
            'index'        => count($this->chain) + 1,
            'timestamp'    => time(),
            'transactions' => $this->currentTransactions,
            'proof'        => $proof,
            'previous_hash' => $preBlockInfo['hash'],
            'hash'         => ''
        ];
        $block['hash'] = (new Block($block['index'],$block['timestamp'],$block['transactions'],$block['previous_hash'],$block['proof']))->getHash();
        //新增區塊
        $this->chain[] = $block;
        //重置交易事務
        $this->currentTransactions = [];
        return true;
    }

        /**
         * 校驗算力
         * @param string $proof
         * @param string $preProof
         * @return bool
         */
        private function checkProof(string $proof,string $preProof)
        {
            $string = $proof.$preProof;
            $hash   = hash('sha256',$string);
            if(substr($hash,0,4) == '0000'){
                return true;
            }else{
                return false;
            }
        }           

Step 4:挖礦

挖礦正是神奇所在,它很簡單,做了一下三件事:

  1. 計算工作量證明 PoW
  2. 通過新增一個交易授予礦工(自己)一個币
  3. 構造新區塊并将其添加到鍊中

讓我們來實作一個相似 PoW 算法

找到一個數字 P ,使得它與前一個區塊的 Proof 拼接成的字元串的 Hash 值以 4 個零開頭。           
/**
     * 挖礦
     * @return void
     */
    public function mine()
    {
//        while (true)
//        {
            $proof = 0;
            //最新區塊
            $blockInfo = $this->chain[count($this->chain)-1];
            $preProof  = $blockInfo['proof'];
            while (true)
            {
                $string = $proof.$preProof;
                $hash   = hash('sha256',$string);
                if(substr($hash,0,4) == '0000'){
                    //增加新區塊
                    $this->addBlock($proof);
                    break;
                }
                $proof++;
            }

//        }
    }           

Step 5:運作測試

$blockChainObj = new Blockchain();

//增加事務
$blockChainObj->createTransaction('','8527147fe1f5426f9dd545de4b27ee00',
    'a77f5cdfa2934df3954a5c7c7da5df1f',1);

//開啟挖礦(挖到則生成新區塊)
$blockChainObj->mine();

//檢視目前區塊清單
$blockList = $blockChainObj->getChainList();
var_dump($blockList);

//結果:
$ php Blockchain.php
array(2) {
  [0]=>
  array(6) {
    ["index"]=>
    int(1)
    ["timestamp"]=>
    int(1580717292)
    ["transactions"]=>
    array(0) {
    }
    ["proof"]=>
    int(100)
    ["previous_hash"]=>
    string(64) "0000000000000000000000000000000000000000000000000000000000000000"
    ["hash"]=>
    string(64) "567b2848f3ff87a614b3ba5ddc13389d4d7440699b1857935412561721d86d05"
  }
  [1]=>
  array(6) {
    ["index"]=>
    int(2)
    ["timestamp"]=>
    int(1580717292)
    ["transactions"]=>
    array(1) {
      [0]=>
      array(4) {
        ["from"]=>
        string(32) "8527147fe1f5426f9dd545de4b27ee00"
        ["to"]=>
        string(32) "a77f5cdfa2934df3954a5c7c7da5df1f"
        ["amount"]=>
        int(1)
        ["timestamp"]=>
        int(1580717292)
      }
    }
    ["proof"]=>
    int(28)
    ["previous_hash"]=>
    string(64) "567b2848f3ff87a614b3ba5ddc13389d4d7440699b1857935412561721d86d05"
    ["hash"]=>
    string(64) "3a599c88ddd60fb25605df33d33b19252117c3d7d0e70c66dbc45ed81ab295a9"
  }
}           

Setp5:完整代碼

雲栖号線上課堂,每天都有産品技術專家分享

立即加入圈子:

https://c.tb.cn/F3.Z8gvnK 與專家面對面,及時了解課程最新動态!

原文釋出時間:2020-03-17

本文作者:ar414

本文來自:“

阿裡雲雲栖社群

”,了解相關資訊可以關注“