用Python 实现一个区块链项目

区块链概念

区块链的官方定义是:一个分布式账本,一种通过去中心化、去信任的方式集体维护一个可靠数据库的技术方案。那么对于圈外人该如何理解呢?以下我会详细描述一个区块链的产生过程和实现意义,从而给大家构建出一个清晰的区块链概念。我们先讲原理、再说特点、然后论用途、最后回归代码,这样你就会对区块链有个清晰地认识。

区块链,顾名思义,就是由一个个区块依次连接起来组成的链条,可以类比为一条无限长度的直线铁链,每个铁环就是一个区块。那么区块的内容应该是什么呢?区块狭义上是有两种的,一个是普通区块,一个就是创世区块。

那么,一个普通区块中到底有什么?

1.index:就是从0-n依次产生的数字,可以称之为链高度。

2.hash:一个长度为256位随机数,是这个区块的唯一编号。

3.previous hash:上一个区块的hash,一个普通区块有且仅有一个previous hash,这就是区块链之所以称为链的原因,就是这么一环套一环链接而成的。

4.tempstamp:用于记录该区块诞生的时间。

5.difficulty:直观体现创造该区块的难度。

6.nonce:随机数,用于产生下一个区块。

7.data:存储的交易记录。

这就是一个区块需要具备的最基本的几条要素,要分析区块链的工作过程,要先问两个问题:为什么要产生新的区块?怎么产生新的区块?

为什么要产生新的区块?

一个区块记录的就是一份账单,账单中存储着若干条交易记录,是买卖双方具体活动的最有力的证明,例如我们在某宝上的购买记录,就是我们的消费账单。人们每天的消费记录是不断增长的,不可能永远放在一个区块里,随着买卖记录的不断增加,就需要不断产生新的区块来存储这些数据。

怎么产生新的区块?

挖矿实际上就是由那些矿工来生成新的区块的过程。在BTC项目中,BTC矿工挖矿成功(其实就是成功的创建了一个区块)就可以获得一定数量的BTC,所以BTC数量是在一定范围内慢慢增加的。在一般允许挖矿的区块链项目(也存在限制coin数量不允许挖矿的区块链项目)中,矿工的数量一般会大于6个,一般超过6个矿工认可的新区块就可以加入到区块链中。如果区块无限制的快速增加,不就引起很大的问题,幸好根据中本聪的设定,目前全网每10分钟只能产生一个新区块。而且这10分钟不是靠自己掐表算的,生成新的区块是需要大量的运算的,这10分钟是人家预先设计好的,让计算量大到全网10分钟一般只能产生一个。

以上就是区块链的基本概念,下面讲下区块的工作流程:

第一步:确认交易双方身份。

如果A要和B达成一笔交易,比如A转给B一个btc,B给A打10w的RMB。A首先将自己的btc来源信息、交易人等发送给B,同时还要拷贝一份发到全网。在区块链中,每个交易个体(也可以理解为每个网络节点)都会有一对公钥和私钥,公钥相当于一个“收款地址”,而私钥是一个表明自己身份的256位的数字,目前一般是用sha265来生成的,这样,别人并不知道交易的双方是谁。发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私钥对摘要进行加密,加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。

第二步,进行交易并确认交易成功

第一步完成后,全网的矿工都会得到这个交易记录,全网的矿工都会为了若干奖励开始创建区块的工作,矿工会利用hash函数生成一个256位的唯一编号赋予这个区块,但是这个编号并不是简简单单随便生成的。编号是根据区块的具体内容如交易内容、nonce等唯一确定的,换句话说,两块内容相同的区块所对应的编号一定是唯一的。中本聪为了控制区块的生成时间,使区块的生成速率满足全网的每10分钟一个的标准,制定了严格的区块生成校验规则,也就是说,能不能生成一个成功的区块要看你的编号是否符合这个规则。由于区块的交易内容是无法修改的,因此矿工们只能通过修改nonce去不断尝试这个函数,直到生成了一个成功的区块为止。如果当区块平均生成时间变快或者变慢,那么系统会对区块校验规则进行相应的调整,从而使平均的生成时间能够控制在规定范围。

如果一个矿工完成了一个区块,会立刻告知其他矿工,如果其他矿工此时没有完成新的区块生成,则会停下手头的工作,对区块进行验证,需要确认的信息主要有如下几点:

1)区块的编号有效;这个只要将区块放入哈希函数中,看产生的编号是否和该区块中的编号一致即可。

2)区块的前一个区块有效;之前提过,区块是一个串联的,每一个普通区块都会记载前一个区块的编号,这需要其他矿工对比当前的区块链的最后一个区块,看是否相同。

3)交易清单有效;就是说要验证A到底有没有这一个BTC可以给B。在区块链的交易信息中,会记录交易中所有BTC的前世今生,区块链可以做到追本溯源,因此每一个BTC在哪里,为什么在这里都可以一目了然。

当验证完一个全新的区块后,全网就会认为这个区块有效,会将它添加到现有的区块链末端,同时结束针对该区块的挖矿工作,投入到下一个挖矿周期中。

第三步,当两个矿工同时计算出正确的区块链

不难想象,这样的机制是存在冲突隐患的,当两个矿工同时制作了一个正确的区块,那么此时不必二选一,可以将原来线性的区块链改成树状:

但是这样会导致未来在A、B后都会增加相应的区块,那么谁长谁将作为主链延伸下去,另一个也许会渐渐被遗忘,除非哪天它变得更长。

以上就是区块链最基本的知识,接下来使用 Python 演示如何实现一个挖矿的流程。

代码实例:

首先,创建一个表示区块链的类:

初始化函数中的chain表示当前的区块链,在其中存储区块对象;pitmen表示为这个区块链服务的矿工们,这个列表中也会存有矿工对象;results则会存储每个阶段产生的区块;new_block方法是创建区块的方法,如果当前生成的区块为第一个区块,则产生创世区块。

一下是区块链类型的方法:

last_block会返回当前区块链的最后一个区块对象。

get_trans方法则用来随机生成一份交易信息。

这是生成区块的核心部分,这个方法主要分成两个部分:根据传参区分是否是创世区块,如果需要的是创世区块,那就由该类型自动生成一个区块占据区块链的头一个位置。如果需要生成的是普通区块,那么则会将一些基本信息分发给矿工们进行挖矿操作。这里设置了6个矿工,为了公平起见,这里也开了个多线程尽量让矿工们同时收到消息从而可以同时进行挖矿操作。按理说,最先挖矿成功的矿工会将消息发给其他矿工,其他矿工会立刻停止进行校验,但由于时间有限,这一步校验环节我没有实现。在这里,我允许所有矿工都完成工作,并提交成果和相应的工作时间,生成耗时最短的区块讲作为正确的区块添加到区块链上。本质上也是依照了“快者优先”的区块链生成原则。

那么区块内部是什么样的呢?

在这里区块就是一个非常简单的数据结构,这里的所有字段在上述中已经有了详细的说明,因此不再赘述。

那么我们再看看矿工,毕竟矿工才是区块链的生产者和推动者,地位最为核心。矿工类中有两个方法,一个mine方法,也就是挖矿的意思,用来生成新的区块,并会返回该区块生成的用时长短。

另一个方法是hash生成的方法,生成原则我们一切从简,因为一般使用的 PC 计算力不足,区块的成功标准很简单,就是用sha256生成的编码最后结尾是0就满足要求,如果改成00,那会半天看不到结果。

下面我们看下这套实例的运行结果,设置一个长度为6的区块链,由于第一个区块是创世区块,所以真正开始创建的区块是从第二个开始。

最后看下整个区块链的结果:

这就是由这6个矿工依次创建的六个区块,根据hash值环环相扣。

以上就是本篇文章的全部内容,希望大家对区块链有更深入的了解。

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

扫码关注云+社区

领取腾讯云代金券