简介

本系统在基本上参考了这篇博客,访问可能需要搭梯子;本文主要是进行了翻译和验证,同时提供了一个基本的思路,肯定有很多不足之处,希望dalao们积极指正,因为是刚开始学习区块链。。。需要少部分的Flask的知识,这是一个轻型的web框架,在这里我们用来模拟结点联网的操作。

本系统的可以实现的功能:

  1. 产生区块,把区块添加到区块链上。
  2. 根据加密算法,验证交易的合法性 。
  3. 验证区块的合法性。
  4. 验证区块链的合法性,选择最长的有效链作为主链。
  5. 进行简单的加密货币交易 。

本系统的不足:
1. 没有签名验证机制
2. 所有的数据都是存储在内存中的,暂时没有存储到硬盘中。
3. 一个区块中存储的交易是线性表存储的,没有使用Merkle树的数据结构,因此必须进行线性的计算验证,而不是对数级别的。
4. 交易机制有缺陷,无法验证交易金额的合理性。假设A可以向B支付任意数值的比特币。
5. 挖矿机制存在缺陷,仅仅是根据哈希数值计算出来的,只要是先计算出首位是4个0的,就可以获得记账权;但是比特币是每10分钟,看谁的计算力更强。
6. 全部都是零确认交易,很容易出现双重支付攻击。
7. 广播算法存在问题,可能会引起循环播放

总体说明:本系统主要是为了学习区块链基本思想的,仅仅是学习参考。后期我会逐步完善,整取做一个更加完善的系统,可以持续关注。

区块的结构

区块的数据用dict格式存放,正好方便与json格式进行交互。一个区块包含以下结构:

  • 在区块链中的编号
  • 时间戳,创建区块的时间
  • 包含的交易,如果区块入链,那么交易加入区块链;否则是待验证的交易。(list)
  • 用于证明工作量的数据。该数据随机生成,与前一个区块的proof进行哈希计算,之后得到算力证明的数据

之后,按照区块链的设计思路,一个区块分为区块头和区块体,区块体包含交易,区块头包含其余的信息。在这里单独介绍一下交易的数据结构。因为本系统仅仅是验证使用的,我们不检验交易的合理性,用户也没有自己的钱包,一笔交易的数据结构只有发送方、接收方和交易的比特币。

区块链的结构

一个区块链包含如下结构:

  • 主链,包含了当前所有经过验证的区块(list)
  • 缓冲链,包含了未经过验证的区块和有关的交易信息(list)
  • 结点集合,因为一个结点包含一条区块链,因此把邻接点的集合也放在主链中。(set)
  • 区块,包含了交易信息

加密算法检验有效性

真正的比特币的签名机制我在这篇博客中有详细介绍。但是,由于本文仅仅介绍基本工作流程,这里仅仅是验证区块的数据没有被更改过和工作量的有效性。本文的具体检验步骤如下:

  1. 工作量的证明。把前一个区块的proof和本区块的proof一起进行哈希,检验开头四个字符是否都是0
  2. 链的有效性证明。把一个区块链从前往后所有的区块执行1的操作,根据哈希值是否匹配来判断链的有效性。因为在创建新区块的时候,就把前一个区块的哈希值添加到了新区块的头部了。而创世区块的前一个区块的哈希值默认1,proof默认100。

工作量证明和挖矿机制

把前一个区块的proof值和当前区块的proof值进行哈希,如果前四个字符是0,表示工作量是有效的。寻找的过程如下:从0开始,逐渐累加,不断与前一个区块的proof进行hash,直到满足条件。挖矿的过程就是一个寻找proof的过程。

代码说明:

全部代码的github地址:https://github.com/StudentErick/BlockChains_in_python/tree/master

头文件

用到的头文件请自行安装,需要Flask框架。

import hashlib
import json
from time import time
from urllib.parse import urlparse
from uuid import uuid4
import requestsfrom flask import Flask, jsonify, request

区块的数据结构

初始化代码。self.current_transactions是未加入区块链的交易列表;self.chain是合法的区块链;self.node作为邻接结点,使用集合维护;同时,包含一个创世区块。

class BlockChains(object):def __init__(self):self.current_transactions = []  # 当前区块的交易self.chain = []  # 区块链self.new_block(previous_hash=1, proof=100)  # 产生创世区块self.nodes = set()  # 区块链中的结点,防止重复结点的出现......

创建新节点和添加区块的代码。区块的结构使用字典维护,方便后期与json格式转化;区块中包含一个交易列表、时间戳、前一个区块的哈希值和工作量证明proof。其实这里还有完善的地方,实际情况中,由于网络延时等的原因,交易列表里面会有很多信息没有经过验证,直接清空会有问题;不过,在这里仅仅作为示范,我们假设所有的交易都经过了验证。

class BlockChains(object):........def register_node(self, address):'''在区块链中添加新的结点:param address: <str>结点的地址,格式为'http://192.168.0.5:5000':return: None'''parsed_url = urlparse(address)self.nodes.add(parsed_url.netloc)  # 自动忽略已经存在的结点def new_block(self, proof, previous_hash=None):'''生成新的区块:param proof::param previous_hash:  前一个区块的哈希值:return: <dict> 新的区块'''s = str(previous_hash).encode('utf-8')block = {'index': len(self.chain) + 1,'timestamp': time(),'transactions': self.current_transactions,'proof': proof,'previous_hash': s or self.hash(self.chain[-1])}self.current_transactions = []self.chain.append(block)return block@propertydef last_block(self):return self.chain[-1]  # 返回最后一个区块...........

哈希以工作量证明部分的代码。正如之前提到的那样,我们把整个区块的内容进行哈希操作,得到一个256位哈希值的字符串作为标识。工作量证明也像之前提到的那样,前一个区块的proof与当前区块的proof进行哈希操作。区块链的有效性证明也像之前提到的那样。

class BlockChains(object):..........@staticmethoddef hash(block):'''生成区块的SHA-256哈希值:param block: <Block>当前区块的哈希值:return: <str>'''block_string = json.dumps(block, sort_keys=True)return hashlib.sha256(block_string).hexdigest()def proof_of_work(self, last_proof):'''寻找一个p,使得与前一个区块proof哈希后的数值有4个0开头:param last_proof: <int>:return: <int>'''proof = 0while self.valid_proof(last_proof, proof) is False:proof += 1return proof@staticmethoddef valid_proof(last_proof, proof):'''验证是否以4个0开头:param last_proof: 上一个区块的proof:param proof: 当前的proof:return: <bool>'''guess = (str(last_proof) + str(proof)).encode()  # 相当于一个字符串的拼接guess_hash = hashlib.sha256(guess).hexdigest()return guess_hash[:4] == "0000"def valid_chain(self, chain):'''判断当前的区块链是否是有效的,检查:param chain: <list>一个区块链的列表:return: <bool>'''last_block = chain[0]current_index = 1# 从前往后,逐个检查区块的合理性while current_index < len(chain):block = chain[current_index]print(str(last_block))print(str(block))print("\n-----------\n")# 检查区块的哈希值是否正确if block['previous_hash'] != self.hash(last_block):return False# 检查工作量证明是否是正确的if not self.valid_proof(last_block['proof'], block['proof']):return Falselast_block = blockcurrent_index += 1return True..........

解决区块链冲突的问题,系统中可能有多个不同的区块链,结点应该选择当前最长的有效链作为主链。代码如下:

class BlockChains(object):
..........def resolve_conclicts(self):'''检查区块链的冲突,必须是选择网络中最长的区块链:return:<bool> True如果当前链被取代,否则False'''neighbours = self.nodes  # 获取所有的邻接结点的消息new_chain = Nonemax_length = len(self.chain)for node in neighbours:s = str(node)st = 'http://' + s + '/chain'response = requests.get(st)if response.status_code == 200:length = response.json()['length']chain = response.json()['chain']# 检查区块链的合法性if length > max_length and self.valid_chain(chain):max_length = lengthnew_chain = chain# 决定是否替换if new_chain:self.chain = new_chainreturn Truereturn False

网络测试端

以下是网络端,我们在这里进行本地模拟即可。Flask部分可以查看有关文档,仅需要一些基本功能即可。需要postman或者curl进行查看。

app = Flask(__name__)  # 初始化结点
node_identifier = str(uuid4()).replace('-', '')  # 为每一个结点生成唯一的编号
blockchain = BlockChains()  # 初始化区块链@app.route('/mine', methods=['GET'])
def mine():last_block = blockchain.last_blocklast_proof = last_block['proof']proof = blockchain.proof_of_work(last_proof)# 给工作量证明的结点提供奖励,"0"表示新挖出的比特币blockchain.new_transaction(sender='0', recipient=node_identifier, amount=1)block = blockchain.new_block(proof)response = {'message': "New Block Forged",'index': block['index'],'transactions': block['transactions'],'proof': block['proof'],'previous_hash': block['previous_hash'],}return jsonify(response), 200@app.route('/transactions/new', methods=['POST'])
def new_transaction():values = request.get_json()required = ['sender', 'recipient', 'amount']if not all(k in values for k in required):return 'Missing values', 400index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])s = str(index)response = {'message': 'Transaction will be added to Block' + s}return jsonify(response), 201@app.route('/chain', methods=['GET'])
def full_chain():response = {'chain': blockchain.chain,'length': len(blockchain.chain),}return jsonify(response), 200if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

测试结果

我是用了postman客户端,大家根据需要自己调整即可。
程序运行:

挖矿:

查看区块链:

进行交易:

200行Python实现简单的区块链系统相关推荐

  1. 【Python】实现一个简单的区块链系统

    本文章利用 Python 实现一个简单的功能较为完善的区块链系统(包括区块链结构.账户.钱包.转账),采用的共识机制是 POW. 一.区块与区块链结构 Block.py import hashlib ...

  2. 国外大牛教你,如何用Python开发一个简单的区块链数据结构| 建议收藏

    来源 | Medium 作者 | arjuna sky kok 整理 / Aholiab 出品 | 区块链大本营(blockchain_camp) 根据IEEE此前的一项调查,Python已成为最受开 ...

  3. 如何用 Python 快速开发一个区块链数据结构?

    作者 | arjuna sky kok 整理 | Aholiab 出品 | 区块链大本营(blockchain_camp) 根据IEEE此前的一项调查,Python已成为最受开发者欢迎的语言之一.由于 ...

  4. 200 行代码实现一个简单的区块链应用1

    区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用区块链来解决的问题,这两者很容易混淆.像 ...

  5. 200 行代码实现一个简单的区块链

    英文原文:Lauri Hartikka 区块链的基础概念很简单:一个分布式数据库,存储一个不断加长的 list,list 中包含着许多有序的记录.然而,在通常情况下,当我们谈到区块链的时候也会谈起使用 ...

  6. 从零开始用 Python 打造自己的区块链

    本文来自作者 Frank 在 GitChat 上分享 「从零开始用 Python 打造自己的区块链」 编辑 | 毛利 前言 2018 年 4 月以来,随着加密货币价格的回升,各种关于区块链的话题甚嚣尘 ...

  7. 走进区块链(一):用Python实现第一个区块链小程序

    源代码链接:https://github.com/dvf/blockchain 大家好!这是本人踩在巨人的肩膀上,实现的第一个区块链小程序.在实现代码的过程中,我遇到了很多问题,不过,幸好都解决了.在 ...

  8. 头歌-信息安全技术-用Python实现自己的区块链、支持以太坊的云笔记服务器端开发、编写并测试用于保存云笔记的智能合约、支持以太坊的云笔记小程序开发基础

    头歌-信息安全技术-用Python实现自己的区块链.支持以太坊的云笔记服务器端开发.编写并测试用于保存云笔记的智能合约.支持以太坊的云笔记小程序开发基础 一.用Python实现自己的区块链 1.任务描 ...

  9. Python实战2 - 200行Python代码实现2048(控制台)

    Python实战系列用于记录实战项目中的思路,代码实现,出现的问题与解决方案以及可行的改进方向 本文为第2篇–200行Python代码实现2048 一.分析与函数设计 1.1 游戏玩法 2048这款游 ...

最新文章

  1. php获取搜索框的函数,php获取搜索引擎入站关键词的函数
  2. 【Java 线程的深入研究3】最简单实例说明wait、notify、notifyAll的使用方法
  3. php中的全局异常,PHP的全局错误处理详解
  4. Linux CentOS 6.x 关闭图形化界面的方法
  5. 面试官 | 讲一下如何给高并发系统做限流?
  6. python输出自己的名字_【Python】Python-用大写字母打印你的名字
  7. web图片铺满网页_html5的video的背景图片poster铺满全屏大小方法
  8. 企业微信应用设置可信域名_怎么设置企业微信朋友圈功能?企业微信朋友圈功能有哪些限制?...
  9. java调用自身_Java有趣的自己调用自己
  10. 制作chrome插件教程
  11. AsyncTask与Thread+Handler的区别、AsyncTask的使用
  12. android exifinterface 经纬度,Android10获取图片的地理位置信息[GPS位置]
  13. 恩尼格玛模拟器_使用ENIGMA模拟器进行数据加密和解密
  14. 如何让域用户安装需要管理员权限的软件
  15. FlashFXP 便携版,U盘版,真正绿色
  16. 几道经典的面试题53
  17. 鸿蒙要出来了,安卓开发工程师有影响吗?
  18. springboot整合全文搜索引擎Elasticsearch | Spring Boot 28
  19. 书法在平面设计中有哪些作用
  20. 百度地图安卓版详细接入流程解读(获取密钥详解)

热门文章

  1. ROS入门 通信架构
  2. 质数——埃式筛法和欧式筛法
  3. github克隆仓库加速
  4. 《人工智能》实验二——搜索技术(八数码问题)
  5. 夏侯南溪搭建目标检测模型——数据读取篇
  6. [转]我们都是花栗鼠
  7. 3n+1b 备忘录方法
  8. CSS知识点补充收集
  9. JS记坑 ----- children返回的类数组
  10. 运算符重载——左移运算符重载