ブロックチェーン学習ロードマップ

ブロックチェーンの状態遷移:トランザクションがシステムの状態をどう変え、検証されるか

Tags: 状態遷移, トランザクション, UTXOモデル, アカウントモデル, 検証

ブロックチェーンにおける「状態」とは何か

ウェブアプリケーションやデータベースシステムにおいて、「状態」とは、システムが特定の瞬間に持っているデータの集合やその配置を指します。例えば、データベースであればテーブル内のレコードの内容が状態であり、アプリケーションであれば変数やメモリ上のデータ、ファイルシステムの内容などが状態を構成します。ユーザーがデータベースのレコードを更新したり、ファイルを編集したりすることで、システムの状態は変化します。

ブロックチェーンにおいても同様に「状態」という概念が存在します。これは、ネットワーク上の全ての参加者(ノード)が共有し、合意している特定の時点でのデータのスナップショットです。しかし、中央集権的なデータベースと異なり、ブロックチェーンの状態は分散されたネットワーク全体で維持され、特定のルール(プロトコル)に従ってのみ変化します。この状態の変化を引き起こす唯一の方法が「トランザクション」です。

ブロックチェーンにおける状態は、単にデータの集合であるだけでなく、そのチェーン上で定義された「ルール」に基づいて計算され、常に検証可能な形で存在します。これは、後述するUTXOモデルとアカウントモデルでその詳細が異なりますが、共通しているのは、過去の状態と有効なトランザクションの列から現在の状態が一意に定まるという特性です。

トランザクションによる状態遷移の基本プロセス

ブロックチェーンにおける状態遷移(State Transition)とは、ある時点の状態(State S)から、一つの有効なトランザクション(Transaction T)を適用することで、次の状態(State S')へ変化するプロセスを指します。これを関数のように表現すると、S' = Apply(S, T) となります。

このプロセスの信頼性と整合性を保つことが、ブロックチェーンの根幹をなす技術の一つです。トランザクションが状態を変化させるためには、いくつかのステップを経る必要があります。

  1. トランザクションの生成: ユーザーやアプリケーションが、状態を変更するための意図を表現したトランザクションを作成します。これは、例えば「AさんからBさんに10コインを送金する」や「スマートコントラクトの特定の関数を呼び出す」といった操作です。
  2. 署名: 生成されたトランザクションに、送信者(操作を行う主体)が自身の秘密鍵を用いて電子署名を行います。これにより、トランザクションが本人の意思で作成されたことと、内容が改ざんされていないことが証明されます。
  3. ネットワークへの伝播: 署名されたトランザクションは、ブロックチェーンのP2Pネットワークを通じて他のノードに伝播されます。
  4. トランザクションの検証: 各ノードは、受信したトランザクションがプロトコルのルールに則っているかを検証します。この検証には、署名の有効性、送信者の権限(例えば、送金に必要な残高があるか)、トランザクションの形式などが含まれます。この検証プロセスこそが、状態遷移が正しく行われるための重要なステップです。
  5. ブロックへの格納と合意形成: 有効と判断されたトランザクションは、マイナーまたはバリデーターによってブロックにまとめられます。そして、ネットワーク全体でそのブロックの内容(つまり、そのブロックに含まれるトランザクションによる状態遷移の結果)について合意形成が行われます。
  6. 状態の確定: 合意が形成され、新しいブロックがチェーンに追加されると、そのブロックに含まれるトランザクションによって引き起こされた状態遷移が確定し、ネットワーク全体の状態が更新されます。

このプロセスの中で、特に重要な技術的要素が「トランザクションの検証」と、それに伴う「状態の計算と更新」です。ブロックチェーンの二つの主要な取引モデルであるUTXOモデルとアカウントモデルでは、この状態の持ち方と、それに伴う状態遷移および検証の仕組みが大きく異なります。

UTXOモデルにおける状態遷移と検証(例:Bitcoin)

UTXO(Unspent Transaction Output:未使用トランザクション出力)モデルは、Bitcoinによって採用されたモデルです。このモデルにおける「状態」は、ネットワーク上に存在する全ての未使用のトランザクション出力(UTXO)の集合として定義されます。銀行口座の残高のようにアカウントごとに金額を管理するのではなく、「いくらの金額が、どのトランザクションのどの出力として、まだ誰にも使われていないか」という「未使用コインの断片」の集合が状態なのです。

状態遷移の仕組み

トランザクションは、既存のUTXOを「入力(Input)」として消費し、新しいUTXOを「出力(Output)」として生成することで状態を変化させます。

例えば、「AさんがBさんに10 BTCを送金する」トランザクションは、Aさんが以前受け取ったUTXO(合計が10 BTC以上、例えば15 BTCのUTXO)を入力として指定し、それを消費します。そして、新しい出力として、Bさん宛ての10 BTCのUTXOと、Aさん自身へのお釣り(15 BTC - 10 BTC - 手数料、例えば4.9 BTC)のUTXOを生成します。

このトランザクションが処理されると、元の15 BTCのUTXOは「使用済み」となり状態(UTXO集合)から削除され、新しく生成された10 BTCと4.9 BTCのUTXOが状態に追加されます。これがUTXOモデルにおける状態遷移です。

// UTXOモデルにおける状態遷移のイメージ(概念図の表現)

現在の状態(UTXO集合S):
[UTXO_X (金額: 15 BTC, 所有者: A), UTXO_Y (金額: 5 BTC, 所有者: C), ...]

トランザクションT (A -> Bへ10 BTC送金):
  入力: UTXO_X (15 BTC, 所有者A)  // これを消費
  出力: UTXO_Z (10 BTC, 所有者B)  // これを生成
        UTXO_W (4.9 BTC, 所有者A) // お釣りとして生成 (手数料 0.1 BTCを仮定)

新しい状態(UTXO集合S'):
[UTXO_Y (金額: 5 BTC, 所有者: C), UTXO_Z (金額: 10 BTC, 所有者: B), UTXO_W (金額: 4.9 BTC, 所有者: A), ...]
// UTXO_X は状態から削除されている

検証プロセス

UTXOモデルにおけるトランザクションの検証は、主に以下の点を確認します。

  1. 入力UTXOの存在と有効性: 指定された入力UTXOが、現在の状態(UTXO集合)に未使用として存在することを確認します。すでに使用済みのUTXOを二重に使用しようとする「二重支払い(Double Spending)」を防ぐ最も基本的な検証です。
  2. 入力UTXOの使用権: 入力UTXOを使用するための条件(通常はスクリプトと呼ばれるロック条件)を満たしているか、特に送信者の秘密鍵による署名が正しく、対応する公開鍵ハッシュと一致することを確認します。
  3. 入力金額 >= 出力金額 + 手数料: トランザクションの入力として指定された全てのUTXOの合計金額が、出力として生成される全てのUTXOの合計金額とトランザクション手数料の合計以上であることを確認します。これにより、新たなコインが不正に発行されることを防ぎます。差額がマイナーへの手数料となります。
  4. 形式の有効性: トランザクションのデータ構造がプロトコルの定める形式に準拠しているかを確認します。

これらの検証が全て成功した場合にのみ、そのトランザクションは有効な状態遷移を引き起こすものとみなされ、ブロックに取り込まれる候補となります。

アカウントモデルにおける状態遷移と検証(例:Ethereum)

アカウントモデルは、Ethereumなどのブロックチェーンで採用されています。このモデルにおける「状態」は、全てのアカウント(外部所有アカウント EOA とコントラクトアカウント CA)の集合とその関連データ(残高、Nonce、ストレージ、コード)として定義されます。これは、一般的なデータベースシステムや銀行システムにおけるアカウント残高管理に概念的に近いです。

状態遷移の仕組み

アカウントモデルにおける状態は、アカウントごとの以下の情報で構成されます。

トランザクションは、これらのアカウントの状態を直接的に変更します。例えば、「AさんからBさんに10 ETHを送金する」トランザクションは、Aさんのアカウント残高を減らし、Nonceを増やし、Bさんのアカウント残高を増やします。「スマートコントラクトの関数を呼び出す」トランザクションは、そのコントラクトアカウントのNonceを増やし、実行結果によってはコントラクトのストレージ状態(Storage Root)や他のアカウントの残高などを変更します。

アカウントモデルにおける状態は、全ての有効なアカウントの状態を効率的に管理するために、通常マークルパトリシアツリー(Merkle Patricia Tree)のようなツリー構造で表現されます。ツリーのルートハッシュがその時点でのグローバルな状態のフィンガープリントとなります。トランザクションによる状態変更は、このツリーの一部を更新することに相当します。

// アカウントモデルにおける状態遷移のイメージ(概念図の表現)

現在の状態(アカウント状態ツリーS):
  ルートハッシュ: H1
  アカウントA: { Nonce: 10, Balance: 50 ETH, ... }
  アカウントB: { Nonce: 5, Balance: 30 ETH, ... }
  コントラクトC: { Nonce: 3, Balance: 0 ETH, StorageRoot: R_C, CodeHash: CH_C, ... }
  ...

トランザクションT (A -> Bへ10 ETH送金):
  送信元: アカウントA
  送信先: アカウントB
  金額: 10 ETH
  Nonce: 10 (アカウントAの現在のNonceと一致)
  Gas Limit, Gas Price, Signature ...

トランザクション実行による状態変更:
  アカウントA: Balance = 50 - 10 = 40 ETH, Nonce = 10 + 1 = 11
  アカウントB: Balance = 30 + 10 = 40 ETH

新しい状態(アカウント状態ツリーS'):
  ルートハッシュ: H2 (アカウントAとBの状態変更により、ツリーのルートハッシュが変わる)
  アカウントA: { Nonce: 11, Balance: 40 ETH, ... }
  アカウントB: { Nonce: 5, Balance: 40 ETH, ... }
  コントラクトC: { Nonce: 3, Balance: 0 ETH, StorageRoot: R_C, CodeHash: CH_C, ... }
  ...

検証プロセス

アカウントモデルにおけるトランザクションの検証は、トランザクション自体が有効であることと、そのトランザクションを実行した結果の状態遷移が有効であることを確認するステップに分けられます。

  1. トランザクションの事前検証:
    • 署名の有効性: 送信者の秘密鍵による署名が正しいことを確認します。これにより、送信者のアドレスが特定されます。
    • Nonceの一致: トランザクションに含まれるNonceが、送信者アカウントの現在のNonceと一致することを確認します。
    • 残高とガスの確認: 送信者のアカウントに残高があり、トランザクションの実行に必要なガス代(Gas Limit * Gas Price)を支払えるかを確認します。
  2. 状態遷移の実行と検証:
    • 状態のロード: トランザクションの実行に必要なアカウントの状態(残高、Nonce、ストレージなど)を現在の状態ツリーからロードします。
    • トランザクションの実行: Ethereum Virtual Machine (EVM) などの実行環境でトランザクションを実行します。これは、送金処理であったり、スマートコントラクトのコード実行であったりします。
    • 状態の更新: 実行結果に基づいて、関与したアカウントの状態を更新します(残高の増減、Nonceの増加、ストレージの変更など)。実行によって消費されたガス代を送信者から差し引き、マイナー/バリデーターに分配する処理も行われます。
    • 結果の検証: 実行が成功したか、ガスの使用量がGas Limitを超えていないか、などの結果を確認します。

この実行と検証のプロセス全体が、有効な状態遷移であるかを判断します。全ての検証を通過したトランザクションのみがブロックに取り込まれます。

UTXOモデルとアカウントモデルの比較

状態管理と状態遷移の観点から、両モデルには以下のような違いがあります。

| 特徴 | UTXOモデル (例: Bitcoin) | アカウントモデル (例: Ethereum) | | :---------------- | :------------------------------------------------ | :-------------------------------------------------------- | | 状態の定義 | 未使用トランザクション出力 (UTXO) の集合 | 全てのアカウントの状態 (残高, Nonce, ストレージなど) の集合 | | 状態遷移の方法| 既存UTXOの消費と新規UTXOの生成 | アカウント状態(残高, Nonce, ストレージ)の直接的な変更 | | トランザクションの構造 | 入力 (参照するUTXO + 署名), 出力 (新規UTXO) | 送信元, 送信先, 金額, Nonce, Gas Limit, Gas Price, データ(コントラクト呼び出し) | | 検証のポイント | 入力UTXOの存在/使用権、入力合計 >= 出力合計+手数料 | 署名, Nonce, 残高, ガス代、実行結果による状態変更の妥当性 | | 二重支払い防止| UTXOが一度しか入力として使用されないことを確認 | Nonceによってトランザクションの順序を保証し、一度しか処理されないようにする | | スマートコントラクトとの相性 | スクリプトは限定的(複雑な状態管理は難しい) | EVMなどで複雑なコントラクトロジックと状態管理が可能 | | プライバシー | トランザクションを追跡することで資金の流れを把握しやすい(ミキシングなどで複雑化) | アカウント単位で活動が可視化されやすい |

UTXOモデルはシンプルで、特にコインの所有権管理と送金においては高いセキュリティ(二重支払い防止)を効率的に実現できます。一方、アカウントモデルは、アカウント状態を直接操作するため、スマートコントラクトによる複雑なアプリケーション(dApps)の状態管理や、開発者が馴染みやすいプログラミングモデルに適しています。

コンセンサスによる状態の確定

ブロックチェーンにおける状態遷移は、個々のノードがトランザクションを検証するだけでは最終的に確定しません。検証され有効と判断されたトランザクションは、ブロックにまとめられ、ネットワーク全体でそのブロックの有効性について合意形成(コンセンサス)が行われます。

Proof of Work(PoW)やProof of Stake(PoS)のような合意形成アルゴリズムは、どのブロック(つまり、どの状態遷移の集合)が正当であるかを決定するメカニズムです。ノードが新しいブロックを検証する際には、そのブロックに含まれる全てのトランザクションを、直前のブロックで確定した状態に順次適用し、その結果得られる状態が、新しいブロックヘッダーに含まれる状態ルートハッシュ(アカウントモデルの場合)や、新しいUTXO集合(UTXOモデルの場合、直接状態ルートを持たない場合も多い)と一致するかを確認します。

このブロック全体の検証と合意形成を経て、初めてそのブロックに含まれるトランザクションによる状態遷移がネットワーク全体で確定的なものとして受け入れられ、グローバルな状態が更新されます。チェーンが分岐(フォーク)した場合、コンセンサスルールに従って最も有効と判断されたチェーンの状態が「真の状態」となります。

まとめと次のステップ

この記事では、ブロックチェーンにおける「状態」の概念と、トランザクションによってその状態がどのように遷移し、どのように検証されるのかを、UTXOモデルとアカウントモデルの違いを交えて解説しました。Webエンジニアの視点から見ると、ブロックチェーンは分散されたステートマシンであり、トランザクションはその状態遷移を引き起こすインプットであると理解できます。従来のデータベースにおけるトランザクション処理とは異なり、ブロックチェーンでは全てのノードが独立してトランザクションを検証し、その結果の状態遷移の正当性を確認するというプロセスが、非中央集権的な信頼性を支えています。

ブロックチェーンの状態遷移と検証メカニズムを理解することは、 * トランザクションが実際にネットワーク上でどのように処理されるか * なぜ二重支払いが困難なのか * スマートコントラクトの実行がグローバルな状態にどう影響するか * 異なるブロックチェーンモデルがどのように状態を管理しているか といった、ブロックチェーン技術の深い部分を理解する上で非常に重要です。

この知識を足がかりに、さらに以下のトピックについて学習を進めることをお勧めします。

これらの技術要素は密接に関連しており、一つずつ理解を深めることで、ブロックチェーン全体システムの動作原理がよりクリアになるでしょう。