90使用Python从零开始开发区块链应用程序您将能够使用Flask微框架

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

使用Python从零开始开发区块链应用程序您将能够使用Flask微框架为区块链的不同功能创建端点,比如添加事务,然后在多个机器上运行脚本来创建一个去中心化网络。您还将了解如何构建一个简单的用户界面,以便与区块链进行交互,并存储任何用例的信息,比如对等支付、聊天或电子商务。Python是一种容易理解的编程语言,这是我在本教程中选择它的原因。通过学习本教程,您将实现一个公有区块链并了解它的实际应用。GitHub上提供了一个完整的样本应用程序代码,该应用程序完全是用Python编写的。获取代码主要逻辑包含在views.py文件中。让我们一起分析一下该逻辑,以便真正全面了解区块链。前提条件Python的基础编程知识Flask微框架(用于创建区块链服务器的端点)背景2008年,一个名叫SatoshiNakamoto的人(或者可能是一个小组)发表了一篇名为《比特币:一种对等电子现金系统》的白皮书。该文章结合了密码学技术和对等网络,不需要依靠中心化权威机构(比如银行)就能在人们之间实现付款。比特币应运而生。除了比特币之外,这篇文章还介绍了一种存储数据的分布式系统(即现在广为人知的“区块链”),该系统的适用范围远不只是付款或加密货币。从那时起,几乎每个行业都对区块链产生了浓厚的兴趣。无论是像比特币这样的完全数字化的货币、像以太坊这样的分布式计算技术,还是像IBMBlockchainPlatform所基于的HyperledgerFabric这样的开源框架,现在都以区块链作为其背后的基础技术。“区块链”是什么?区块链是一种存储数字数据的方式。数据可以是任何内容。对于比特币,它是事务(在帐户之间转移比特币),它甚至可以是文件;这都无关紧要。数据是以区块形式进行存储的,区块使用哈希值链接在一起。因此得名“区块链”。区块链的神奇之处是在其中添加和存储此类数据的方式,该方式造就了一些非常理想的特征:历史记录无法更改系统无法攻破数据的持久保存没有单点故障那么区块链如何能够实现这些特征呢?我们将通过实现一个区块链来深入剖析它。让我们开始吧。关于该应用程序首先定义一下我们将要构建的应用程序的用途。我们的目的是构建一个允许用户共享信息的简单网站。因为内容将存储在区块链中,所以它无法更改且会永远存在。我们将采用自下而上的实现方式。首先定义我们将存储在区块链中的数据的结构。一篇帖子(任何用户在我们的应用程序上发布的一条消息)将由3个基本要素来标识:.1内容2.作者3.时间戳将事务存储到区块中我们将采用一种广泛使用的格式来将数据存储在区块链中:JSON。以下是一篇存储在区块链中的帖子的格式:{author:some_author_name,content:Somethoughtsthatauthorwantstoshare,timestamp:Thetimeatwhichthecontentwascreated}术语“数据”通常在互联网上被“事务”一词所取代。所以,为了避免混淆并保持一致,我们将使用术语“事务”来表示在我们的示例应用程序中发布的数据。事务被打包到区块中。一个区块可以包含一个或许多个事务。包含事务的区块频繁地生成并添加到区块链中。因为可能有多个区块,所以每个区块都应有一个唯一ID:classBlock:def__init__(self,index,transactions,timestamp):self.index=[]self.transactions=transactionsself.timestamp=timestamp让区块不可更改我们希望检测出对区块内存储的数据的任何篡改。在区块链中,这是使用一个哈希函数来实现的。哈希函数接受任何大小的数据并生成固定大小的数据,该结果通常用于识别输入。下面是Python中的一个使用sha256哈希函数的示例:fromhashlibimportsha256data=Somevariablelengthdatasha256(data).hexdigest()'b919fbbcae38e2bdaebb6c04ed4098e5c70563d2dc51e085f784c058ff208516'sha256(data).hexdigest()#nomatterhowmanytimesyourunit,theresultisgoingtobethesame256characterstring'b919fbbcae38e2bdaebb6c04ed4098e5c70563d2dc51e085f784c058ff208516'一个理想的哈希函数包括以下特征:它应该很容易计算。哪怕只更改数据中的一个位,哈希值也应该完全发生变化。应该无法根据输出哈希值猜出输入。您现在知道哈希函数是什么了吧。我们将每个区块的哈希值都存储在Block对象内的一个字段中,其作用类似于它所包含的数据的数字指纹:fromhashlibimportsha256importjsondefcompute_hash(block):Afunctionthatcreatesthehashoftheblock.block_string=json.dumps(self.__dict__,sort_keys=True)returnsha256(block_string.encode()).hexdigest()备注:在大多数加密货币中,甚至对区块中的各个事务也进行了哈希运算,从而形成一棵哈希树(也称为二进制哈希树),这棵树的根可以用作区块的哈希值。它不是区块链正常运作的必要条件,所以我们将省略它,以保持代码简洁。链接区块我们已设置了区块。区块链应该是一个区块集合。我们可以将所有区块都存储在Python列表中(等效于数组)。但这还不够,因为如果有人故意替换了集合中的一个区块该怎么办?用修改过的事务创建一个新的区块,计算哈希值,然后替换任何旧区块,这在我们的当前实现中并不是什么难事,因为我们会保持区块的不可更改性和顺序。我们需要采用某种途径来确保对过去的区块的任何更改都会造成整个链的失效。一种方法是通过哈希值将区块链接起来。谈到链接,我们指的是将前一个区块的哈希值包含在当前区块中。所以,如果任何以前的区块的内容发生更改,该区块的哈希值也会发生更改,导致与下一个区块中的previous_hash字段不匹配。每个区块都通过previous_hash字段链接到前一个区块,但是第一个区块该如何处理?第一个区块称为创始区块,大多数情况下,它是手动生成或通过某种独特逻辑生成的。让我们将previous_hash字段添加到Block类中,并实现我们的Blockchain类的初始结构(参见清单1)。清单1.我们的Blockchain类的初始结构fromhashlibimportsha256importjsonimporttimeclassBlock:def__init__(self,index,transactions,timestamp,previous_hash):self.index=indexself.transactions=transactionsself.timestamp=timestampself.previous_hash=previous_hashdefcompute_hash(self):block_string=json.dumps(self.__dict__,sort_keys=True)returnsha256(block_string.encode()).hexdigest()这是我们的Blockchain类:classBlockchain:def__init__(self):self.unconfirmed_transactions=[]#datayettogetintoblockchainself.chain=[]self.create_genesis_block()defcreate_genesis_block(self):Afunctiontogenerategenesisblockandappendsittothechain.Theblockhasindex0,previous_hashas0,andavalidhash.genesis_block=Block(0,[],time.time(),0)genesis_block.hash=genesis_block.compute_hash()self.chain.append(genesis_block)@propertydeflast_block(self):returnself.chain[-1]实现工作量证明算法但这里存在一个问题。如果我们更改前一个区块,我们可以非常轻松地重新计算所有后续区块的哈希值,并创建一个不同的有效区块链。为了预防这种情况,我们必须让计算哈希值的任务变得困难和随机化。以下是我们实现此操作的方式。我们不会接受任何区块哈希值,而是对它添加某种约束。让我们来添加一种约束:哈希值应以两个前导零开始。另外我们知道,除非更改区块的内容,否则哈希值不会发生更改。所以我们将在区块中引入一个称为随机数的新字段。随机数会不断变化,直到我们获得满足约束条件的哈希值。前导零的数量(在我们的例子中为值2)决定了工作量证明算法的“难度”。您可能还注意到,我们的工作量证明很难计算,但在我们确定随机数后很容易验证(对于验证,您只需要再次运行哈希函数即可):classBlockchain:#difficultyofPoWalgorithmdifficulty=2Previouscodecontd..defproof_of_work(self,block):Functionthattriesdifferentvaluesofnoncetogetahashthatsatisfiesourdifficultycriteria.block.nonce=0computed_hash=block.compute_hash()whilenotcomputed_hash.startswith('0'*Blockchain.difficulty):block.nonce+=1computed_hash=block.compute_hash()returncomputed_hash请注意,没有明确的逻辑来快速确定随机数;只能通过暴力破解。将区块添加到链中要将区块添加到链中,首先需要验证所提供的工作量证明是否正确,以及要添加的区块的previous_hash字段是否指向链中的最新区块的哈希值。让我们看看将区块添加到链中的代码:classBlockchain:Previouscodecontd..defadd_block(self,block,proof):Afunctionthataddstheblocktothechainafterverification.previous_hash=self.last_block.hashifprevious_hash!=block.previous_hash:returnFalseifnotself.is_valid_proof(block,proof):returnFalseblock.hash=proofself.chain.append(block)returnTruedefis_valid_proof(self,block,block_hash):Checkifblock_hashisvalidhashofblockandsatisfiesthedifficultycriteria.return(block_hash.startswith('0'*Blockchain.difficulty)andblock_hash==block.compute_hash())挖矿事务最初存储在一个未确认事务池中。将未确认事务放入区块中并计算工作量证明的过程被称为区块挖矿。一旦找到满足我们的约束条件的随机数,我们就可以说挖到了一个区块,这个区块就会放入区块链中

1 / 15
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功