太简单!只学十分钟,Python菜鸟也能开发一个区块链客户端
区块链技术以其去中心化特性成为又一具有颠覆性特征的技术。Python作为一种面向对象的解释型计算机程序设计语言,因其具有丰富和强大的库,常被称为“胶水语言”,简单、易上手,是区块链技术爱好者快速学习区块链的首选之一。
本文作者Adil Moujahid 是世界IT服务企业排名前十、日本IT服务企业排名榜首的NTT DATA集团的数据科学家,对Python在区块链方向的应用有着十分深入的研究。
在这篇文章中,Adil Moujahid 由双重支付问题引出去中心化支付方案,介绍公钥密码学、Hash函数、挖矿等区块链核心概念,并详细阐述如何产生一个新区快、如何将新区快添加到区块链等问题,最后,利用Python实现基本的区块链和区块链客户端。
在了解区块链的核心概念之后,让Adil Moujahid 手把手,教你用Python实现区块链和区块链客户端的实操吧!干货满满!
作者 | Adil Moujahid
编译 | kou、Eli
可以说,区块链是自互联网诞生以来最重要和最具颠覆性的技术之一。作为比特币和其他加密货币背后的核心技术,区块链在过去几年获得了广泛关注。
区块链是一个分布式数据库,允许双方之间直接进行交易,而无需第三方权限,对银行、政府和市场等机构具有很大影响。
任何依赖中心化数据库作为核心竞争优势的企业或组织都可能被区块链技术所颠覆。
本文分三部分,前两部分介绍区块链的核心概念;第三部分介绍如何利用Python实现区块链以及2个区块链Web应用程序,以便终端用户轻松与区块链进行链上交互,效果图如下。
极简的区块链速成教程
2008年中本聪发布标题为“比特币:点对点电子现金系统” 的比特币白皮书,奠定了区块链的基础。
在最初的比特币白皮书中,中本聪描述了如何建立一个点对点电子现金系统,允许不通过中心化机构实现在线支付,直接从一方发送到另一方。该系统解决了数字货币中一个称为双重支付的重要问题。
什么是双重支付?
假设Alice想要支付Bob 1美元。如果Alice和Bob使用实物现金,那么Alice在执行交易后将不再拥有1美元;如果Alice和Bob使用数字货币,那么问题会变得更加复杂。
数字货币以数字形式存在,可以轻松进行复制。例如,如果Alice通过电子邮件向Bob发送价值1美元的数字文件,则Bob无法确定Alice是否删除了她的文件副本,如果Alice仍然拥有1美元数字文件,那么她可以选择将相同的文件发送给Carol。这个问题就叫做双重支付。
解决双重支付问题的一种方法是在Alice、Bob和网络中其他参与者之间建立可信任的第三方(例如银行),该第三方负责管理中心化分类账,而分类账跟踪并验证网络中的所有交易。该解决方案的缺点是,为了使系统运行,它需要信任中心化的第三方。
比特币:双重支付问题的去中心化方案
为了解决双重支付问题,中本聪提出了一个公共分类账,即通过比特币的区块链来跟踪网络中的所有交易。比特币的区块链具有以下特征:
分布式:分类帐在多台计算机上复制,而不是存储在中央服务器上。任何具有互联网连接的计算机都可以下载区块链的完整副本。
加密:用于确认发送人持有她想要发送的比特币,并决定如何将交易添加到区块链中。
不可变:交易只能添加到区块链中,但不能删除或修改。
工作量证明(PoW):网络中一种特殊类型的参与者称为矿工,他们竞争搜索加密难题的解决方案,该解决方案允许他们向比特币的区块链添加一个交易区块,此过程称为工作量证明,它能确保系统安全。
发送比特币资金流程如下:
创建一个比特币钱包。用于发送或接收比特币,比特币钱包存储2条信息:私钥和公钥。私钥是一个秘密号码,允许所有者将比特币发送给另一个用户,或者消费比特币。公钥是接收比特币所需的数字。钱包本身不存储比特币,有关比特币余额的信息存储在比特币的区块链中。
创建比特币交易。如果Alice想要向Bob发送1个比特币,Alice需要使用她的私钥连接到她的比特币钱包,并创建一个包含她想要发送的比特币数量和地址的交易。
将交易广播到比特币网络。一旦Alice创建比特币交易,她需要将此交易广播到整个比特币网络。
确认交易。收听到比特币网络的矿工使用Alice的公钥验证交易,确认Alice的钱包中有足够的比特币,并向比特币区块链添加一条包含交易详细信息的新纪录。
将区块链的变更广播给所有矿工。 一旦交易得到确认,该矿工应向所有矿工广播区块链变更,以确保他们的区块链副本全部同步。
区块链技术深度研究
为深入研究区块链技术构建模块,作者系统介绍了公钥密码学,Hash函数和区块链挖掘及安全性等。
公钥密码学
公钥密码学或非对称加密学是任何使用密钥对的加密系统:包括可以广泛传播的公钥,以及只有所有者知道的私钥。 这实现了两个基本功能:
身份验证:公钥验证发送消息的配对私钥的持有者
加密:只有配对的私钥持有者可以解密用公钥加密的消息。
RSA和ECDSA(椭圆曲线数字签名算法)是最流行的公钥加密算法,ECDSA算法用于生成比特币钱包。
为了发送或接收BTC,用户首先生成包含一对私钥和公钥的钱包。
如果Alice想要向Bob发送一定数量的BTC,她会创建一个交易,在该交易中输入她和Bob的公钥以及她想要发送的BTC数量,然后使用她的私钥签署交易。
区块链上的计算机使用Alice的公钥来验证交易是否可信,并将交易写入即将添加到区块链的区块中。
Hash函数和挖掘
所有比特币交易都存储在称为区块的文件中。比特币每10分钟增加一个新的交易区块,将新区块添加到区块链后,它将不可变、无法删除和修改。
网络中一组特殊的参与者称为矿工(连接到区块链的计算机),负责创建新的交易区块。矿工必须使用发件人的公钥对每笔交易进行身份验证,确认发件人有足够的余额用于所请求的交易,并将交易添加到块中。
矿工可以完全自由选择区块中的交易,因此发件人需要包含交易费以激励矿工将他们的交易添加到区块中。
对于区块链接受的区块,需要进行“挖掘”。为了挖掘区块,矿工需要找到一种非常罕见的加密难题解决方案。如果区块链接受了采矿区块,则矿工将获得比特币奖励,这是对交易费用的额外奖励。挖掘过程也称为工作量证明(PoW),它是使区块链无信任和安全的主要机制。
哈希和区块链加密难题
哈希函数是任何可以用来将任意大小的数据映射到固定大小的数据的函数。哈希函数返回的值称为Hash值。哈希函数通常用于通过检测重复的记录来加速数据库查找,它们在密码学中也被广泛使用。
哈希函数允许我们轻松地验证某些输入数据映射到给定的散列值,但是如果输入数据是未知的,那么通过存储的散列值来重构它是很困难的。
比特币使用称为SHA-256的加密哈希函数。SHA-256应用于区块数据(比特币交易)和名为Nonce的数字组合。通过更改区块数据或Nonce,我们得到完全不同的Hash值。
对于被认为有效或“已挖掘”的区块,区块和Nonce的Hash值需要满足特定条件。例如,Hash值的四个前导数字需要等于“0000”。 我们可以通过使条件更复杂来增加挖矿的复杂性,例如我们可以增加Hash值开头0的数量。
矿工需要解决的密码难题是找到一个Nonce值,使Hash值满足挖掘条件。
使用下面的应用程序来模拟区块挖掘。
当你在“Data”文本框中输入或更改Nonce值时,你会注意到Hash值的变化。 当你单击“Mine”按钮时,应用程序从Nonce等于零开始,计算Hash值并检查Hash值的前四位是否等于“0000”。
如果前四位数不等于“0000”,则将Nonce增加1并重复整个过程,直到找到满足条件的Nonce值。如果区块已开采,背景颜色变为绿色。
从区块到区块链
交易按区块分组,区块被附加到区块链。
为了创建一条由区块组成的链,每个新块使用前一个块的Hash值作为其数据的一部分。为了创建新块,矿工选择一组交易,添加前一个块的Hash值开始区块挖掘工作。
对任何区块数据进行的任何更改都将影响其后所有区块的Hash值,并且它们将变为无效,这就是区块链的不变性。
使用下面的应用程序模拟包含3个区块的区块链。
当你在“Data”文本框中输入或更改Nonce值时,你可以注意到当前区块Hash值以及下一区块的“Prev”值(上一个Hash值)的变化。
你可以通过单击每个块的“Mine”按钮来模拟挖矿过程。挖掘出3个区块之后,尝试更改块1或2中的数据,你将注意到之后的所有区块都变为无效。
将区块添加到区块链
比特币网络中的所有矿工互相竞争,以找到一个有效的区块,该区块将被添加到区块链并从网络获得奖励。
虽然找到验证区块Nonce几率很低,但由于矿工的数量很多,网络中矿工验证区块的概率非常高。第一个提交有效区块的矿工将他的区块添加到区块链中并获得比特币的奖励。
如果两个矿工或更多的矿工同时提交,会发生什么呢?
解决冲突
如果2名矿工几乎同时解决一个区块,那么我们将在网络中有2个不同的区块链,我们需要等待下一个区块来解决冲突。 一些矿工选择在区块链1顶部挖掘,其他矿工选择在区块链2顶部挖掘。
当有矿工找到一个新的区块之后,冲突就被解决了。
如果新区块在区块链1的顶部被挖掘出来,则区块链2变为无效,前一区块的奖励通过区块链1奖励给矿工,区块链2部分和未添加到区块链中的交易将被退回到交易池并添加到下一个块。
简而言之,如果区块链存在冲突,那么最长的链就会获胜。
区块链和双重支付
接下来,详细介绍对区块链进行双重支付攻击的常见形式,以及用户为防止受到损害应采取的措施。
种族攻击:攻击者将相同的硬币快速发送到两个不同的地址。为防止此类攻击,建议在接受付款前等待至少一次区块确认。
芬尼攻击:攻击者使用交易预先挖掘区块,并在释放区块之前在第二个交易中花费相同的币。 在这种情况下,将不验证第二个交易。为防止此类攻击,建议在接受付款前等待至少6次区块确认。
51%攻击:在这类攻击中,攻击者拥有网络51%的算力。攻击者首先向整个网络广播进行交易,然后挖掘一个私有区块链,在那里将上一笔交易的币加倍。
由于攻击者拥有大部分算力,因此保证他在某些时候会拥有比正常网络更长的链。然后,他可以发布更长的区块链,取代正常区块链并取消原始交易。
这种攻击极不可能,因为它在像比特币这样的区块链网络中非常昂贵。
Python中的区块链实现
在本节中,我们将使用Python实现基本的区块链和区块链客户端。
区块链将具有以下功能:
在区块链中添加多个节点
工作量证明(PoW)
节点之间的简单冲突解决方案
区块链客户端将具有以下功能:
使用公钥/私钥加密生成钱包(基于RSA算法)
使用RSA加密生成交易
还将实现2个显示页:
供矿工使用的“区块链前端”
供用户生成钱包和发送数字货币的“区块链客户端”
本文区块链实现主要参考下面的GitHub项目,作者对原始代码进行了一些修改,以便为交易添加RSA加密。
使用Jupyter notebook生成电子钱包,进行加密交易,使用HTML / CSS / JS2完成2个显示页。
区块链客户端
切换到blockchain_client文件夹下,在终端输入python blockchain_client.py,启动区块链客户端。在浏览器中,转到http:// localhost:8080,你将看到下面的显示页面。
显示页面在导航栏中有3个选项卡:
Wallet Generator:使用RSA加密算法生成钱包(公钥/私钥对)
Make Transaction:生成交易并将其发送到区块链节点
View Transasctions:查看区块链上的交易
要创建或查看交易,你至少需要运行一个区块链节点。
下面,对blockchain_client.py代码重要的部分进行解释。
定义一个名为Transaction的python类,它有 sender_address,sender_private_key,recipient_address 和 value 4个属性。这些是发件人创建交易所需的4条信息。
使用to_dict()方法以Python字典格式(没有发件人的私钥)返回交易信息。
通过使用 sign_transaction()方法获取交易信息(没有发件人的私钥),并使用发件人的私钥对其进行签名。
启动一个Python Flask应用程序,使用它来创建不同的API,与区块链及其客户端进行交互。
下面定义3个Flask html页面返回路径,每个标签连接一个html页面。
然后,定义一个生成钱包的API(私钥/公钥对)。
下面定义一个API,将sender_address,sender_private_key,recipient_address,value 作为输入项,并返回交易(没有私钥)和签名。
区块链
转到blockchain文件夹从终端启动区块链节点,然后键入python blockchain_client.py或python blockchain_client.py -p <PORT NUMBER>。如果未指定端口号,则默认为端口5000。在浏览器中,转到http:// localhost:<PORT NUMBER>查看区块链前端显示页。
导航栏下显示页有2个选项卡:
Mine:用于查看交易和区块链数据,以及挖掘新的交易区块。
Configure:用于配置不同区块链节点之间的连接。
接下来,对blockchain.py代码中重要部分进行解释。
首先定义一个具有以下属性的Blockchain类:
transactions:将添加到下一区块的交易列表。
chain:由一系列区块组成的区块链。
nodes:包含节点url的集合。区块链使用这些节点从其他节点检索区块链数据,如果它们不同步则更新其区块链。
node_id:用于标识区块链节点的随机字符串。
Blockchain类还实现了以下方法:
register_node(node_url):将新的区块链节点添加到节点列表中。
verify_transaction_signature(sender_address, signature, transaction):检查提供的签名是否与公钥(sender_address)签名的交易相对应。
socmit_transaction(sender_address,recipient_address,value,signature):如果签名已验证,则将交易添加到交易列表中。
create_block(Nonce,previous_hash):向区块链添加一个包含交易信息的区块。
hash(block):创建一个区块的SHA-256 Hash值。
proof_of_work():工作量证明。寻找满足挖掘条件的Nonce。
valid_proof(transactions,last_hash,Nonce,difficulty = MINING_DIFFICULTY):检查Hash值是否满足挖掘条件,此函数在proof_of_work函数中使用。
valid_chain(chain):检查区块链是否有效。
resolution_conflicts():通过用网络中最长的链替换链来解决区块链节点之间的冲突。
启动一个Python Flask应用程序,使用它创建不同的API以与区块链进行交互。
接下来,启动Blockchain实例。
定义2条返回区块链前端html页面的Flask路径。
下面定义Flask API来管理交易和挖掘区块链。
'/ transactions / new':此API用来输入 'sender_address', 'recipient_address','amount'和'signature',并将交易添加到签名有效的、可添加到下一区块的交易列表中。
'/ transactions / get':此API返回可以被添加到下一区块的所有交易。
'/ chain':此API返回所有区块链数据。
'/ mine':此API运行工作量证明算法,并将新的交易块添加到区块链中。
下面定义Flask API来管理区块链节点。
'/ nodes / register':此API将节点URL列表作为输入,并将它们添加到节点列表中。
'/ nodes / resolve':此API通过用网络中可用的最长链替换本地链来解决区块链节点之间的冲突。
'/ nodes / get':此API返回节点列表。
原文链接:
http://adilmoujahid.com/posts/2018/03/intro-blockchain-bitcoin-python/
源代码:
https://github.com/adilmoujahid/blockchain-python-tutorial
参考资源:
1 - Wikipedia - Public-key cryptography
2 - Wikipedia - Hash function
3 - Bitcoin Stackexchange - What happens to a transaction once generated?
4 - Bitcoin Wiki - Majority attack
5 - 比特币白皮书、
6 - 比特币维基
7 - Andreas Antonopoulos:Mastering Bitcoin: Programming the Open
最新热文:
扫码加入区块链大本营读者群,群满加微信 qk15732632926 入群
了解更多区块链技术及应用内容
敬请关注: