「ブロックチェーンってよく聞くけど、実際にはどう動いているの?」
そんな疑問を、シンプルなPythonコードを書きながら理解するのがこの記事のゴールです。
ここでは以下のような、最小限のブロックチェーンを作ります。
- ブロック(Block)というデータ構造を定義
- ブロック同士を「ハッシュ値」で鎖のようにつなぐ
- 「改ざんがあればすぐにバレる」仕組みをPythonで確認
- 余裕があれば、簡易的な「マイニング(Proof of Work)」も追加
※あくまで学習・理解用の簡易版です。実運用のセキュリティやネットワーク機能などは省いています。
1. ブロックチェーンのざっくりしたイメージ
ブロックチェーンは、ざっくり言うと:
- 取引データのまとまり → 「ブロック」
- 各ブロックが、ひとつ前のブロックのハッシュ値を覚えている
- すべてをつなげた**「鎖(チェーン)」**になっている
という構造です。
もし途中のブロックが改ざんされると、
- そのブロックのハッシュ値が変わる
- それを参照していた次のブロックの「前のハッシュ」と噛み合わなくなる
- チェーン全体の整合性が崩れる
→ 改ざんがすぐに検出できる、という仕組みです。
2. 開発環境と前提知識
- Python 3.x(3.8以上を推奨)
- 必要な標準ライブラリ:
hashlib,time - Pythonの基本的なクラス・関数・リストの使い方がわかる前提で説明します
3. 最初の「Block」クラスを作る
まずは1つのブロックを表すクラスから作っていきます。
ブロックが持つ情報(最小構成の例):
-
index:ブロック番号(0, 1, 2, …) -
timestamp:作成した日時 -
data:ブロックに記録したいデータ(ここでは文字列) -
previous_hash:一つ前のブロックのハッシュ値 -
hash:このブロック自身のハッシュ値
import hashlib
import time
class Block:
def __init__(self, index, timestamp, data, previous_hash):
self.index = index # ブロック番号
self.timestamp = timestamp # 作成時刻(UNIX時間など)
self.data = data # 保存したいデータ
self.previous_hash = previous_hash # ひとつ前のブロックのハッシュ
self.hash = self.calculate_hash() # 自分自身のハッシュを計算
def calculate_hash(self):
"""
ブロックの内容からSHA-256ハッシュを計算する
"""
block_string = (
str(self.index)
+ str(self.timestamp)
+ str(self.data)
+ str(self.previous_hash)
)
return hashlib.sha256(block_string.encode("utf-8")).hexdigest()
ポイント:
-
calculate_hash()では、ブロックの中身を文字列に連結してSHA-256でハッシュ化しています。 -
同じ内容のブロックなら同じハッシュになりますが、
どこか1文字でも変えると、ハッシュ値は大きく変わるという性質があります。
4. ジェネシスブロック(最初のブロック)を作る
ブロックチェーンの一番最初のブロックは「ジェネシスブロック」と呼ばれ、
前のブロックが存在しない特別なブロックです。
def create_genesis_block():
"""
チェーンの最初のブロック(ジェネシスブロック)を作る
index: 0
previous_hash: "0" などの適当な値
"""
return Block(
index=0,
timestamp=time.time(),
data="Genesis Block",
previous_hash="0"
)
5. Blockchainクラスを作る
次に、複数のブロックをまとめて管理するBlockchainクラスを作ります。
機能としては:
- 最初のブロック(ジェネシスブロック)を作る
- 新しいブロックをチェーンに追加する
- チェーンが正しいか検証する(
is_chain_valid)
class Blockchain:
def __init__(self):
# 最初にジェネシスブロックだけを持つリストを作る
self.chain = [create_genesis_block()]
def get_latest_block(self):
"""
チェーンの最新のブロックを返す
"""
return self.chain[-1]
def add_block(self, new_data):
"""
新しいデータからブロックを作り、チェーンに追加する
"""
latest_block = self.get_latest_block()
new_index = latest_block.index + 1
new_timestamp = time.time()
new_previous_hash = latest_block.hash
new_block = Block(
index=new_index,
timestamp=new_timestamp,
data=new_data,
previous_hash=new_previous_hash
)
self.chain.append(new_block)
def is_chain_valid(self):
"""
チェーンが有効かどうかを検証する:
- 各ブロックのハッシュが中身から再計算したものと一致するか
- previous_hash が、一つ前のブロックの hash と一致するか
"""
for i in range(1, len(self.chain)):
current_block = self.chain[i]
previous_block = self.chain[i - 1]
# 1. 自分のハッシュが正しいか
if current_block.hash != current_block.calculate_hash():
print(f"Error: block {current_block.index} のハッシュが不正です")
return False
# 2. 前のブロックのハッシュと一致しているか
if current_block.previous_hash != previous_block.hash:
print(f"Error: block {current_block.index} のprevious_hashが不正です")
return False
return True
6. 実際にチェーンを動かしてみる
ここまでで、簡単なブロックチェーンができたので、
実際にブロックを追加して中身を確認してみましょう。
if __name__ == "__main__":
# ブロックチェーンを作成
my_chain = Blockchain()
# 適当なデータを3つくらい追加
my_chain.add_block("AliceがBobに1 BTC支払った")
my_chain.add_block("BobがCharlieに0.5 BTC支払った")
my_chain.add_block("CharlieがDaveに0.2 BTC支払った")
# チェーンの中身を表示
for block in my_chain.chain:
print("--------------")
print(f"Index: {block.index}")
print(f"Timestamp: {block.timestamp}")
print(f"Data: {block.data}")
print(f"Previous Hash: {block.previous_hash}")
print(f"Hash: {block.hash}")
# チェーンが有効かどうか検証
print("Blockchain valid?:", my_chain.is_chain_valid())
これを実行すると、各ブロックが前のハッシュを参照しながら
鎖のようにつながっている様子が確認できます。
7. 改ざんするとどうなるか試してみる
ブロックチェーンのポイントは、「改ざんするとすぐバレる」というところです。
例えば、途中のブロックのdataを書き換えてみましょう。
if __name__ == "__main__":
my_chain = Blockchain()
my_chain.add_block("AliceがBobに1 BTC支払った")
my_chain.add_block("BobがCharlieに0.5 BTC支払った")
# 正常な状態
print("Valid before tampering?:", my_chain.is_chain_valid())
# 2番目のブロック(インデックス1)を改ざん
my_chain.chain[1].data = "AliceがBobに100 BTC支払った!!"
# もう一度検証
print("Valid after tampering?:", my_chain.is_chain_valid())
出力例(イメージ):
Valid before tampering?: True
Error: block 1 のハッシュが不正です
Valid after tampering?: False
1つのブロックをいじるだけで、そのブロックのハッシュが変わり、
previous_hashと噛み合わなくなるため、チェーンが無効と判定されます。
8. (発展)簡単な Proof of Work を追加する
ビットコインのようなブロックチェーンでは、「マイニング」と呼ばれる
計算問題を解くことで、新しいブロックが追加されます。
ここでは超シンプルに:
- ハッシュ値が
"0000"で始まるまで、nonceをひたすら変えて計算する
という「なんちゃってProof of Work」を追加してみます。
8.1 Blockクラスに nonce とマイニングメソッドを追加
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.nonce = 0 # 追加: マイニング用のカウンタ
self.hash = self.calculate_hash()
def calculate_hash(self):
block_string = (
str(self.index)
+ str(self.timestamp)
+ str(self.data)
+ str(self.previous_hash)
+ str(self.nonce) # nonceもハッシュに含める
)
return hashlib.sha256(block_string.encode("utf-8")).hexdigest()
def mine_block(self, difficulty):
"""
difficultyで指定した個数分、先頭が"0"のハッシュになるまで
nonceを増やしながら探す
例: difficulty = 4 のとき、"0000xxxx..." から始まるハッシュを探す
"""
target = "0" * difficulty
while not self.hash.startswith(target):
self.nonce += 1
self.hash = self.calculate_hash()
print(f"Block {self.index} mined! nonce={self.nonce}, hash={self.hash}")
8.2 Blockchain側でマイニングを呼び出す
Blockchainクラスに、difficulty を持たせて、
ブロック追加時に mine_block() を呼びます。
class Blockchain:
def __init__(self, difficulty=4):
self.chain = [create_genesis_block()]
self.difficulty = difficulty
def get_latest_block(self):
return self.chain[-1]
def add_block(self, new_data):
latest_block = self.get_latest_block()
new_index = latest_block.index + 1
new_timestamp = time.time()
new_previous_hash = latest_block.hash
new_block = Block(
index=new_index,
timestamp=new_timestamp,
data=new_data,
previous_hash=new_previous_hash
)
# ここでマイニングを実行
new_block.mine_block(self.difficulty)
self.chain.append(new_block)
これで、add_block()を呼ぶたびに、
指定した難易度の条件を満たすハッシュが見つかるまで計算を行います。
難易度(difficulty)を大きくすると、マイニングにかかる時間が急激に伸びます。
9. ここまでで何がわかったか
この簡易ブロックチェーンを通して、以下のポイントが体感できたと思います。
-
ブロックは、取引データ + 前のハッシュ + 自分のハッシュ で構成される
-
ブロック同士がハッシュでつながっているので、途中の改ざんがすぐバレる
-
(発展)簡易的なProof of Work(マイニング)を入れることで、
- ブロック追加には一定の計算コストが必要になる
- 「好き放題にブロックを追加できない」ような制約をかけられる
実際のブロックチェーン(ビットコインやイーサリアムなど)は、ここにさらに:
- P2Pネットワーク・ノード
- 取引の署名(公開鍵暗号)
- コンセンサスアルゴリズム(PoW, PoSなど)
- スマートコントラクト
- セキュリティ・攻撃パターン対策
など、様々な要素が乗ってきます。
10. 次に学ぶと良いトピック
もしこの記事で「ブロックチェーンの仕組みのイメージ」がつかめたなら、
次のようなトピックを学ぶと理解がより深まります。
- 公開鍵暗号・電子署名(取引に署名する仕組み)
- P2Pネットワーク(ノード同士の通信・ブロックの伝播)
- ビットコインのブロック構造と実際のフィールド
- イーサリアムのアカウントモデルとスマートコントラクト
- UTXOモデル vs アカウントモデルの違い
11. まとめ
この記事では、
- Pythonで最小限のブロックチェーンを自作しながら
- ブロック、チェーン、ハッシュ、改ざん検知、簡易PoW
といった基本の仕組みを学びました。
実務レベルのブロックチェーンはもっと複雑ですが、
「中身はただのデータ構造とハッシュの組み合わせなんだ」という感覚が持てれば、
論文や公式ドキュメントもぐっと読みやすくなるはずです。
もしよければ、このコードをベースに、
- ブロックをJSONで保存する
- 簡易なREST APIを作って、ブラウザからブロック追加
- 署名や残高の概念を追加して「なんちゃって仮想通貨」を作る
といった発展にもチャレンジしてみてください。