Dev Docs: Add Section About Headers-First IBD

* Add flowchart illustration to blocks-first section to match new
  headers-first flowchart

* Add new headers-first initial block download (IBD) section

* Revise Block Broadcasting section

* Add paragraph about orphan block handling in headers-first to the
  Orphan Blocks section
This commit is contained in:
David A. Harding 2015-02-05 15:44:05 -05:00
parent 7dcf67d5a8
commit 72cc5f7f9e
No known key found for this signature in database
GPG key ID: 4B29C30FF29EC4B7
18 changed files with 772 additions and 4 deletions

View file

@ -117,6 +117,10 @@ hard fork:
hard forks: hard fork
hardened extended private key:
HD protocol:
header chain:
headers-first: headers-first sync
headers-first sync:
headers-first IBD: headers-first sync
'`headers` message': headers message
'`headers` messages': headers message
high-priority transaction: high-priority transactions
@ -301,6 +305,7 @@ SPV:
stack:
stale block:
stale blocks: stale block
standard block relay:
standard script:
standard scripts: standard script
standard transaction: standard script
@ -321,11 +326,12 @@ txids: txid
unconfirmed:
unconfirmed transactions:
unencrypted wallet:
unlocked wallet:
unix epoch time:
unix time: unix epoch time
unique address: unique addresses
unique addresses:
unlocked wallet:
unsolicited block push:
utxo:
utxos: utxo
'`verack` message': verack message

View file

@ -160,7 +160,7 @@ all the blocks which were produced since the last time it was online.
Bitcoin Core uses the IBD method any time the last block on its local
best block chain has a block header time more than 24 hours in the past.
Bitcoin Core 0.10.0 will also perform IBD if its local best block chain is
more than 144 blocks lower than its local best headers chain (that is,
more than 144 blocks lower than its local best header chain (that is,
the local block chain is more than about 24 hours in the past).
{% endautocrossref %}
@ -174,6 +174,8 @@ Bitcoin Core (up until version [0.9.3][bitcoin core 0.9.3]) uses a
simple initial block download (IBD) method we'll call *blocks-first*.
The goal is to download the blocks from the best block chain in sequence.
![Overview Of Blocks-First Method](/img/dev/en-blocks-first-flowchart.svg)
The first time a node is started, it only has a single block in its
local best block chain---the hardcoded genesis block (block 0). This
node chooses a remote peer, called the sync node, and sends it the
@ -308,14 +310,166 @@ to the reference page for that message.
{% endautocrossref %}
#### Headers-First
{% include helpers/subhead-links.md %}
{% autocrossref %}
Bitcoin Core 0.10.0 uses a initial block download (IBD) method called
*headers-first*. The goal is to download the headers for the best [header
chain][]{:#term-header-chain}{:.term}, partially validate them as best
as possible, and then download the corresponding blocks in parallel. This
solves several problems with the older blocks-first IBD method.
![Overview Of Headers-First Method](/img/dev/en-headers-first-flowchart.svg)
The first time a node is started, it only has a single block in its
local best block chain---the hardcoded genesis block (block 0). The
node chooses a remote peer, which we'll call the sync node, and sends it the
`getheaders` message illustrated below.
![First getheaders message](/img/dev/en-ibd-getheaders.svg)
In the header hashes field of the `getheaders` message, the new node
sends the header hash of the only block it has, the genesis block
(6fe2...0000 in internal byte order). It also sets the stop hash field
to all zeroes to request a maximum-size response.
Upon receipt of the `getheaders` message, the sync node takes the first
(and only) header hash and searches its local best block chain for a
block with that header hash. It finds that block 0 matches, so it
replies with 2,000 header (the maximum response) starting from
block 1. It sends these header hashes in the `headers` message
illustrated below.
![First headers message](/img/dev/en-ibd-headers.svg)
The IBD node can partially validate these block headers by ensuring that
all fields follow consensus rules and that the hash of the header is
below the target threshold according to the nBits field. (Full
validation still requires all transactions from the corresponding
block.)
After the IBD node has partially validated the block headers, it can do
two things in parallel:
1. **Download More Headers:** the IBD node can send another `getheaders`
message to the sync node to request the next 2,000 headers on the
best header chain. Those headers can be immediately validated and
another batch requested repeatedly until a `headers` message is
received from the sync node with fewer than 2,000 headers, indicating
that it has no more headers to offer. As of this writing, headers
sync can be completed in fewer than 200 round trips, or about 32 MB
of downloaded data.
Once the IBD node receives a `headers` message with fewer than 2,000
headers from the sync node, it sends a `getheaders` message to each
of its outbound peers to get their view of best header chain. By
comparing the responses, it can easily determine if the headers it
has downloaded belong to the best header chain reported by any of
its outbound peers. This means a dishonest sync node will quickly be
discovered even if checkpoints aren't used (as long as the IBD node
connects to at least one honest peer; Bitcoin Core will continue to
provide checkpoints in case honest peers can't be found).
2. **Download Blocks:** While the IBD node continues downloading
headers, and after the headers finish downloading, the IBD node will
request and download each block. The IBD node can use the block
header hashes it computed from the header chain to create `getdata`
messages that request the blocks it needs by their inventory. It
doesn't need to request these from the sync node---it can request
them from any of its full node peers. (Although not all full nodes
may store all blocks.) This allows it to fetch blocks in parallel and
avoid having its download speed constrained to the upload speed of a
single sync node.
To spread the load between multiple peers, Bitcoin Core will only
request up to 16 blocks at a time from a single peer. Combined with
its maximum of 8 outbound connections, this means headers-first
Bitcoin Core will request a maximum of 128 blocks simultaneously
during IBD (the same maximum number that blocks-first Bitcoin Core
requested from its sync node).
![Simulated Headers-First Download Window](/img/dev/en-headers-first-moving-window.svg)
Bitcoin Core's headers-first mode uses a 1,024-block moving download
window to maximize download speed. The lowest-height block in the window
is the next block to be validated; if the block hasn't arrived by the
time Bitcoin Core is ready to validate it, Bitcoin Core will wait a
minimum of two more seconds for the stalling node to send the block. If
the block still hasn't arrived, Bitcoin Core will disconnect from the
stalling node and attempt to connect to another node. For example, in
the illustration above, Node A will be disconnected if it doesn't send
block 3 within at least two seconds.
Once the IBD node is synced to the tip of the block chain, it will
accept blocks sent through the regular block broadcasting described in a
later subsection.
**Resources:** The table below summarizes the messages mentioned
throughout this subsection. The links in the message field will take you
to the reference page for that message.
| **Message** | [`getheaders`][getheaders message] | [`headers`][headers message] | [`getdata`][getdata message] | [`block`][block message]
| **From→To** | IBD→Sync | Sync→IBD | IBD→*Many* | *Many*→IBD
| **Payload** | One or more header hashes | Up to 2,000 block headers | One or more block inventories derived from header hashes | One serialized block
{% endautocrossref %}
### Block Broadcasting
{% include helpers/subhead-links.md %}
{% autocrossref %}
At the start of a connection with a peer, both nodes send `getblocks` messages containing the hash of the latest known block. If a peer believes they have newer blocks or a longer chain, that peer will send an `inv` message which includes a list of up to 500 hashes of newer blocks, stating that it has the longer chain. The receiving node would then request these blocks using the command `getdata`, and the remote peer would reply via `block`<!--noref--> messages. After all 500 blocks have been processed, the node can request another set with `getblocks`, until the node is caught up with the network. Blocks are only accepted when validated by the receiving node.
When a miner discovers a new block, it broadcasts the new block to its
peers using one of the following methods:
New blocks are also discovered as miners publish their found blocks, and these messages are propagated in a similar manner. Through previously established connections, an `inv` message is sent with the new block hashed, and the receiving node requests the block via the `getdata` message.
* **[Unsolicited Block Push][]{:#term-unsolicited-block-push}{:.term}:**
the miner sends a `block` message to each of its full node peers with
the new block. The miner can reasonably bypass the standard relay
method in this way because it knows none of its peers already have the
just-discovered block.
* **[Standard Block Relay][]{:#term-standard-block-relay}{:.term}:**
the miner, acting as a standard relay node, sends an `inv` message to
each of its peers (both full node and SPV) with an inventory referring
to the new block. The most common responses are:
* Each blocks-first (BF) peer that wants the block replies with a
`getdata` message requesting the full block.
* Each headers-first (HF) peer that wants the block replies with a
`getheaders` message containing the header hash of the
highest-height header on its best header chain, and likely also
some headers further back on the best header chain to allow fork
detection. That message is immediately followed by a `getdata`
message requesting the full block. By requesting headers first, a
headers-first peer can refuse orphan blocks as described in the
subsection below.
* Each Simplified Payment Verification (SPV) client that wants the
block replies with a `getdata` message typically requesting a
merkle block.
The miner replies to each request accordingly by sending the block
in a `block` message, one or more headers in a `headers` message,
or the merkle block and transactions relative to the SPV client's
bloom filter in a `merkleblock` message followed by zero or more
`tx` messages.
Full nodes validate the received block and then advertise it to their
peers using the standard block relay method described above. The condensed
table below highlights the operation of the messages described above
(Relay, BF, HF, and SPV refer to the relay node, a blocks-first node, a
headers-first node, and an SPV client; *any* refers to a node using any
block retrieval method.)
| **Message** | [`inv`][inv message] | [`getdata`][getdata message] | [`getheaders`][getheaders message] | [`headers`][headers message]
| **From→To** | Relay→*Any* | BF→Relay | HF→Relay | Relay→HF
| **Payload** | The inventory of the new block | The inventory of the new block | One or more header hashes on the HF node's best header chain (BHC) | Up to 2,000 headers connecting HF node's BHC to relay node's BHC
| **Message** | [`block`][block message] | [`merkleblock`][merkleblock message] | [`tx`][tx message] |
| **From→To** | Relay→BF/HF | Relay→SPV | Relay→SPV |
| **Payload** | The new block in [serialized format][serialized block] | The new block filtered into a merkle block | Serialized transactions from the new block that match the bloom filter |
{% endautocrossref %}
@ -342,6 +496,20 @@ message. The downloading node will validate those blocks, and once the
parent of the former orphan block has been validated, it will validate
the former orphan block.
Headers-first nodes avoid some of this complexity by always requesting
block headers with the `getheaders` message before requesting a block
with the `getdata` message. The broadcasting node will send a `headers`
message containing all the block headers (up to 2,000) it thinks the
downloading node needs to reach the tip of the best header chain; each of
those headers will point to its parent, so when the downloading node
receives the `block` message, the block shouldn't be an orphan
block---all of its parents should be known (even if they haven't been
validated yet). If, despite this, the block received in the `block`
message is an orphan block, a headers-first node will discard it immediately.
However, orphan discarding does mean that headers-first nodes will
ignore orphan blocks sent by miners in an unsolicited block push.
{% endautocrossref %}
### Transaction Broadcasting

View file

@ -67,6 +67,8 @@ http://opensource.org/licenses/MIT.
[hard fork]: /en/developer-guide#term-hard-fork "A permanent divergence in the the block chain, commonly occurs when non-upgraded nodes can't validate blocks created by upgraded nodes following newer consensus rules."
[hardened extended private key]: /en/developer-guide#term-hardened-extended-private-key "A private key whose corresponding public key cannot derive child keys"
[HD protocol]: /en/developer-guide#term-hd-protocol "The Hierarchical Deterministic (HD) key creation and transfer protocol"
[header chain]: /en/developer-guide#term-header-chain "A chain of block headers with each header linking to the header that preceded it; the most-difficult-to-recreate chain is the best header chain"
[headers-first sync]: /en/developer-guide#headers-first "Synchronizing the block chain by downloading block headers before downloading the full blocks"
[headers message]: /en/developer-reference#headers "A P2P protocol message containing one or more block headers"
[high-priority transactions]: /en/developer-guide#term-high-priority-transactions "Transactions which don't pay a transaction fee; only transactions spending long-idle outputs are eligible"
[initial block download]: /en/developer-guide#initial-block-download "The process used by a new node (or long-offline node) to download a large number of blocks to catch up to the tip of the best block chain"
@ -184,6 +186,7 @@ http://opensource.org/licenses/MIT.
[ssl signature]: /en/developer-examples#term-ssl-signature "Signatures created and recognized by major SSL implementations such as OpenSSL"
[stack]: /en/developer-guide#term-stack "An evaluation stack used in Bitcoin's script language"
[stale block]: /en/developer-guide#term-stale-block "Blocks which were successfully mined but which aren't included on the current valid block chain; not to be confused with orphan blocks"
[standard block relay]: /en/developer-guide#term-standard-block-relay "The regular block relay method: announcing a block with an inv message and waiting for a response"
[standard script]: /en/developer-guide#standard-transactions "A pubkey script which matches the IsStandard() patterns specified in Bitcoin Core---or a transaction containing only standard outputs. Only standard transactions are mined or broadcast by peers running the default Bitcoin Core software"
[start string]: /en/developer-reference#term-start-string "Four defined bytes which start every message in the P2P protocol to allow seeking to the next message"
[target]: /en/developer-guide#term-target "The threshold below which a block header hash must be in order for the block to be added to the block chain"
@ -201,6 +204,7 @@ http://opensource.org/licenses/MIT.
[unencrypted wallet]: /en/developer-reference#encryptwallet "A wallet that has not been encrypted with the encryptwallet RPC"
[unique addresses]: /en/developer-guide#term-unique-address "Address which are only used once to protect privacy and increase security"
[unlocked wallet]: /en/developer-reference#walletpassphrase "An encrypted wallet that has been unlocked with the walletpassphrase RPC"
[unsolicited block push]: /en/developer-guide#term-unsolicited-block-push "When a miner sends a block message without sending an inv message first"
[URI QR Code]: /en/developer-guide#term-uri-qr-code "A QR code containing a bitcoin: URI"
[utxo]: /en/developer-guide#term-utxo "Unspent Transaction Output (UTXO) holding satoshis which have not yet been spent"
[verack message]: /en/developer-reference#verack "A P2P network message sent in reply to a version message to confirm a connection has been established"

View file

@ -0,0 +1,32 @@
digraph {
// This file is licensed under the MIT License (MIT) available on
// http://opensource.org/licenses/MIT.
size=6.25;
rankdir=TB
splines = "true";
ranksep = 0.2;
nodesep = 0.9;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "none", fontname="Sans"]
graph [ penwidth = 1.75, fontname="Sans" ]
fsbc [ label = "Fully-Synced Block Chain?", style = "filled" ];
listen [ label = "Listen For New Blocks (Inv)" ];
request_blocks [ label = "Request Blocks (GetData)" ];
request_invs [ label = "Request Inventories (GetBlocks)" ];
have_invs [ label = "Have Inventories?", style = "filled" ];
fsbc -> have_invs [ label = " No" ];
fsbc -> listen [ label = "Yes", constraint = false ];
have_invs -> request_invs [ label = " No" ];
have_invs -> request_blocks [ label = "Yes", constraint=false ];
listen -> request_blocks [ style = "invis" ];
label = "\ \nOverview Of Blocks-First Initial Blocks Download (IBD)"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="450pt" height="173pt"
viewBox="0.00 0.00 450.00 173.11" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.801425 0.801425) rotate(0) translate(4 212)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-212 557.5,-212 557.5,4 -4,4"/>
<text text-anchor="middle" x="276.75" y="-22.8" font-family="Sans" font-size="14.00"> </text>
<text text-anchor="middle" x="276.75" y="-7.8" font-family="Sans" font-size="14.00">Overview Of Blocks&#45;First Initial Blocks Download (IBD)</text>
<!-- fsbc -->
<g id="node1" class="node"><title>fsbc</title>
<polygon fill="lightgrey" stroke="none" stroke-width="1.75" points="218,-208 21,-208 21,-172 218,-172 218,-208"/>
<text text-anchor="middle" x="119.5" y="-186.3" font-family="Sans" font-size="14.00">Fully&#45;Synced Block Chain?</text>
</g>
<!-- listen -->
<g id="node2" class="node"><title>listen</title>
<text text-anchor="middle" x="450.5" y="-186.3" font-family="Sans" font-size="14.00">Listen For New Blocks (Inv)</text>
</g>
<!-- fsbc&#45;&gt;listen -->
<g id="edge2" class="edge"><title>fsbc&#45;&gt;listen</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M218.363,-190C255.697,-190 298.464,-190 337.033,-190"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="337.265,-193.5 347.265,-190 337.265,-186.5 337.265,-193.5"/>
<text text-anchor="middle" x="282.75" y="-196.8" font-family="Sans" font-size="14.00">Yes</text>
</g>
<!-- have_invs -->
<g id="node5" class="node"><title>have_invs</title>
<polygon fill="lightgrey" stroke="none" stroke-width="1.75" points="190.5,-141 48.5,-141 48.5,-105 190.5,-105 190.5,-141"/>
<text text-anchor="middle" x="119.5" y="-119.3" font-family="Sans" font-size="14.00">Have Inventories?</text>
</g>
<!-- fsbc&#45;&gt;have_invs -->
<g id="edge1" class="edge"><title>fsbc&#45;&gt;have_invs</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M119.5,-171.922C119.5,-165.702 119.5,-158.5 119.5,-151.6"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="123,-151.19 119.5,-141.19 116,-151.19 123,-151.19"/>
<text text-anchor="middle" x="133.5" y="-152.8" font-family="Sans" font-size="14.00"> &#160;No</text>
</g>
<!-- request_blocks -->
<g id="node3" class="node"><title>request_blocks</title>
<text text-anchor="middle" x="450.5" y="-119.3" font-family="Sans" font-size="14.00">Request Blocks (GetData)</text>
</g>
<!-- listen&#45;&gt;request_blocks -->
<!-- request_invs -->
<g id="node4" class="node"><title>request_invs</title>
<text text-anchor="middle" x="119.5" y="-52.3" font-family="Sans" font-size="14.00">Request Inventories (GetBlocks)</text>
</g>
<!-- have_invs&#45;&gt;request_blocks -->
<g id="edge4" class="edge"><title>have_invs&#45;&gt;request_blocks</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M190.508,-123C234.937,-123 293.028,-123 343.029,-123"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="343.241,-126.5 353.241,-123 343.241,-119.5 343.241,-126.5"/>
<text text-anchor="middle" x="272" y="-129.8" font-family="Sans" font-size="14.00">Yes</text>
</g>
<!-- have_invs&#45;&gt;request_invs -->
<g id="edge3" class="edge"><title>have_invs&#45;&gt;request_invs</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M119.5,-104.922C119.5,-98.7016 119.5,-91.4999 119.5,-84.5999"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="123,-84.1896 119.5,-74.1896 116,-84.1896 123,-84.1896"/>
<text text-anchor="middle" x="133.5" y="-85.8" font-family="Sans" font-size="14.00"> &#160;No</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,37 @@
digraph {
// This file is licensed under the MIT License (MIT) available on
// http://opensource.org/licenses/MIT.
size=6.25;
rankdir=TB
splines = "true";
ranksep = 0.2;
nodesep = 0.9;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "none", fontname="Sans"]
graph [ penwidth = 1.75, fontname="Sans" ]
fsbc [ label = "Fully-Synced Block Chain?", style = "filled" ];
fshc [ label = "Fully-Synced Header Chain?", style = "filled" ];
more_headers_than_blocks [ label = "More Headers Than Blocks?", style = "filled" ];
listen_for_new_blocks [ label = "Listen For New Blocks (Inv)" ];
request_blocks [ label = "Request Blocks (GetData)" ];
request_headers [ label = "Request Headers (GetHeaders)" ];
fsbc -> fshc [ label = " No" ];
fshc -> more_headers_than_blocks [ label = "No" ];
fshc -> request_headers [ label = " No" ];
fsbc -> listen_for_new_blocks [ label = "Yes", constraint=false ];
fshc -> request_blocks [ label = "Yes", constraint=false ];
request_blocks -> more_headers_than_blocks [ dir=back, label = " Yes" ];
//request_headers -> fshc [ style = "dotted", constraint = false ];
//request_blocks -> fsbc [ style = "dotted", constraint = false ];
label = "\ \nOverview Of Headers-First Initial Blocks Download (IBD)"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="450pt" height="175pt"
viewBox="0.00 0.00 450.00 174.51" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.807899 0.807899) rotate(0) translate(4 212)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-212 553,-212 553,4 -4,4"/>
<text text-anchor="middle" x="274.5" y="-22.8" font-family="Sans" font-size="14.00"> </text>
<text text-anchor="middle" x="274.5" y="-7.8" font-family="Sans" font-size="14.00">Overview Of Headers&#45;First Initial Blocks Download (IBD)</text>
<!-- fsbc -->
<g id="node1" class="node"><title>fsbc</title>
<polygon fill="lightgrey" stroke="none" stroke-width="1.75" points="213.5,-208 16.5,-208 16.5,-172 213.5,-172 213.5,-208"/>
<text text-anchor="middle" x="115" y="-186.3" font-family="Sans" font-size="14.00">Fully&#45;Synced Block Chain?</text>
</g>
<!-- fshc -->
<g id="node2" class="node"><title>fshc</title>
<polygon fill="lightgrey" stroke="none" stroke-width="1.75" points="219.5,-141 10.5,-141 10.5,-105 219.5,-105 219.5,-141"/>
<text text-anchor="middle" x="115" y="-119.3" font-family="Sans" font-size="14.00">Fully&#45;Synced Header Chain?</text>
</g>
<!-- fsbc&#45;&gt;fshc -->
<g id="edge1" class="edge"><title>fsbc&#45;&gt;fshc</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M115,-171.922C115,-165.702 115,-158.5 115,-151.6"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="118.5,-151.19 115,-141.19 111.5,-151.19 118.5,-151.19"/>
<text text-anchor="middle" x="129" y="-152.8" font-family="Sans" font-size="14.00"> &#160;No</text>
</g>
<!-- listen_for_new_blocks -->
<g id="node4" class="node"><title>listen_for_new_blocks</title>
<text text-anchor="middle" x="446" y="-186.3" font-family="Sans" font-size="14.00">Listen For New Blocks (Inv)</text>
</g>
<!-- fsbc&#45;&gt;listen_for_new_blocks -->
<g id="edge4" class="edge"><title>fsbc&#45;&gt;listen_for_new_blocks</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M213.863,-190C251.197,-190 293.964,-190 332.533,-190"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="332.765,-193.5 342.765,-190 332.765,-186.5 332.765,-193.5"/>
<text text-anchor="middle" x="278.25" y="-196.8" font-family="Sans" font-size="14.00">Yes</text>
</g>
<!-- more_headers_than_blocks -->
<g id="node3" class="node"><title>more_headers_than_blocks</title>
<polygon fill="lightgrey" stroke="none" stroke-width="1.75" points="514.5,-74 307.5,-74 307.5,-38 514.5,-38 514.5,-74"/>
<text text-anchor="middle" x="411" y="-52.3" font-family="Sans" font-size="14.00">More Headers Than Blocks?</text>
</g>
<!-- fshc&#45;&gt;more_headers_than_blocks -->
<g id="edge2" class="edge"><title>fshc&#45;&gt;more_headers_than_blocks</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M192.771,-104.922C232.969,-96.0945 282.167,-85.291 323.668,-76.1776"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="324.476,-79.5837 333.492,-74.0203 322.974,-72.7466 324.476,-79.5837"/>
<text text-anchor="middle" x="299.5" y="-85.8" font-family="Sans" font-size="14.00">No</text>
</g>
<!-- request_blocks -->
<g id="node5" class="node"><title>request_blocks</title>
<text text-anchor="middle" x="446" y="-119.3" font-family="Sans" font-size="14.00">Request Blocks (GetData)</text>
</g>
<!-- fshc&#45;&gt;request_blocks -->
<g id="edge5" class="edge"><title>fshc&#45;&gt;request_blocks</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M219.73,-123C257.72,-123 300.669,-123 338.863,-123"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="338.981,-126.5 348.981,-123 338.981,-119.5 338.981,-126.5"/>
<text text-anchor="middle" x="284.25" y="-129.8" font-family="Sans" font-size="14.00">Yes</text>
</g>
<!-- request_headers -->
<g id="node6" class="node"><title>request_headers</title>
<text text-anchor="middle" x="115" y="-52.3" font-family="Sans" font-size="14.00">Request Headers (GetHeaders)</text>
</g>
<!-- fshc&#45;&gt;request_headers -->
<g id="edge3" class="edge"><title>fshc&#45;&gt;request_headers</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M115,-104.922C115,-98.7016 115,-91.4999 115,-84.5999"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="118.5,-84.1896 115,-74.1896 111.5,-84.1896 118.5,-84.1896"/>
<text text-anchor="middle" x="129" y="-85.8" font-family="Sans" font-size="14.00"> &#160;No</text>
</g>
<!-- request_blocks&#45;&gt;more_headers_than_blocks -->
<g id="edge6" class="edge"><title>request_blocks&#45;&gt;more_headers_than_blocks</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M431.998,-95.9964C428.049,-88.6617 423.851,-80.8669 420.256,-74.1896"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="428.981,-97.7767 436.804,-104.922 435.145,-94.4579 428.981,-97.7767"/>
<text text-anchor="middle" x="449" y="-85.8" font-family="Sans" font-size="14.00"> &#160;&#160;Yes</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -0,0 +1,45 @@
digraph {
// This file is licensed under the MIT License (MIT) available on
// http://opensource.org/licenses/MIT.
size="6.25";
rankdir=LR
nodesep=0.2;
ranksep=0.3;
splines="false"
edge [ penwidth = 1.75, fontname="Sans", dir=none ]
node [ penwidth = 1.75, shape = "box", fontname="Sans", ]
graph [ penwidth = 1.75, fontname="Sans", fontsize = 16 ]
subgraph cluster_verified {
graph [ penwidth = 0 ];
node [ style = "filled" ];
block0 [ width=0, style = "invis", label = "" ];
block1 [ label = "1\nDownloaded\nFrom Node A" ];
block2 [ label = "2\nDownloaded\nFrom Node B" ];
label = "Downloaded And Validated\n "
}
block0 -> block1;
block1 -> block2;
block2 -> block3 -> block4 -> block5;
block5 -> block6 [ minlen = 2 ];
block6 [ style = "invis", width = 0, label = "" ];
subgraph cluster_download_window {
block3 [ label = "3\nRequested\nFrom Node A" ];
block4 [ label = "4\nDownloaded\nFrom Node B", style = "filled" ];
block5 [ label = "5\nRequested\nFrom Node B" ];
label = "Download Window\nBlocks Not Validated Yet"
}
label = " \nSimulated Headers-First Download Window (Real Window Is Much Larger)"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="450pt" height="116pt"
viewBox="0.00 0.00 450.00 115.68" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.635593 0.635593) rotate(0) translate(4 178)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-178 704,-178 704,4 -4,4"/>
<text text-anchor="middle" x="350" y="-27.2" font-family="Sans" font-size="16.00"> </text>
<text text-anchor="middle" x="350" y="-9.2" font-family="Sans" font-size="16.00">Simulated Headers&#45;First Download Window (Real Window Is Much Larger)</text>
<g id="clust1" class="cluster"><title>cluster_verified</title>
<polygon fill="none" stroke="black" stroke-width="0" points="8,-52 8,-166 279,-166 279,-52 8,-52"/>
<text text-anchor="middle" x="143.5" y="-149.2" font-family="Sans" font-size="16.00">Downloaded And Validated</text>
<text text-anchor="middle" x="143.5" y="-131.2" font-family="Sans" font-size="16.00"> </text>
</g>
<g id="clust2" class="cluster"><title>cluster_download_window</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="287,-52 287,-166 662,-166 662,-52 287,-52"/>
<text text-anchor="middle" x="474.5" y="-149.2" font-family="Sans" font-size="16.00">Download Window</text>
<text text-anchor="middle" x="474.5" y="-131.2" font-family="Sans" font-size="16.00">Blocks Not Validated Yet</text>
</g>
<!-- block0 -->
<!-- block1 -->
<g id="node2" class="node"><title>block1</title>
<polygon fill="lightgrey" stroke="black" stroke-width="1.75" points="144,-113.5 39,-113.5 39,-60.5 144,-60.5 144,-113.5"/>
<text text-anchor="middle" x="91.5" y="-98.3" font-family="Sans" font-size="14.00">1</text>
<text text-anchor="middle" x="91.5" y="-83.3" font-family="Sans" font-size="14.00">Downloaded</text>
<text text-anchor="middle" x="91.5" y="-68.3" font-family="Sans" font-size="14.00">From Node A</text>
</g>
<!-- block0&#45;&gt;block1 -->
<g id="edge1" class="edge"><title>block0&#45;&gt;block1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M17.0533,-87C17.8357,-87 27.1458,-87 38.8907,-87"/>
</g>
<!-- block2 -->
<g id="node3" class="node"><title>block2</title>
<polygon fill="lightgrey" stroke="black" stroke-width="1.75" points="271,-113.5 166,-113.5 166,-60.5 271,-60.5 271,-113.5"/>
<text text-anchor="middle" x="218.5" y="-98.3" font-family="Sans" font-size="14.00">2</text>
<text text-anchor="middle" x="218.5" y="-83.3" font-family="Sans" font-size="14.00">Downloaded</text>
<text text-anchor="middle" x="218.5" y="-68.3" font-family="Sans" font-size="14.00">From Node B</text>
</g>
<!-- block1&#45;&gt;block2 -->
<g id="edge2" class="edge"><title>block1&#45;&gt;block2</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M144.064,-87C151.193,-87 158.517,-87 165.651,-87"/>
</g>
<!-- block3 -->
<g id="node4" class="node"><title>block3</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="400,-113.5 295,-113.5 295,-60.5 400,-60.5 400,-113.5"/>
<text text-anchor="middle" x="347.5" y="-98.3" font-family="Sans" font-size="14.00">3</text>
<text text-anchor="middle" x="347.5" y="-83.3" font-family="Sans" font-size="14.00">Requested</text>
<text text-anchor="middle" x="347.5" y="-68.3" font-family="Sans" font-size="14.00">From Node A</text>
</g>
<!-- block2&#45;&gt;block3 -->
<g id="edge3" class="edge"><title>block2&#45;&gt;block3</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M271.156,-87C278.984,-87 287.062,-87 294.89,-87"/>
</g>
<!-- block4 -->
<g id="node5" class="node"><title>block4</title>
<polygon fill="lightgrey" stroke="black" stroke-width="1.75" points="527,-113.5 422,-113.5 422,-60.5 527,-60.5 527,-113.5"/>
<text text-anchor="middle" x="474.5" y="-98.3" font-family="Sans" font-size="14.00">4</text>
<text text-anchor="middle" x="474.5" y="-83.3" font-family="Sans" font-size="14.00">Downloaded</text>
<text text-anchor="middle" x="474.5" y="-68.3" font-family="Sans" font-size="14.00">From Node B</text>
</g>
<!-- block3&#45;&gt;block4 -->
<g id="edge4" class="edge"><title>block3&#45;&gt;block4</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M400.064,-87C407.193,-87 414.517,-87 421.651,-87"/>
</g>
<!-- block5 -->
<g id="node6" class="node"><title>block5</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="654,-113.5 549,-113.5 549,-60.5 654,-60.5 654,-113.5"/>
<text text-anchor="middle" x="601.5" y="-98.3" font-family="Sans" font-size="14.00">5</text>
<text text-anchor="middle" x="601.5" y="-83.3" font-family="Sans" font-size="14.00">Requested</text>
<text text-anchor="middle" x="601.5" y="-68.3" font-family="Sans" font-size="14.00">From Node B</text>
</g>
<!-- block4&#45;&gt;block5 -->
<g id="edge5" class="edge"><title>block4&#45;&gt;block5</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M527.064,-87C534.193,-87 541.517,-87 548.651,-87"/>
</g>
<!-- block6 -->
<!-- block5&#45;&gt;block6 -->
<g id="edge6" class="edge"><title>block5&#45;&gt;block6</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M654.229,-87C675.25,-87 695.351,-87 698.935,-87"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,57 @@
digraph {
// This file is licensed under the MIT License (MIT) available on
// http://opensource.org/licenses/MIT.
size=6.25;
rankdir=LR
splines = "false";
ranksep = 0.4;
nodesep = 0.1;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "box", fontname="Sans"]
graph [ penwidth = 1.75, fontname="Sans" ]
ibd -> getblocks:f1 -> sync;
ibd [ label = "IBD\nNode", shape="none" ];
sync [ label = "Sync\nNode", shape="none" ];
getblocks [ shape="plaintext", label=<
<table border="2" cellborder="1" cellpadding="1">
<tr>
<td colspan="4" port="f1" border="0" cellpadding="4"><b>GetHeaders Message</b></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Message Header</i></td>
</tr>
<tr>
<td border="1"><i>Start String</i><br/><font face="courier">f9beb4d9</font></td>
<td border="1" cellpadding="4"><i>Command</i><br/><font face="courier">getheaders</font></td>
<td border="1"><i>Size</i><br/><font face="courier">69</font></td>
<td border="1"><i>Checksum</i><br/><font face="courier">f5fcbcad</font></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Payload</i></td>
</tr>
<tr>
<td colspan="2"><i>Protocol Version</i><br /><font face="courier">70002</font></td>
<td colspan="2"><i>Header Hash Count</i><br /><font face="courier">1</font></td>
</tr>
<tr>
<td colspan="4"><i>Header Hashes (Highest-Height First)</i><br /><font face="courier">6fe28c0ab6f1b3...d6190000000000</font></td>
</tr>
<tr>
<td colspan="4"><i>Stopping Hash (Zero Is "No Stop")</i><br /><font face="courier">00000000000000...00000000000000</font></td>
</tr>
</table>>];
label = "First getheaders message sent from Initial Blocks Download (IBD) node"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="450pt" height="216pt"
viewBox="0.00 0.00 450.00 215.93" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.863724 0.863724) rotate(0) translate(4 246)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-246 517,-246 517,4 -4,4"/>
<text text-anchor="middle" x="256.5" y="-7.8" font-family="Sans" font-size="14.00">First getheaders message sent from Initial Blocks Download (IBD) node</text>
<!-- ibd -->
<g id="node1" class="node"><title>ibd</title>
<text text-anchor="middle" x="27" y="-226.3" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="27" y="-211.3" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- getblocks -->
<g id="node2" class="node"><title>getblocks</title>
<text text-anchor="start" x="171" y="-219.3" font-family="Sans" font-weight="bold" font-size="14.00">GetHeaders Message</text>
<text text-anchor="start" x="199.5" y="-197.3" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="95.5,-151.5 95.5,-189.5 179.5,-189.5 179.5,-151.5 95.5,-151.5"/>
<text text-anchor="start" x="97.5" y="-174.3" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="104" y="-160.3" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="181.5,-151.5 181.5,-189.5 274.5,-189.5 274.5,-151.5 181.5,-151.5"/>
<text text-anchor="start" x="193" y="-174.3" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="186.5" y="-160.3" font-family="Courier,monospace" font-size="14.00">getheaders</text>
<polygon fill="none" stroke="black" points="276.5,-151.5 276.5,-189.5 324.5,-189.5 324.5,-151.5 276.5,-151.5"/>
<text text-anchor="start" x="286" y="-174.3" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="292" y="-160.3" font-family="Courier,monospace" font-size="14.00">69</text>
<polygon fill="none" stroke="black" points="326.5,-151.5 326.5,-189.5 418.5,-189.5 418.5,-151.5 326.5,-151.5"/>
<text text-anchor="start" x="336" y="-174.3" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="339" y="-160.3" font-family="Courier,monospace" font-size="14.00">f5fcbcad</text>
<text text-anchor="start" x="229.5" y="-138.3" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="95.5,-98.5 95.5,-130.5 274.5,-130.5 274.5,-98.5 95.5,-98.5"/>
<text text-anchor="start" x="128.5" y="-118.3" font-family="Sans" font-style="italic" font-size="14.00">Protocol Version</text>
<text text-anchor="start" x="164" y="-104.3" font-family="Courier,monospace" font-size="14.00">70002</text>
<polygon fill="none" stroke="black" points="276.5,-98.5 276.5,-130.5 418.5,-130.5 418.5,-98.5 276.5,-98.5"/>
<text text-anchor="start" x="279.5" y="-118.3" font-family="Sans" font-style="italic" font-size="14.00">Header Hash Count</text>
<text text-anchor="start" x="343" y="-104.3" font-family="Courier,monospace" font-size="14.00">1</text>
<polygon fill="none" stroke="black" points="95.5,-64.5 95.5,-96.5 418.5,-96.5 418.5,-64.5 95.5,-64.5"/>
<text text-anchor="start" x="127.5" y="-84.3" font-family="Sans" font-style="italic" font-size="14.00">Header Hashes (Highest&#45;Height First)</text>
<text text-anchor="start" x="129" y="-70.3" font-family="Courier,monospace" font-size="14.00">6fe28c0ab6f1b3...d6190000000000</text>
<polygon fill="none" stroke="black" points="95.5,-30.5 95.5,-62.5 418.5,-62.5 418.5,-30.5 95.5,-30.5"/>
<text text-anchor="start" x="138.5" y="-50.3" font-family="Sans" font-style="italic" font-size="14.00">Stopping Hash (Zero Is &quot;No Stop&quot;)</text>
<text text-anchor="start" x="129" y="-36.3" font-family="Courier,monospace" font-size="14.00">00000000000000...00000000000000</text>
<polygon fill="none" stroke="black" stroke-width="2" points="92,-28 92,-237 421,-237 421,-28 92,-28"/>
</g>
<!-- ibd&#45;&gt;getblocks -->
<g id="edge1" class="edge"><title>ibd&#45;&gt;getblocks:f1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M54.2826,-222.5C64.8835,-222.5 76.4737,-222.5 84.4768,-222.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="84.5,-226 94.5,-222.5 84.5,-219 84.5,-226"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="486" y="-226.3" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="486" y="-211.3" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- getblocks&#45;&gt;sync -->
<g id="edge2" class="edge"><title>getblocks:f1&#45;&gt;sync</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M419.5,-222.5C419.5,-222.5 433.372,-222.5 448.348,-222.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="448.736,-226 458.736,-222.5 448.736,-219 448.736,-226"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,67 @@
digraph {
// This file is licensed under the MIT License (MIT) available on
// http://opensource.org/licenses/MIT.
size=6.25;
rankdir=LR
splines = "false";
ranksep = 0.2;
nodesep = 0.1;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "box", fontname="Sans"]
graph [ penwidth = 1.75, fontname="Sans" ]
ibd -> inv:f1 -> sync [ dir = "back" ];
ibd [ label = "IBD\nNode", shape="none" ];
sync [ label = "Sync\nNode", shape="none" ];
inv [ shape="plaintext", label=<
<table border="2" cellborder="1">
<tr>
<td colspan="4" port="f1" border="0" cellpadding="4"><b>Headers Message</b></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Message Header</i></td>
</tr>
<tr>
<td border="1"><i>Start String</i><br/><font face="courier">f9beb4d9</font></td>
<td border="1"><i>Command</i><br/><font face="courier">headers</font></td>
<td border="1"><i>Size</i><br/><font face="courier">162003</font></td>
<td border="1"><i>Checksum</i><br/><font face="courier">a65b2b77</font></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Payload</i></td>
</tr>
<tr>
<td colspan="4"><i>Number Of Headers (Max 2,000 In Reply To GetHeaders) </i><br /><font face="courier">2000</font></td>
</tr>
<tr>
<td colspan="4">
<table border="0">
<tr>
<td><i>80-byte Block Headers + 0x00 (The Empty Tx Count)</i></td>
</tr>
<tr>
<td><font face="courier">010000006fe28cab...ff001d01e3629900</font></td>
</tr>
<tr>
<td><font face="courier">010000004860eb18...ff001d08d2bd6100</font></td>
</tr>
<tr>
<td colspan="2"><i>...............1,998 more block headers...............</i></td>
</tr>
</table>
</td>
</tr>
</table>>];
label = "First headers message reply sent to Initial Blocks Download (IBD) node"
}

BIN
img/dev/en-ibd-headers.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
-->
<!-- Title: %3 Pages: 1 -->
<svg width="450pt" height="216pt"
viewBox="0.00 0.00 450.00 216.44" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.778547 0.778547) rotate(0) translate(4 274)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-274 574,-274 574,4 -4,4"/>
<text text-anchor="middle" x="285" y="-7.8" font-family="Sans" font-size="14.00">First headers message reply sent to Initial Blocks Download (IBD) node</text>
<!-- ibd -->
<g id="node1" class="node"><title>ibd</title>
<text text-anchor="middle" x="27" y="-254.3" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="27" y="-239.3" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- inv -->
<g id="node2" class="node"><title>inv</title>
<text text-anchor="start" x="213.5" y="-247.3" font-family="Sans" font-weight="bold" font-size="14.00">Headers Message</text>
<text text-anchor="start" x="227.5" y="-224.3" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="80,-181.5 80,-215.5 219,-215.5 219,-181.5 80,-181.5"/>
<text text-anchor="start" x="109.5" y="-202.3" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="116" y="-188.3" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="221,-181.5 221,-215.5 324,-215.5 324,-181.5 221,-181.5"/>
<text text-anchor="start" x="237.5" y="-202.3" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="243.5" y="-188.3" font-family="Courier,monospace" font-size="14.00">headers</text>
<polygon fill="none" stroke="black" points="326,-181.5 326,-215.5 395,-215.5 395,-181.5 326,-181.5"/>
<text text-anchor="start" x="346" y="-202.3" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="335.5" y="-188.3" font-family="Courier,monospace" font-size="14.00">162003</text>
<polygon fill="none" stroke="black" points="397,-181.5 397,-215.5 490,-215.5 490,-181.5 397,-181.5"/>
<text text-anchor="start" x="407" y="-202.3" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="410" y="-188.3" font-family="Courier,monospace" font-size="14.00">a65b2b77</text>
<text text-anchor="start" x="257.5" y="-167.3" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="80,-124.5 80,-158.5 490,-158.5 490,-124.5 80,-124.5"/>
<text text-anchor="start" x="86" y="-145.3" font-family="Sans" font-style="italic" font-size="14.00">Number Of Headers (Max 2,000 In Reply To GetHeaders) </text>
<text text-anchor="start" x="268" y="-131.3" font-family="Courier,monospace" font-size="14.00">2000</text>
<polygon fill="none" stroke="black" points="80,-30.5 80,-122.5 490,-122.5 490,-30.5 80,-30.5"/>
<text text-anchor="start" x="93" y="-105.3" font-family="Sans" font-style="italic" font-size="14.00">80&#45;byte Block Headers + 0x00 (The Empty Tx Count)</text>
<text text-anchor="start" x="133.5" y="-83.3" font-family="Courier,monospace" font-size="14.00">010000006fe28cab...ff001d01e3629900</text>
<text text-anchor="start" x="133.5" y="-62.3" font-family="Courier,monospace" font-size="14.00">010000004860eb18...ff001d08d2bd6100</text>
<text text-anchor="start" x="127" y="-42.3" font-family="Sans" font-style="italic" font-size="14.00">...............1,998 more block headers...............</text>
<polygon fill="none" stroke="black" stroke-width="2" points="77,-28 77,-265 493,-265 493,-28 77,-28"/>
</g>
<!-- ibd&#45;&gt;inv -->
<g id="edge1" class="edge"><title>ibd&#45;&gt;inv:f1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M64.0987,-250.5C72.4781,-250.5 79,-250.5 79,-250.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="64.0976,-247 54.0976,-250.5 64.0976,-254 64.0976,-247"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="543" y="-254.3" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="543" y="-239.3" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- inv&#45;&gt;sync -->
<g id="edge2" class="edge"><title>inv:f1&#45;&gt;sync</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M501.038,-250.5C505.35,-250.5 510.609,-250.5 515.902,-250.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="501,-247 491,-250.5 501,-254 501,-247"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB