在开始构建之前,您需要了解区块链的基础知识。
区块链是可以用来记录数据的系统。例如这意味着可以在正规银行进行转账,但也可以包含所有权合约、协议、个人信息或其他数据。
区块链的特殊之处在于,无需中央授权就可以实现。 无法通过破坏一个中心点来伪造记录数据。区块链最著名的实现是比特币。
本教程是供具有一点Python知识的绝对初学者使用的,让我们开始吧!
要求
确保您已安装最新版本的Python。 另外,您需要安装两个称为Flask和Requests的Python库:
对于这些请求,我建议下载Postman。
入门
创建一个新的Python文件。我称它为app.py。首先我们应该创建一个Blockchain类:
创建构造函数时,我们添加一个空列表来存储链:
def __init__(self):
self.chain = []
现在,我们需要创建一个列表来存储我们的交易,因此我们的Blockchain类现在看起来像这样:
class Blockchain(object):
def __init__(self):
self.chain = []
self.current_transactions = []
为了用数据填充这些列表,我们创建了两个方法(addBlock()和addTransaction()):
def addBlock(self):
pass
def addTransaction(self):
pass
这些函数目前无法执行任何操作,但是我们在后面将进行数据填充。
为了以安全的方式存储数据,我们对数据进行哈希处理。 创建一个hash()方法。 这是一种静态方法,因此不要忘记添加@staticmethod:
@staticmethod
def hash(block):
pass
最后,创建一个lastBlock()方法:
@property
def lastBlock(self):
pass
创建一个区块
现在我们需要考虑如何显示块。 首先它需要一个index和timestamp。 我敢打赌,您会明白的,但是证明呢? 那是什么? 最好的解释方法是稍后再做。
我们的区块还需要一个transactions和一个previous_hash,它是前一个块的哈希。
创建新事务
为了创建一个新的事务,我们创建了addTransaction()方法。 现在让我们用代码填充它。
首先,我们应该传入一些参数(self、sender、receiver、amount):
现在,我们将新交易添加到我们的交易列表中:
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
最后,此方法需要返回事务的索引:
这使得方法如下所示:
def addTransaction(self, sender, recipient, amount):
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
return self.last_block['index'] + 1
创建一个新区块
在开始创建新区块之前,需要在构造函数中创建一个核心去块:
然后我们可以填写addBlock()方法:
def addBlock(self, proof, previous_hash=None):
block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'proof': proof,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}
self.current_transactions = []
self.chain.append(block)
return block
如您所见,我们需要创建hash()方法以使其工作:
@staticmethod
def hash(block):
block_string = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
哈希很简单。 基本上它是编码一个字符串。 然后,我们需要另一个方法,那就是lastBlock()方法:
@property
def last_block(self):
return self.chain[-1]
什么是证明?
工作量证明是一种旨在抵抗网络攻击(例如DDoS攻击)的协议。 工作量证明是Cynthia Dwork和Moni Naor最初于1993年发布的想法。
该协议是密集计算形式(也称为挖掘)的要求,必须执行密集计算形式才能在区块链上创建新的一组不信任交易。
为了验证这些交易,矿工们必须解决一个数学难题。第一个解决这个问题的矿工将获得奖励(以新的加密货币)。已验证的交易存储在公共区块链中。这个谜题对每一个新的方块都有点困难。这就是为什么矿工们必须提高工作效率。
如何实施PoW
现在,让我们通过以下难题将其实现到我们的blockChain中:
找出一个数字x。 当使用上一个区块的解决方案进行哈希处理时,会生成带有两个前导0的哈希值。
为此,我们首先添加以下模块:
import hashlib
import json
from time import time
from uuid import uuid4
并创建两个新方法:
和:
@staticmethod
def valid_proof(last_proof, proof):
填写如下:
使用Flask服务我们的API
创建一个区块链很有趣,但是现在我们要使用它,Python有一个完美的模块来创建API:Flask。 让我们添加一些基本的Flask代码:
from flask import Flask
app = Flask(__name__)
node_identifier = str(uuid4()).replace('-', '')
blockchain = Blockchain()
@app.route('/mine', methods=['GET'])
def mine():
return "Mining a new Block"
@app.route('/transactions/new', methods=['POST'])
def new_transaction():
return "Adding a new Transaction"
@app.route('/chain', methods=['GET'])
def full_chain():
response = {
'chain': blockchain.chain,
'length': len(blockchain.chain),
}
return jsonify(response), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
新交易
API的新交易端点将如下所示,并且由于我们已经创建了类似的方法,因此非常简单:
@app.route('/transactions/new', methods=['POST'])
def newTransaction():
values = request.get_json()
required = ['sender', 'recipient', 'amount']
if not all(k in values for k in required):
return 'Missing values', 400
index = blockchain.new_transaction(values['sender'], values['recipient'], values['amount'])
response = {'message': f'Transaction will be added to Block '}
return jsonify(response), 201
挖矿
挖矿是我们需要在其工作之前添加一点代码的地方。需要做几件事:
证明
矿工奖励
新区块+将其添加到链中
@app.route('/mine', methods=['GET'])
def mine():
last_block = blockchain.last_block
last_proof = last_block['proof']
proof = blockchain.proof_of_work(last_proof)
blockchain.new_transaction(
sender="0",
recipient=node_identifier,
amount=1,
)
previous_hash = blockchain.hash(last_block)
block = blockchain.new_block(proof, previous_hash)
response = {
'message': "New Block Created",
'index': block['index'],
'transactions': block['transactions'],
'proof': block['proof'],
'previous_hash': block['previous_hash'],
}
return jsonify(response), 200
运行我们的BlockChain API
让我们尝试通过打开Python程序来运行API:
$ python app.py
$ Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
您可以使用Postman或Curl挖掘块:
$ curl -X POST -H "Content-Type: application/json" -d '{
"sender": "d4ee26eee15148ee92c6cd394edd974e",
"recipient": "address2",
"amount": 5
}' "http://localhost:5000/transactions/new"
要检查挖掘了多少区块,请转到http://localhost5000/chain,将显示一个JSON格式的链:
{
"chain": [
{
"index": 1,
"previous_hash": 1,
"proof": 100,
"timestamp": 1606910340,
"transactions": []
},
}
以下是完整代码:
import requests
from time import time
import hashlib
import json
from flask import Flask
from time import time
from uuid import uuid4
class Blockchain(object):
app = Flask(__name__)
node_identifier = str(uuid4()).replace('-', '')
blockchain = Blockchain()
@app.route('/mine', methods=['GET'])
def mine():
last_block = blockchain.last_block
last_proof = last_block['proof']
proof = blockchain.proof_of_work(last_proof)
blockchain.new_transaction(
sender="0",
recipient=node_identifier,
amount=1,
)
previous_hash = blockchain.hash(last_block)
block = blockchain.new_block(proof, previous_hash)
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 newTransaction():
values = request.get_json()
required = ['sender', 'recipient', 'amount']
if not all(k in values for k in required):
return 'Missing values', 400
index = blockchain.new_transaction(
values['sender'], values['recipient'], values['amount'])
response = {'message': f'Transaction will be added to Block '}
return jsonify(response), 201
@app.route('/chain', methods=['GET'])
def full_chain():
response = {
'chain': blockchain.chain,
'length': len(blockchain.chain),
}
return jsonify(response), 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
def __init__(self):
self.chain = []
self.current_transactions = []
def proof_of_work(self, last_proof):
proof =
while self.valid_proof(last_proof, proof) is False:
proof += 1
return proof
@staticmethod
def valid_proof(last_proof, proof):
guess = f''.encode()
guess_hash = hashlib.sha256(guess).hexdigest()
return guess_hash[:4] == "0000"
def addBlock(self, proof, previous_hash=None):
block = {
'index': len(self.chain) + 1,
'timestamp': time(),
'transactions': self.current_transactions,
'proof': proof,
'previous_hash': previous_hash or self.hash(self.chain[-1]),
}
self.current_transactions = []
self.chain.append(block)
return block
def addTransaction(self, sender, recipient, amount):
self.current_transactions.append({
'sender': sender,
'recipient': recipient,
'amount': amount,
})
return self.last_block['index'] + 1
@staticmethod
def hash(block):
block_string = json.dumps(block, sort_keys=True).encode()
return hashlib.sha256(block_string).hexdigest()
@property
def last_block(self):
return self.chain[-1]