Python学习入门之区块链详解
作者:101python 发布时间:2021-07-15 18:21:55
前言
本文将给大家简单介绍关于区块链(BlockChain)的相关知识,并用Python做一简单实现。下面话不多说,来一起看看详细的介绍:
什么是区块链
简单来说,区块链就是把加密数据(区块)按照时间顺序进行叠加(链)生成的永久、不可逆向修改的记录。具体来说,它区块链是由一串使用密码学方法产生的数据块组成的,每一个区块都包含了上一个区块的哈希值(hash),从创始区块(genesis block)开始连接到当前区块,形成块链。每一个区块都确保按照时间顺序在上一个区块之后产生,否则前一个区块的哈希值是未知的。它是比特币的一个重要概念。
特点
区块链有如下特点:
去中心化:区块链不依赖于某个中心节点,而是依赖于分布式的各个节点。
无须信任系统:区块链中基于密码学算法,数据需要网络内其他用户的批准,所以不需要一套第三方中介结构或信任机构背书。
不可篡改和加密安全性:区块链采取单向哈希算法,同时每个新产生的区块严格按照时间线形顺序推进,时间的不可逆性导致任何试图入侵篡改区块链内数据 信息的行为都很容易被追溯,导致被其他节点的排斥,从而可以限制相关不法行为。
以上特点使得区块链在银行、证券市场和金融等诸多领域有着越来越多的应用。
区块链工作原理
区块链式一系列加密的数据块。这些区块由一个包含元数据的区块头和紧跟其后的构成区块主体的一长串交易组成。比特币中的区块结构如下:
区块头
区块头中包含了与区块链中其它区块中的连接信息、时间戳和nonce等信息,具体如下:
区块标识符
区块有两个标示符,一是区块头的哈希值,二是区块高度。区块头的哈希值是通过SHA256算法对区块头进行二次哈希计算而得到的数字。区块哈希值可以唯一、明确地标识一个区块,并且任何节点通过简单地对区块头进行哈希计算都可以独立地获取该区块哈希值。区块高度是指该区块在区块链中的位置。区块高度并不是唯一的标识符。虽然一个单一的区块总是会有一个明确的、固定的区块高度,但反过来却并不成立,一个区块高度并不总是识别一个单一的区块。两个或两个以上的区块可能有相同的区块高度,在区块链里争夺同一位置。
了解了以上基础后下面开始用Python实现一个简单的区块链。
区块链的Python实现
一、定义区块结构
In [16]:
# block.py
import hashlib
import uuid
class Block(object):
def __init__(self, data=None, previous_hash=None):
self.identifier = uuid.uuid4().hex # 产生唯一标示
self.nonce = None # nonce值
self.data = data # 区块内容
self.previous_hash = previous_hash # 父节点哈希值
def hash(self, nonce=None):
'''
计算区块的哈希值
'''
message = hashlib.sha256()
message.update(self.identifier.encode('utf-8'))
message.update(str(nonce).encode('utf-8'))
message.update(str(self.data).encode('utf-8'))
message.update(str(self.previous_hash).encode('utf-8'))
return message.hexdigest()
def hash_is_valid(self, the_hash):
'''
校验区块哈希值有否有效
'''
return the_hash.startswith('0000')
def __repr__(self):
return 'Block<Hash: {}, Nonce: {}>'.format(self.hash(), self.nonce)
In [37]:
# 创建一个内容为hello world的内容块
block = Block('Hello World')
block
Out[37]:
Block<Hash: 238a65a101c8829d7fc406eb78a71cfc19ad702b437e2c1be8d9061ddb81e900, Nonce: None>
以上一个区块虽然创建完成,但其哈希值不是有效的。
In [38]:
block.hash_is_valid(block.hash())
Out[38]:
False
改变nonce的值就可以得到一个新的哈希值。
In [39]:
block.hash(1)
Out[39]:
'a6431938ba10270dfcfdf7a2371312446914fedadf79632c2c0adb3b463f4838'
哈希值更新了,但还不是有效的哈希值。为了得到有效哈希值,是一个不断更新nonce值的过程,或者说一个挖矿(mine)过程。下面添加一个mine函数用来得到一个合适的nonce值。
In [78]:
# block.py
import hashlib
import uuid
class Block(object):
def __init__(self, data=None, previous_hash=None):
self.identifier = uuid.uuid4().hex # 产生唯一标示
self.nonce = None # nonce值
self.data = data # 区块内容
self.previous_hash = previous_hash # 父节点哈希值
def hash(self, nonce=None):
'''
计算区块的哈希值
'''
message = hashlib.sha256()
message.update(self.identifier.encode('utf-8'))
message.update(str(nonce).encode('utf-8'))
message.update(str(self.data).encode('utf-8'))
message.update(str(self.previous_hash).encode('utf-8'))
return message.hexdigest()
def hash_is_valid(self, the_hash):
'''
校验区块哈希值有否有效
'''
return the_hash.startswith('0000')
def __repr__(self):
return 'Block<Hash: {}, Nonce: {}>'.format(self.hash(self.nonce), self.nonce)
'''
新增挖矿函数
'''
def mine(self):
# 初始化nonce为0
cur_nonce = self.nonce or 0
# 循环直到生成一个有效的哈希值
while True:
the_hash = self.hash(nonce=cur_nonce)
if self.hash_is_valid(the_hash): # 如果生成的哈希值有效
self.nonce = cur_nonce # 保持当前nonce值
break # 并退出
else:
cur_nonce += 1 # 若当前哈希值无效,更新nonce值,进行加1操作
In [75]:
block = Block('Hello World')
# 挖矿,循环直至找到合适的nonce
block.mine()
# 打印
block
Out[75]:
Block<Hash: 000087359d5264153d624556f0a0c6f25cba06e453975c1c02587862e823911b, Nonce: 64751>
至此,第一个有效的区块生成完成,下面开始定义区块链。
二、定义区块链结构
In [81]:
class BlockChain(object):
def __init__(self):
self.head = None # 指向最新的一个区块
self.blocks = {} # 包含所有区块的一个字典
'''
添加区块函数
'''
def add_block(self, new_block):
previous_hash = self.head.hash() if self.head else None
new_block.previous_hash = previous_hash
self.blocks[new_block.identifier] = {
'block': new_block,
'previous_hash': previous_hash,
'previous': self.head,
}
self.head = new_block
def __repr__(self):
num_existing_blocks = len(self.blocks)
return 'Blockchain<{} Blocks, Head: {}>'.format(
num_existing_blocks,
self.head.identifier if self.head else None
)
定义好区块链结构后,下面就开始初始化一条区块链。
In [82]:
# 初始化
chain = BlockChain()
# 打印
chain
Out[82]:
Blockchain<0 Blocks, Head: None>
In [83]:
# 添加区块
chain.add_block(block)
# 打印
chain
Out[83]:
Blockchain<1 Blocks, Head: 364c0cf963384ca28a2763499a140405>
In [84]:
# 添加更多的区块
for i in range(6):
new_block = Block(i)
new_block.mine()
chain.add_block(new_block)
# 打印
chain
Out[84]:
Blockchain<7 Blocks, Head: e7cb24ec7acd42a4aaebe7faee9e0713>
来源:https://ask.hellobi.com/blog/101python/8978


猜你喜欢
- 一、类型1.变量没有类型,数据有类型例:num = 1 ---->num是没有类型的,1是int类型二、格式化输出2.na
- PIL vs PillowPIL: Python Imaging Library,是python的图像处理库。由于PIL不兼容setupto
- 快速+简单搭建环境。如果有问题,欢迎进群讨论留言。第一步:安装python解释器官网地址:https://www.python.org/自动
- IE中的获取文本方法innerText在firefox中不支持 firefox改成了textContent方法/属性 并且在Firefox中
- 一、Python+unittest+requests+HTMLTestRunner 完整的接口自动化测试框架搭建_00——框架结构简解&nb
- 1) 使用字典dict()循环遍历出一个可迭代对象中的元素,如果字典没有该元素,那么就让该元素作为字典的键,并将该键赋值为1,如果存在就将该
- slice:eg:>>>e=[0,1,2,3,4,5,6]>>>s=slice(2,3)>>
- 1、检测登录状态base.pydef checkLogin(func):""" 查看session
- Python函数的设计规范1、Python函数设计时具备耦合性和聚合性1)、耦合性:(1).尽可能通过参数接受输入,以及通过return产生
- 前言个人感觉骨架提取提取的就是开运算过程的不可逆。一.算法步骤1.算法步骤首先上一下比较官方的算法步骤:1.获得原图像的首地址及图像的宽和高
- 接触python已有一段时间了,下面针对python基础知识的使用做一完整梳理:1)避免‘\n'等特殊字符的两种方式:a)利用转义字
- 本文以一段简单的监听鼠标、键盘事件的程序,实现获取用户的输入(比如登录某些网站的账号、密码)的功能。经测试,对于一台“裸奔”的电脑,完全能获
- Mac下mysql安装配置方法图文教程记录如下使用安装包安装mysql双击pkg文件安装一路向下,记得保存最后弹出框中的密码(它是你mysq
- PyCharm是由JetBrains打造的一款Python IDE,VS2010的重构插件Resharper就是出自JetBrains之手。
- 一、为什么使用Python进行网络爬虫?由于Python语言十分简洁,使用起来又非常简单、易学,通过Python 进行编写就像使用英语进行写
- 处理前文件内容代码处理后的# 读取代码fr = open('three.txt', 'r')dic = {}
- 现在要解决的问题如下:我们有一个数据的表第7列有许多数字,并且是用逗号分隔的,数字又有一个对应的关系:我们要得到第7列对应关系的统计,就是每
- JavaScript/Dom中有很多很零碎的东西,让人总是感觉理解的有些“朦胧”,因此,有时候还是应该总结一下,对于Event对象,前两天看
- 分区表的概念 分区致力于解决支持极大表和索引的关键问题。它采用他们分解成较小和易于管理的称为分区的片(piece)的方法。一旦分区被定义,S
- 这篇文章中的内容是来源于去年我用美国的VPS搭建博客的初始阶段,那是有很多恶意访问,我就根据access log中的源IP来进行了很多统计,