前回のプログラムを使ってジェネシスブロックのマイニングを行う.ジェネシスブロックはブロックチェーンのインスタンス生成時にコンストラクタを通じて作成する.ジェネシスブロックに入れるトランザクションは,コインベーストランザクション(プルーフオブワークによりブロックを生成したマイナーに報酬として与えられるコインのトランザクション)のみとする.ここでは,senderを"0"とし,Satoに1000コインを支払うとした.
import hashlib, json from time import time from flask import Flask, jsonify, request app = Flask(__name__) class Blockchain(): # ハッシュ値の上4文字が0000となるナンスを見つける difficulty = 4 target = '0000' def __init__(self): # ブロックチェーン本体 self.blockchain = [] # 1ブロックのトランザクションリスト self.tx_list = [] # ジェネシスブロックの"前ブロック"のハッシュ値 self.prev_block_hash = hashlib.sha256("genesis".encode()).hexdigest() # ジェネシスブロック block = { 'index': 0, 'timestamp': time(), # コインベーストランザクション: 'Sato'に1000コインを送付 'tx_list': [{'sender': '0', 'recipent': 'Sato', 'amount': 1000}], 'nonce': 0, 'prev_block_hash': self.prev_block_hash } # ジェネシスブロックのノンスを計算 block['nonce'] = self.proof_of_work(block) # ジェネシスブロックをブロックチェーンに追加 self.blockchain.append(block) # プルーフオブワーク # ターゲットの条件を満たすハッシュ値を与えるノンスを見つける def proof_of_work(self, block): while True: hash = hashlib.sha256(json.dumps(block, sort_keys=True).encode()).hexdigest() if hash[:self.difficulty] == self.target: # 見つけたブロックのハッシュ値(次のブロックに必要) self.prev_block_hash = hash break block['nonce'] += 1 return block['nonce'] # ブロックチェーンインスタンス bc = Blockchain() print(bc.blockchain) print(bc.prev_block_hash) # ブロック生成 @app.route("/block", methods=["GET"]) def block(): nonce = 0 block = { 'index': len(bc.blockchain), 'tiemstamp': time(), 'tx_list': bc.tx_list, 'nonce': nonce, 'prev_block_hash': bc.prev_block_hash } # 次のブロック用に現在のブロックのハッシュを計算しておく bc.prev_block_hash = hashlib.sha256(json.dumps(block, sort_keys=True).encode()).hexdigest() # トランザクションリストをブロックに入れたのでクリア bc.tx_list = [] # ブロックチェーンにブロックを追加 bc.blockchain.append(block) return jsonify(bc.blockchain), 200 # トランザクション生成 @app.route("/tx", methods=['POST']) def tx(): tx = request.get_json() fields = ['sender', 'recipient', 'amount'] if (not all(k in tx for k in fields)) or (tx['amount'] <= 0): message = 'Input Error' status_code = 400 else: bc.tx_list.append(tx) message ='Tx added' status_code = 201 print(bc.tx_list) responce = {'message': message} return jsonify(responce), status_code if __name__ == "__main__": app.run()
結果
> curl http://localhost:5000/block|jq [ { "index": 0, "nonce": 55557, "prev_block_hash": "aeebad4a796fcc2e15dc4c6061b45ed9b373f26adfc798ca7d2d8cc58182718e", "timestamp": 1624842624.1001291, "tx_list": [ { "amount": 1000, "recipent": "Sato", "sender": "0" } ] }, { "index": 1, "nonce": 0, "prev_block_hash": "0000271953947ae4849069f9fd73b2c489a76d4cc02f98c1c9a3a8327e46e89b", "tiemstamp": 1624842626.487038, "tx_list": [] } ]