Pythonでブロックチェーンに入門。コードを書いてみた
あけましておめでとうございます。
今年もよろしくお願いいたします!
ブロックチェーンに入門
なんだかスゴいらしい!と前から気になってはいたものの、実際にどんなものかはよく知らなかったので、手を動かしてみることにしました。
まずは事前のインプット。ブロックチェーンに関する説明スライドがあり、分かりやすいです。
mayonez.jp
つまりはハッシュコードの数珠繋ぎなのですねー。ふむふむ。
「前のブロックのハッシュコードを次のブロックに渡す」を延々と繰り返すので、もし途中で割り込んだり改ざんするとつじつまが合わなくなってドカーン。納得。
コードを書いてみよう
今回の教科書はこちらです。ありがとうございます!
qiita.com
ブロックを定義&ハッシュ生成
# cryptocurrency_block.py import hashlib class Block(): def __init__(self, index, timestamp, data, previous_hash): self.index = index self.timestamp = timestamp self.data = data self.previous_hash = previous_hash self.hash = self.hash_block() def hash_block(self): """ generates a cryptographic hash of the block's index, timestamp, data, and the hash of the previous block's hash. """ sha = hashlib.sha3_256() sha.update((str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash)).encode('utf-8')) return sha.hexdigest()
hash_block()のshaは「Secure Hash Algorithm」の意味で、
暗号学的ハッシュ関数であり、アメリカ国立標準技術研究所(NIST)によって標準のハッシュ関数Secure Hash Standardに指定されている
とかなんとか。最新はSHA3です。
上でインポートしているhashlibがハッシュオブジェクトを作ってくれるライブラリで、例えば「SHA1」のハッシュオブジェクトを作るには 「sha1()」とする、という寸法です。hashlibではこれらのアルゴリズムを提供していて、下に行くほど強度が上がります。
ちなみに大昔のMD2は、今もRSA暗号といっしょに公開鍵証明書を発行する公開鍵基盤として使われ続けているとか。
1個目のブロックを生成
# cryptocurrency_genesis.py from cryptocurrency_block import * import datetime as date def create_genesis_block(): return Block(0, date.datetime.now(), "Genesis Block", 0)
で1個目のブロックを生成します。やることはいたってシンプル。
2個目以降のブロックを生成
# cryptocurrency_new_block.py import datetime as date from cryptocurrency_block import * def next_block(last_block): this_index = last_block.index + 1 this_timestamp = date.datetime.now() this_data = "Hey! I'm block " + str(this_index) this_hash = last_block.hash return Block(this_index, this_timestamp, this_data, this_hash)
前のブロックのハッシュ値を受け取って、新しいブロックを生成します。
ブロックチェーンを生成
# cryptocurrency_blockchain.py from cryptocurrency_genesis import * from cryptocurrency_new_block import * blockchain = [create_genesis_block()] previous_block = blockchain[0] num_of_blocks_to_add = 20 for _ in range(0, num_of_blocks_to_add): blocks_to_add = next_block(previous_block) blockchain.append(blocks_to_add) previous_block = blocks_to_add print("Block {} has been added to the blockchain.".format(blocks_to_add.index)) print("Hash: {}\n".format(blocks_to_add.hash))
指定した数だけブロックを作りブロックチェーンを形成します。
リストのblockchainにぽこぽこ入っていく感じですね。
では動かしてみましょう
上のコードを実行すると……
Block 1 has been added to the blockchain. Hash: ca0c12b49fc89333cd1014583a82848ec82830c478c1900c9014f9ea3c978ffa Block 2 has been added to the blockchain. Hash: 7e4a495e4968e18e68f6bd4654077f676aaf7a9e246706e5a53eaa42ae3ad14b Block 3 has been added to the blockchain. Hash: 39b78c338c6de63e966c6fd27fab7dc9776c634e83daab06dbc5467f9cc6e028 Block 4 has been added to the blockchain. Hash: 8aca7ff98f5c06f24aa2fb93ff41ef6dc18bda1afdca830292e20a558f310c7f ... Block 20 has been added to the blockchain. Hash: 37beeb24777c466273c5f2c9062d303ec3dee37d2eef2c87be72e46c9782e8fb
と、めでたくブロックチェーンが作られます。もう出来ちゃった!
ちなみに、blockchainの中をのぞくと……
print(blockchain) [<__main__.Block object at 0x0000020BA7F62C18>, ... , <__main__.Block object at 0x0000020BA7F4D630>]
最初のブロックを含めて、21個分のオブジェクトのリストができています。
これらのオブジェクトのハッシュ値を表示すると、
print(blockchain[0].previous_hash) print(blockchain[0].hash) print(blockchain[1].previous_hash) print(blockchain[1].hash) print(blockchain[2].previous_hash) print(blockchain[2].hash) print(blockchain[3].previous_hash) print(blockchain[3].hash) print(blockchain[4].previous_hash) print(blockchain[4].hash) 0 # [0]の前のブロックのハッシュ値(存在しないので設定した0が入っている) dea7d8146b5243f8ec31530a8d2f7a74d62c03da38ec1d8bccec3ff6026b33a8 # [0]のハッシュ値 dea7d8146b5243f8ec31530a8d2f7a74d62c03da38ec1d8bccec3ff6026b33a8 # [1]の前のブロックのハッシュ値 ca0c12b49fc89333cd1014583a82848ec82830c478c1900c9014f9ea3c978ffa # [1]のハッシュ値 ca0c12b49fc89333cd1014583a82848ec82830c478c1900c9014f9ea3c978ffa # [2]の前のブロックのハッシュ値 7e4a495e4968e18e68f6bd4654077f676aaf7a9e246706e5a53eaa42ae3ad14b # [2]のハッシュ値 7e4a495e4968e18e68f6bd4654077f676aaf7a9e246706e5a53eaa42ae3ad14b # [3]の前のブロックのハッシュ値 39b78c338c6de63e966c6fd27fab7dc9776c634e83daab06dbc5467f9cc6e028 # [3]のハッシュ値 39b78c338c6de63e966c6fd27fab7dc9776c634e83daab06dbc5467f9cc6e028 # [4]の前のブロックのハッシュ値 8aca7ff98f5c06f24aa2fb93ff41ef6dc18bda1afdca830292e20a558f310c7f # [4]のハッシュ値
となり、ハッシュ値が次のブロックに渡されていることが分かります。