<?php
/**
* author : forecho <caizhenghai@gmail.com>
* createTime : 2018/1/23 18:35
* description:
*/
/**
* 区块
* Class Block
*/
class Block
{
/**
* @var string 时间
*/
public $timestamp;
/**
* @var integer 索引
*/
public $index;
/**
* @var string 数据
*/
public $data;
/**
* @var string 上一个哈希值
*/
public $prevHash;
/**
* @var string 当前哈希
*/
public $hash;
public function __construct($index, $timestamp, $data, $prevHash = '')
{
$this->index = $index;
$this->timestamp = $timestamp;
$this->data = $data;
$this->prevHash = $prevHash;
$this->hash = $this->calculateHash(); }
/**
* 加密算法
* @return string
*/
public function calculateHash()
{
return hash('sha256', $this->index . $this->prevHash . $this->timestamp . json_encode($this->data)); }
}
/**
* 区块链
* Class BlockChain
*/
class BlockChain
{
/**
* @var Block[]
*/
public $chain = [];
public function __construct()
{
$this->chain = [$this->createGenesisBlock()];
}
/**
* 创世区块
* @return Block
*/
public function createGenesisBlock()
{
return new Block(0, '2017-01-23', 'forecho', '0');
}
/**
* 获取最新的区块
* @return Block|mixed
*/
public function getLatestBlock()
{
return $this->chain[count($this->chain) - 1]; }
/**
* 添加区块
* @param Block $newBlock
*/
public function addBlock(Block $newBlock)
{
$newBlock->prevHash = $this->getLatestBlock()->hash; $newBlock->hash = $newBlock->calculateHash(); }
/**
* 验证区块链
* @return bool
*/
public function isChainValid()
{
for ($i = 1; $i < count($this->chain); $i++) { $currentBlock = $this->chain[$i];
$prevBlock = $this->chain[$i - 1];
if ($currentBlock->hash !== $currentBlock->calculateHash()) { return false;
}
if ($currentBlock->prevHash !== $prevBlock->hash) { return false;
}
}
return true;
}
}
// test
$blockChain = new BlockChain();
$blockChain->addBlock(new Block(1, '2017-02-23', ['amount' => 1]));
$blockChain->addBlock(new Block(2, '2017-03-23', ['amount' => 3]));
$blockChain->addBlock(new Block(3, '2017-04-23', ['amount' => 20]));
echo "区块链验证通过吗?" . ($blockChain->isChainValid() ? '通过' : '失败') . PHP_EOL;
$blockChain->chain[1]->data = ['amount' => 2];
$blockChain->chain[1]->hash = $blockChain->chain[1]->calculateHash(); echo "区块链验证通过吗?" . ($blockChain->isChainValid() ? '通过' : '失败') . PHP_EOL;
PD9waHAKCi8qKgogKiBhdXRob3IgICAgIDogZm9yZWNobyA8Y2FpemhlbmdoYWlAZ21haWwuY29tPgogKiBjcmVhdGVUaW1lIDogMjAxOC8xLzIzIDE4OjM1CiAqIGRlc2NyaXB0aW9uOgogKi8KLyoqCiAqIOWMuuWdlwogKiBDbGFzcyBCbG9jawogKi8KY2xhc3MgQmxvY2sKewogICAgLyoqCiAgICAgKiBAdmFyIHN0cmluZyDml7bpl7QKICAgICAqLwogICAgcHVibGljICR0aW1lc3RhbXA7CiAgICAvKioKICAgICAqIEB2YXIgaW50ZWdlciDntKLlvJUKICAgICAqLwogICAgcHVibGljICRpbmRleDsKICAgIC8qKgogICAgICogQHZhciBzdHJpbmcg5pWw5o2uCiAgICAgKi8KICAgIHB1YmxpYyAkZGF0YTsKICAgIC8qKgogICAgICogQHZhciBzdHJpbmcg5LiK5LiA5Liq5ZOI5biM5YC8CiAgICAgKi8KICAgIHB1YmxpYyAkcHJldkhhc2g7CiAgICAvKioKICAgICAqIEB2YXIgc3RyaW5nIOW9k+WJjeWTiOW4jAogICAgICovCiAgICBwdWJsaWMgJGhhc2g7CiAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoJGluZGV4LCAkdGltZXN0YW1wLCAkZGF0YSwgJHByZXZIYXNoID0gJycpCiAgICB7CiAgICAgICAgJHRoaXMtPmluZGV4ID0gJGluZGV4OwogICAgICAgICR0aGlzLT50aW1lc3RhbXAgPSAkdGltZXN0YW1wOwogICAgICAgICR0aGlzLT5kYXRhID0gJGRhdGE7CiAgICAgICAgJHRoaXMtPnByZXZIYXNoID0gJHByZXZIYXNoOwogICAgICAgICR0aGlzLT5oYXNoID0gJHRoaXMtPmNhbGN1bGF0ZUhhc2goKTsKICAgIH0KICAgIC8qKgogICAgICog5Yqg5a+G566X5rOVCiAgICAgKiBAcmV0dXJuIHN0cmluZwogICAgICovCiAgICBwdWJsaWMgZnVuY3Rpb24gY2FsY3VsYXRlSGFzaCgpCiAgICB7CiAgICAgICAgcmV0dXJuIGhhc2goJ3NoYTI1NicsICR0aGlzLT5pbmRleCAuICR0aGlzLT5wcmV2SGFzaCAuICR0aGlzLT50aW1lc3RhbXAgLiBqc29uX2VuY29kZSgkdGhpcy0+ZGF0YSkpOwogICAgfQp9Ci8qKgogKiDljLrlnZfpk74KICogQ2xhc3MgQmxvY2tDaGFpbgogKi8KY2xhc3MgQmxvY2tDaGFpbgp7CiAgICAvKioKICAgICAqIEB2YXIgQmxvY2tbXQogICAgICovCiAgICBwdWJsaWMgJGNoYWluID0gW107CiAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoKQogICAgewogICAgICAgICR0aGlzLT5jaGFpbiA9IFskdGhpcy0+Y3JlYXRlR2VuZXNpc0Jsb2NrKCldOwogICAgfQogICAgLyoqCiAgICAgKiDliJvkuJbljLrlnZcKICAgICAqIEByZXR1cm4gQmxvY2sKICAgICAqLwogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZUdlbmVzaXNCbG9jaygpCiAgICB7CiAgICAgICAgcmV0dXJuIG5ldyBCbG9jaygwLCAnMjAxNy0wMS0yMycsICdmb3JlY2hvJywgJzAnKTsKICAgIH0KICAgIC8qKgogICAgICog6I635Y+W5pyA5paw55qE5Yy65Z2XCiAgICAgKiBAcmV0dXJuIEJsb2NrfG1peGVkCiAgICAgKi8KICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRMYXRlc3RCbG9jaygpCiAgICB7CiAgICAgICAgcmV0dXJuICR0aGlzLT5jaGFpbltjb3VudCgkdGhpcy0+Y2hhaW4pIC0gMV07CiAgICB9CiAgICAvKioKICAgICAqIOa3u+WKoOWMuuWdlwogICAgICogQHBhcmFtIEJsb2NrICRuZXdCbG9jawogICAgICovCiAgICBwdWJsaWMgZnVuY3Rpb24gYWRkQmxvY2soQmxvY2sgJG5ld0Jsb2NrKQogICAgewogICAgICAgICRuZXdCbG9jay0+cHJldkhhc2ggPSAkdGhpcy0+Z2V0TGF0ZXN0QmxvY2soKS0+aGFzaDsKICAgICAgICAkbmV3QmxvY2stPmhhc2ggPSAkbmV3QmxvY2stPmNhbGN1bGF0ZUhhc2goKTsKICAgICAgICBhcnJheV9wdXNoKCR0aGlzLT5jaGFpbiwgJG5ld0Jsb2NrKTsKICAgIH0KICAgIC8qKgogICAgICog6aqM6K+B5Yy65Z2X6ZO+CiAgICAgKiBAcmV0dXJuIGJvb2wKICAgICAqLwogICAgcHVibGljIGZ1bmN0aW9uIGlzQ2hhaW5WYWxpZCgpCiAgICB7CiAgICAgICAgZm9yICgkaSA9IDE7ICRpIDwgY291bnQoJHRoaXMtPmNoYWluKTsgJGkrKykgewogICAgICAgICAgICAkY3VycmVudEJsb2NrID0gJHRoaXMtPmNoYWluWyRpXTsKICAgICAgICAgICAgJHByZXZCbG9jayA9ICR0aGlzLT5jaGFpblskaSAtIDFdOwogICAgICAgICAgICBpZiAoJGN1cnJlbnRCbG9jay0+aGFzaCAhPT0gJGN1cnJlbnRCbG9jay0+Y2FsY3VsYXRlSGFzaCgpKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCRjdXJyZW50QmxvY2stPnByZXZIYXNoICE9PSAkcHJldkJsb2NrLT5oYXNoKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICB9Cn0KLy8gdGVzdAokYmxvY2tDaGFpbiA9IG5ldyBCbG9ja0NoYWluKCk7CiRibG9ja0NoYWluLT5hZGRCbG9jayhuZXcgQmxvY2soMSwgJzIwMTctMDItMjMnLCBbJ2Ftb3VudCcgPT4gMV0pKTsKJGJsb2NrQ2hhaW4tPmFkZEJsb2NrKG5ldyBCbG9jaygyLCAnMjAxNy0wMy0yMycsIFsnYW1vdW50JyA9PiAzXSkpOwokYmxvY2tDaGFpbi0+YWRkQmxvY2sobmV3IEJsb2NrKDMsICcyMDE3LTA0LTIzJywgWydhbW91bnQnID0+IDIwXSkpOwpwcmludF9yKCRibG9ja0NoYWluKTsKZWNobyAi5Yy65Z2X6ZO+6aqM6K+B6YCa6L+H5ZCX77yfIiAuICgkYmxvY2tDaGFpbi0+aXNDaGFpblZhbGlkKCkgPyAn6YCa6L+HJyA6ICflpLHotKUnKSAuIFBIUF9FT0w7CiRibG9ja0NoYWluLT5jaGFpblsxXS0+ZGF0YSA9IFsnYW1vdW50JyA9PiAyXTsKJGJsb2NrQ2hhaW4tPmNoYWluWzFdLT5oYXNoID0gJGJsb2NrQ2hhaW4tPmNoYWluWzFdLT5jYWxjdWxhdGVIYXNoKCk7CmVjaG8gIuWMuuWdl+mTvumqjOivgemAmui/h+WQl++8nyIgLiAoJGJsb2NrQ2hhaW4tPmlzQ2hhaW5WYWxpZCgpID8gJ+mAmui/hycgOiAn5aSx6LSlJykgLiBQSFBfRU9MOw==