ブロックチェーンの世界では、Proof of Workによるマイニングが重要な役割を果たしています。しかし、マイナーが単独で作業するのは非効率なため、多くのマイナーはマイニングプールに参加します。このマイナーとマイニングプールを効率的に結びつける通信プロトコルがStratumプロトコルです。このプロトコルは、マイナーがプールから作業単位(ジョブ)を受け取り、計算結果を提出するまでの流れを標準化し、ネットワーク全体の安定性と採掘効率を大幅に向上させました。本記事では、Stratumプロトコルの基本的な仕組みと、マイナーとマイニングプール間の通信の流れを分かりやすく解説していきます。
Stratumプロトコル入門:サービスディスカバリとプロキシ機能の仕組み
Stratumプロトコルとは何か
Stratumプロトコルは、マイナー(採掘者)とマイニングプール(採掘プール)の間で効率的な通信を行うために設計された重要なプロトコルです。従来の`getwork`プロトコルに比べて非常に効率的で、現代のビットコインをはじめとする暗号通貨のマイニングにおいて事実上の標準として広く採用されています。このプロトコルは、マイナーがプールからワーク(作業単位)を継続的かつ遅延なく受け取り、計算できたシェア(共有結果)を素早く提出することを可能にします。これにより、ネットワーク全体のハッシュパワーを有効活用し、マイナーの収益性を高めることができます。
| 用語 | 説明 |
|---|---|
| Stratumプロトコル | マイナーとマイニングプール間の効率的な通信規格 |
| マイナー (Miner) | 実際に計算処理を行いブロック生成を試みる機器またはソフトウェア |
| マイニングプール (Mining Pool) | 複数のマイナーの計算力を集約するサーサーバー |
| ワーク (Work) | マイナーに割り当てられる計算作業の単位 |
| シェア (Share) | マイナーが完了したワークの証拠となる計算結果 |
Stratumプロトコルの基本的な仕組み
Stratumプロトコルの核心は、TCP/IPソケット上で動作し、JSON-RPCという形式のメッセージを利用した非同期通信にあります。接続が確立されると、マイニングプールはマイナーに対して、ブロックヘッダーを含むマイニングジョブを絶えず送信し続けます。マイナーはこのジョブを受け取り、ノンス(Nonce)やエクストラノンス(ExtraNonce)の値を変化させながら、指定された難易度ターゲットを満たす解答(=有効なシェア)の探索を開始します。そして解答が見つかり次第、その結果をプールに提出するという流れを繰り返します。この一連の流れが途切れることなく行われるため、マイナーのハードウェアを常に稼働させることが可能になります。
| 要素 | 役割 |
|---|---|
| TCP/IP接続 | マイナーとプール間の確実な通信路を提供 |
| JSON-RPCメッセージ | データを構造化して交換するための軽量なプロトコル |
| マイニングジョブ (mining.notify) | 新しい作業単位をマイナーに通知・配布するメッセージ |
| ノンス (Nonce) | マイナーが変更可能な4バイトの値。ハッシュ計算に使用 |
| エクストラノンス (ExtraNonce) | より多くの作業空間を提供するための追加領域 |
マイナーからマイニングプールへの主要なメッセージ
マイナー側からマイニングプールに対して送信される主なメッセージには、接続の確立、ジョブの受信確認、そして計算結果の提出があります。まず、最初にmining.subscribeメッセージを送信して接続を開始し、自身の能力(バージョンンマスキングなど)を通知します。次に、mining.authorizeメッセージで採掘報酬を受け取るためのワーカー名とパスワードを用いて認証を行います。そして最も重要なメッセージがmining.submitです。このメッセージの中で、マイナーは見つけた有効なシェアの情報(ワーカー名、ジョブID、ノンス、タイムスタンプなど)を全て含めてプールに提出します。プールはこの提出を検証し、有効であればマイナーの貢献として記録します。
| メッセージ | 目的 |
|---|---|
| mining.subscribe | プールへの接続を開始し、マイナーの能力を通知 |
| mining.authorize | ワーカー名とパスワードで認証を行い、採掘権限を取得 |
| mining.submit | 計算が完了したシェアをプールに提出するためのメッセージ |
| ワーカー名 (Worker Name) | マイナーを識別し、報酬を振り分けるための名前 |
マイニングプールからマイナーへの主要なメッセージ
マイニングプールからマイナーへの主要なメッセージは、作業の配布とネットワーク状態の通知が中心です。中でも最も頻繁に送信されるのがmining.notifyメッセージです。これには、マイニングを行うために必要な全てのデータ(ジョブID、前のブロックのハッシュ、コインインベーストランザクションなど)が含まれており、新しいブロックの候補ができるたびに送信されます。また、プール側の都合やネットワークの状況に応じて採掘難易度を変更する必要がある場合、mining.set difficultyメッセージを送信してマイナーに新しい難易度ターゲットを通知します。これにより、プールはネットワークの混雑度やマイナーの総計算力に応じて、シェアの提出頻度を最適に調整することができます。
| メッセージ | 目的 |
|---|---|
| mining.notify | 新しいマイニングジョブの詳細をマイナーに通知・配布 |
| mining.set difficulty | マイナーに対して、シェア提出の目標難易度を変更するよう指示 |
| ジョブID (Job ID) | 各マイニングジョブを一意に識別するためのID |
| 難易度 (Difficulty) | 有効なシェアとみなされるためのハッシュ値の目標値 |
Stratumプロトコルの実際のメッセージ例
Stratumプロトコルの理解を深めるため、実際のメッセージ交換の例を見てみましょう。まず、マイナーがプールに接続する際の最初のメッセージである`mining.subscribe`は、`{id: 1, method: mining.subscribe, params: []}`のようなシンプルな形式です。これに対してプールは、`mining.notify`メッセージとして`{params: [job id, prevhash, coinb1, coinb2, …], …}`のように、採掘に必要な全てのデータを含む大きなメッセージを返信します。マイナーがシェアを見つけて提出する`mining.submit`メッセージは、`{params: [worker name, job id, ExtraNonce2, nTime, nonce], …}`の形式を取ります。これらのメッセージは全てJSON形式で書かれ、人間が読むことも可能ですが、実際の処理はマシンによって高速に行われています。
| メッセージの種類 | 具体例 (簡略化) |
|---|---|
| mining.subscribe (マイナー→プール) | {id: 1, method: mining.subscribe, params: []} |
| mining.notify (プール→マイナー) | {id: null, method: mining.notify, params: [job id, prevhash, …]} |
| mining.submit (マイナー→プール) | {id: 4, method: mining.submit, params: [worker.1, job id, …]} |
年金Q&A
Stratumプロトコルとは何ですか?
Stratumプロトコルはマイナーとマイニングプールの間で効率的な通信を実現するために設計されたプロトコルです。従来のgetblocktemplateプロトコルに比べて低遅延かつ軽量な通信が特徴で、マイニングプールが新しい作業をマイナーに迅速に分配することを可能にします。このプロトコルではJSON-RPCをベースにしたメッセージ形式を使用し、マイナー側の計算リソースを最大限に活用できる仕組みとなっています。
マイナーはどのようにマイニングプールと接続しますか?
マイナーはまずマイニングプールが指定するストラタムサーバーのアドレスとポート番号に対してTCP接続を確立します。接続後、マイナーはmining.subscribeメソッドでセッションを開始し、続いてmining.authorizeメソッドで認証を行います。この認証プロセスではウォレットアドレスやワーカー名を送信し、マイニングプール側で正当なマイナーであることを確認します。
作業の割り当てと提出の流れはどうなっていますか?
マイニングプールは接続済みのマイナーに対してmining.notifyメソッドで新しいマイニングジョブをブロードキャストします。この通知にはジョブID、前ブロックハッシュ、コインベーストランザクションなどが含まれます。マイナーは受け取った情報をもとにノンスの探索を開始し、有効な解答を見つけた場合はmining.submitメソッドで結果をプールに提出します。
難易度調整はどのように行われますか?
マイニングプールは各マイナーの計算能力に応じて個別の難易度を設定できます。mining.set difficultyメソッドを使用して、接続中のマイナーに対して動的に難易度を変更することが可能です。これにより高スペックなマイナーには高い難易度を、低スペックなマイナーには低い難易度を割り当てることで、ネットワーク全体の効率を最適化しています。
