本文主要参考用Python从零开始创建区块链 | 登链社区 | 区块链技术社区 (learnblockchain.cn)
区块链作为一种新型去中心化分布式数据系统,确保了数字加密货币交易等数据的安全存储。其不可篡改、公开透明、匿名的特性降低了互联网信任成本,助力实现从信息互联网向价值互联网的跨越。基于区块链技术,我开发的山寨比特币交易系统提供了一种安全且可验证的交易方式。在系统中,各方共享信息并达成具有预定义规则的协议。本文对山寨比特币交易系统主要工作内容如下:
山寨比特币交易系统以Python语言为基础,构建了一个分布式数字货币交易平台。该系统主要包括区块链、节点、交易、工作量证明和共识算法等核心模块。区块链模块以时间顺序打包交易记录,形成链式结构,确保数据安全和不间断;节点模块维护区块链同步和扩展,通过分布式共识算法确保数据一致性;交易模块支持数字货币发送、接收和交易,保障交易安全性和隐私;工作量证明模块模拟比特币工作量证明算法,确保交易安全性和不可篡改;共识算法模块在多个节点间达成共识,实现交易快速高效。
山寨比特币交易系统为用户提供安全、可靠、可验证的数字货币交易方式,有望在数字经济领域发挥重要作用。
-
原理阐述
在本项目中,我通过定义一个`Blockchain`类来模拟区块链。在类的构造方法中,我将调用已封装的创建区块方法`new_block()`,生成一个创世区块。同时,我设置该区块的前一个哈希值为1,以表明其为创世区块。此外,我使用列表来保存当前交易和链,并采用集合(set)来存储分布式的节点(node)。
为了模拟分布式,我将注册节点的方法封装到register_node()方法中;为了实现共识算法,我将“检查一条链是否有效”的方法和“找出最长连”的方法分别封装为valid_chain() 和 resolve_conflicts()。
然后创建区块和创建新的交易分别对应new_block() 方法和 new_transaction()方法。
模拟工作量证明时,我将会计算前一个区块的hash值,这部分内容我封装在了 proof_of_work() 方法中。
鉴于我的项目采用Web架构,并需运用Flask框架,在处理请求方法时,调用`Blockchain`类中的方法以模拟交易。
-
需求分析
本项目是一个基于Python的山寨比特币交易系统,实现了区块链中的部分基本算法,如共识算法等,并具备创建交易、打包区块、工作量证明等核心功能。通过模仿区块链的分布式特性,实现了高性能和安全性。该项目采用Web架构,并以Python的Flask框架为基础。通过定义一个模拟区块链操作的类,实现了与Flask的交互。在测试过程中,我们使用了Postman这款API测试工具。
-
系统实现
1 功能设计
1.1 初始化区块链
在Blockchain的构造函数中,初始化当前交易,当前链,以及当前节点,同时创建一个创世区块,设置previous_hash 的值为1表示当前区块为创世区块。
- # 定义一个区块链类
- class Blockchain:
- def __init__(self): # 初始化当前交易、区块链、节点和创世区块
- self.current_transactions = [] # 当前交易
- self.chain = [] # 一条链
- self.nodes = set() # 用set来存储node节点
- self.new_block(previous_hash='1', proof=100) # 创建一个创世区块
1.2 注册节点
为的是模拟比特币的分布式交易系统,系统中可能总是存在多个节点,这些节点都知道对方的存在。在这里我们通过将Web服务启动在不同的端口,来模拟分布式交易系统中的多个不同节点。
让一个节点知道其他节点的存在,这里我们使用的方法是将另一个节点注册到当前节点中来,即将另一个节点的信息存放在当前节点Blockchain类中的 nodes 属性中。
我们这里模拟注册节点的方法是register_node() 函数,我们需要传入另一个节点的url地址,然后解析得到服务器路径,再存入nodes集合中。
- def register_node(self, address): # 注册网络中的节点
- parsed_url = urlparse(address) # 将一个url的字符串解析并返回一个url的对象
- if parsed_url.netloc: # 如果地址包含域名
- self.nodes.add(parsed_url.netloc) # 添加域名
- elif parsed_url.path: # 如果地址包含路径
- self.nodes.add(parsed_url.path) # 添加路径
- else:
- raise ValueError('Invalid URL') # 如果地址无效,抛出异常
1.3 创建交易
有了一个创世区块之后,我们就可以在这个创世区块中进行交易了,我们使用new_transaction() 函数来模拟一次交易,传入的参数:sender表示发送者的地址,recipient表示接受者的地址,amount表示数量,该函数的返回值是本次交易的index索引,这些信息最终都会被打包添加到下一个区块中。
- def new_transaction(self, sender, recipient, amount): # 创建一笔新的交易
- # 创建一个新的交易到下一个区块中
- self.current_transactions.append({
- 'sender': sender,
- 'recipient': recipient,
- 'amount': amount,
- })
- return self.last_block['index'] + 1 # 返回下一个区块的索引
1.4 工作量证明
我们知道,区块链中的每一个新的区块都来自于工作量证明,工作量证明的目标是计算出一串解决问题的数字,这个结果是十分难计算的,但是却十分容易验证,网络上的任何人都可以验证这个结果。
这里我们也用Python代码实现一个简单的工作量证明算法,我们的规则是:找到一个数字P,使得它与前一个区块的proof拼接而成的字符串的Hash值以4个零开头。
- # 工作量证明
- def proof_of_work(self, last_block):
- # 简单工作量证明算法
- # (1) 找出一个数字 P',使得 hash(PP') 包含前导的4个0
- # (2) 其中 P 是前一个证明, P' 是新的证明
- last_proof = last_block['proof']
- last_hash = self.hash(last_block)
- proof = 0
- while self.valid_proof(last_proof, proof, last_hash) is False:
- proof += 1
- return proof
- # 验证工作量
- @staticmethod
- def valid_proof(last_proof, proof, last_hash):
- # 验证数据
- # :param last_proof: <int> 前一个证明
- # :param proof: <int> 当前证明
- # :param last_hash: 前一个区块的哈希值
- # :return: <bool> 如果正确,返回 True;否则返回 False
- guess = f'{last_proof}{proof}{last_hash}'.encode()
- guess_hash = hashlib.sha256(guess).hexdigest()
- return