您现在的位置是:首页 > 文章详情

PHP 创建区块链

日期:2020-03-16点击:467

前话

提供一个思路帮助你了解区块链基础运作,文本并不是一个完整的区块链,希望你能举一反三

源码: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: ar414.com@gmail.com * 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. 构造新区块并将其添加到链中

在比特币中,工作量证明算法被称为 Hashcash ,它和上面的问题很相似,只不过计算难度非常大。这就是矿工们为了争夺创建区块的权利而争相计算的问题。 通常,计算难度与目标字符串需要满足的特定字符的数量成正比,矿工算出结果后,就会获得一定数量的比特币奖励(通过交易)

让我们来实现一个相似 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:完整代码ar414-com/phpblock

原文链接:https://yq.aliyun.com/articles/750118
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章