从零开始用 Python 打造自己的区块链

本文来自作者Frank在GitChat上分享 「从零开始用 Python 打造自己的区块链」

编辑 | 毛利

前言

2018 年 4 月以来,随着加密货币价格的回升,各种关于区块链的话题甚嚣尘上,各大媒体对其商业性质、技术原理、发展前景各个方面,都有各种非常深入的探讨。

同时,新的项目、概念也层出不穷,让人眼花缭乱。笔者认为,“区块链” 本质上还是一种软件算计 / 架构上的创新。

只有自己搭建环境,编写代码,实现从建立账本到完成交易的全过程,才能真正体会区块链的精髓。

比特币近十年来的价格逐波上升

本场 Chat 的目的是,就是帮助广大的区块链爱好者或者开发人员,从零开始打造属于您自己的区块链应用。

力求用最简单的语言,介绍这个最热门的技术,没有任何基础的读者也能按图索骥,一窥究竟,消除各种专家为其增添的很多迷思。

本文首先将介绍一些区块链的背景知识,而后将循序渐进地介绍在本地开发区块链应用所需要的模块和算法,做出一个简单的区块链交易程序。

在此过程中,会穿插很多关于相关名字、术语、算法的解释。相关源代码都保存在笔者的 GitHub 项目中(https://github.com/marmul2/blockchain),欢迎读者直接使用或者提交修改申请(pull request)。

GitHub 是一个面向开源及个人软件项目的托管平台,因为只支持 git 作为唯一的版本管理格式,故名 GitHub。

因为这里聚集了超过 350 万开发者,其中又以男性程序员为主,所以被戏称为 “全球最大同性交友网站”。

它不光支持代码的发布、管理,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱、代码片段分享等功能。

任何用户都可以在其上保存和发布自己的个人项目,很多知名的开源项目如 Ruby on Rails、jQuery、python 等都托管在该平台上。

1. 区块链简介

一位名为 “中本聪” (Satoshi Nakamoto) 的人于 2008 年 11 月 1 日,在 metzdowd.com网站的密码学邮件列表中,发表了一篇名为《比特币:一种点对点式的电子现金系统》(Bitcoin: A Peer to Peer Electronic Cash System) 的论文,首次提出了 “区块链”(Blockchain)的概念。

白皮书发布之后不久,中本聪于 2009 年 1 月 3 日,开发出首个实现了比特币算法的客户端程序,并进行了首次 “采矿”,获得了第一批 50 个比特币。

这标志着比特币的正式诞生。中本聪出于知识分享和推广的理念,把比特币程序的代码全部开源,与世界各地的软件开发人员共同分享。

中本聪的原始论文

经过这十年的发展,区块链已经发展成为全球最具影响力的创新技术之一。

从金融行业、制造产品到教育机构的各行各业,都可能会被这项技术全面改造。它的三大最主要的特点是:

去中心化交易

区块链的本质是一种分散在所有用户电脑上(即所谓的 “分布式”)的计算机账本,每个分散的账本会记录区块链上进行的所有交易活动的信息。所以,它不需要一个集中的机构、网站、公司来管理这些信息。

法国大作家大仲马在 1884 这年出版的小说《三个火枪手》中有这么一句著名的话,“人人为我,我为人人”(All for one, one for all)。用这句话来形容区块链的去中心化特征非常贴切。

信息不可篡改,一旦写入无法改变

作为一个记录交易的账本,人们最不希望的是它被坏人恶意篡改。任何一个用户,都可以通过交易编号,访问区块链上发生的所有交易记录和注释。

由于中本聪巧妙的算法设计,配合密码限制和共识机制,如果要修改区块链中的某一个数据,就必须更改其后发生的所有数据记录,计算量无可想象,非常庞大,几乎不可能实现。

实际上,比特币诞生到现在已经接近 10 年,每天都有无数的黑客绞尽脑汁攻击这个系统,但是从来没有发生过一起交易记录被篡改的事件,这足以证明了它的安全性。

完全匿名

在互联网诞生初期,有句话说:“在互联网上,没人知道你是一只狗。” 这强调的是在互联网上的匿名访问性。

在区块链世界里,所有的账户(或者说 “钱包”)都是通过一个密码来访问。如果你失去了密码,也就失去了账户里面的所有货币。

在现实生活中,如果你忘记了密码或者丢失了银行卡,你可以去银行柜台申请补办,手续很简单。

但是在 “去中心化” 的区块链世界里,没有这样的 “银行柜台”,谁也不知道你是谁,你也无法向别人证明你是某个钱包的主人。

当然,与大部分技术一样,区块链也是一个 “双刃剑”,有它的不足之处:

过度消耗能源

想要生成一个新的区块,必须要大量服务器资源进行大量无谓的尝试性计算进行 “挖矿”,严重耗费电能(后文将详细介绍 “挖矿” 的过程)。

信息的网络延迟

以比特币为例,任何一笔交易数据都需要同步到其他所有节点,同步过程中难免会受到网络传输延迟的影响,带来较长的耗时。

区块链应用的实际开发,可以分为以下几步。下面我们将针对每个步骤详细介绍。

除了主要介绍环境配置的第二节和介绍交易步骤的第七节以外,其他步骤都分为概念介绍、代码实现、深入讲解这三个部分。

所有代码均已放在我的 GitHub 项目之中,您可以直接下载使用。如果对具体的代码实现不感兴趣,您也可以直接只关注每节中的概念介绍和深入讲解这两个部分。

如果您对具体的算法也不感兴趣,没关系,您可以直接跳过这些部分,进入第七节,逐步尝试自己完成 “虚拟交易”。

2. 环境配置:建立 “交易所”

为了便于初学者学习,笔者会尽可能详细地记录开发环境配置的每一个步骤,如果您已经熟悉 Python 环境和相关模块的使用,您可以选择跳过这一部分。

1. 首先,您需要一台安装了 Win7 或者 Win10 系统的电脑,可以是台式机或者是笔记本电脑。

当然,不一定非要用 Windows 系统来开发区块链应用,Linux 或者 Mac 系统也是很好的选择,这里我们为了照顾大部分读者,只介绍 Windows 系统下的操作。

下载Python

3. 安装完毕 Python 之后,从 Windows 的开始菜单输入 “cmd”:

在命令行窗口输入以下指令,安装 Flask 和 requests 库。Flask 库将用于在本地构建一个 Web 服务器,把 Python 的功能映射到一定的端口,便于我们稍后通过针对不同的地址终端(endpoint)发送 HTTP 请求,执行各项交易,从而构成我们自己的 “虚拟交易所” ;requests 库则用于自动发送 HTTP 请求到服务器。

4. 访问 https://www.getpostman.com/apps, 下载并安装 Postman,它可以把我们定制的交易内容,发送到我们的 “虚拟交易所”。

Postman的开始界面

5. 现在,打开电脑在带的写字板编辑器,保存这样一个文件到 D:\hello.py:

fromflaskimportFlaskapp = Flask(__name__)@app.route('/')defhello_world():return'您好,欢迎来到我的虚拟货币交易所!'

这里实际上用的 Flask 模块的路由功能,具体语法信息请参阅 Flask 介绍页面(http://flask.pocoo.org/docs/0.12/quickstart/#a-minimal-application)。

6. 回到命令行控制界面,输入下列指令:

c:\>set FLASK_APP=D:\hello.pyc:\>python -m flask run

你可以看到屏幕显示 “Running on https://127.0.0.1:5000/”。 这时,打开你的浏览器,访问 https://127.0.0.1:5000/, 你可以看到这样的显示结果:

交易所开始运行

这就意味着,我们的运行环境已经搭建成功,您的 “虚拟交易所” 已经准备好接受交易了!

3. 构建区块链:把 “区块” ,“链” 到一起

3.1 概念介绍

“区块链”(Blockchina)可以理解为把一个个符合特定格式的区块(Block),按照一定的方法 “链”(chain)到一起。

这里先预习几个需要涉及的概念:

“类” (class):类是面向对象程序设计中的概念,是面向对象编程的基础。

类是对现实生活中一类具有共同特征的事物的抽象,譬如区块链这个概念,就是一类具有共同特征的事物,我们可以用一个类来代表它。

类可以描述一个对象(在本文中即某个区块链)能够做什么,以及做的方法(method)。

哈希值(Hash):所谓 “哈希值” 就是计算机可以对任意内容,计算出一个长度相同的特征值。

区块链的哈希值长度是 256 位,这也就是说,不管原始内容是什么,最后都会计算出一个 256 位的二进制数字。

而且可以保证,只要原始内容不同,对应的哈希一定是不同的。举例来说,字符串 123 的哈希值是 a8fdc205a9f19cc1c7507a60c4f01b13d11d7fd0(十六进制),转成二进制就是 256 位,而且只有 123 能得到这个哈希。

(理论上,其他字符串也有可能得到这个哈希,但是概率极低,可以近似认为不可能发生。) 由此可以得到两个重要的结论:

结论 1:每个区块的哈希都是不一样的,可以通过哈希标识一个区块。

结论 2:如果区块的内容变了,它的哈希一定会改变。

3.2 代码实现

首先,我们要用一个构造函数来创建一个区块链类 ,其中包括两个表:一个用于存储区块,一个用于记录交易。另外,我们还要定义一个方法,用于生成区块的哈希值。

此外,我们还为这个类定义了一个属性 last_block, 这样可以通过调用该类获得区块链中最后一个区块的信息。下面是这个类的初步结构:

这个类负责管理整个区块链,包括存储交易信息,把新的区块添加到整个区块链之中。

下面,我们再来看看一个典型的区块是什么样的,以及它们是怎么构成一条区块链的。按照中本聪的原始定义,下面是一个典型的区块:

3.3 深入讲解

由上面的定义可以看出,一个区块包括下面几项内容:

区块索引 / 编号

区块产生时间

上一个区块的哈希值

工作量证明(PoW)

交易信息

这揭示了区块链的核心理念:每个区块中包含了上一个区块的哈希值或者说信息。这一点对区块链有重大意义:如果有人修改了一个区块,该区块的哈希值就变了。

为了让后面的区块还能连到它,就必须依次修改后面所有的区块,否则被改掉的区块就脱离区块链了。

由于哈希值的计算非常耗时(后面将解释原因),短时间内修改多个区块几乎不可能发生,除非有人真的掌握了全球网络中 51% 以上的计算能力。

正是通过这种联动机制,区块链保证了自身的可靠性,数据一旦写入,就无法被篡改。这就像历史一样,发生了就是发生了,从此再无法改变。每个区块都连着上一个区块,这也是 “区块链” 这个名字的由来。

4. 记录交易: 怎么给区块添加交易记录?

4.1 概念介绍

在建立起区块链之后,接下来我们看看怎么为其添加交易信息。所谓 “交易”(Transaction)的过程,实际上就是给区块链加一笔数据更新的记录,其中包含了付款人的钱包地址、收款人的钱包地址、交易金额。如果把区块链作为一个状态机,则每次交易就是试图改变一次状态,而每次生成的区块,就是参与者对于区块中交易导致状态改变的结果进行确认。

4.2 代码实现

具体的添加过程,是通过 new_transaction 这个方法来实现的。下面是对这个方法的定义实例。

......

5. “挖矿” 解密

6. 在网络中传播区块链:共识算法

7. 执行交易

后记

本 Chat 中所有的代码都放置在我的 GitHub 项目 “Frank—Blockchain” 上,请自由索取或者提交修改。

或者您也可以分叉(fork)一个自己的分支,创建您自己的区块链项目。开句玩笑话,这就像是在麻将的基本原则基础上,开辟出各种分支:四川麻将、上海麻将等等。

希望本 Chat 能帮助您了解并实践区块链的基本概念和实现方法。请注意,这里提到的只是区块链最核心的部分,还有很多很多其他的技术细节和算法,譬如非对称加密、点对点网络等,我将会在以后的其他 Chat 中详细说明。

如果有任何其他的问题,欢迎到我的读者圈中继续提问。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180522B07MC800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券