区域链 PHP,PHP 创建区块链

前话

了解区块链基础运作

什么是区块链?

区块链是一个 不可变的、有序的 被称为块的记录链。它们可以包含交易、文件或任何您喜欢的数据。但重要的是,他们用哈希 一起被链接在一起

需要准备什么?

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)。

/**

* 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"

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值