🌏
ブロックチェーン(簡易版:Python)の実装(前半)
今日は、ブロックチェーン(簡易版)を実装しよーと思います。
ざっくりの仕組みを把握することを、目的にしてる感じです。
やり取りするのは、通貨ではなく感謝(単位は MIK)をイメージしてます♪
ややボリュームが多めになるので、2回に分けよーと思います。
では、前半いきまっしょい♪
今回やること
- ユーザー作成
- トランザクション作成(MIK を発行)
- トランザクション作成(MIK で感謝)
- トランザクション検証
- 実行
(後半予定)
- マイニング
- ブロックチェーン検証
- ブロックチェーン作成
- 実行
準備:インポート
block_chain.py
import binascii
from datetime import datetime
import json
import pprint
from ecdsa import BadSignatureError, SECP256k1, SigningKey, VerifyingKey
1. ユーザー鍵データ作成関数
block_chain.py
def make_key_data() -> dict:
"""
curve: SECP256k1
return: dict(keys=['secret_key_str', 'public_key_str'])
"""
secret_key = SigningKey.generate(curve=SECP256k1)
secret_key_str = secret_key.to_string().hex()
public_key = secret_key.verifying_key
public_key_str = public_key.to_string().hex()
key_data = {
'secret_key_str': secret_key_str,
'public_key_str': public_key_str
}
return key_data
2. トランザクション作成関数1(MIK を発行)
block_chain.py
def make_mikoto_trasaction(receiver_public_key_str: str, MIK: int) -> dict:
"""
MIK 発行用トランザクションを作成
return: dict(keys=['time', 'sender', 'receiver', 'MIK', 'signature'])
sender, signature = 'mikoto_project'
"""
mikoto_transaction = {
"time": datetime.now().isoformat(),
"sender": "mikoto_project",
"receiver": receiver_public_key_str,
"MIK": MIK,
"signature": "mikoto_project",
}
return mikoto_transaction
3. トランザクション作成関数2(MIK で感謝)
block_chain.py
ef make_thanks_transaction(
sender_secret_key_str: str, sender_public_key_str: str,
receiver_public_key_str: str, MIK: int) -> dict:
"""
MIK 感謝用トランザクションを作成
return: dict(keys=['time', 'sender', 'receiver', 'MIK', 'signature'])
"""
thanks_transaction = {
"time": datetime.now().isoformat(),
"sender": sender_public_key_str,
"receiver": receiver_public_key_str,
"MIK": MIK,
}
sender_secret_key = SigningKey.from_string(
binascii.unhexlify(sender_secret_key_str), curve=SECP256k1)
signature = sender_secret_key.sign(
json.dumps(thanks_transaction).encode('utf-8')).hex()
thanks_transaction['signature'] = signature
return thanks_transaction
4. トランザクション検証関数
block_chain.py
def verify_transaction(transaction: dict) -> bool:
"""
トランザクションの signature を検証する
return: bool
print: error(BadSignatureError)
"""
public_key_str = transaction['sender']
public_key = VerifyingKey.from_string(binascii.unhexlify(public_key_str), curve=SECP256k1)
# binascii.Error: Odd-length string
# ecdsa.errors.MalformedPointError
signature = binascii.unhexlify(transaction['signature'])
# binascii.Error: Odd-length string
copy_transaction = transaction.copy()
copy_transaction.pop('signature')
try:
public_key.verify(signature, json.dumps(copy_transaction).encode('utf-8'))
return True
except BadSignatureError as e:
print(e)
return False
5. 実行
block_chain.py
if __name__ == "__main__":
# ユーザー情報の辞書を作成
name_list = ['Dog', 'Cat', 'Lion']
user_info_dict = {}
for name in name_list:
user_info_dict[name] = make_key_data()
transaction_pool = []
# mikoto_project -> Dog: 100MIK
transaction_pool.append(
make_mikoto_trasaction(user_info_dict['Dog']['public_key_str'], 100)
)
# Dog -> Cat: 10MIK, Dog -> Lion: 20MIK
transaction_pool.append(
make_thanks_transaction(
user_info_dict['Dog']['secret_key_str'],
user_info_dict['Dog']['public_key_str'],
user_info_dict['Cat']['public_key_str'],
10
)
)
transaction_pool.append(
make_thanks_transaction(
user_info_dict['Dog']['secret_key_str'],
user_info_dict['Dog']['public_key_str'],
user_info_dict['Lion']['public_key_str'],
20
)
)
print('トランザクション・プール')
pprint.pprint(transaction_pool, sort_dicts=False)
for transaction in transaction_pool:
# 発行したものは検証しない
if transaction["sender"] == "mikoto_project":
continue
else:
# 検証結果を表示
print(verify_transaction(transaction))
結果
参考文献など
Satoshi Nakamoto (2008), ビットコイン:P2P 電子通貨システム,
https://bitcoin.org/files/bitcoin-paper/bitcoin_jp.pdf, 論文
モヤっとデータサイエンティスト (2022), 『Python によるブロックチェーン開発教本』, 電子書籍
安田恒 (2023), 『ブロックチェーンを作る!』, 秀和システム, 書籍
以上になります!ありがとうございましたー♪
Discussion