簡単なブロックチェーンをつくる(その2 ブロック)

前回はトランザクションをつくった.今回はブロックの骨格をつくる.ブロックの構造もトランザクションと同様に辞書を使って

block = {
    'index': ブロック高(ジェネシスブロックを0とする)
    'tiemstamp': ブロック作成日時
    'tx_list': トランザクションリスト
    'nonce': ノンス
    'prev_block_hash': 直前ブロックのハッシュ値
}

とする.ブロックをまとめたものがブロックチェーンで,リストを使って

blockchain = [block1, block2, ...]

と表す.

 前回は tx 関数を呼び出してトランザクションを生成したので,今回も同様な感じで block 関数を呼び出してブロックを生成する.ブロックに含まれるトランザクションは,当該ブロックが生成されるまでにつくられたものをすべて取り入れることにする.

from time import time
from flask import Flask, jsonify, request

app = Flask(__name__)

# ブロックチェーン
blockchain = []
# 1ブロックのトランザクションリスト
tx_list = []

# ブロック生成
@app.route("/block", methods=["GET"])
def block():
    global blockchain, tx_list
    nonce = 0
    prev_block_hash = "to_be_hashed"
    block = {
        'index': len(blockchain),
        'tiemstamp': time(),
        'tx_list': tx_list,
        'nonce': nonce,
        'prev_block_hash': prev_block_hash
    }

    # トランザクションをブロックに入れたのでトランザクションリストをクリア
    tx_list = []

    # ブロックチェーンに追加
    blockchain.append(block)
    return jsonify(blockchain), 200

# トランザクション生成
@app.route("/tx", methods=['POST'])
def tx():
    global tx_list
    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:
        # トランザクションリストに追加
        tx_list.append(tx)
        message ='Tx added'
        status_code = 201

    responce = {'message': message}
    return jsonify(responce), status_code

if __name__ == "__main__":
    app.run()

blockchain と tx_list をグローバル変数にしているが,@app.routeの関数内では明示的にglobal宣言しないとうまく動かない.nonce と prev_block_hash の機能はこれからつくっていく.

 最初にトランザクションを2つ生成する.

> curl -X POST -H "Content-Type: application/json" -d "{\"sender\": \"Yamada\", \"recipient\": \"Sato\", \"amount\": 23}" "http://localhost:5000/tx" | jq

> curl -X POST -H "Content-Type: application/json" -d "{\"sender\": \"Goto\", \"recipient\": \"Yamada\", \"amount\": 34}" "http://localhost:5000/tx" | jq

次にブロックを生成する.

> curl http://localhost:5000/block | jq

結果

[
  {
    "index": 0,
    "nonce": 0,
    "prev_block_hash": "to_be_hashed",
    "tiemstamp": 1624633190.2628531,
    "tx_list": [
      {
        "amount": 23,
        "recipient": "Sato",
        "sender": "Yamada"
      },
      {
        "amount": 34,
        "recipient": "Yamada",
        "sender": "Goto"
      }
    ]
  }
]