python3
Blockchain

python3でブロックチェーンを作ってみる

50行以下のpythonコードでブロックチェーンが作れる?

Let’s Build the Tiniest Blockchainという投稿を見かけたので学習がてら早速やってみることにします。元記事はpython2で書かれていますが個人的な都合によりpython3のフォーマットに書き直しています。*note: all credit goes to Gerald Nash

ブロックチェーンとは

ここでは「とりあえず簡易ブロックチェーンを作りながらブロックチェーンとは何かを体感してみる」ことを目的としているのでブロックチェーンに関する諸処の説明は省きます。詳しい説明や補足的な事柄に関しては下のブロックチェーンを概念的に学べる記事一覧に記載したので参考にしてみてください。

だいぶ稚拙で簡略化されすぎていますが、僕は一言にブロックチェーンを「非中央集権型ネットワークを採用した時系列に並べられたハッシュ値の塊」として解釈しています。ブロックチェーンはデータ構造とデータの管理において従来の方法とは異なります。

Blockchain vs Linked List

個人談ではありますが、僕は過去に勉強したlinked listとの類似点がきっかけでブロックチェーンの存在を少し身近に感じることができました。

Yes, as a data structure a blockchain is similar to a linked list (but it refers to the previous block using its hash rather than using a pointer, thus strictly speaking it is not a linked list). But a blokchain is not so much a data structure as it is a protocol for arriving to a consensus in a decentralized environment. A blockchain isn't a blockchain without rules which describe how nodes validate blocks, select the best chain etc.
(「ブロックチェーンは結局linked listのことをさしているのか」という質問に対して)データ構造としてはlinked listと似ているがブロックチェーンではlinked listでいうポインター(lst1 = [lst0[len(lst0)-1], 1, 2, 3, lst2[0]...)を採用せずにハッシュ値を使っているという点で異なるため厳密にはlinked listとして定義されない。加えてブロックチェーンは分散環境のコンセンサスに到達するためのプロトコルであるため、(linked listと違って)データ構造とは言えない。ブロックチェーンは各ブロックを検証するための規定なしではブロックチェーンとしてなり得ない。

(参照: Is a blockchain essentially a linked list?

簡易ブロックチェーンを作ってみる

そもそも各ブロックにはどういったデータが格納されているのか

まずはブロックチェーンの各ブロックの構造を簡単に整理。

  1. timestamp
  2. index(実際は任意だが今回は含める)
  3. data
  4. previous_hash
  5. hash(ここではブロックの統合性維持のためにhash自体を入れる)

Like Bitcoin, each block’s hash will be a cryptographic hash of the block’s index, timestamp, data, and the hash of the previous block’s hash. Oh, and the data can be anything you want.

全体の流れ

  • blockchainをpythonのリストと見立てて生成している。
  • 1-4のrecursionになっている。
  1. create_genesis_block関数がブロックチェーン一つ目となるブロック及びブロックチェーンそのものとなるリストを生成する
  2. blocks_to_add = next_block(previous_block)リストの最後にあるブロック(ハッシュ値)を取り出し、その値を元に新たなブロックを生成する。
  3. blockchain.append(blocks_to_add)そのブロックをブロックチェーン(リスト)に追加する。
  4. previous_block = blocks_to_add2で使うブロックを用意しておく。
cryptocurrency_block.py
import hashlib as hasher

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.
        hash_block => '18627f84562249c397955a1bbde617992fea2180afe0e4645ea131df12051a20'
        """
        sha = hasher.sha256()
        sha.update((str(self.index) +
                   str(self.timestamp) +
                   str(self.data) +
                   str(self.previous_hash)).encode('utf-8'))
        return sha.hexdigest()

ブロック=>ブロックチェーン

ブロックをチェーンとして繋げるために以下のような関数2つを用意。1つ目は最初のブロックをマニュアルで追加してくれる関数。もう一つは既存のブロックと新たに生成されたブロックを繋げてくれる関数。

一つ目のブロック生成

cryptocurrency_genesis.py
from cryptocurrency_block import *
import datetime as date

def create_genesis_block():
    """
    manually creates a first block of a blockchain with index of 0 and
    arbitrary previous hash.
    first_block = create_genesis_block()
    first_block
    """
    return Block(0, date.datetime.now(), "Genesis Block", "0")

n>=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 i 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))

実行結果

Screen Shot 2017-09-03 at 7.53.02 PM.png

ちゃんと動いてくれているみたいです!

ブロックチェーンを概念的に学べる記事一覧

概念的な理解は複数のリソースを平行読みして掴んだほうが効率的だと思うのでそちらをオススメします。参考までに僕が個人的に読んだ記事を貼ってみたので興味があれば読んでみてください。

ブロックチェーン、ビットコインという単語しか聞いたことのない人向け

ブロックチェーンという概念と仕組み、ビットコインとの関わりなどが何となく分かってきた人向け