社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  区块链

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

区块链技术学习 • 6 年前 • 224 次点击  

来自:巴比特,作者:洒脱喜

链接:https://www.8btc.com/article/1422497


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


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


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


在你开始之前……


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


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



挖矿端点


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


计算工作量证明

通过一笔交易授予矿工(我们)代币,以作为奖励;

创造新区块,并将其添至区块链;



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


步骤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:5000 和 http://localhost:5001



注册一个新节点


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



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


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



●编号130,输入编号直达本文

●输入m获取文章目录


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/29776
 
224 次点击