この記事では、Tendermintで使用されるBCA(ビザンチンコンセンサスアルゴリズム)について説明します。 DLSプロトコルに基づいて開発されており、Proof-of-Workのように「アクティブ」マイニングを必要とせず、少なくとも2/3 +(厳密には3分の2以上)の「正直な」ネットワーク参加者でネットワークの安全な運用を保証できます。 以下では、このアルゴリズムがTendermintでどのように実装されるかを説明し、その動作に関する統計を提供し、5人の参加者の小さなネットワークでアルゴリズムの動作をシミュレートします。
目次
- はじめに
- バリデーター
- シンプルなスキーム
- アルゴリズムの手順
- 悪意のある提案者
- 最適なシナリオ
- おわりに
- リンク集
はじめに
BitcoinのProof-of-Workの登場以来、新しいコンセンサスアルゴリズムを見つけるために膨大な作業が行われてきました。 すべてが改訂されました。
- ネットワーク帯域幅(VisaとBitcoinの競合について話すのは難しく、4000 TPSに対して7 TPSを持っています)
- ネットワークのスケーリング(データシャーディングの問題など)
- ブロックチェーンネットワークに特徴的な新しい攻撃のクラス全体に対する耐性
現時点では、これらの問題に対して潜在的に興味深い解決策を持つプロジェクトは多くないようです。 まず第一に、これはもちろんDelegated-Proof-of-Stakeファミリー(BitShares、EOS、Lisk)です。 さらに、Proof-of-Importanceおよび主張された 4000 TPSを備えたNEMがあります(これがどのように一般的に可能かについては、以下の記事のいずれかで確実に説明します)。 IOTAで作成されたもつれには注意が必要です。 ただし、この記事では、BCAアルゴリズムとTendermintプロジェクトでの実装について詳しく説明します。
バリデーター
まず、ネットワークを稼働状態に維持する(つまり、コンセンサスの構築に参加する)人について話す必要があります。 誰でもいつでもマイナーになることができる同じProof-of-WorkまたはProof-of-Stakeとは異なり、BCAではいわゆるバリデーターのみがブロックチェーンの形成に参加できます。
通常のネットワークメンバーがバリデータになる方法は、特定の実装に依存します。 最も単純なケースでは、バリデーターはジェネシスブロックで宣言され、そのリストは将来変更されません(主なことは、バリデーターバリデーターの初期リストは厳密に1/3未満でなければならないことです!)。 同じTendermintで、バリデーターのローテーションを簡単に実装できます。 これを行うには、参加者が「実行」したい場合に送信される特別なトランザクションをプロトコルで示すだけで十分です。 さらに、同じLisk内で、候補者に投票を入力したり、既存のパラメータに従って候補者を選択したりすることができます。
Tendermintの実装では、どのブロックでも常にバリデーターの正確なリストを取得できます*。 それらは公開鍵によって識別され、投票プロセス中に、他の検証者および通常のネットワーク参加者に送信されるメッセージに対応する秘密鍵で署名します。 したがって、特定の声の作者をいつでも決定でき、「外部から」誰もコンセンサスの構築に参加できないことを確認できます。
*初期リストは、genesisファイルに設定されています。 バリデータのリストを変更するトランザクションは、他のトランザクションと同じトランザクションです。つまり、それらはブロックチェーンにも保存され、すべてのネットワーク参加者が現在のバリデータのリストを取得できます。
シンプルなスキーム
ブロックNを見つけたときにアルゴリズムで何が起こるかについての抽象的な説明から始めましょう。
NewHeight -> (Propose -> Prevote -> Precommit)+ -> Commit -> NewHeight ->...
Propose
-一部の提案者*は、ブロックのバージョンをNの高さに提供します。
Prevote
-このステップでは、各バリデーターがブロックに「評価意見」を与えます。 最も単純なケースでは、バリデーターは「Received block <ブロックハッシュ>、すべてに同意します」という形式のメッセージをネットワークに送信します。
Precommit
- Precommit
ステップに割り当てられた一定の時間の後、各検証Precommit
は、他の参加者から「蓄積」されたPrecommit
メッセージの量をチェックします。 バリデータの総数のPrecommit
+がある場合、バリデータはトランザクションをPrecommit
送信しPrecommit
。
括弧内の3つのステップ(Propose -> Prevote -> Precommit)
-これはいわゆるラウンドです。 その本質は、何らかの理由で新しいブロックを見つけることができなかった多くの場合があるということです。 たとえば、選択された提案者はオフラインになったり、意図的に誤ったブロックを提供したりする可能性があります(このケースの詳細については後述します)。
この場合、コンセンサス構築プロセスに2つの変更が加えられます。
- 新しい提案者が選択されました
- 各ステップには、すべてに共通の期間があります(条件付きで、
Prevote
ステップは5秒続き、その後すべての参加者がPrecommit
)。 接続が弱いために問題が発生した可能性が高いため(たとえば、提案者がインターネットに接続できず、ダウンロードしてネットワーク上にブロックを分散させる時間がなかったため)、各ステップの継続時間はある程度増加します。
以下は、テンダーミントの公式文書からのプロセス全体の図解です。
*提案者は、その重みに比例してバリデータのリストからラウンドロビンアルゴリズムによって選択されることに注意することが重要です**。 これにより、2つの興味深い特性が得られます。まず、必要な決定論(ネットワークの各メンバーが、このラウンドでどのバリデーターが提案者になるかを明確に把握できる必要があります)。 ただし、同時に、選択プロセスで提案者の既知のシーケンスに関連付けられた攻撃を無効にする擬似ランダムな選択肢があります。
**重量とはプロトコル開発者次第です。 最も単純なケースでは、すべてのバリデーターに同じ重みを割り当てることができます。つまり、提案者の選択は統一されます。
アルゴリズムの手順
このセクションでは、提案されたブロックに問題がある場合と、すべてが正常に機能している場合の2つのケースで、「指で」アルゴリズムの動作を説明しました。 もちろん、より多くの異なるブランチとケースを思い付くことができますが、これら2つは基本的なものであり、それらを理解しているので、残りのケースでアルゴリズムの動作を独立してモデル化できます。
悪意のある提案者
アルゴリズムを完全に理解するために、「実際の」ネットワーク上でその作業を解析することを提案します。 まず、ネットワーク自体を設定しましょう。
- 5つのバリデーターがあります: A 、 B 、 C 、 D 、 E (既に理解したように、ネットワーク参加者の総数は役割を果たしません。バリデーターのみがBCAにとって重要です)。
- 検証者Aが提案者として選択されます。 さらに、 Aをビザンチン検証器にして、ネットワークを侵害しようとしている瞬間にネットワークを調べることを提案します。
- 各ステップはt秒続きます。 アルゴリズムは時間Tで開始します。
それでは、 #Xブロックの作成を始めましょう。 1つ目は、 Propose
者がブロックを作成し、ネットワーク上で「分散」する必要がある期間t秒のPropose
ステップです。他の検証者がこのブロックを取得することは非常に重要です。
それでは、 Prevote
ステップにPrevote
ましょう。 現在、バリデータの主なタスクは、ブロックをチェックし、ブロックに「同意する」かどうかを判断することです。 この場合、 B 、 C 、 D 、 Eは、ネットワーク上でPrevote nil
メッセージを送信します。つまり、提案されたブロックに同意するものはいないということです。 よりリアルにするには、 Eのインターネットが悪く、t秒以内に何も受信しなかったとします。 (提案者も投票します!)不正なブロックをサポートするためにPrevote
送信します。 より現実的にするために、 Eにいつものように悪いインターネットを持たせ、 A 、 B 、 C 、 Dからの新しいメッセージをまったく受け取らないようにします 。
次に、各バリデータのPrevote
ステップで受信したメッセージは次のとおりです。
Eのインターネットは悪く、他の参加者には彼からのメッセージを受信する時間がありません。
ラウンドの最後のステップは残った- Precommit
。 B 、 C 、 D 、 Eは、 Precommit nil
ネットワークにメッセージを送信します(それぞれのPrecommit nil
メッセージの数はPrevote
+バリデータの数より少ないため)。 各バリデータに対してPrecommit
によって収集されたメッセージを見てみましょう。
明らかに、 Precommit
+ Precommit
メッセージを収集するバリデーターはありません。つまり、上記のスキームによれば、このラウンドは高さ#Xの新しいブロックを作成せずに完了します。 重要な注意-各ブロックには、これらの同じPrecommit
メッセージが含まれている必要があり、明らかに、少なくともPrecommit
以上が必要です。 したがって、 Aがネットワーク上に「偽」ブロックを分散させたい場合でも、必要な数のPrecommit
メッセージが署名されないため、参加者はすぐにキャッチに気付くことになります。
最適なシナリオ
既に理解したように、上記のラウンドでは、新しいブロックの作成は機能しませんでした。 これは、次のラウンドの開始前に、提案者が別のバリデーターを選択し( Bにします )、ステップの継続時間をわずかに増やして、低速接続の影響を相殺することを意味します。 そのため、このラウンドでは、検証者Eはインターネットの品質が悪いために傍観者ではなくなりますが、完全に参加します。
繰り返しますが、 Propose
ステップから開始しますが、今回はブロックが完全に有効であり、すべてのバリデーターに到達することができます。 したがって、すぐにPrevote
ステップに切り替えて、 Prevote
メッセージのリストが各バリデータをどのように表示するかを確認することを提案します。 さらに興味を引くために、 Aがまだ悪意があると仮定します。したがって、今回はブロックの作成を阻止しようとします。
すべてのバリデーターには、 Precommit
メッセージを送信するのに十分なPrecommit
メッセージがあることがPrecommit
ます。 繰り返しになりますが、楽しみのために、 Aが Precommit nil
メッセージを送信Precommit nil
ますが、これは正式には間違っています。
いずれにせよ、これは他の参加者に問題をPrecommit
、新しいブロックを作成するためにPrecommit
+ Precommit
メッセージを持っていることがPrecommit
ます。
おわりに
この場所で読んだので、この記事がお役に立てば幸いです:) Tendermintについてもう少し語ってください。近い将来、この素晴らしい技術に関する記事を少なくとも3つ公開する予定です。 最初は、プロジェクト全体とその機能の概要です。 2つ目は、独自のブロックチェーンを作成するプロセスです(ICOなし、約束します!)Tendermint + Python 3の束で、可能な限り詳細に説明します。