使用Python从零开始撸一个区块链
简介
本文将介绍如何使用Python从零开始构建一个简单的区块链。区块链是一个去中心化的分布式数据库,其中的数据被存储在一系列的区块中。每个区块包含一些数据和指向前一个区块的指针。由于它们的分布式本质,区块链不容易受到单个点或攻击的影响。这使得它们对于许多不同类型的应用都有价值。
在本文中,我们将使用Python和Flask来编写我们的区块链。我们将涵盖以下主题:
- 区块链基础知识
- 结构化我们的区块
- 使用hash函数保护区块链
- 实现中央控制器
- 实现网络节点
- 实现新的区块的添加
区块链基础知识
区块链的本质是一串区块的链式存储机制,每个区块都包含一定的数据和指向前一个区块的指针。我们的第一步是定义一个表示单个区块的类。
import hashlib
import json
from time import time
class Block:
def __init__(self, index, transactions, timestamp, previous_hash):
self.index = index
self.transactions = transactions
self.timestamp = timestamp
self.previous_hash = previous_hash
self.nonce = 0
def hash_block(self):
"""
通过将区块的属性串联成一个字符串,并对其进行哈希运算来计算区块的哈希值。
"""
block_string = json.dumps(self.__dict__, sort_keys=True)
return hashlib.sha256(block_string.encode()).hexdigest()
在上面的代码中,我们定义了一个Block类,它有一个索引(index)、交易信息(transactions)、时间戳(timestamp)和指向前一个区块的哈希(previous_hash)属性。它还有一个nonce属性,我们稍后将解释其如何工作。最后,我们还为该类定义了一个hash_block()方法,它将对整个区块进行哈希运算,并返回哈希值。
结构化我们的区块
我们可以使用Python List来存储区块。在这种情况下,我们将需要使用创世区块(genesis block)来启动我们的链。
class Blockchain:
def __init__(self):
self.chain = [self.create_genesis_block()]
def create_genesis_block(self):
"""
创建创世区块
"""
return Block(0, [], time(), "0")
def add_block(self, transactions):
"""
添加一个新的区块。
"""
previous_block = self.chain[-1]
new_block = Block(previous_block.index + 1, transactions, time(), previous_block.hash_block())
self.chain.append(new_block)
在上面的代码中,我们定义了另一个名为Blockchain的类。它有一个自己的属性叫作chain。在初始化方法中,我们将创建一个创世区块并将其添加到链中。
我们还定义了一个方法add_block(),它接受一个transactions参数,该参数是一个交易数组,表示该区块中的交易。我们首先获取当前区块链的最后一个区块,并将其存储在previous_block变量中。然后,我们创建一个新区块,将其添加到链的末尾并返回。
使用hash函数保护区块链
哈希函数是计算机科学中的重要工具,用于将数据转换为唯一的数字字符串。我们利用哈希函数保护区块链。每个区块包含指向前一个区块的哈希值。这使得任何尝试篡改区块链的恶意行为都变得更加困难。如果恶意行为者想要将一个区块替换为自己的区块,则必须重新计算所有后续区块的哈希值,这几乎是不可能的。
def hash_block(self):
"""
通过将区块的属性串联成一个字符串,并对其进行哈希运算来计算区块的哈希值。
"""
block_string = json.dumps(self.__dict__, sort_keys=True)
return hashlib.sha256(block_string.encode()).hexdigest()
在上面的代码中,我们利用Python的hashlib模块的sha256()函数来计算区块的哈希值。该函数接受一个可以安全地哈希的bytes类型参数,并返回一个带有256位数字字符串的hexdigest()。
实现中央控制器
中央控制器是我们区块链系统的核心。它将存储区块链,并提供一组API来允许外部用户与之交互。例如,它将允许用户添加新的交易或查看当前的区块链。
from flask import Flask, jsonify, request
app = Flask(__name__)
blockchain = Blockchain()
@app.route('/chain', methods=['GET'])
def get_chain():
"""
返回整个区块链
"""
chain_data = []
for block in blockchain.chain:
chain_data.append(block.__dict__)
return jsonify({"length": len(chain_data), "chain": chain_data})
@app.route('/add_transaction', methods=['POST'])
def add_transaction():
"""
添加新的交易
"""
transaction_data = request.get_json()
blockchain.add_block(transaction_data)
return "Transaction added to Blockchain"
在上面的代码中,我们首先引用Flask lib库。我们还创建了一个名为blockchain的Blockchain实例。然后,我们定义了两个API端点:一个用于获取当前区块链,并将其表示为JSON格式的字符串;另一个用于添加新的交易数据。
实现网络节点
下一步是实现网络节点。节点可以相互通信,并将新的区块添加到它们各自的链中。在我们的实现中,我们将使用简单的HTTP请求来完成此操作。
from urllib.parse import urlparse
class Node:
def __init__(self, address):
self.address = address
def add_block(self, block):
"""
向节点的区块链中添加新块。
"""
# 发送POST请求以将块添加到节点的链中。
response = requests.post(self.address + "/add_block", json=block.__dict__)
if response.status_code == 200:
print("Block added to Node")
def sync(self):
"""
从其他节点同步区块链。
"""
# 发送GET请求以获取最长的链。
response = requests.get(self.address + "/chain")
if response.status_code == 200:
chain_data = response.json()['chain']
chain = []
for block_data in chain_data:
block = Block(block_data['index'], block_data['transactions'], block_data['timestamp'], block_data['previous_hash'])
chain.append(block)
blockchain.chain = chain
在上述代码中,我们定义了一个名为Node的类,它代表了我们网络中的单个节点。每个节点由一个网络地址(address)和相应的区块链组成。
该类也有两个方法。第一个是add_block(),它接受一个块对象,并将其添加到对应节点的区块链中。我们使用Python的requests库向节点发出POST请求,以添加新的块。
第二个方法是sync(),它获取节点当前的链,并将其与当前的链进行同步。我们使用Python的requests库向节点发出GET请求,以获取最新的链。然后,我们重建区块并将链数据存储在中央控制器对象(blockchain)中。这样,我们就可以将其他节点的链与我们的链进行同步。
实现新的区块的添加
现在我们已经实现了所有必备的功能,下一步是为我们的区块链添加一些交易数据。下面是一些示例代码,它将声明两个网络节点,并将一些交易数据添加到他们的区块链中。
node1 = Node('http://127.0.0.1:5000')
node2 = Node('http://127.0.0.1:5001')
node1.add_block([])
node2.sync()
node1.add_block([{'sender': 'Alice', 'recipient': 'Bob', 'amount': 3}])
node2.sync()
node1.add_block([{'sender': 'Bob', 'recipient': 'Charlie', 'amount': 5}])
node2.sync()
node1.add_block([{'sender': 'Charlie', 'recipient': 'Alice', 'amount': 1}])
node2.sync()
在上面的代码中,我们首先创建了两个节点对象,然后向第一个节点添加了一个初始块。接下来,我们向第一个节点添加了三个交易块,并使用sync()函数将其与另一个节点同步。```
结论
在本文中,我们用Python和Flask实现了区块链的一个简单版本。我们学习了区块链的基础和工作原理,以及如何使用hash函数来保护我们的数据。我们还实现了一个中央控制器,它允许用户添加新的交易和查看当前的区块链。最后,我们还描述了如何将其他节点的链与我们自己的链进行同步,以实现分布式的区块链数据存储。
在这个示例中,我们展示了如何将区块链技术应用于一个简单的示例。通过基于我们的示例,读者可以更全面地了解如何使用Python构建更加完整和功能丰富的区块链系统。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用Python从零开始撸一个区块链 - Python技术站