ブロックチェーンを実装してみる（入門編）

<img width="300" alt="blockchain" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524398/23200f60-8f46-33a6-33ae-301833c4b2f4.png"> 


# 概要

簡単なブロックチェーンを実装してみることで、実際にどういう動きをするのかといった部分の理解が深まるのではないか、ということで実装してみようという記事です。
今回は最低限の動きのみ確認し、次回以降、徐々により本格的なものを実装していく予定です。

# 前提

Pyhton 3.11.1 を使用しています。

# 実装

## ブロックの定義

ブロックチェーンの各ブロックには以下のような情報を設定できるようにします。

- インデックス
- タイムスタンプ
- データ
    - 暗号通貨の場合は、送金元、送金先、金額といった取引履歴（トランザクション）が記録されています。
        - 具体例: https://www.blockchain.com/explorer/transactions/btc/0c9074f65fda2d7b70dc1ccb28e17becd3892a630e3ff919a523c963ef696994 
    - ここではとりあえず文字列を設定します。
- １つ前のブロックのハッシュ値
- 上記4つから算出した、このブロックのハッシュ値
    - ハッシュ値の算出に１つ前のブロックのハッシュ値を利用しているため、一つ前のブロックの内容が改竄された場合はこのブロックのハッシュ値も修正する必要があります。
    - ハッシュ関数にはバイト列を渡す必要があるため、encodeしています。

```python
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):
		# ブロックのデータからこのブロックのハッシュ値を算出する
        sha = hashlib.sha256()
        sha.update(
            (
                str(self.index)
                + str(self.timestamp)
                + str(self.data)
                + str(self.previous_hash)
            ).encode(encoding="utf-8")
        )
        return sha.hexdigest()
```

## 最初のブロックの生成処理

ブロックを生成する際、一つ前のブロックのハッシュ値が必要となりますが、最初のブロックには一つ前のブロックがないため、手動で生成する必要があります。
ブロックチェーンの最初のブロックは、genesis block と呼ばれています。

```python
import datetime

def create_genesis_block():
	# index=0でデータとprevious hashに任意の値を設定し、最初のブロックを生成する
    return Block(0, datetime.datetime.now(), "Genesis Block", "0")
```

ビットコインのgenesis blockには以下のような文字列が書き込まれています。（https://sourceforge.net/p/bitcoin/code/133/tree/trunk/main.cpp#l1630）

> The Times 03/Jan/2009 Chancellor on brink of second bailout for banks

これはイギリスのThe Times誌の2009年1月3日の見出しで、世界金融危機（日本ではリーマン・ショックとも呼ばれている）を受けて英政府による銀行の救済について報じたものです。ビットコイン開発者のサトシ・ナカモト氏の設計思想が表れていると言えそうですね。


## ブロックチェーンの生成

ここまででブロックチェーンの生成に必要な処理を定義できたので、これらを組み合わせてブロックチェーンの生成処理を行います。

```python
# ブロックチェーンを作成し、genesis blockを追加
blockchain = [create_genesis_block()]

# 追加するblock数
num_of_blocks_to_add = 20

# ブロックチェーンにブロックを追加
for i in range(0, num_of_blocks_to_add):
    # 一つ前のブロックを取得
    previous_block = blockchain[len(blockchain) - 1]

    # 追加するブロックを生成
    block_to_add = Block(
        index=previous_block.index + 1,
        timestamp=datetime.datetime.now(),
        data="Hey! I'm block " + str(previous_block.index + 1),
        previous_hash=previous_block.hash
    )

    # ブロックチェーンに追加
    blockchain.append(block_to_add)

    # ログに出力
    print(
        "Block #{} has been added to the blockchain!".format(
            block_to_add.index))
    print("Data: {}".format(block_to_add.data))
    print("Previous Hash: {}".format(block_to_add.previous_hash))
    print("Hash: {}\n".format(block_to_add.hash))
```

### 結果ログ

上記を実行すると以下のようなログが出力されます。
ブロックのハッシュ値（Hash）が次のブロックのPrevious Hashに設定されています。

```python
Block #1 has been added to the blockchain!
Data: Hey! I'm block 1
Previous Hash: a2d2d5f94a8637c85a3413131c70acf38652950c507f59e4d2859207005c4c6f
Hash: 6c57095c28fd3aa350f53aba7cbb714fe30008aaafad788ef712cba440e2234c

Block #2 has been added to the blockchain!
Data: Hey! I'm block 2
Previous Hash: 6c57095c28fd3aa350f53aba7cbb714fe30008aaafad788ef712cba440e2234c
Hash: b6c8be3c87b913782e53734bd8e4c34e315a4505d9108ed66f7b8c2b24673c30

Block #3 has been added to the blockchain!
Data: Hey! I'm block 3
Previous Hash: b6c8be3c87b913782e53734bd8e4c34e315a4505d9108ed66f7b8c2b24673c30
Hash: 0e43f6a938da17b1910c5db1494c72627f4eb247120df8d85e7da3b1650070c6

Block #4 has been added to the blockchain!
Data: Hey! I'm block 4
Previous Hash: 0e43f6a938da17b1910c5db1494c72627f4eb247120df8d85e7da3b1650070c6
Hash: 150c1b701b8c177ca4d8596def4f86d1d986a9c9b9b5412e77e322d8f72c9add

Block #5 has been added to the blockchain!
Data: Hey! I'm block 5
Previous Hash: 150c1b701b8c177ca4d8596def4f86d1d986a9c9b9b5412e77e322d8f72c9add
Hash: 5ddcd703cf1cad4d79046f1fdedc348bafa113def026947cf28f66abaf7dfe0e

Block #6 has been added to the blockchain!
Data: Hey! I'm block 6
Previous Hash: 5ddcd703cf1cad4d79046f1fdedc348bafa113def026947cf28f66abaf7dfe0e
Hash: a80b4b3aefd74642ca1e64bae5cf471ff9b7eebfa294869144a87e5c63a95342

Block #7 has been added to the blockchain!
Data: Hey! I'm block 7
Previous Hash: a80b4b3aefd74642ca1e64bae5cf471ff9b7eebfa294869144a87e5c63a95342
Hash: c8f2a6b3ce78650ddee7d24d83b83f828a7e683c6a351e146923d67150f21d07

Block #8 has been added to the blockchain!
Data: Hey! I'm block 8
Previous Hash: c8f2a6b3ce78650ddee7d24d83b83f828a7e683c6a351e146923d67150f21d07
Hash: 6fa98dd692c325aec53b01c200adc6242f25f87aea04ff16020ec3928654a784

Block #9 has been added to the blockchain!
Data: Hey! I'm block 9
Previous Hash: 6fa98dd692c325aec53b01c200adc6242f25f87aea04ff16020ec3928654a784
Hash: 28b6e83ffbe49aac8b2cb3fd31517a65166390e99b49486a5f303d3635b5f1be

Block #10 has been added to the blockchain!
Data: Hey! I'm block 10
Previous Hash: 28b6e83ffbe49aac8b2cb3fd31517a65166390e99b49486a5f303d3635b5f1be
Hash: 728b7e845990653e97a08e784f0962236ba1108b2efe80784d58d5cb6ddaf4f4

Block #11 has been added to the blockchain!
Data: Hey! I'm block 11
Previous Hash: 728b7e845990653e97a08e784f0962236ba1108b2efe80784d58d5cb6ddaf4f4
Hash: 1943869ece91a5e85d4b88dbcb8ca5f1256fd6e03f67a076d0f271cd3d7b2710

Block #12 has been added to the blockchain!
Data: Hey! I'm block 12
Previous Hash: 1943869ece91a5e85d4b88dbcb8ca5f1256fd6e03f67a076d0f271cd3d7b2710
Hash: 20bbee9f00e2514a8f1580b7b02e7c3dffced4ce98ee2a5e91875231a6d0f7aa

Block #13 has been added to the blockchain!
Data: Hey! I'm block 13
Previous Hash: 20bbee9f00e2514a8f1580b7b02e7c3dffced4ce98ee2a5e91875231a6d0f7aa
Hash: 28fec5d54bd70bff3e63021cb9537bfe22053708d8c16b58f82825c8a4e84a40

Block #14 has been added to the blockchain!
Data: Hey! I'm block 14
Previous Hash: 28fec5d54bd70bff3e63021cb9537bfe22053708d8c16b58f82825c8a4e84a40
Hash: 185045e4f6c89f41e8df84dc4371671433fe36e3955c02091f57442ff53723dd

Block #15 has been added to the blockchain!
Data: Hey! I'm block 15
Previous Hash: 185045e4f6c89f41e8df84dc4371671433fe36e3955c02091f57442ff53723dd
Hash: 3e047a781cc8c7de0ac72a8594dc65c6c340f6c593ce2c82c1f9f85ff0ba520d

Block #16 has been added to the blockchain!
Data: Hey! I'm block 16
Previous Hash: 3e047a781cc8c7de0ac72a8594dc65c6c340f6c593ce2c82c1f9f85ff0ba520d
Hash: d50401f79f001eaa503cc83a48dbc6371867648ec7e330ac2294dbad0c1b96a9

Block #17 has been added to the blockchain!
Data: Hey! I'm block 17
Previous Hash: d50401f79f001eaa503cc83a48dbc6371867648ec7e330ac2294dbad0c1b96a9
Hash: 7c9f735ba8526fb9a16938aba6505323755cab42b08be694cdb7ecb357801828

Block #18 has been added to the blockchain!
Data: Hey! I'm block 18
Previous Hash: 7c9f735ba8526fb9a16938aba6505323755cab42b08be694cdb7ecb357801828
Hash: 615ea90f2ef49e3cb7713e34c2dd8054eb8c99e04522fb2908a4399b3f412bad

Block #19 has been added to the blockchain!
Data: Hey! I'm block 19
Previous Hash: 615ea90f2ef49e3cb7713e34c2dd8054eb8c99e04522fb2908a4399b3f412bad
Hash: 250b147b17ca70c85be94775fbe5fb0316b620e2873c634d2e97f801f76cd532

Block #20 has been added to the blockchain!
Data: Hey! I'm block 20
Previous Hash: 250b147b17ca70c85be94775fbe5fb0316b620e2873c634d2e97f801f76cd532
Hash: b2b9c4e6daeb27d78a6e5833d065d778fa88b2f36e6db36cb8f51de8e673287a
```


例えば5番目のブロックのデータを変更した場合、ハッシュ値が変わってしまうため6番目のブロックも変更する必要があり、それ以降のすべてのブロックを書き換えなければならなくなります。

# おわりに

このように実際に実装して動かしてみることで、動きのイメージが掴みやすくなった方もいると思います。この仕組みを何かに使えそうな気がしてきましたね。
今回はまだ雰囲気のみの実装であり、コンセンサスアルゴリズムやネットワークの構築などはできていないため、今後勉強して更に理解を深めていこうと思いました。
今後も様々な技術について取り上げていきますので、よろしくお願いいたします。


# 参考リンク

https://bitcoin.dmm.com/glossary/genesis_block

https://github.com/yjjnls/awesome-blockchain#implementation-of-blockchain

https://medium.com/crypto-currently/lets-build-the-tiniest-blockchain-e70965a248b

https://hackernoon.com/learn-blockchains-by-building-one-117428612f46