読者です 読者をやめる 読者になる 読者になる

Tech と Culture

テクノロジーとカルチャー

翻訳:Satoshi Clientブロック交換

次はこれ。

https://en.bitcoin.it/wiki/Satoshi_Client_Block_Exchange

大事な部分の英語が分からない。。。

誰か偉い人教えて。

Satoshi Clientブロック交換
 
1 概要
2 Inventoryメッセージ
3 ブロックバッチング
4 バッチ継続メカニズム
5 ストールリカバリ
6 ロングオーファンチェイン
7 Flood Limit効果
8 パフォーマンス
9 脚注
 
1 概要
この記事はノード間でどのようにブロックの交換が行われるかを説明します。 どのようにブロックがバリデートされるかについても詳しい情報はProtocol rulesを参照してください。
最初のコネクションで、コネクションが内向きでない場合、言い換えるとコネクションがローカルノードから始まっている場合、versionメッセージがキューイングされ、即座に送信されます。リモートのノードがversionメッセージを受信した時に、リモートのノードは自分のversionメッセージを返信します。
ノードが”version”メッセージを受信した時に、もし下記のいずれかの条件が成り立つ時、”getblocks”リクエストをリモートノードに送ります。
 1 ノードは最初のgetblocksリクエストを他のいかなるノードにも送っていない
 2 もしくは、これが唯一のアクティブなノードコネクションである。おそらくノードはこのコネクション以前にはゼロコネクションであり、おそらく長い間接続できていないと思われる。そこでキャッチアップのためにブロックを要求する。
getblocksメッセージは、リクエストしたノードがすでに所有している複数のブロックハッシュを含み、リモートノードがノード間の最後の共通するブロックを見つけ出すのを助けます。ハッシュのリストは最新のブロックから10そして次にべき上倍にジェネシスブロックに届くまで戻っていきます。両方のノードはジェネシスブロックはハードコードされているため、少なくともそこから始めることができることは保証されています。もしなんらかの理由でそのブロックが一致しない場合、ブロックは一つも交換されません。
 
2 Inventoryメッセージ
ノードはgetblocksリクエストを受信しても返信において完全なブロックを実際に送信するわけではないことに注意しましょう。ノードはリクエストに相当するブロック群のハッシュのみを含んでいる”inv”メッセージを送ります。それによって、リモートノードが持っていない(しかしまだリモートノードが完全なブロックを望んでいるとは仮定しないように)実際のブロックを送ることを検証します。
ローカルのノードが”inv”メッセージを受信した時、”getdata”メッセージによって実際のブロックをリクエストします。下記を参照。
しかし、最初にローカルノードによって送られた”getblocks”リクエストへのレスポンスとしてどのようにリモートノードが”inv”メッセージを送るのか、詳細を見てみましょう。リモートノードはpFrom->PushInventoryをコールします。それはブロックをリクエストしたノード(このウォークスルー中ではローカルノードです)を表しているCNodeインスタンスメソッドです。そして、PushInventoryはCNodeの変数であるvInventoryToSendへブロックハッシュを追加します。main.cpp内のSendMessages関数はvInentoryToSendの中からinvのアイテムを取り出し、vInvの変数に追加していきます。それによって実際の送信の準備ができます。変数を分離させている理由は幾つかのInventoryアイテムは(現在はトランザクションのみです)リモートノードに対して”trickled"されています。それは即座に送信される訳ではないことを意味します。vInv変数が1000エントリ満たされた時、メッセージはこれらの1000個のエントリと共にキューイングされ、ループが続きます。最後に、残ったエントリは最後の”inv”メッセージで送信されます。
ローカルノードが”inv”メッセージを受け取った時、”getdata”メッセージで実際のブロックをリクエストします。正確に言うと、ノードはpfrom->AskForをブロックをリクエストするためにコールし、そのメソッドはmapAskForの中にあるブロックのリクエストをキューイングし、多目的なSendMessage()がmapから1000エントリのバッチの”getdata”リクエストを送信します。
 

The code attempts to limit redundant requests to every 2 minutes for the same block by using a map called mapAlreadyAskedFor to delay the message if necessary.[6]

(コードはmapAlreadyAskedForをコールし必要ならばメッセージを遅らせることで2分毎に冗長に同じブロックをリクエストすることを制限しようとします????)
 
3 ブロックバッチング
“getblocks”リクエストに対応するノードは要求者への応答に対して500ブロックの制限をつけようとします。
しかしながら変わったtwistがあります。もし要求者が、メインのブランチから分岐しているように見える時、ノードは要求者のバッドチェーン、最後の共通ブロックから要求者が持っている最後のブロック(間違ったメインブランチ)、を完全に置き換えることができるように必要な多数のブロックを送ります。これは500個のメインブランチアップデートをキャッチアップするためのものに追加でおこなわれます。
加えて、送信のためにキューイングされるブロックの数に制限があるだけでなく、bitcoindはキューイングされるブロックのサイズにも制限があることに注意しましょう。これは現在のところ、送信バッファサイズ、10MB、の半分に制限されており、5MBとなっています(?)。
 
4 バッチ継続メカニズム
ノードがブロックinventoryのバッチの送信を終了した時、バッチの最後のブロックのハッシュを記録します。
 
When the node receives a request for that full block, it realizes the remove node is done with the current batch and directly queues a special "inv" message (bypassing the normal SendMessage mechanism) with one block hash entry containing the latest block hash.[12] When the remote node receives that "inv" message, it will see that it does not have that block and it it will ask for that block as described above.
 
(ノードが完全なブロックのリクエストを受信した時、現在のバッチに合わせてノードの削除が行われ最新のブロックハッシュを含む一つのブロックハッシュエントリを持った特別な”inv”メッセージ(通常のSendMessageメカニズムをバイパスして)を直接キューイングします(?)。リモートのノードがそのような”inv”メッセージを受信した時に
?????)
 
 
しかしながら、ブロックを受信して処理する時に、一つ前のブロックを持っていないことに気がつきます。そこで、最後のブロックをオーファンブロックだと記録し、ギャップを埋めるためにオーファンブロックの直前のブロックから始まるブロックをアップデートするリクエストを送ります。その結果”getblocks”リクエストを出し、全体のバッチ処理が繰り返されます。
しかしながら、twistがあります。次のバッチが終了した時に、ブロックを送信しているリモートノードは”inv”を通常は最新のブロックハッシュとともに送信し、ローカルノードはこのブロックはオーファンブロックマップの中にすでに持っていると気がつき、ブロックのリクエストをスキップし、直接ブロックのアップデートを依頼します。
 
This process will continue until the last block prior to the latest block is received. At the end of processing that block, it will notice there is an orphan that pointed to this block and will process the orphan block, (and any other orphans, recursively) thus completing the entire process.[15]
 
 
5 ストールリカバリ
もしバッチング処理がなんらかの理由で中断した場合、例えばリモートノードが"バッチ継続メカニズム”を失敗したり、接続切れが起きたりしたとき、処理を再スタートする方法があります。新しいブロックが発見されアドバタイズされる時に、”inv”の中に新しいブロックがあると気がついたいかなるノードもメッセージを送ったノードに対して”getblock”アップデートをリクエストするトリガーをかけます。それはノードが現在持っているブロックチェーンのいかなる場所からでもブロックを送信させることができます。
 
6 長いオーファンチェイン
多数のテストにおいて、ブロックチェーンの同期が非常に遅れているノードを発見することが頻繁に起きる(十回に一回以上)ということが分かっています。おそらくそれらのノードはキャッチアップの最中です。きちんと接続されたノードは少なくとも8以上のコネクションをもっていますので、新しいノードが他のキャッチアップ中のノードに接続することはしばしば起こります。
キャッチアップ中のノードは自身がメインチェーンとして受け入れたブロックを他の全てのノードに対してアドバタイズします。あるチェックポイント以前に古いブロックをアドバタイズするのを防ぐコードが存在していますが、そのコードはもしブロック高さがリモートノードの現在の最大のブロック高さマイナス2000を超えていればリモートノードに対してアドバタイズするという条項を持っています。これは、両者が古いブロックを処理中であっても、ノードは他のノードのキャッチアップを助けることを許しているということです。
 
These advertisements cause the local node to request those blocks from the remote node, which could be blocks well into the future compared to what has been processed locally.
 
(これらのアドバタイズにより、ローカルノードはこれらのブロックをリモートノードにリクエストします。….????  。)
 
ブロックがリクエストされる方法により、リモートノードは応答として、大きなブロックのバッチを送信します。そして最後までローカルノードに対して続けて送信します。ローカルノードがメインチェーンのブロックを同時にダウンロードしていることが起こり得ることに注意しましょう。その処理は次第にオーファンチェインをキャッチアップし、非常に、非常に長い再評価のオペレーションを生み出し、全てのオーファンブロックとつながります。
一万を超える長さのオーファンチェインでは、一時間を超える処理になることもあり得ます。
それゆえ、二つのキャッチアップ中のノードがお互いにコミュニケーションを取っている時に、Suboptimalなインタラクションに陥ることがあり得ます。特に、片側がひじょうに遅れていて、もう一方が相手よりだいぶ進んでいる場合に。
 
7 Flood Limit Effects
上記のバッチングメカニズムをもってしても、ブロックの交換の際にリモートノードがローカルの受信バッファをオーバーフローさせることが起き得ます。
例えば、リモートノードがキャッチアップ中の時、ある条件では(上記[17]参照)ローカルノードに対して全てのブロックをアドバタイズします。ローカルノードはそれぞれのブロックを即座にリクエストするでしょう。ローカルノードがこれらのブロックを多すぎるリクエストすることを止める手立てはありません。リモートノードはリクエストされたブロックを全て送るでしょう。この状況下では、リモートノードがローカルノードが処理が終わる前にあまりにたくさんのブロックを送ることを防ぐ手立てはありません。
ローカル受信バッファはいっぱいになることがあり得ます。ローカルノードが受信バッファが一杯になったことに木がついた時、ノードのコネクションを切断します。もし、fDisconnectフラグが建てられた場合、一度バッファは空にされソケットは閉じられます。
 
8 パフォーマンス
2011年9月1日現在、circa 2005のサーバークラスのコンピュータで、コムキャストケーブルインターネットに接続したUbuntuにおいて、ブロックチェーンのダウンロード処理に10時間以上かかります。
 

While it is debatable what the bottleneck is early in the download process, it is clear from the processing of recent blocks that the network is not the bottleneck for all but the slowest internet connections.

(??????????)
 
ブロックは平均してダウンロードするのに一秒以上かかります。しかしながら、2011年の8月で、平均的なブロックサイズは24KBです。24Kバイトをダウンロードするのに1秒はかかりません。
 
Also, testing reveals very large queues of blocks being processed per message loop, which is not what you would expect if the thread was pulling them out of the queue as they arrive on the sockets.
(???????)
 
ネットワークパフォーマンスが問題であると信じる、幾つかの”false signal”が存在します。
最初のfalse signalは、2011年8月において、最初の60%〜70%のダウンロードされたブロックはひじょうに小さいです。最近の平均ブロックサイズは約100倍も大きい! そのため、突如として、ブロックレートは早い状態から非常に遅い状態になります。何か問題が起きたかのようです。実際のところ、KB単位のブロック処理のレートを計測すると、レートはほぼ定数のままであることが分かります。
 
他のfalse signalは、メッセージキューはノード毎に一つづつ完了するように処理されるという事実に関連します。このことによって、非常に大きな他のノードからのメッセージのバックアップが作成されます。
So, a long period of increasing blocks may freeze for long periods as other nodes are serviced.
(そのため、他のノードがサービスされている時に増加するブロックの時間に合わせて長い時間フリーズします。?)
 
 ブロックのダウンロードが典型的にはただ一つのリモートノードから行われ(少なくともマイナーか他のリレーノードかダウンロードノードが新しいブロックをアドバタイズしてプロセスを止めるまで)、そのため全ての処理が一つのノードで行われることを考えましょう。
また、上記のオーファン効果がオーファンチェインに接続するまで何の証拠もなしに過剰なブロック処理に導く可能性もあります。また、突如として反応の遅いノードにつながることもありえます。おそらくブロックを処理しているか、遅いマシンまたは遅いコネクションであることによります。
上記の全てがブロックダウンロードのプロセスにおいて、大きなジッタに貢献しえます。そしてそれは、一定のダウンロードレートよりもユーザ体験をフラストレーションが多いものにします。