Python学习入门之区块链详解


Posted in Python onJuly 25, 2017

前言

本文将给大家简单介绍关于区块链(BlockChain)的相关知识,并用Python做一简单实现。下面话不多说,来一起看看详细的介绍:

什么是区块链

简单来说,区块链就是把加密数据(区块)按照时间顺序进行叠加(链)生成的永久、不可逆向修改的记录。具体来说,它区块链是由一串使用密码学方法产生的数据块组成的,每一个区块都包含了上一个区块的哈希值(hash),从创始区块(genesis block)开始连接到当前区块,形成块链。每一个区块都确保按照时间顺序在上一个区块之后产生,否则前一个区块的哈希值是未知的。它是比特币的一个重要概念。

特点

区块链有如下特点:

  • 去中心化:区块链不依赖于某个中心节点,而是依赖于分布式的各个节点。
  • 无须信任系统:区块链中基于密码学算法,数据需要网络内其他用户的批准,所以不需要一套第三方中介结构或信任机构背书。
  • 不可篡改和加密安全性:区块链采取单向哈希算法,同时每个新产生的区块严格按照时间线形顺序推进,时间的不可逆性导致任何试图入侵篡改区块链内数据 信息的行为都很容易被追溯,导致被其他节点的排斥,从而可以限制相关不法行为。

以上特点使得区块链在银行、证券市场和金融等诸多领域有着越来越多的应用。

区块链工作原理

区块链式一系列加密的数据块。这些区块由一个包含元数据的区块头和紧跟其后的构成区块主体的一长串交易组成。比特币中的区块结构如下:

Python学习入门之区块链详解

区块头

区块头中包含了与区块链中其它区块中的连接信息、时间戳和nonce等信息,具体如下:

Python学习入门之区块链详解

区块标识符

区块有两个标示符,一是区块头的哈希值,二是区块高度。区块头的哈希值是通过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)

以上就是一个区块结构,这里实现的是一个简化版,没有完全对应比特币中的区块。这里的区块包含一个唯一标识符、父节点的哈希值、nonce值和该区块的内容字段。可以看到一个区块的哈希值必须满足一定的条件才是有效的,比如以0000开始。下面对这个区块结构进行初始化。

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>

以上就是一个简单区块链,后面还会涉及到区块链的有效性。当区块链中一个区块被改变后,这个区块的哈希就会改变,从而影响到这块区块之后的区块,致使这个区块链不再有效。这些将在后续继续深入。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
用Python实现一个简单的能够发送带附件的邮件程序的教程
Apr 08 Python
仅用50行代码实现一个Python编写的计算器的教程
Apr 17 Python
Python的Scrapy爬虫框架简单学习笔记
Jan 20 Python
详解常用查找数据结构及算法(Python实现)
Dec 09 Python
Python基于回溯法子集树模板解决全排列问题示例
Sep 07 Python
python多进程中的内存复制(实例讲解)
Jan 05 Python
Django中使用Celery的教程详解
Aug 24 Python
Python常用特殊方法实例总结
Mar 22 Python
python 实现提取log文件中的关键句子,并进行统计分析
Dec 24 Python
Python 窗体(tkinter)下拉列表框(Combobox)实例
Mar 04 Python
Python reversed函数及使用方法解析
Mar 17 Python
opencv 图像礼帽和图像黑帽的实现
Jul 07 Python
Python列表list解析操作示例【整数操作、字符操作、矩阵操作】
Jul 25 #Python
Python中的错误和异常处理简单操作示例【try-except用法】
Jul 25 #Python
Python中函数及默认参数的定义与调用操作实例分析
Jul 25 #Python
Python实现类的创建与使用方法示例
Jul 25 #Python
python数据结构之链表的实例讲解
Jul 25 #Python
python数据结构链表之单向链表(实例讲解)
Jul 25 #Python
利用python模拟实现POST请求提交图片的方法
Jul 25 #Python
You might like
浅析PHP页面局部刷新功能的实现小结
2013/06/21 PHP
PHP session_start()问题解疑(详细介绍)
2013/07/05 PHP
在Windows XP下安装Apache+MySQL+PHP环境
2015/02/22 PHP
php mysql操作mysql_connect连接数据库实例详解
2016/12/26 PHP
利用php-cli和任务计划实现刷新token功能的方法
2017/05/03 PHP
PHP Socket网络操作类定义与用法示例
2017/08/30 PHP
Jquery AJAX 用于计算点击率(统计)
2010/06/30 Javascript
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
2010/12/04 Javascript
js解析xml字符串和xml文档实现原理及代码(针对ie与火狐)
2013/02/02 Javascript
js switch case default 的用法示例介绍
2013/10/23 Javascript
随鼠标移动的时钟非常漂亮遗憾的是只支持IE
2014/08/12 Javascript
JavaScript返回0-1之间随机数的方法
2015/04/06 Javascript
微信小程序 使用picker封装省市区三级联动实例代码
2016/10/28 Javascript
简单的渐变轮播插件
2017/01/12 Javascript
JavaScript条件判断_动力节点Java学院整理
2017/06/26 Javascript
VUE实现表单元素双向绑定(总结)
2017/08/08 Javascript
vue-iview动态新增和删除的方法
2020/06/17 Javascript
vue解决跨域问题(推荐)
2020/11/10 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
2020/12/07 Vue.js
[01:00]DOTA2 store: Collection of Artisan's Wonders
2015/08/12 DOTA
[01:33:25]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第一场 1月24日
2021/03/11 DOTA
Python文件夹与文件的操作实现代码
2014/07/13 Python
黑科技 Python脚本帮你找出微信上删除你好友的人
2016/01/07 Python
Python基于回溯法子集树模板解决0-1背包问题实例
2017/09/02 Python
python 实现视频流下载保存MP4的方法
2019/01/09 Python
实例讲解Python3中abs()函数
2019/02/19 Python
Python pandas RFM模型应用实例详解
2019/11/20 Python
python实现局域网内实时通信代码
2019/12/22 Python
Spring http服务远程调用实现过程解析
2020/06/11 Python
python 读txt文件,按‘,’分割每行数据操作
2020/07/05 Python
详解PyQt5中textBrowser显示print语句输出的简单方法
2020/08/07 Python
公司优秀员工获奖感言
2014/08/14 职场文书
详细的本科生职业生涯规划范文
2014/09/16 职场文书
装修公司工程部经理岗位职责
2015/04/09 职场文书
改进工作作风心得体会
2016/01/23 职场文书
JavaScript文档对象模型DOM
2021/11/20 Javascript