PHP从零实现区块链(一)基本原型

前言

学习区块链有些时间了,根据大佬的文章用Go也实现了一遍,但作用一名web码农,平时用的最多的还是PHP,所以打算用PHP再搞一搞,当是复习了。本教程基于LaravelZero(因为构建命令行省事儿)简单构建一个属于你的区块链,如果你有一些区块链的前置知识那就最好不过啦。

参考文章:

初始化

  1. 根据 LaravelZero 文档,先创建一个项目,确保能顺利跑起来。
  2. 在app目录下创建 Services 文件夹,咱们的代码都写在这里面。

区块链是什么

简单来说,区块链是一个提供了拜占庭容错、并保证了最终一致性的分布式数据库;从数据结构上看,它是基于时间序列的链式数据块结构;从节点拓扑上看,它所有的节点互为冗余备份;从操作上看,它提供了基于密码学的公私钥管理体系来管理账户。

组成区块链的核心技术主要有

  1. P2P 网络协议
  2. 分布式一致性算法
  3. 加密签名算法
  4. 账户与存储模型

在本文中,我们将利用数组来存储区块,来实现区块链的基本原型。

区块

在区块链中,真正存储有效信息的是区块(block)。

那就创建一个区块,在 App/Services 目录新建一个 Block.php。

<?php

namespace App\Services;

use Carbon\Carbon;

class Block
{
    /**
     * 当前时间戳,也就是区块创建的时间
     * @var int $timestamp
     */
    public $timestamp;

    /**
     * 区块存储的信息,也就是交易
     * @var string $data
     */
    public $data;

    /**
     * 前一个块的哈希,即父哈希
     * @var string $prevBlockHash
     */
    public $prevBlockHash;

    /**
     * 当前块的哈希 
     * @var string $hash
     */
    public $hash;
}

在比特币中,区块的结构主要有如下信息:

Field Purpose Size(Bytes)
Block Size 区块大小 4
Block Header 区块头 80
Transaction Counter 交易计数器 1~9
Transactions 交易 -

区块头的主要结构:

字段 描述 大小
Version Block version number 4
hashPrevBlock 256-bit hash of the previous block header 32
hashMerkleRoot 256-bit hash based on all of the transactions in the block 32
Time Current timestamp as seconds since 1970-01-01T00:00 UTC 4
Bits Current target in compact format 4
Nonce 32-bit number (starts at 0) 4

其中交易(Transactions)也就是我们创建的 data 字段;而其他字段(prevBlockHash,timestamp)在比特币中由专门的数据结构,即区块头存储;另外为了方便,我们还加上了当前块的 hash 字段,在比特币中是没有直接存储当前块的哈希的。

为了方便,我们就不单独实现区块头了,而是所有数据都放在一起,这样我们就创建了一个简单的区块。

下面我们来完善区块的创建:
Block.php


    public function __construct(string $data, string $prevBlockHash)
    {
        $this->prevBlockHash = $prevBlockHash;
        $this->data = $data;
        $this->timestamp = time();
        $this->hash = $this->setHash();
    }

    public function setHash(): string
    {
        return hash('sha256', implode('', [$this->timestamp, $this->prevBlockHash, $this->data]));
    }

区块链

本质上,区块链就是一个有着特定结构的数据库,是一个有序,每一个块都连接到前一个块的链表。也就是说,区块按照插入的顺序进行存储,每个块都与前一个块相连。这样的结构,能够让我们快速地获取链上的最新块,并且高效地通过哈希来检索一个块。

有了区块,下面让我们来实现区块链。在基本原型阶段,我们用数组来存放区块结构。新建一个文件 BlockChain.php

<?php
namespace App\Services;

class BlockChain
{
    /**
     * @var Block[] $blocks
     */
    public $blocks;

    public function __construct(Block $block)
    {
        $this->blocks[] = $block;
    }

    // 加入一个块到区块链中
    public function addBlock(string $data)
    {
        $prevBlock = $this->blocks[count($this->blocks) - 1];
        $newBlock = new Block($data, $prevBlock->hash);
        $this->blocks[] = $newBlock;
    }
}

addBlock() 方法使我们有了向链中添加区块的能力,但是还没完,在添加区块以前,区块链中应该存在一个创世区块。

    // 初始化创世区块
    public static function NewGenesisBlock()
    {
        $block = new Block('Genesis Block', '');

        return new BlockChain($block);
    }

大功告成,下面让我们来测试一下!

$bc = BlockChain::NewGenesisBlock();
$bc->addBlock('i am 2 block');
$bc->addBlock('i am 3 block');
dd($bc->blocks);

结果如下:

array:3 [
  0 => App\Services\Block {#155
    +timestamp: 1587700797
    +data: "Genesis Block"
    +prevBlockHash: ""
    +hash: "e0ecf169c2ea5143743438fd91778ca6cdff1c870120c784f836650cfaaaff38"
  }
  1 => App\Services\Block {#153
    +timestamp: 1587700797
    +data: "i am 2 block"
    +prevBlockHash: "e0ecf169c2ea5143743438fd91778ca6cdff1c870120c784f836650cfaaaff38"
    +hash: "c33a37e9708a2871c6b03fd2f6468081edb4e96d911c7227ad84271d9c4f8b6d"
  }
  2 => App\Services\Block {#160
    +timestamp: 1587700797
    +data: "i am 3 block"
    +prevBlockHash: "c33a37e9708a2871c6b03fd2f6468081edb4e96d911c7227ad84271d9c4f8b6d"
    +hash: "de300a998179bfeeb3ea60be3f49e205f8552b8ab9d506a76d847f0ba9d93646"
  }
]

NICE!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,726评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,697评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,734评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,508评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,522评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,051评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,429评论 3 427
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,403评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,930评论 1 323
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,977评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,122评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,763评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,454评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,931评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,047评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,613评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,150评论 2 363

推荐阅读更多精彩内容

  • 8.1 简介 挖矿是增加比特币货币供应的一个过程。挖矿同时还保护着比特币系统的安全,防止欺诈交易,避免“双重支付”...
    冉冉升起的沙丁鱼阅读 1,624评论 0 1
  • AS 有一项极其便利的重构操作,称为 Refactor | Refactor this可以进行如下操作: 重命名类...
    菜鸟冲冲冲阅读 571评论 0 0
  • 今天是来到长春的第四天,依旧是磨蹭到了下午1点多才开始收拾出门,今天的目的地是在大众点评上享誉盛名的磨时光咖啡馆。...
    软小圆0720阅读 1,109评论 0 0
  • 下午看着群里有人发了求助的信息,说的是同事的孩子生下来重度窒息,现在还没脱离危险,可是治疗需要的庞大费用不是他们普...
    檐下阅读 471评论 2 1
  • 夏天, 艳阳高照, 五彩缤纷, ...
    觅音少女阅读 70评论 0 0