首页 » 漏洞 » 学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

 

你愿意阅读这篇文章,是因为你对加密货币的崛起感到兴奋,你想知道它们背后的基层技术——区块链是怎样运作的。

但想要了解区块链并不是一件易事,至少于我而言是这样的。在艰难跋涉般浏览了大量的视频并学习很多教程后,我开始亲手进行实践。

我喜欢通过动手来学习,它迫使我从代码层来了解区块链的本质,如果你也做同样的事情,在学习完这个指南之后,你就会扎实地掌握区块链的基本运作原理。

在你开始之前……

记住,我们所谓的区块链,是一种由不易篡改的数据区块,按顺序链接而形成的记录账本。它们可以包含交易、文件或任何你想要的数据。重要的是,它们被链接到一起的过程,是使用了哈希(hash)。

如果你并不清楚哈希是什么鬼, 这篇文章 会给你一个很好的解释。

这篇指南文章面向的读者是?你应该能熟练阅读并能编写基本的Python语言,并且能够对 HTTP请求的工作原理有一些了解,因为我们会通过HTTP来和我们的区块链对话。

我需要准备些什么?确保你安装了 Python 3.6+ 。你还需要安装Flask以及 Requests library:

pip install Flask==0.12.2 requests==2.18.4

哦,对了,你还需要一个 HTTP客户端,例如 Postman

或者cURL 。当然,其他的客户端也是可以的。 最终的代码在哪里?这里可以找到:

https://github.com/dvf/blockchain

步骤一:构建一个区块链

打开你最喜欢的文本编辑器或IDE,我个人喜欢用PyCharm。创建一个新的文件,并命名为blockchain.py 。我们只使用一个文件,但如果你搞丢了它,你可以随时引用 源代码 。 我们创建了一个区块链类,其构造函数创建了一个初始空列表(存储我们的区块链),而另一个则用于存储交易。下面是我们的类设计大纲: 学习区块链的捷径:构建一个属于自己的区块链

区块链类设计大纲

我们的区块链类负责管理这个区块链。它将用于存储交易,并具有一些辅助方法为区块链添加新区块。让我们开始执行一些方法。 一个区块看起来是怎样的? 每一个区块都有一个 索引 ,一个 时间戳 ( Unix时间), 一系列交易 ,一个 证明 (稍后会提到),以前 之前区块的哈希 。 下面就是一个区块所包含的一些信息: 学习区块链的捷径:构建一个属于自己的区块链 在这一点上,区块链的概念应该是明显的,每一个新区块除了其本身的信息,还包括之前区块的哈希。这是关键的,因为是它使得区块链不可更改:如果攻击者破坏了区块链当中之前的一个区块,那么所有后续的区块都会包含不正确的哈希。 这有什么用吗?如果你觉得没有,花一点时间好好思考一下,这是区块链背后的核心理念。 将交易添加到一个区块当中 我们需要一种方式将交易添加到一个区块当中。我们的 new_transaction() 代码就是负责做这个的,它也是非常简单的: 学习区块链的捷径:构建一个属于自己的区块链new_transaction() 指令将一笔交易添加到列表后,它会返回添加交易区块(也就是下一个有待挖出的区块)的索引。之后,这对于提交交易的用户而言是有用的。 创建新区块 当我们的区块链部署完之后,我们需要生成创始区块(最初的区块)来启动它。我们还需要为我们的创始区块添加一个“证明”,也就是挖矿的结果(或者说工作量证明)。我们之后会谈到更多关于挖矿的问题。 除了用我们的构造函数来创建创始区块,我们还会详细了解 new_block() , new_transaction()hash()学习区块链的捷径:构建一个属于自己的区块链 学习区块链的捷径:构建一个属于自己的区块链 学习区块链的捷径:构建一个属于自己的区块链 上述的代码应该说是简单的,我添加了一些注释和文档字符串,让代码更容易阅读。我们几乎完成了区块链的构造部分工作。但在这一点上,你一定想知道新的区块是如何创建或者挖取的。 理解工作量证明(pow) 所谓工作量证明,就是发现一个解决数学问题的字符串。这个字符串必需很难找到,但易于被网络上的所有人所验证。这就是工作量证明背后的核心思想。 我们来看看一个非常简单的例子,帮助你去理解工作量证明。 我们决定,某些整数 x 乘以另一个整数 y 的哈希,其结果的末尾必需是0.所以, hash(x * y) = ac23dc...0 。为了简化,我们把x设为5.然后用Python来实现它:

from hashlib import sha256 x = 5 y = 0  # We don't know what y should be yet... while sha256(f'{x*y}'.encode()).hexdigest()[-1] != "0":     y += 1 print(f'The solution is y = {y}')

在这里的解, y = 21 ,因此,其生成的哈希末尾为0:

hash(5 * 21) = 1253e9373e...5e3600155e860

在比特币当中,它的工作量证明算法被称为Hashcash(哈希现金算法)。这个算法和我们上述的基本例子没有太多的区别。在这个算法下,矿工为创建一个新区块而去争相解决这个新的解。矿工们在得出这个新解之后,就会收到比特币代币的奖励。

网络可以很容易地验证它们的解。

部署基本的工作量证明

让我们来为区块链部署一种类似的算法。我们的规则将类似于上面的例子:

学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

想要调整算法的难度,我们可以修改前导零的数字。不过4就已经足够了。你会发现,加上一个前导零,就会导致找到一个解所需的时间大为不同。

我们的类几乎已经完成了,我们准备开始用HTTP请求来进行交互。

步骤二:区块链作为一个API

我们要使用的是Python Flask框架。这是一个微框架,这让我们可以通过HTTP请求来和我们的区块链谈话。

我们有三种创建方式:

  1.  /transactions/new 为一个区块创建一笔新的交易;
  2.  /mine告知我们的服务器挖取一个新区块
  3.  /chain来返回整个区块链

设置Flask

我们的“服务器”将在我们的区块链网络中形成一个单一节点。让我们创建一些样板代码:

学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

以上代码的部分说明:

第15行:实例化我们的节点。你可以在这里阅读更多关于Flask的信息: http://flask.pocoo.org/docs/0.12/quickstart/#a-minimal-application

第18行:为我们的节点创建一个随机名称

第21行:实例化我们的区块链类

第24-26行:创建/mine 端点,这是一个GET 请求;

第28-30行:创建 /transactions/new 端点,这是一个POST请求,因为我们会把数据发送给它;

第32-38行:创建/chain 端点,它会返回整个区块链;

第40-41行:在端口5000上运行服务器;

交易端点

这是一笔交易请求的样子,它是用户发给服务器的信息:

{ "sender": "my address", "recipient": "someone else's address", "amount": 5 }

因为我们已经有了添加区块交易的类,剩下的工作就很容易了。让我们来编写下添加交易的函数:

学习区块链的捷径:构建一个属于自己的区块链

挖矿端点

我们的挖矿端点是魔法所发生的地方,实际上它也很容易。它要做的是三件事:

  1. 计算工作量证明
  2. 通过一笔交易授予矿工(我们)代币,以作为奖励;
  3.  创造新区块,并将其添至区块链;

学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

注意,挖取区块的接收方正是我们的节点地址。到了这一步,我们可以说已经完成了,可以开始和我们的区块链进行交互。

步骤3:和我们的区块链进行交互

你可以使用普通的 cURL或者Postman来交互我们的API 。

启动服务器:

$ python blockchain.py * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

让我们试着通过一个 GET 请求挖取一个区块

http://localhost:5000/mine:

学习区块链的捷径:构建一个属于自己的区块链

使用Postman 来创建一个GET请求

让我们通过创建一个 POST请求来创建一笔新的交易

http://localhost:5000/transactions/new

其包含着我们的交易结构:

学习区块链的捷径:构建一个属于自己的区块链

使用Postman来创建一个POST请求

如果你使用的并不是Postman,那么你可以使用cURL来创建等效的请求;

$ curl -X POST -H "Content-Type: application/json" -d '{ "sender": "d4ee26eee15148ee92c6cd394edd974e", "recipient": "someone-other-address", "amount": 5 }' "http://localhost:5000/transactions/new"

我重新启动了我的服务器,并挖取了两个区块,使得总共挖取的区块数为3.

让我们通过http://localhost:5000/chain: 请求来检查整个区块链:

{ "chain": [ { "index": 1, "previous_hash": 1, "proof": 100, "timestamp": 1506280650.770839, "transactions": [] }, { "index": 2, "previous_hash": "c099bc...bfb7", "proof": 35293, "timestamp": 1506280664.717925, "transactions": [ { "amount": 1, "recipient": "8bbcb347e0634905b0cac7955bae152b", "sender": "0" } ] }, { "index": 3, "previous_hash": "eff91a...10f2", "proof": 35089, "timestamp": 1506280666.1086972, "transactions": [ { "amount": 1, "recipient": "8bbcb347e0634905b0cac7955bae152b", "sender": "0" } ] } ], "length": 3 }

步骤4:共识

这是非常酷的一部分。我们已经有了一个接受交易的基础区块链,它允许我们挖取新的区块。但区块链的灵魂在于它要实现去中心化。如果其实现了去中心化,我们究竟如何才能确保所有参与者所用的链是相同的呢?这就是所谓的共识问题,如果我们想要网络当中存在多个节点,我们就必须部署一种共识算法。

注册新节点

在我们部署一种共识算法之前,我们需要一种让节点能够识别网络相邻节点的方法。我们网络上的每一个节点,应该有网络其他节点的登记表。因此,我们需要更多的端点:

1 、 /nodes/register 来接受一系列URL形式的新节点;

2、 /nodes/resolve 来部署我们的共识算法,其负责解决任何冲突,确保节点所在的链是正确的。

我们需要修改我们的区块链构造函数,并为注册节点提供一个方法:

学习区块链的捷径:构建一个属于自己的区块链

注意,我们使用了一个 set() 来持有节点列表。这是一种确保新添加的节点是幂等的的廉价方法。这意味着无论我们添加一个特定的节点多少次,其出现的次数都只有1 。

部署共识算法

如前所述,冲突是当一个节点与另一个节点所在的链不同时的情况。为了解决这个问题,我们将制定一条规则,即最长有效链是权威链。换句话说,网络上最长的链就是有效的区块链。使用这种算法,我们网络中的节点之间就达成了共识。

学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

第一种方法 valid_chain() 是通过遍历每个区块并验证哈希和证明,其负责检查一条链是否是有效的;

resolve_conflicts() 则是遍历所有我们的相邻节点,下载它们的链,并使用上述方法来验证它们。如果一个有效链被找到了,其长度要高于我们所在的链,我们就用这个新链取代我们所在的旧链。

让我们将这两个端点注册到我们的API中,一个用于添加相邻节点,另一个用于解决冲突:

学习区块链的捷径:构建一个属于自己的区块链

学习区块链的捷径:构建一个属于自己的区块链

在这一点上,如果你喜欢的话,你可以使用不同的机器,并在你的网络上启动不同的节点。或者你可以使用相同的机器,使用不同的端口来启动程序。我在我的机器上用不同的端口启动了另一个节点,并用我目前的节点进行了注册。因此,我有了两个节点:

http://localhost:5000http://localhost:5001 .

学习区块链的捷径:构建一个属于自己的区块链

注册一个新节点

然后我在节点2上挖取了一些新的区块,确保链更长。之后,我在节点1上调用 GET /nodes/resolve 函数,然后节点1所在的链就被共识算法替换成节点2的链了。

学习区块链的捷径:构建一个属于自己的区块链

你也可以找一些朋友,帮你一起测试你的区块链……

我希望这能够启发你创造出新的东西。我相信,区块链会迅速改变我们思考经济、政府以及记录的方式。

更新:我计划在接下来的第二部分,扩展一下交易验证机制,并讨论产品化区块链的一些方式。

如果你喜欢这个教程,或有任何建议或疑问,请在评论中告诉我。如果你发现任何错误,你可以帮忙在这里https://github.com/dvf/blockchain 修正!。

发文时比特币价格 ¥30489

原文链接:学习区块链的捷径:构建一个属于自己的区块链,转载请注明来源!

0