「Satoshi Client Block Exchange」の版間の差分

提供: tezos-wiki
移動先: 案内検索
(Overview)
(バッチ継続メカニズム)
 
(3人の利用者による、間の12版が非表示)
1行目: 1行目:
概要
 
 
この記事では、ノード間でどのようにブロックが交換されるかについて説明します。ブロックの検証方法の詳細については、「プロトコルルール」を参照してください。
 
この記事では、ノード間でどのようにブロックが交換されるかについて説明します。ブロックの検証方法の詳細については、「プロトコルルール」を参照してください。
  
10行目: 9行目:
 
getblocksメッセージは、遠隔ノートがノード間の最新の共通ブロックを見つけるのを助けるために、要求側ノードが既に所有している複数のブロックハッシュを含む。ハッシュのリストは、最新のブロックから始まり、10に戻り、起点ブロックに達するまで指数関数的に2倍になります。[3]両方のノードは起源ブロックでハードコードされているので、そこでの開始が最も少ないことが保証されています。そのブロックが何らかの理由で一致しない場合、ブロックは交換されません。
 
getblocksメッセージは、遠隔ノートがノード間の最新の共通ブロックを見つけるのを助けるために、要求側ノードが既に所有している複数のブロックハッシュを含む。ハッシュのリストは、最新のブロックから始まり、10に戻り、起点ブロックに達するまで指数関数的に2倍になります。[3]両方のノードは起源ブロックでハードコードされているので、そこでの開始が最も少ないことが保証されています。そのブロックが何らかの理由で一致しない場合、ブロックは交換されません。
  
== Inventory Messages ==
+
Hello my family member! I want to say that this article is amazing, great written and come with almost all significant infos. Id like to peer extra posts like this . ckbafbbefakakffd
  
Note that the node receiving the getblocks request does not actually send
+
Hello!
full blocks in response. The node sends an "inv" message containing just
 
the hashes of the series of blocks that fit the request, which verifies
 
that the node does indeed have blocks to send that the remote node does
 
not have (but does not presume the remote node wants the full blocks yet).
 
  
When the local node receives the "inv" message, it will request the actual
+
Hello!
blocks with a "getdata" message. See Below.
 
  
But first, here is more detail how the remote node sends the "inv" message
+
==失速の回復 ==
in response to the "getblocks" request sent by the local node. The remote
 
node calls pFrom->PushInventory which is a method on the CNode instance that
 
represents the node that requested the blocks (the local node in this
 
walkthrough), and PushInventory adds the block hash to the vInventoryToSend
 
variable of the CNode. The SendMessages function in [https://github.com/bitcoin/bitcoin/blob/master/src/main.cpp main.cpp] will take the
 
inv items out of vInventoryToSend and add it to a vInv variable which
 
means they are really ready for sending.[4]
 
The reason for the seperate variable is that some inventory items
 
(transactions only right now) may be "trickled" to the remote node,
 
which means they may kept from from being sent right away.
 
When the vInv variable fills up with 1000 entries, a message is queued
 
with those 1000 entries and the loop continues.  At the end, any
 
remaining entries are sent in a final "inv" message.
 
  
When the local node receives the "inv" message, it will request the actual
 
block with a "getdata" message. To be precise, the node calls pfrom->AskFor
 
to request the block, and that method queues the request for the blocks in
 
mapAskFor, and the multipurpose SendMessage() sends the "getdata" requests
 
in batches of 1000 entries from the map.[5]
 
  
The code attempts to limit redundant requests to every 2 minutes for the
+
リモートノードが「バッチ継続メカニズム」を守らないなどの何らかの理由でバッチ処理が中断された場合、または切断が発生した場合は、プロセスを再起動する方法があります。 新しいブロックが解決され、[16]の周りに宣伝されると、後ろにあるノードは "inv"の新しいブロックに気づき、メッセージを送信したノードから "getblocks"更新を要求するようトリガーします。 これは、後ろにあるノードが現在あるブロックチェーンのどこからでもブロックが送信されるようにします。
same block by using a map called mapAlreadyAskedFor to delay the message
 
if necessary.[6]
 
  
== Block Batching ==
+
== ロングオーファンチェーン ==
  
The responding node to a "getblocks" request attempts to limit the response
+
さまざまなテストでは、ブロックチェーン上でかなり遅れているノードを検出することが比較的一般的であると分かっています(おそらく10人に1人以上)。これはおそらくキャッチアップの過程にあるためです。うまく接続されたノードには少なくとも8つの接続と最大で十数の接続があるため、新しいノードが追いついている別のノードに接続する可能性は非常に高いです。
to the requestor to 500 blocks.[7]
 
  
However, in a peculiar twist, if the requestor appears to have diverged
+
追いついているノードは、メイン・チェーン内のブロックを他のすべてのノードに受け入れるので、処理中のブロックをアドバタイズします。[16]特定のチェックポイントの前に古いブロックを広告するのを防ぐコードがありますが、ブロックの高さがリモートノードの現在の最高の高さから2000ブロックを差し引いたものであれば、ブロックにはリモートノードにブロックを広告する節もあります。これは、たとえ両方が古いブロックを処理していても、ノードが他のノードに追いつくのを助けることを可能にするように見える。
from the main branch, the node will send as many blocks as necessary to
 
replace the entire bad chain of the requestor, from the lastest common block
 
between the nodes, up to the last block the requestor has (on their bad main
 
branch). That is in addition to the 500 "catch up" blocks for main branch
 
updates that will also be sent.[8]
 
  
Note that in addition to a flat limit on the number of blocks queued for
+
これらの広告により、ローカル・ノードはリモート・ノードからこれらのブロックを要求します。これは、ローカルで処理されたものと比較して将来的にブロックされる可能性があります。ブロックが要求される方法のため、リモートノードは応答して大きなブロックのバッチを送信し、ブロックが最後に達するまでブロックをローカルノードに送信し続けます。これは、ローカルノードが別のノードからメインチェーン上の以前のブロックをダウンロードしているときに発生する可能性が高いことに注意してください。そのプロセスは最終的に孤立チェーンに追いつき、すべての孤立ブロックを再検証して接続する非常に長い操作を生成する可能性があります。 1万ブロック以上の孤立した鎖が処理に1時間以上かかる。
sending, bitcoind also limits the total size of the blocks that are being
 
queued. This is currently limited to half the send buffer size[9], which is
 
10MB, for a limit of 5MB of queued blocks for send.[10]
 
  
== Batch Continue Mechanism ==
+
したがって、両方のノードが互いに話し合っている2つのノードは、特にどちらか一方が遠く、もう一方が他方よりはるかに遠い場合に、最適ではない対話につながる可能性があります。
  
When a node is finished sending a batch of block inventory, it records the
+
==洪水制限効果 ==
hash of the last block in the batch.[11]  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. However, this time when it receives the block
 
and processes it, it will notice that it does not have the previous block,
 
so it will record the latest block as an "orphan" block, and will request a
 
block update starting with the latest block it has up to the block before
 
the orphan [13], in order to fill in the gap. That goes out as a "getblocks"
 
request and the whole batch process repeats itself.
 
  
However, there is a twist. When the next batch finishes, the remote node
 
sending the blocks will send the "inv" with latest block hash as usual, and
 
the local node will notice it already has this block in the orphan block
 
map this time and so it will skip requesting the block and directly ask
 
for a block update.[14] 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]
 
  
 +
上述のバッチ処理メカニズムがあっても、ブロックが交換されている間にリモートノードがローカル受信バッファをオーバーフローさせるというシナリオが発生します。
  
== Stall Recovery ==
+
例えば、リモートノードが「追いついている」場合、特定の状況でローカルノードに処理する各ブロックをアドバタイズします(上記[17]を参照)。 ローカルノードは、それらのブロックのそれぞれを直ちに要求する。 これらのブロックをあまりにも多く要求しているローカルノードに対する保護はありません。 リモート・ノードは、要求されたすべてのブロックを送信します。 この状況では、ローカル・ノードが処理する時間が過ぎる前に、リモート・ノードが過度に多くのブロックを送信することに対する保護はありません。
  
If the batching processes is interrupted for some reason, such as the
+
ローカル受信バッファがいっぱいになる可能性があります。 ローカルノードが受信バッファがいっぱいであることに気付くと、そのノード接続は切断されます。[18] fDisconnectフラグをセットすると、バッファが空になったら[19]、ソケットは閉じます。
remote node failing to honor the "Batch Continue Mechanism" or if a
 
disconnection occurs, there is a way for the process to restart. When
 
a new block is solved and advertised around[16], any nodes that are
 
behind will notice the new block in the "inv" and that will trigger it
 
to request a "getblocks" update from the node that sent it the message.
 
That will cause blocks to be sent starting from wherever in the block
 
chain that the node that is behind is currently at.
 
  
 +
==パフォーマンス ==
  
== Long Orphan Chains ==
+
パフォーマンス
 +
2011年9月1日現在、Comcastケーブルインターネット接続を使用してUbuntuを実行しているサーバークラスのコンピュータでは、ブロックチェーンをダウンロードして処理するのに10時間以上かかります。ダウンロードプロセスの初期段階でボトルネックがどのようなものかは議論の余地がありますが、最近のブロックの処理からは、ネットワークが最も遅いインターネット接続以外のボトルネックではないことは明らかです。
  
In various tests, it has proven relatively common (say more than one
+
ブロックは、一度ダウンロードされると処理に平均して1秒以上かかる[20]しかし、ブロックの平均サイズは2011年8月にわずか24キロバイトです.24Kをダウンロードするのに1秒かかることはありません。また、テストでは、メッセージループごとに処理されるブロックの非常に大きなキューが明らかになります。スレッドがソケットに到着したときにキューからスレッドを引き出していた場合に期待されるものではありません。
in ten) to discover nodes that are significantly behind on the block
 
chain, probably because they are in the process of catching up as well.
 
Since a well connected node will have at least 8 and up to dozens of
 
connections, it is fairly likely that a new node will connect to
 
another node that is also catching up.
 
  
Nodes that are catching up will advertise the blocks they are processing,
+
問題がネットワークのパフォーマンスであると信じさせる多くの「偽の信号」があります。最初の誤った信号は、2011年8月現在、ダウンロードされたブロックの最初の60〜70%のほぼすべてが非常に小さいことです。最近の平均ブロックサイズは約100倍です!だから、突然、ほぼすべてのブロックレートは非常に高速から非常に遅くになります。何かが間違っているように見えます。現実には、ブロック処理の速度をキロバイト単位で測定すると、速度は比較的一定です。
as they accept blocks into their main chain, to every other node.[16]
 
While there is code to prevent advertising old blocks before a certain
 
checkpoint, that code also has a clause that does advertise blocks to
 
remote nodes if the block height is over the remote node's current best
 
height minus 2000 blocks.[17] This appears to allow nodes to "help" other
 
nodes catch up, even if they are both processing old blocks.
 
  
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. Due to the way blocks are requested,
 
the remote node will send a large batch of blocks in response and will
 
continue sending blocks to the local node until it reaches the end.
 
Note that this is likely to occur at the same time the local node is
 
downloading earlier blocks on the main chain from another node. That
 
process may eventually catch up with the orphan chain and produce a
 
very, very long operation to revalidate and connect up all the orphan
 
blocks. Orphan chains over ten thousand blocks long, taking over an hour
 
to process are possible.
 
  
Therefore, two nodes talking to each other that are both catching up can
+
もう1つの誤った信号は、ノードごとに1つずつメッセージキューが完了するまで処理されるという事実に関連しています。これは、他のノードからのメッセージの大きなバックアップをもたらす可能性があります。したがって、他のノードがサービスされるにつれて、長期間にわたるブロックの増加が長時間にわたってフリーズする可能性があります。ブロックダウンロードは、通常、1つのリモートノードから(少なくとも、鉱山者または他の中継またはダウンロードノードが遅延ブロックを宣伝してプロセスを中断するまで)、すべての作業が1つのノード上にあることを考えてください。ノードからブロックを処理することが速くなり、 "addr"メッセージが他のノードから処理され、他の作業が完了すると停止するように見えます。しかし何かが間違っているように見えます。
lead to suboptimal interactions, especially when one both are far behind
 
and one is far ahead of the other.
 
  
 +
また、上記の孤立効果は、孤立チェーンが接続されるまで、何も表示せずに過剰なブロック処理につながる可能性があります。また、おそらく処理ブロックであるか、マシンや接続が遅いために、応答が遅いノードに陥ることもあります。
  
== Flood Limit Effects ==
+
上記のすべてが、ブロックダウンロードプロセスでの「ジッタ」に大きく寄与します。これは、一定のダウンロード速度よりもユーザーの不満を感じます。
  
Even with the batching mechanism described above, there are scenarios
+
==脚注==
that occur that result in the remote node overflowing the local receive
 
buffer while blocks are being exchanged.
 
  
For example, if a remote node is "catching up", it will advertise each block
+
脚注
it processes to the local node in certain circumstances (see above [17]).
+
1. pfrom-> fInboundを参照してください。ここで、pfromはCNodeです。
The local node will request each of those blocks right away. There is no
 
protection against the local node requesting too many of these blocks.
 
The remote node will send all blocks requested. There is no protection
 
against the remote node sending too many blocks before the local node has
 
time to process them, in this circumstance.
 
  
The local receive buffer can fill up. When the local node notices a receive
+
2. main.cppのProcessMessage()を参照してください。strCommand == "version"となります。
buffer is full, it disconnects that node connection.[18]
 
If sets the fDisconnect flag, and once the buffers are empty[19], the
 
socket is closed.
 
  
 +
3. main.hのCBlockLocatorを参照してください。
  
== Performance ==
+
4.メッセージ:main.cppのSendMessageのinventoryを参照してください。
  
As of September 1, 2011, on a server class computer circa 2005 running
+
5. main.cppのSendMessageの最後にあるMessage:getdataを参照してください。
Ubuntu with a Comcast cable internet connection takes over 10 hours
 
to download and process the block chain. 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.
 
  
Blocks are taking over a second, on average, to process once downloaded.[20]
+
6. net.hのCNode :: AskForを参照してください。
However, the average size of a block is only around 24 kilobytes
 
in August 2011. It certainly does not take 1 second to download 24K.
 
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.  
 
  
There are a number of "false signals" that lead one to believe the problem
+
7. main.cppのProcessMessage()を参照してください。strCommand == "getblocks"となります。
is with network performance. The first false signal is that, as of
 
August 2011, nearly all of the first 60 or 70% of  blocks downloaded are
 
very small. Recent average block sizes are around one hundred times bigger!
 
So, almost all of a sudden, the block rate goes from very fast to very slow.
 
It looks like something went wrong. In reality, if you measure the rate
 
of block processing by kilobyte, the rate remains relatively constant.
 
  
 +
8.参照
  
Another false signal is related to the fact that message queues are
 
processed to completion, one at a time per node. This can result in big
 
backups of messages from other nodes. So, a long period of increasing
 
blocks may freeze for long periods as other nodes are serviced. Consider
 
that block downloads typically come from just one remote node (at
 
least until a miner or other relaying or downloading node advertises
 
a late block and disrupts the process) and so all the work might
 
be on one node. Things go fast processing the blocks from a node,
 
and then that looks like it stops as "addr" messages are processed from
 
other nodes and other work is done. But it looks like something is wrong.
 
 
Also, the orphaning effects described above can lead to excessive block
 
processing with nothing to show for it until the orphan chain is connected.
 
Also, you do ocassionally run into a node that is slow to respond, perhaps
 
because they are also processing blocks or because they have a slow machine
 
or connection.
 
 
All of the above contributes to heavy "jitter" in the block download process,
 
and that is a more frustrating user experience than a constant download rate.
 
 
 
==Footnotes==
 
1. See pfrom->fInbound where pfrom is a CNode.
 
 
2. See ProcessMessage() in main.cpp where strCommand == "version".
 
 
3. See CBlockLocator in main.h.
 
 
4. See Message: inventory in SendMessage in main.cpp.
 
 
5. See Message: getdata at the end of SendMessage in main.cpp.
 
 
6. See CNode::AskFor in net.h.
 
 
7. See ProcessMessage() in main.cpp where strCommand =="getblocks".
 
 
8. See
 
 
  int nLimit = 500 + locator.GetDistanceBack();
 
  int nLimit = 500 + locator.GetDistanceBack();
 
in ProcessMessage in main.cpp where strCommand =="getblocks".
 
in ProcessMessage in main.cpp where strCommand =="getblocks".
  
9. See
+
9. 参照
 
  if (--nLimit <= 0 || nBytes >= SendBufferSize()/2)
 
  if (--nLimit <= 0 || nBytes >= SendBufferSize()/2)
 
in ProcessMessage() in main.cpp where strCommand =="getblocks".
 
in ProcessMessage() in main.cpp where strCommand =="getblocks".
  
10. See
+
10. 参照
 
  inline unsigned int SendBufferSize() {
 
  inline unsigned int SendBufferSize() {
 
         return 1000*GetArg("-maxsendbuffer", 10*1000); }
 
         return 1000*GetArg("-maxsendbuffer", 10*1000); }
 
in net.h.
 
in net.h.
  
11. See pfrom->hashContinue = pindex->GetBlockHash();
+
11.参照 pfrom->hashContinue = pindex->GetBlockHash();
 
     in ProcessMessage() in main.cpp where strCommand =="getblocks".
 
     in ProcessMessage() in main.cpp where strCommand =="getblocks".
12. See: if (inv.hash == pfrom->hashContinue)
+
12. 参照: if (inv.hash == pfrom->hashContinue)
 
     in ProcessMessage() in main.cpp where strCommand =="getdata".
 
     in ProcessMessage() in main.cpp where strCommand =="getdata".
  
13. See:
+
13. 参照:
 
         // Ask this guy to fill in what we're missing
 
         // Ask this guy to fill in what we're missing
 
         if (pfrom)
 
         if (pfrom)
241行目: 97行目:
 
in ProcessBlock() in main.cpp.
 
in ProcessBlock() in main.cpp.
  
14. See:
+
14. 参照:
 
         else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
 
         else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
 
             pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
 
             pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
 
in ProcessMessage() in main.cpp where strCommand =="inv".
 
in ProcessMessage() in main.cpp where strCommand =="inv".
  
15. See:
+
15. 参照:
 
     // Recursively process any orphan blocks that depended on this one
 
     // Recursively process any orphan blocks that depended on this one
 
in ProcessBlock() in main.cpp.
 
in ProcessBlock() in main.cpp.
  
16. See the last block of code in AcceptBlock in main.cpp.
+
16. 参照the last block of code in AcceptBlock in main.cpp.
  
17. See:
+
17. 参照:
 
         if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 134444))
 
         if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 134444))
 
     in AcceptBlock() in main.cpp.
 
     in AcceptBlock() in main.cpp.
  
18. See:
+
18. 参照:
 
  if (nPos > ReceiveBufferSize()) {
 
  if (nPos > ReceiveBufferSize()) {
 
in ThreadSocketHandler2() in net.cpp.
 
in ThreadSocketHandler2() in net.cpp.
  
19. See:
+
19. 参照:
 
         if (pnode->fDisconnect ||
 
         if (pnode->fDisconnect ||
 
             (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
 
             (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))

2018年10月12日 (金) 13:30時点における最新版

この記事では、ノード間でどのようにブロックが交換されるかについて説明します。ブロックの検証方法の詳細については、「プロトコルルール」を参照してください。

初期接続時に、接続がインバウンド[1]でなかった場合、つまり接続がローカルノードによって開始された場合、バージョンメッセージはすぐに送信するためにキューに入れられます。リモートノードがバージョンメッセージを受信すると、それはそれ自身のバージョンメッセージで応答する[2]

ノードが「バージョン」メッセージを受信すると、ノードは「getblocks」要求をリモートノードに送信することができる。

ノードは、まだどのノードにも初期getblocks要求を送信していません。 または、これは唯一のアクティブノード接続です。おそらく、ノードはこの接続に先立って接続がゼロであったため、おそらく長時間切断されていた可能性があります。それで、それはブロックが追いつくように求めるでしょう。 getblocksメッセージは、遠隔ノートがノード間の最新の共通ブロックを見つけるのを助けるために、要求側ノードが既に所有している複数のブロックハッシュを含む。ハッシュのリストは、最新のブロックから始まり、10に戻り、起点ブロックに達するまで指数関数的に2倍になります。[3]両方のノードは起源ブロックでハードコードされているので、そこでの開始が最も少ないことが保証されています。そのブロックが何らかの理由で一致しない場合、ブロックは交換されません。

Hello my family member! I want to say that this article is amazing, great written and come with almost all significant infos. Id like to peer extra posts like this . ckbafbbefakakffd

Hello!

Hello!

失速の回復[編集]

リモートノードが「バッチ継続メカニズム」を守らないなどの何らかの理由でバッチ処理が中断された場合、または切断が発生した場合は、プロセスを再起動する方法があります。 新しいブロックが解決され、[16]の周りに宣伝されると、後ろにあるノードは "inv"の新しいブロックに気づき、メッセージを送信したノードから "getblocks"更新を要求するようトリガーします。 これは、後ろにあるノードが現在あるブロックチェーンのどこからでもブロックが送信されるようにします。

ロングオーファンチェーン[編集]

さまざまなテストでは、ブロックチェーン上でかなり遅れているノードを検出することが比較的一般的であると分かっています(おそらく10人に1人以上)。これはおそらくキャッチアップの過程にあるためです。うまく接続されたノードには少なくとも8つの接続と最大で十数の接続があるため、新しいノードが追いついている別のノードに接続する可能性は非常に高いです。

追いついているノードは、メイン・チェーン内のブロックを他のすべてのノードに受け入れるので、処理中のブロックをアドバタイズします。[16]特定のチェックポイントの前に古いブロックを広告するのを防ぐコードがありますが、ブロックの高さがリモートノードの現在の最高の高さから2000ブロックを差し引いたものであれば、ブロックにはリモートノードにブロックを広告する節もあります。これは、たとえ両方が古いブロックを処理していても、ノードが他のノードに追いつくのを助けることを可能にするように見える。

これらの広告により、ローカル・ノードはリモート・ノードからこれらのブロックを要求します。これは、ローカルで処理されたものと比較して将来的にブロックされる可能性があります。ブロックが要求される方法のため、リモートノードは応答して大きなブロックのバッチを送信し、ブロックが最後に達するまでブロックをローカルノードに送信し続けます。これは、ローカルノードが別のノードからメインチェーン上の以前のブロックをダウンロードしているときに発生する可能性が高いことに注意してください。そのプロセスは最終的に孤立チェーンに追いつき、すべての孤立ブロックを再検証して接続する非常に長い操作を生成する可能性があります。 1万ブロック以上の孤立した鎖が処理に1時間以上かかる。

したがって、両方のノードが互いに話し合っている2つのノードは、特にどちらか一方が遠く、もう一方が他方よりはるかに遠い場合に、最適ではない対話につながる可能性があります。

洪水制限効果[編集]

上述のバッチ処理メカニズムがあっても、ブロックが交換されている間にリモートノードがローカル受信バッファをオーバーフローさせるというシナリオが発生します。

例えば、リモートノードが「追いついている」場合、特定の状況でローカルノードに処理する各ブロックをアドバタイズします(上記[17]を参照)。 ローカルノードは、それらのブロックのそれぞれを直ちに要求する。 これらのブロックをあまりにも多く要求しているローカルノードに対する保護はありません。 リモート・ノードは、要求されたすべてのブロックを送信します。 この状況では、ローカル・ノードが処理する時間が過ぎる前に、リモート・ノードが過度に多くのブロックを送信することに対する保護はありません。

ローカル受信バッファがいっぱいになる可能性があります。 ローカルノードが受信バッファがいっぱいであることに気付くと、そのノード接続は切断されます。[18] fDisconnectフラグをセットすると、バッファが空になったら[19]、ソケットは閉じます。

パフォーマンス[編集]

パフォーマンス 2011年9月1日現在、Comcastケーブルインターネット接続を使用してUbuntuを実行しているサーバークラスのコンピュータでは、ブロックチェーンをダウンロードして処理するのに10時間以上かかります。ダウンロードプロセスの初期段階でボトルネックがどのようなものかは議論の余地がありますが、最近のブロックの処理からは、ネットワークが最も遅いインターネット接続以外のボトルネックではないことは明らかです。

ブロックは、一度ダウンロードされると処理に平均して1秒以上かかる[20]しかし、ブロックの平均サイズは2011年8月にわずか24キロバイトです.24Kをダウンロードするのに1秒かかることはありません。また、テストでは、メッセージループごとに処理されるブロックの非常に大きなキューが明らかになります。スレッドがソケットに到着したときにキューからスレッドを引き出していた場合に期待されるものではありません。

問題がネットワークのパフォーマンスであると信じさせる多くの「偽の信号」があります。最初の誤った信号は、2011年8月現在、ダウンロードされたブロックの最初の60〜70%のほぼすべてが非常に小さいことです。最近の平均ブロックサイズは約100倍です!だから、突然、ほぼすべてのブロックレートは非常に高速から非常に遅くになります。何かが間違っているように見えます。現実には、ブロック処理の速度をキロバイト単位で測定すると、速度は比較的一定です。


もう1つの誤った信号は、ノードごとに1つずつメッセージキューが完了するまで処理されるという事実に関連しています。これは、他のノードからのメッセージの大きなバックアップをもたらす可能性があります。したがって、他のノードがサービスされるにつれて、長期間にわたるブロックの増加が長時間にわたってフリーズする可能性があります。ブロックダウンロードは、通常、1つのリモートノードから(少なくとも、鉱山者または他の中継またはダウンロードノードが遅延ブロックを宣伝してプロセスを中断するまで)、すべての作業が1つのノード上にあることを考えてください。ノードからブロックを処理することが速くなり、 "addr"メッセージが他のノードから処理され、他の作業が完了すると停止するように見えます。しかし何かが間違っているように見えます。

また、上記の孤立効果は、孤立チェーンが接続されるまで、何も表示せずに過剰なブロック処理につながる可能性があります。また、おそらく処理ブロックであるか、マシンや接続が遅いために、応答が遅いノードに陥ることもあります。

上記のすべてが、ブロックダウンロードプロセスでの「ジッタ」に大きく寄与します。これは、一定のダウンロード速度よりもユーザーの不満を感じます。

脚注[編集]

脚注 1. pfrom-> fInboundを参照してください。ここで、pfromはCNodeです。

2. main.cppのProcessMessage()を参照してください。strCommand == "version"となります。

3. main.hのCBlockLocatorを参照してください。

4.メッセージ:main.cppのSendMessageのinventoryを参照してください。

5. main.cppのSendMessageの最後にあるMessage:getdataを参照してください。

6. net.hのCNode :: AskForを参照してください。

7. main.cppのProcessMessage()を参照してください。strCommand == "getblocks"となります。

8.参照

int nLimit = 500 + locator.GetDistanceBack();

in ProcessMessage in main.cpp where strCommand =="getblocks".

9. 参照

if (--nLimit <= 0 || nBytes >= SendBufferSize()/2)

in ProcessMessage() in main.cpp where strCommand =="getblocks".

10. 参照

inline unsigned int SendBufferSize() {
       return 1000*GetArg("-maxsendbuffer", 10*1000); }

in net.h.

11.参照 pfrom->hashContinue = pindex->GetBlockHash();

   in ProcessMessage() in main.cpp where strCommand =="getblocks".

12. 参照: if (inv.hash == pfrom->hashContinue)

   in ProcessMessage() in main.cpp where strCommand =="getdata".

13. 参照:

       // Ask this guy to fill in what we're missing
       if (pfrom)
           pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2));

in ProcessBlock() in main.cpp.

14. 参照:

       else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash))
           pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));

in ProcessMessage() in main.cpp where strCommand =="inv".

15. 参照:

   // Recursively process any orphan blocks that depended on this one

in ProcessBlock() in main.cpp.

16. 参照the last block of code in AcceptBlock in main.cpp.

17. 参照:

       if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 134444))
   in AcceptBlock() in main.cpp.

18. 参照:

if (nPos > ReceiveBufferSize()) {

in ThreadSocketHandler2() in net.cpp.

19. 参照:

       if (pnode->fDisconnect ||
           (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))

in ThreadSocketHandler2() in net.cpp.

20. This is from the authors experience and also

   see https://bitcointalk.org/index.php?topic=31376.0.