云栖号: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: 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:挖矿
挖矿正是神奇所在,它很简单,做了一下三件事:
- 计算工作量证明 PoW
- 通过新增一个交易授予矿工(自己)一个币
- 构造新区块并将其添加到链中
在比特币中,工作量证明算法被称为 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://c.tb.cn/F3.Z8gvnK
与专家面对面,及时了解课程最新动态!
原文链接
本文为云栖社区原创内容,未经允许不得转载。