fork download
  1. <?php
  2.  
  3. /**
  4.  * author : forecho <caizhenghai@gmail.com>
  5.  * createTime : 2018/1/23 18:35
  6.  * description:
  7.  */
  8. /**
  9.  * 区块
  10.  * Class Block
  11.  */
  12. class Block
  13. {
  14. /**
  15.   * @var string 时间
  16.   */
  17. public $timestamp;
  18. /**
  19.   * @var integer 索引
  20.   */
  21. public $index;
  22. /**
  23.   * @var string 数据
  24.   */
  25. public $data;
  26. /**
  27.   * @var string 上一个哈希值
  28.   */
  29. public $prevHash;
  30. /**
  31.   * @var string 当前哈希
  32.   */
  33. public $hash;
  34. public function __construct($index, $timestamp, $data, $prevHash = '')
  35. {
  36. $this->index = $index;
  37. $this->timestamp = $timestamp;
  38. $this->data = $data;
  39. $this->prevHash = $prevHash;
  40. $this->hash = $this->calculateHash();
  41. }
  42. /**
  43.   * 加密算法
  44.   * @return string
  45.   */
  46. public function calculateHash()
  47. {
  48. return hash('sha256', $this->index . $this->prevHash . $this->timestamp . json_encode($this->data));
  49. }
  50. }
  51. /**
  52.  * 区块链
  53.  * Class BlockChain
  54.  */
  55. class BlockChain
  56. {
  57. /**
  58.   * @var Block[]
  59.   */
  60. public $chain = [];
  61. public function __construct()
  62. {
  63. $this->chain = [$this->createGenesisBlock()];
  64. }
  65. /**
  66.   * 创世区块
  67.   * @return Block
  68.   */
  69. public function createGenesisBlock()
  70. {
  71. return new Block(0, '2017-01-23', 'forecho', '0');
  72. }
  73. /**
  74.   * 获取最新的区块
  75.   * @return Block|mixed
  76.   */
  77. public function getLatestBlock()
  78. {
  79. return $this->chain[count($this->chain) - 1];
  80. }
  81. /**
  82.   * 添加区块
  83.   * @param Block $newBlock
  84.   */
  85. public function addBlock(Block $newBlock)
  86. {
  87. $newBlock->prevHash = $this->getLatestBlock()->hash;
  88. $newBlock->hash = $newBlock->calculateHash();
  89. array_push($this->chain, $newBlock);
  90. }
  91. /**
  92.   * 验证区块链
  93.   * @return bool
  94.   */
  95. public function isChainValid()
  96. {
  97. for ($i = 1; $i < count($this->chain); $i++) {
  98. $currentBlock = $this->chain[$i];
  99. $prevBlock = $this->chain[$i - 1];
  100. if ($currentBlock->hash !== $currentBlock->calculateHash()) {
  101. return false;
  102. }
  103. if ($currentBlock->prevHash !== $prevBlock->hash) {
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. }
  110. // test
  111. $blockChain = new BlockChain();
  112. $blockChain->addBlock(new Block(1, '2017-02-23', ['amount' => 1]));
  113. $blockChain->addBlock(new Block(2, '2017-03-23', ['amount' => 3]));
  114. $blockChain->addBlock(new Block(3, '2017-04-23', ['amount' => 20]));
  115. print_r($blockChain);
  116. echo "区块链验证通过吗?" . ($blockChain->isChainValid() ? '通过' : '失败') . PHP_EOL;
  117. $blockChain->chain[1]->data = ['amount' => 2];
  118. $blockChain->chain[1]->hash = $blockChain->chain[1]->calculateHash();
  119. echo "区块链验证通过吗?" . ($blockChain->isChainValid() ? '通过' : '失败') . PHP_EOL;
Success #stdin #stdout 0.02s 23400KB
stdin
Standard input is empty
stdout
BlockChain Object
(
    [chain] => Array
        (
            [0] => Block Object
                (
                    [timestamp] => 2017-01-23
                    [index] => 0
                    [data] => forecho
                    [prevHash] => 0
                    [hash] => 8862e987005e1ebf5f72488a41faba2b00deba05fbed894da742a1dd572dcafe
                )

            [1] => Block Object
                (
                    [timestamp] => 2017-02-23
                    [index] => 1
                    [data] => Array
                        (
                            [amount] => 1
                        )

                    [prevHash] => 8862e987005e1ebf5f72488a41faba2b00deba05fbed894da742a1dd572dcafe
                    [hash] => 19aad00d07e897fb110b15cf3b26a8602a70796c964586f14e78e4c2fee8c14c
                )

            [2] => Block Object
                (
                    [timestamp] => 2017-03-23
                    [index] => 2
                    [data] => Array
                        (
                            [amount] => 3
                        )

                    [prevHash] => 19aad00d07e897fb110b15cf3b26a8602a70796c964586f14e78e4c2fee8c14c
                    [hash] => d4d41ec0d43bde09e8d794dd7ba80f77bed5a693724c7ee382092be8df740c29
                )

            [3] => Block Object
                (
                    [timestamp] => 2017-04-23
                    [index] => 3
                    [data] => Array
                        (
                            [amount] => 20
                        )

                    [prevHash] => d4d41ec0d43bde09e8d794dd7ba80f77bed5a693724c7ee382092be8df740c29
                    [hash] => 90f13918cba4bd89078e058b6d69f3eab00bbd3c71a825c1113efff523006339
                )

        )

)
区块链验证通过吗?通过
区块链验证通过吗?失败