PHP Create Blockchain

PHP Create Blockchain

#What is blockchain?

The blockchain is an immutable and orderly chain of records called blocks. They can contain transactions, files, or any data you like. But the important thing is that they are linked together with a hash

#php version

  • php5.6+

#1.Block

#What is the block?

Each block has an index, a time stamp (Unix timestamp), a transaction list, a check (a proof generated by a proof of work algorithm) and a hash of the previous block

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

At this point, the concept of a blockchain should be obvious-each new block contains the hash of the previous block. This is crucial because this is why the blockchain is immutable: if an attacker damages an earlier block in the blockchain, all subsequent blocks will contain incorrect hash values.

Create a new Block class. The blockchain consists of N blocks. In the blockchain, value information is stored in the blocks. For example, Bitcoin blocks store transaction records, and transaction records are the core of any cryptocurrency. In addition, the block also contains technical information, such as its version number, current timestamp, and the hash of the previous block (Hash).

<?php
/**
 * Created by PhpStorm.
 * User: ar414.com@gmail.com
 * Date: 2020/2/2
 * Time: 18:42
 */

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

    /**
     * @var integer timestamp
     */
    private $timestamp;

    /**
     * @var array transaction list
     */
    private $transactions;

    /**
     * @var string The hash value of the previous block
     */
    private $previousHash;

    /**
     * @var integer The proof generated by the proof of work algorithm
     */
    private $proof;

    /**
     * @var string the hash value of the current block
     */
    private $hash;

    /**
     * Return the hash of the newly generated block by calling the method
     * Prevent outside changes
     * @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();
    }

    /**
     * Current block signature
     * @return string
     */
    private function blockHash()
    {
        //We must ensure that this dictionary (block) is sorted, otherwise we will get inconsistent hash values
        $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 is the index of the current block
  • timestamp is the generation time of the current block
  • transactions is the transaction list of the current block (there are multiple or one transaction)
  • previousHash is the signature hash of the previous block
  • hash is the signature hash of the current block
  • proof is the proof of miner workload of the current block

#proof

Use the Proof of Work (PoW) algorithm to prove how to create or mine new blocks on the blockchain. The goal of PoW is to calculate a number that meets certain conditions. This number must be computationally difficult for everyone, but easy to verify. This is the core idea behind proof of work.

In Bitcoin, the proof-of-work algorithm is called Hashcash, which is similar to the above problem, except that the calculation is very difficult. This is the problem that miners are competing for the right to create blocks. Usually, the calculation difficulty is proportional to the number of specific characters that the target string needs to meet. After the miner calculates the result, he will get a certain amount of bitcoin rewards (through transactions)

#2. Create a blockchain

We are going to create a Blockchain class, his constructor creates an initial empty list (to store our blockchain) and creates Century Express, and initializes the transaction list. Below is an instance of our class

#Step 1: Initialize the block list and create the genesis block

     /**
      * @var array block list
      */
     private $chain;

     /**
      * @var array transaction transaction list
      */
     private $currentTransactions;

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

      /**
      * Create genesis block
      * @return array
      */
     private function createGenesisBlock()
     {
         $block = [
             'index' => 1,
             'timestamp' => time(),
             'transactions' => [

             ],
             'proof' => 100,
             'previous_hash' => '0000000000000000000000000000000000000000000000000000000000000000000000', //Refer to the first genesis block of BTC
         ];
         $block['hash'] = (new Block($block['index'],$block['timestamp'],$block['transactions'],$block['previous_hash'],$block['proof' ]))->getHash();
         return $block;
     }

#Step 2: New transaction

Create a new transaction and wait for the new block to be packaged in the transaction transaction list, and clear the list every time a new block is generated.

     /**
       * New transaction transaction
       * @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 private key signature (just like a check signature)
          //TODO blockchain nodes can use the sender’s signature to derive the public key, then pass the public key verification and compare the data
          $this->currentTransactions[] = $row;
          return true;
      }

#Step 3: Create a new block

In the current example, the quick operation of creating a new area can only be operated by miners who have successfully mined. The mining explanation is in Step4

    /**
     * Add new block
     * @param int $proof
     * @return bool
     */
    public function addBlock(int $proof)
    {
        //The information of the previous block
        $preBlockInfo = $this->chain[count($this->chain)-1];
        //Verify proof of work
        if($this->checkProof($proof,$preBlockInfo['proof']) == false){
            return false;
        }
        //TODO rewards miners (in transaction transactions)
        $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();
        //New block
        $this->chain[] = $block;
        //Reset transaction transaction
        $this->currentTransactions = [];
        return true;
    }

        /**
         * Check computing power
         * @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: Mining

Mining is the magic. It is very simple. It does three things:

  1. Calculate proof of work PoW
  2. Grant the miner (self) a coin by adding a new transaction
  3. Construct a new block and add it to the chain

In Bitcoin, the proof-of-work algorithm is called Hashcash, which is similar to the above problem, except that the calculation is very difficult. This is the problem that miners are competing for the right to create blocks. Usually, the calculation difficulty is proportional to the number of specific characters that the target string needs to meet. After the miner calculates the result, he will get a certain amount of bitcoin rewards (through transactions)

Let's implement a similar PoW algorithm

找到一个数字 P ,使得它与前一个区块的 Proof 拼接成的字符串的 Hash 值以 4 个零开头。
     /**
      * Mining
      * @return void
      */
     public function mine()
     {
         while (true)
         {
             $proof = 0;
             //Latest block
             $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'){
                     //Add new block
                     $this->addBlock($proof);
                     break;
                 }
                 $proof++;
             }        
        }
     }

#Step 5: Run the test

$blockChainObj = new Blockchain();

//Increase transaction
$blockChainObj->createTransaction('','8527147fe1f5426f9dd545de4b27ee00',
    'a77f5cdfa2934df3954a5c7c7da5df1f',1);

//Enable mining (a new block will be generated after mining)
$blockChainObj->mine();

//View the current block list
$blockList = $blockChainObj->getChainList();
var_dump($blockList);

//result:
$ 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"
  }
}

#Step 6: Complete code ar414-com/phpblock

#Support Author

coffee


Did you enjoyed the article ?
Subscribe to the newsletter 👨‍💻

Be the first to know when I write something new! If you don't like emails, you can follow me on GitHub.