Dev Docs: Document Blocks-First IBD & Orphan Blocks

This commit provides a detailed overview of the current block download
method, which I've retroactively named blocks-first for parallelism with
headers-first.

New And Significantly Revised:

* New Initial Block Download (IBD) section (h3) with Blocks-First
  subsection (h4)

* New Orphan Block subsection (under Blocks Broadcasting) describing
  orphan blocks and how they're handled under blocks-first. Also
  includes a simple illustration of the difference between orphan blocks
  and stale blocks. Thanks to luke-jr for his s/orphan block/stale
  block/ commit a couple months ago---that made this commit much easier.

Edits:

* Cleaned up a couple cases missed by previous s/orphan/stale/ commit
  because they used past tense (orphaned).

* In P2P reference section, mentioned that a `block` message can be sent
  unsolicited by miners.

* Mention that `getheaders` and `headers` were added in protocol
  version 31800.

* Moved a few internal links around and added a few new internal links.

Administrivia:

* Started adding "TODOv0.10" in HTML comments to places that need to be
  updated when 0.10 is released so that I can easily git grep for that
  tag later.
This commit is contained in:
David A. Harding 2014-11-27 19:36:59 -05:00
parent c4cce0e8f9
commit ccda4caa0c
No known key found for this signature in database
GPG key ID: 4B29C30FF29EC4B7
25 changed files with 1010 additions and 18 deletions

View file

@ -30,6 +30,7 @@ block:
block chain:
block-chain: block chain
block header:
block headers: block header
block height:
'`block` message': block message
'`block` messages': block message
@ -37,6 +38,10 @@ block reward:
block time:
block version:
blocks: block
blocks-first: blocks-first sync
blocks-first sync:
blocks-first IBD: blocks-first sync
bloom filter:
broadcast:
broadcasts: broadcast
broadcasting:
@ -115,6 +120,8 @@ HD protocol:
'`headers` messages': headers message
high-priority transaction: high-priority transactions
high-priority transactions:
IBD: initial block download
initial block download:
inputs: input
input:
intermediate certificate:
@ -187,6 +194,8 @@ op codes: op code
'`op_hash160`': op_hash160
'`op_return`': op_return
'`op_verify`': op_verify
orphan block:
orphan blocks: orphan block
outpoint:
outpoints: outpoint
outputs: output
@ -216,6 +225,7 @@ pki:
'`point()`': point function
'`pong` message': pong message
'`pong` messages': pong message
previous block header hash:
private key:
private keys: private key
proof of work:
@ -226,6 +236,7 @@ protocol version 106: section protocol versions
protocol version 209: section protocol versions
protocol version 311: section protocol versions
protocol version 31402: section protocol versions
protocol version 31800: section protocol versions
protocol version 60000: section protocol versions
protocol version 60001: section protocol versions
protocol version 60002: section protocol versions
@ -267,10 +278,10 @@ script hash:
secp256k1:
sequence number:
sequence numbers: sequence number
serialized block: section serialized blocks
serialized blocks: section serialized block
serialized transaction: raw transaction format
serialized transactions: raw transaction format
serialized block:
serialized blocks: serialized block
serialized transaction: raw format
serialized transactions: raw format
SIGHASH: signature hash
'`SIGHASH_ANYONECANPAY`': shacp
'`SIGHASH_ALL`': sighash_all
@ -522,6 +533,7 @@ Bitcoin Core 0.1.6:
Bitcoin Core 0.2.9:
Bitcoin Core 0.3.11:
Bitcoin Core 0.3.15:
Bitcoin Core 0.3.18:
Bitcoin Core 0.6.0:
Bitcoin Core 0.6.1:
Bitcoin Core 0.7.0:

View file

@ -181,8 +181,8 @@ the fork stronger than the other side.
Assuming a fork only contains valid
blocks, normal peers always follow the the most difficult chain
to recreate and throw away [stale blocks][stale block]{:#term-stale-block}{:.term} belonging to shorter forks.
(Stale blocks are also sometimes called orphans or orphan blocks, but
those terms are also used for blocks without a known parent block.)
(Stale blocks are also sometimes called orphans or orphan blocks<!--noref-->, but
those terms are also used for true orphan blocks without a known parent block.)
[Long-term forks][long-term fork]{:#term-long-term-fork}{:.term} are possible if different miners work at cross-purposes,
such as some miners diligently working to extend the block chain at the

View file

@ -140,6 +140,180 @@ In order to maintain a connection with a peer, nodes by default will send a mess
{% endautocrossref %}
### Initial Block Download
{% include helpers/subhead-links.md %}
{% autocrossref %}
Before a full node can validate unconfirmed transactions and
recently-mined blocks, it must download and validate all blocks from
block 1 (the block after the hardcoded genesis block) to the current tip
of the best block chain. This is the Initial Block Download (IBD) or
initial sync.
Although the word "initial" implies this method is only used once, it
can also be used any time a large number of blocks need to be
downloaded, such as when a previously-caught-up node has been offline
for a long time. In this case, a node can use the IBD method to download
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,
the local block chain is more than about 24 hours in the past).
{% endautocrossref %}
#### Blocks-First
{% include helpers/subhead-links.md %}
{% autocrossref %}
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.
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
`getblocks` message illustrated below.
![First GetBlocks Message Sent During IBD](/img/dev/en-ibd-getblocks.svg)
In the header hashes field of the `getblocks` message, this 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 `getblocks` 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 500 block inventories (the maximum response to a
`getblocks` message) starting from block 1. It sends these inventories
in the `inv` message illustrated below.
![First Inv Message Sent During IBD](/img/dev/en-ibd-inv.svg)
Inventories are unique identifiers for information on the network. Each
inventory contains a type field and the unique identifier for an
instance of the object. For blocks, the unique identifier is a hash of
the block's header.
The block inventories appear in the `inv` message in the same order they
appear in the block chain, so this first `inv` message contains
inventories for blocks 1 through 501. (For example, the hash of block 1
is 4860...0000 as seen in the illustration above.)
The IBD node uses the received inventories to request 128 blocks from
the sync node in the `getdata` message illustrated below.
![First GetData Message Sent During IBD](/img/dev/en-ibd-getdata.svg)
It's important to headers-first nodes that the blocks be requested and
sent in order because each block header references the header hash of
the preceeding block. That means the IBD node can't fully validate a
block until its parent block has been received. Blocks that can't be
validated because their parents haven't been received are called orphan
blocks; a subsection below describes them in more detail.
Upon receipt of the `getdata` message, the sync node replies with each
of the blocks requested. Each block is put into serialized block format
and sent in a separate `block` message. The first `block` message sent
(for block 1) is illustrated below.
![First Block Message Sent During IBD](/img/dev/en-ibd-block.svg)
The IBD node downloads each block, validates it, and then requests the
next block it hasn't requested yet, maintaining a queue of up to 128
blocks to download. When it has requested every block for which it has
an inventory, it sends another `getblocks` message to the sync node
requesting the inventories of up to 500 more blocks. This second
`getblocks` message contains multiple header hashes as illustrated
below:
![Second GetBlocks Message Sent During IBD](/img/dev/en-ibd-getblocks2.svg)
Upon receipt of the second `getblocks` message, the sync node takes the
first listed header hash and searches its local best block chain for a
block with that header hash. If it finds a block with that hash, it
replies with 500 block inventories starting with the following block.
But if it doesn't find a block with that hash, it takes the next header
hash from the `getblocks` message and searches its block chain for that
hash. If that hash matches, it will reply with 500 block inventories
starting with the following hash from that point. But, again, if it
doesn't find that hash, it will proceed to check the next hash in the
message (and so on until it runs out of hashes in the message). If the
last hash in the message (besides the stopping hash) doesn't match, it
assumes the only block the two nodes have in common is block 0 and so it
sends an `inv` starting with block 1 (the same `inv` message seen
several illustrations above).
This repeated search allows the sync node to send useful inventories even if
the IBD node's local block chain forked from the sync node's local block
chain. This fork detection becomes increasingly useful the closer the
IBD node gets to the tip of the block chain.
When the IBD node receives the second `inv` message, it will request
those blocks using `getdata` messages. The sync node will respond with
`block` messages. Then the IBD node will request more inventories with
another `getblocks` message---and the cycle will repeat until the IBD
node is synced to the tip of the block chain. At that point, the node
will accept blocks sent through the regular block broadcasting described
in a later subsection.
{% endautocrossref %}
##### Blocks-First Advantages & Disadvantages
{:.no_toc}
{% include helpers/subhead-links.md %}
{% autocrossref %}
The primary advantage of blocks-first IBD is its simplicity. The primary
disadvantage is that the IBD node relies on a single sync node for all
of its downloading. This has several implications:
* **Speed Limits:** All requests are made to the sync node, so if the
sync node has limited upload bandwidth, the IBD node will have slow
download speeds. Note: if the sync node goes offline, Bitcoin Core
will continue downloading from another node---but it will still only
download from a single sync node at a time.
* **Download Restarts:** The sync node can send a non-best (but
otherwise valid) block chain to the IBD node. The IBD node won't be
able to identify it as non-best until the initial block download nears
completion, forcing the IBD node to restart its block chain download
over again from a different node. Bitcoin Core ships with several
block chain checkpoints at various block heights selected by
developers to help an IBD node detect that it is being fed an
alternative block chain history---allowing the IBD node to restart
its download earlier in the process.
* **Disk Fill Attacks:** Closely related to the download restarts, if
the sync node sends a non-best (but otherwise valid) block chain, the
chain will be stored on disk, wasting space and possibly filling up
the disk drive with useless data.
* **High Memory Use:** Whether maliciously or by accident, the sync node
can send blocks out of order, creating orphan blocks which can't be
validated until their parents have been received and validated.
Orphan blocks are stored in memory while they await validation,
which may lead to high memory use.
All of these problems are addressed in part or in full by the
headers-first IBD method used in Bitcoin Core 0.10.0.
**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** | [`getblocks`][getblocks message] | [`inv`][inv message] | [`getdata`][getdata message] | [`block`][block message]
| **From→To** | IBD→Sync | Sync→IBD | IBD→Sync | Sync→IBD
| **Payload** | One or more header hashes | Up to 500 block inventories (unique identifiers) | One or more block inventories | One serialized block
{% endautocrossref %}
### Block Broadcasting
{% include helpers/subhead-links.md %}
@ -151,6 +325,31 @@ New blocks are also discovered as miners publish their found blocks, and these m
{% endautocrossref %}
#### Orphan Blocks
{% include helpers/subhead-links.md %}
{% autocrossref %}
Blocks-first nodes may download orphan blocks---blocks whose previous
block header hash field refers to a block header this node
hasn't seen yet. In other words, orphan blocks have no known parent
(unlike stale blocks, which have known parents but which aren't part of
the best block chain).
![Difference Between Orphan And Stale Blocks](/img/dev/en-orphan-stale-definition.svg)
When a blocks-first node downloads an orphan block, it will not validate
it. Instead, it will send a `getblocks` message to the node which sent
the orphan block; the broadcasting node will respond with an `inv` message
containing inventories of any blocks the downloading node is missing (up
to 500); the downloading node will request those blocks with a `getdata`
message; and the broadcasting node will send those blocks with a `block`
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.
{% endautocrossref %}
### Transaction Broadcasting
{% include helpers/subhead-links.md %}
@ -179,13 +378,13 @@ unconfirmed transactions tend to slowly disappear from the network as
peers restart or as they purge some transactions to make room in memory
for others.
Transactions which are mined into blocks that are later orphaned may be
Transactions which are mined into blocks that later become stale blocks may be
added back into the memory pool. These re-added transactions may be
re-removed from the pool almost immediately if the replacement blocks
include them. This is the case in Bitcoin Core, which removes orphaned
include them. This is the case in Bitcoin Core, which removes stale
blocks from the chain one by one, starting with the tip (highest block).
As each block is removed, its transactions are added back to the memory
pool. After all of the orphaned blocks are removed, the replacement
pool. After all of the stale blocks are removed, the replacement
blocks are added to the chain one by one, ending with the new tip. As
each block is added, any transactions it confirms are removed from the
memory pool.

View file

@ -21,7 +21,7 @@ serialized header format part of the consensus rules.
| Bytes | Name | Data Type | Description
|-------|---------------------|-----------|----------------
| 4 | version | uint32_t | The [block version][]{:#term-block-version}{:.term} number indicates which set of block validation rules to follow. See the list of block versions below.
| 32 | previous block hash | char[32] | A SHA256(SHA256()) hash in internal byte order of the previous block's header. This ensures no previous block can be changed without also changing this block's header.
| 32 | [previous block header hash][]{:#term-previous-block-header-hash}{:.term} | char[32] | A SHA256(SHA256()) hash in internal byte order of the previous block's header. This ensures no previous block can be changed without also changing this block's header.
| 32 | merkle root hash | char[32] | A SHA256(SHA256()) hash in internal byte order. The merkle root is derived from the hashes of all transactions included in this block, ensuring that none of those transactions can be modified without modifying the header. See the [merkle trees section][section merkle trees] below.
| 4 | time | uint32_t | The [block time][]{:#term-block-time}{:.term} is a Unix epoch time when the miner started hashing the header (according to the miner). Must be greater than or equal to the median time of the previous 11 blocks. Full nodes will not accept blocks with headers more than two hours in the future according to their clock.
| 4 | nBits | uint32_t | An encoded version of the target threshold this block's header hash must be less than or equal to. See the nBits format described below.

View file

@ -71,6 +71,7 @@ please [open an issue][docs issue].)
| 60002 | Bitcoin Core 0.7.0 <br>(Sep 2012) | [BIP35][]: <br>• Added `mempool` message. <br>• Extended `getdata` message to allow download of memory pool transactions
| 60001 | Bitcoin Core 0.6.1 <br>(May 2012) | [BIP31][]: <br>• Added nonce field to `ping` message <br>• Added `pong` message
| 60000 | Bitcoin Core 0.6.0 <br>(Mar 2012) | [BIP14][]: <br>• Separated protocol version from Bitcoin Core version
| 31800 | Bitcoin Core 0.3.18 <br>(Dec 2010) | • Added `getheaders` message and `headers` message.
| 31402 | Bitcoin Core 0.3.15 <br>(Oct 2010) | • Added time field to `addr` message.
| 311 | Bitcoin Core 0.3.11 <br>(Aug 2010) | • Added `alert` message.
| 209 | Bitcoin Core 0.2.9 <br>(May 2010) | • Added checksum field to message headers.
@ -146,11 +147,20 @@ one of these unknown types.
{% autocrossref %}
The `block` message transmits a single serialized block in the format
described in the [serialized blocks section][section serialized blocks].
See that section for an example hexdump.
described in the [serialized blocks section][serialized block].
See that section for an example hexdump. It can be sent for two
different reasons:
It is sent in reply to a `getdata` message which had an inventory type of
`MSG_BLOCK` and the header hash of the particular block being requested.
1. **GetData Response:** Nodes will always send it in response to a
`getdata` message that requests the block with an inventory
type of `MSG_BLOCK` (provided the node has that block available for
relay).
2. **Unsolicited:** Some miners will send unsolicited `block` messages
broadcasting their newly-mined blocks to all of their peers. Many
mining pools do the same thing, although some may be misconfigured to
send the block from multiple nodes, possibly sending the same block
to some peers more than once.
{% endautocrossref %}
@ -235,6 +245,8 @@ identical to the `inv` message; only the message header differs.
{% autocrossref %}
*Added in protocol version 31800.*
The `getheaders` message requests a `headers` message that provides block headers
starting from a particular point in the block chain. It allows a
peer which has been disconnected or started for the first time to get
@ -245,15 +257,21 @@ with one minor difference: the `inv` reply to the `getblocks` message
will include no more than 500 block header hashes; the `headers` reply
to the `getheaders` message will include as many as 2,000 block headers.
{% endautocrossref %}
#### Headers
{% include helpers/subhead-links.md %}
{% autocrossref %}
*Added in protocol version 31800.*
The `headers` message sends one or more block headers to a node which
previously requested certain headers with a `getheaders` message.
| Bytes | Name | Data Type | Description
|----------|---------|------------------|-----------------
| *Varies* | count | compactSize uint | Number of block headers up to a maximum of 2,000.
| *Varies* | count | compactSize uint | Number of block headers up to a maximum of 2,000. Note: headers-first sync assumes the sending node will send the maximum number of headers whenever possible.
| *Varies* | headers | block_header | Block headers: each 80-byte block header is in the format described in the [block headers section][block header] with an additional 0x00 suffixed. This 0x00 is called the transaction count, but because the headers message doesn't include any transactions, the transaction count is always zero.
The following annotated hexdump shows a `headers` message. (The message

View file

@ -15,6 +15,7 @@ http://opensource.org/licenses/MIT.
[bits]: /en/developer-guide#term-bits "0.000001 bitcoins (100 satoshis)"
[block]: /en/developer-guide#term-block "A block of transactions protected by proof of work"
[blocks]: /en/developer-guide#term-block "Blocks of transactions protected by proof of work"
[blocks-first sync]: /en/developer-guide#blocks-first "Synchronizing the block chain by downloading each block from a peer and then validating it"
[block chain]: /en/developer-guide#block-chain "A chain of blocks with each block linking to the block that preceded; the most-difficult-to-recreate chain is The Block Chain"
[block header]: /en/developer-reference#block-headers "An 80-byte header belonging to a single block which is hashed repeatedly to create proof of work"
[block height]: /en/developer-guide#term-block-height "The number of chained blocks preceding this block"
@ -22,6 +23,7 @@ http://opensource.org/licenses/MIT.
[block reward]: /en/developer-reference#term-block-reward "New satoshis given to a miner for creating one of the first 6,929,999 blocks"
[block time]: /en/developer-reference#term-block-time "The time field in the block header"
[block version]: /en/developer-reference#term-block-version "The version field in the block header"
[bloom filter]: /en/developer-guide#bloom-filters "A filter used primarily by SPV nodes to request only matching transactions and merkle blocks from full nodes"
[broadcast]: /en/developer-guide#transaction-broadcasting "Sending transactions or blocks to all other peers on the Bitcoin network (compare to privately transmitting to a single peer or partner"
[broadcasts]: /en/developer-guide#transaction-broadcasting "Sending transactions or blocks to all other peers on the Bitcoin network (compare to privately transmitting to a single peer or partner"
[broadcasting]: /en/developer-guide#transaction-broadcasting "Sending transactions or blocks to all other peers on the Bitcoin network (compare to privately transmitting to a single peer or partner)"
@ -67,6 +69,7 @@ http://opensource.org/licenses/MIT.
[HD protocol]: /en/developer-guide#term-hd-protocol "The Hierarchical Deterministic (HD) key creation and transfer protocol"
[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"
[input]: /en/developer-guide#term-input "The input to a transaction linking to the output of a previous transaction which permits spending of satoshis"
[inputs]: /en/developer-guide#term-input "The input to a transaction linking to the output of a previous transaction which permits spending of satoshis"
[intermediate certificate]: /en/developer-examples#term-intermediate-certificate "A intermediate certificate authority certificate which helps connect a leaf (receiver) certificate to a root certificate authority"
@ -114,6 +117,7 @@ http://opensource.org/licenses/MIT.
[op_return]: /en/developer-reference#term-op-return "Operation which terminates the script in failure"
[op_verify]: /en/developer-reference#term-op-verify "Operation which terminates the script if the entry below it on the stack is non-true (zero)"
[outpoint]: /en/developer-reference#outpoint "The structure used to refer to a particular transaction output, consisting of a 32-byte TXID and a 4-byte output index number (vout)."
[orphan block]: /en/developer-guide#orphan-blocks "Blocks whose parent block has not been processed by the local node; not to be confused with stale blocks"
[output]: /en/developer-guide#term-output "The output of a transaction which transfers value to a pubkey script"
[output index]: /en/developer-guide#term-output-index "The sequentially-numbered index of outputs in a single transaction starting from 0"
[P2PKH]: /en/developer-guide#term-p2pkh "A pubkey script which Pays To PubKey Hashes (P2PKH), allowing spending of satoshis to anyone with a Bitcoin address"
@ -133,6 +137,7 @@ http://opensource.org/licenses/MIT.
[PKI]: /en/developer-examples#term-pki "Public Key Infrastructure; usually meant to indicate the X.509 certificate system used for HTTP Secure (https)."
[point function]: /en/developer-guide#term-point-function "The ECDSA function used to create a public key from a private key"
[pong message]: /en/developer-reference#pong "A P2P network message used to reply to a P2P network ping message"
[previous block header hash]: /en/developer-reference#term-previous-block-header-hash "A field in the block header which contains the SHA256(SHA256()) hash of the previous block's header"
[private key]: /en/developer-guide#term-private-key "The private portion of a keypair which can create signatures which other people can verify using the public key"
[private keys]: /en/developer-guide#term-private-key "The private portion of a keypair which can create signatures which other people can verify using the public key"
[proper money handling]: /en/developer-reference#term-proper-money-handling "Bitcoin amounts need to be correctly processed without introducing rounding errors that could cause monetary loss"
@ -161,8 +166,9 @@ http://opensource.org/licenses/MIT.
[RPC byte order]: /en/developer-reference#hash-byte-order "A hash digest displayed with the byte order reversed; used in Bitcoin Core RPCs and other software."
[satoshi]: /en/developer-guide#term-satoshi "The smallest unit of Bitcoin value; 0.00000001 bitcoins. Also used generically for any value of bitcoins"
[satoshis]: /en/developer-guide#term-satoshi "The smallest unit of Bitcoin value; 0.00000001 bitcoins. Also used generically for any value of bitcoins"
[sequence number]: /en/developer-guide#term-sequence-number "A number intended to allow time locked transactions to be updated before being finalized; not currently used except to disable locktime in a transaction"
[script hash]: /en/developer-guide#term-script-hash "The hash of a redeem script used to create a P2SH output"
[sequence number]: /en/developer-guide#term-sequence-number "A number intended to allow time locked transactions to be updated before being finalized; not currently used except to disable locktime in a transaction"
[serialized block]: /en/developer-reference#serialized-blocks "A block in the serialized form used to compute block byte size"
[sha_shacp]: /en/developer-guide#term-sighash-all-sighash-anyonecanpay "Signature hash type which allows other people to contribute satoshis without changing the number of satoshis sent nor where they go"
[shacp]: /en/developer-guide#term-sighash-anyonecanpay "A signature hash type which modifies the behavior of other signature hash types"
[shn_shacp]: /en/developer-guide#term-sighash-none-sighash-anyonecanpay "Signature hash type which allows unfettered modification of a transaction"
@ -177,7 +183,7 @@ http://opensource.org/licenses/MIT.
[spv]: /en/developer-guide#simplified-payment-verification-spv "A method for verifying particular transactions were included in blocks without downloading the entire contents of the block chain"
[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"
[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 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"
@ -376,8 +382,10 @@ http://opensource.org/licenses/MIT.
[Bitcoin Core 0.2.9]: https://github.com/bitcoin/bitcoin/commit/42605ce8bcc9bd01b86491c74fee14de77960868
[Bitcoin Core 0.3.11]: https://github.com/bitcoin/bitcoin/commit/343328c6b8db85e58a1feea85f0d10e62967fa19
[Bitcoin Core 0.3.15]: https://github.com/bitcoin/bitcoin/commit/c891967b6fcab2e8dc4ce0c787312b36c07efa4d
[Bitcoin Core 0.3.18]: https://github.com/bitcoin/bitcoin/commit/82201801336f64ee77851b9eaab9383ee4e442f0
[bitcoin core fee drop commit]: https://github.com/bitcoin/bitcoin/commit/6a4c196dd64da2fd33dc7ae77a8cdd3e4cf0eff1
[Bitcoin Core issue #2381]: https://github.com/bitcoin/bitcoin/issues/2381
[Bitcoin Core pull #4468]: https://github.com/bitcoin/bitcoin/pull/4468
[Bitcoin Seeder]: https://github.com/sipa/bitcoin-seeder
[bitcoin-documentation mailing list]: https://groups.google.com/forum/#!forum/bitcoin-documentation
[BitcoinJ]: http://bitcoinj.github.io

View file

@ -14,7 +14,8 @@ corresponding commands:
circo -T svg file.circo -o file.svg
neato -T png file.neato -o file.png
Notice: Graphviz can be inconsistent across versions. All of the SVG and
Notice: Graphviz can be inconsistent across versions.
Up until commit ab415e8b6 (2014-12-17), all of the SVG and
PNG images here were generated using graphviz version 2.26.3
(20100126.1600) on Debian 7 using the following shell loop:
@ -26,6 +27,11 @@ PNG images here were generated using graphviz version 2.26.3
optipng -o7 ${f/.dot}.png
done
Images created after commit ab415e8b6 used Debian Graphviz version
2.38.0-7. This higher version is required to support the HTML bold and
italics tags used in some newer images, and we may come to use some of
its other extra features such as the sides="" parameter.
For improved compatability between Graphviz versions, files created or
updated after 6 May 2014 are recommend to include the following code
near the top of the file:

48
img/dev/en-ibd-block.dot Normal file
View file

@ -0,0 +1,48 @@
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.5;
nodesep = 0.1;
edge [ penwidth = 1.75, fontname="Sans" ]
node [ penwidth = 1.75, shape = "box", fontname="Sans"]
graph [ penwidth = 1.75, fontname="Sans" ]
ibd -> block:f1 -> sync [dir="back"];
ibd [ label = "IBD\nNode", shape="none" ];
sync [ label = "Sync\nNode", shape="none" ];
block [ shape="plaintext", label=<
<table border="2" cellborder="1" cellpadding="5">
<tr>
<td colspan="4" port="f1" border="0" cellpadding="4"><b>Block 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">block</font></td>
<td border="1"><i>Size</i><br/><font face="courier">215</font></td>
<td border="1"><i>Checksum</i><br/><font face="courier">934d270a</font></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Payload</i></td>
</tr>
<tr>
<td colspan="4" border="1"><i>Serialized Block</i><br/><font face="courier">010000006fe2...58eeac00000000</font></td>
</tr>
</table>>];
label = "First block message sent to Initial Blocks Download (IBD) node"
}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

56
img/dev/en-ibd-block.svg Normal file
View file

@ -0,0 +1,56 @@
<?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="181pt"
viewBox="0.00 0.00 450.00 180.69" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.868726 0.868726) rotate(0) translate(4 204)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-204 514,-204 514,4 -4,4"/>
<text text-anchor="middle" x="255" y="-7.8" font-family="Sans" font-size="14.00">First block message sent to Initial Blocks Download (IBD) node</text>
<!-- ibd -->
<g id="node1" class="node"><title>ibd</title>
<text text-anchor="middle" x="27" y="-184.3" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="27" y="-169.3" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- block -->
<g id="node2" class="node"><title>block</title>
<text text-anchor="start" x="195" y="-177.3" font-family="Sans" font-weight="bold" font-size="14.00">Block Message</text>
<text text-anchor="start" x="197.5" y="-151.3" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="102,-99.5 102,-139.5 194,-139.5 194,-99.5 102,-99.5"/>
<text text-anchor="start" x="108" y="-123.3" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="114.5" y="-109.3" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="196,-99.5 196,-139.5 278,-139.5 278,-99.5 196,-99.5"/>
<text text-anchor="start" x="202" y="-123.3" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="216" y="-109.3" font-family="Courier,monospace" font-size="14.00">block</text>
<polygon fill="none" stroke="black" points="280,-99.5 280,-139.5 321,-139.5 321,-99.5 280,-99.5"/>
<text text-anchor="start" x="286" y="-123.3" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="288" y="-109.3" font-family="Courier,monospace" font-size="14.00">215</text>
<polygon fill="none" stroke="black" points="323,-99.5 323,-139.5 408,-139.5 408,-99.5 323,-99.5"/>
<text text-anchor="start" x="329" y="-123.3" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="332" y="-109.3" font-family="Courier,monospace" font-size="14.00">934d270a</text>
<text text-anchor="start" x="227.5" y="-82.3" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="102,-30.5 102,-70.5 408,-70.5 408,-30.5 102,-30.5"/>
<text text-anchor="start" x="200.5" y="-54.3" font-family="Sans" font-style="italic" font-size="14.00">Serialized Block</text>
<text text-anchor="start" x="135" y="-40.3" font-family="Courier,monospace" font-size="14.00">010000006fe2...58eeac00000000</text>
<polygon fill="none" stroke="black" stroke-width="2" points="99,-28 99,-195 411,-195 411,-28 99,-28"/>
</g>
<!-- ibd&#45;&gt;block -->
<g id="edge1" class="edge"><title>ibd&#45;&gt;block:f1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M64.3931,-180.5C82.6786,-180.5 101,-180.5 101,-180.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="64.3547,-177 54.3547,-180.5 64.3546,-184 64.3547,-177"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="483" y="-184.3" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="483" y="-169.3" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- block&#45;&gt;sync -->
<g id="edge2" class="edge"><title>block:f1&#45;&gt;sync</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M419.324,-180.5C428.742,-180.5 443.067,-180.5 455.645,-180.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="419,-177 409,-180.5 419,-184 419,-177"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4 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">
<tr>
<td colspan="4" port="f1" border="0" cellpadding="4"><b>GetBlocks 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">getblocks</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 getblocks message sent from Initial Blocks Download (IBD) node"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 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="225pt"
viewBox="0.00 0.00 450.00 224.56" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.877193 0.877193) rotate(0) translate(4 252)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-252 509,-252 509,4 -4,4"/>
<text text-anchor="middle" x="252.5" y="-7.8" font-family="Sans" font-size="14.00">First getblocks 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="-232.3" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="27" y="-217.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="174.5" y="-225.3" font-family="Sans" font-weight="bold" font-size="14.00">GetBlocks Message</text>
<text text-anchor="start" x="195.5" y="-202.3" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="95.5,-159.5 95.5,-193.5 181.5,-193.5 181.5,-159.5 95.5,-159.5"/>
<text text-anchor="start" x="98.5" y="-180.3" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="105" y="-166.3" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="183.5,-159.5 183.5,-193.5 264.5,-193.5 264.5,-159.5 183.5,-159.5"/>
<text text-anchor="start" x="189" y="-180.3" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="186.5" y="-166.3" font-family="Courier,monospace" font-size="14.00">getblocks</text>
<polygon fill="none" stroke="black" points="266.5,-159.5 266.5,-193.5 315.5,-193.5 315.5,-159.5 266.5,-159.5"/>
<text text-anchor="start" x="276.5" y="-180.3" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="282.5" y="-166.3" font-family="Courier,monospace" font-size="14.00">69</text>
<polygon fill="none" stroke="black" points="317.5,-159.5 317.5,-193.5 410.5,-193.5 410.5,-159.5 317.5,-159.5"/>
<text text-anchor="start" x="327.5" y="-180.3" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="330.5" y="-166.3" font-family="Courier,monospace" font-size="14.00">f5fcbcad</text>
<text text-anchor="start" x="225.5" y="-145.3" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="95.5,-102.5 95.5,-136.5 264.5,-136.5 264.5,-102.5 95.5,-102.5"/>
<text text-anchor="start" x="123.5" y="-123.3" font-family="Sans" font-style="italic" font-size="14.00">Protocol Version</text>
<text text-anchor="start" x="159" y="-109.3" font-family="Courier,monospace" font-size="14.00">70002</text>
<polygon fill="none" stroke="black" points="266.5,-102.5 266.5,-136.5 410.5,-136.5 410.5,-102.5 266.5,-102.5"/>
<text text-anchor="start" x="270.5" y="-123.3" font-family="Sans" font-style="italic" font-size="14.00">Header Hash Count</text>
<text text-anchor="start" x="334" y="-109.3" font-family="Courier,monospace" font-size="14.00">1</text>
<polygon fill="none" stroke="black" points="95.5,-66.5 95.5,-100.5 410.5,-100.5 410.5,-66.5 95.5,-66.5"/>
<text text-anchor="start" x="123.5" y="-87.3" font-family="Sans" font-style="italic" font-size="14.00">Header Hashes (Highest&#45;Height First)</text>
<text text-anchor="start" x="125" y="-73.3" font-family="Courier,monospace" font-size="14.00">6fe28c0ab6f1b3...d6190000000000</text>
<polygon fill="none" stroke="black" points="95.5,-30.5 95.5,-64.5 410.5,-64.5 410.5,-30.5 95.5,-30.5"/>
<text text-anchor="start" x="134.5" y="-51.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="125" y="-37.3" font-family="Courier,monospace" font-size="14.00">00000000000000...00000000000000</text>
<polygon fill="none" stroke="black" stroke-width="2" points="92,-28 92,-243 413,-243 413,-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,-228.5C64.8835,-228.5 76.4737,-228.5 84.4768,-228.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="84.5,-232 94.5,-228.5 84.5,-225 84.5,-232"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="478" y="-232.3" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="478" y="-217.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="M411.5,-228.5C411.5,-228.5 425.372,-228.5 440.348,-228.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="440.736,-232 450.736,-228.5 440.736,-225 440.736,-232"/>
</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">
<tr>
<td colspan="4" port="f1" border="0" cellpadding="4"><b>GetBlocks 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">getblocks</font></td>
<td border="1"><i>Size</i><br/><font face="courier">677</font></td>
<td border="1"><i>Checksum</i><br/><font face="courier">52be83ef</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">20</font></td>
</tr>
<tr>
<td colspan="4"><i>Header Hashes (Highest-Height First)</i><br /><font face="courier">db773c8f3b90ef...64f64f00000000<br/>459f16a1c695d0...f66d8000000000</font><br/><i>......18 more header hashes......</i></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 = "Second getblocks message sent from Initial Blocks Download (IBD) node"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,67 @@
<?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="245pt"
viewBox="0.00 0.00 450.00 244.83" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.862069 0.862069) rotate(0) translate(4 280)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-280 518,-280 518,4 -4,4"/>
<text text-anchor="middle" x="257" y="-7.8" font-family="Sans" font-size="14.00">Second getblocks message sent from Initial Blocks Download (IBD) node</text>
<!-- ibd -->
<g id="node1" class="node"><title>ibd</title>
<text text-anchor="middle" x="31.5" y="-260.3" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="31.5" y="-245.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="179" y="-253.3" font-family="Sans" font-weight="bold" font-size="14.00">GetBlocks Message</text>
<text text-anchor="start" x="200" y="-230.3" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="100,-187.5 100,-221.5 186,-221.5 186,-187.5 100,-187.5"/>
<text text-anchor="start" x="103" y="-208.3" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="109.5" y="-194.3" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="188,-187.5 188,-221.5 269,-221.5 269,-187.5 188,-187.5"/>
<text text-anchor="start" x="193.5" y="-208.3" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="191" y="-194.3" font-family="Courier,monospace" font-size="14.00">getblocks</text>
<polygon fill="none" stroke="black" points="271,-187.5 271,-221.5 320,-221.5 320,-187.5 271,-187.5"/>
<text text-anchor="start" x="281" y="-208.3" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="283" y="-194.3" font-family="Courier,monospace" font-size="14.00">677</text>
<polygon fill="none" stroke="black" points="322,-187.5 322,-221.5 415,-221.5 415,-187.5 322,-187.5"/>
<text text-anchor="start" x="332" y="-208.3" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="335" y="-194.3" font-family="Courier,monospace" font-size="14.00">52be83ef</text>
<text text-anchor="start" x="230" y="-173.3" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="100,-130.5 100,-164.5 269,-164.5 269,-130.5 100,-130.5"/>
<text text-anchor="start" x="128" y="-151.3" font-family="Sans" font-style="italic" font-size="14.00">Protocol Version</text>
<text text-anchor="start" x="163.5" y="-137.3" font-family="Courier,monospace" font-size="14.00">70002</text>
<polygon fill="none" stroke="black" points="271,-130.5 271,-164.5 415,-164.5 415,-130.5 271,-130.5"/>
<text text-anchor="start" x="275" y="-151.3" font-family="Sans" font-style="italic" font-size="14.00">Header Hash Count</text>
<text text-anchor="start" x="334.5" y="-137.3" font-family="Courier,monospace" font-size="14.00">20</text>
<polygon fill="none" stroke="black" points="100,-66.5 100,-128.5 415,-128.5 415,-66.5 100,-66.5"/>
<text text-anchor="start" x="128" y="-115.3" font-family="Sans" font-style="italic" font-size="14.00">Header Hashes (Highest&#45;Height First)</text>
<text text-anchor="start" x="129.5" y="-101.3" font-family="Courier,monospace" font-size="14.00">db773c8f3b90ef...64f64f00000000</text>
<text text-anchor="start" x="129.5" y="-87.3" font-family="Courier,monospace" font-size="14.00">459f16a1c695d0...f66d8000000000</text>
<text text-anchor="start" x="148" y="-73.3" font-family="Sans" font-style="italic" font-size="14.00">......18 more header hashes......</text>
<polygon fill="none" stroke="black" points="100,-30.5 100,-64.5 415,-64.5 415,-30.5 100,-30.5"/>
<text text-anchor="start" x="139" y="-51.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.5" y="-37.3" font-family="Courier,monospace" font-size="14.00">00000000000000...00000000000000</text>
<polygon fill="none" stroke="black" stroke-width="2" points="96.5,-28 96.5,-271 417.5,-271 417.5,-28 96.5,-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="M58.7826,-256.5C69.3835,-256.5 80.9737,-256.5 88.9768,-256.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="89,-260 99,-256.5 89,-253 89,-260"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="482.5" y="-260.3" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="482.5" y="-245.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="M416,-256.5C416,-256.5 429.872,-256.5 444.848,-256.5"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="445.236,-260 455.236,-256.5 445.236,-253 445.236,-260"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -0,0 +1,73 @@
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 -> getdata:f1 -> sync;
ibd [ label = "IBD\nNode", shape="none" ];
sync [ label = "Sync\nNode", shape="none" ];
getdata [ shape="plaintext", label=<
<table border="2" cellborder="1">
<tr>
<td colspan="4" port="f1" border="0" cellpadding="4"><b>GetData 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">getdata</font></td>
<td border="1"><i>Size</i><br/><font face="courier">4609</font></td>
<td border="1"><i>Checksum</i><br/><font face="courier">33e41222</font></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Payload</i></td>
</tr>
<tr>
<td colspan="4"><i>Number Of Objects Requested By Inventory</i><br /><font face="courier">128</font></td>
</tr>
<tr>
<td colspan="4">
<table border="0">
<tr>
<td colspan="2"><i>Objects Requested (Inventory Entries)</i></td>
</tr>
<tr>
<td><i>Type</i></td>
<td><i>Unique Identifier (For Blocks, A Header Hash)</i></td>
</tr>
<tr>
<td>Block</td>
<td><font face="courier">4860eb18bf1b1620...688e9a8300000000</font></td>
</tr>
<tr>
<td>Block</td>
<td><font face="courier">bddd99ccfda39da1...065f626a00000000</font></td>
</tr>
<tr>
<td colspan="2"><i>...............126 more inventory entries...............</i></td>
</tr>
</table>
</td>
</tr>
</table>>];
label = "First getdata message sent from Initial Blocks Download (IBD) node"
}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 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="246pt"
viewBox="0.00 0.00 450.00 245.98" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.822669 0.822669) rotate(0) translate(4 295)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-295 543,-295 543,4 -4,4"/>
<text text-anchor="middle" x="269.5" y="-7.8" font-family="Sans" font-size="14.00">First getdata 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="-275.8" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="27" y="-260.8" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- getdata -->
<g id="node2" class="node"><title>getdata</title>
<text text-anchor="start" x="198.5" y="-268.8" font-family="Sans" font-weight="bold" font-size="14.00">GetData Message</text>
<text text-anchor="start" x="212.5" y="-245.8" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="80.5,-203 80.5,-237 212.5,-237 212.5,-203 80.5,-203"/>
<text text-anchor="start" x="106.5" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="113" y="-209.8" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="214.5,-203 214.5,-237 313.5,-237 313.5,-203 214.5,-203"/>
<text text-anchor="start" x="229" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="235" y="-209.8" font-family="Courier,monospace" font-size="14.00">getdata</text>
<polygon fill="none" stroke="black" points="315.5,-203 315.5,-237 366.5,-237 366.5,-203 315.5,-203"/>
<text text-anchor="start" x="326.5" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="324" y="-209.8" font-family="Courier,monospace" font-size="14.00">4609</text>
<polygon fill="none" stroke="black" points="368.5,-203 368.5,-237 459.5,-237 459.5,-203 368.5,-203"/>
<text text-anchor="start" x="377.5" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="380.5" y="-209.8" font-family="Courier,monospace" font-size="14.00">33e41222</text>
<text text-anchor="start" x="242.5" y="-188.8" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="80.5,-146 80.5,-180 459.5,-180 459.5,-146 80.5,-146"/>
<text text-anchor="start" x="118" y="-166.8" font-family="Sans" font-style="italic" font-size="14.00">Number Of Objects Requested By Inventory</text>
<text text-anchor="start" x="257.5" y="-152.8" font-family="Courier,monospace" font-size="14.00">128</text>
<polygon fill="none" stroke="black" points="80.5,-31 80.5,-144 459.5,-144 459.5,-31 80.5,-31"/>
<text text-anchor="start" x="137.5" y="-126.8" font-family="Sans" font-style="italic" font-size="14.00">Objects Requested (Inventory Entries)</text>
<text text-anchor="start" x="91" y="-105.8" font-family="Sans" font-style="italic" font-size="14.00">Type</text>
<text text-anchor="start" x="135" y="-105.8" font-family="Sans" font-style="italic" font-size="14.00">Unique Identifier (For Blocks, A Header Hash)</text>
<text text-anchor="start" x="89" y="-83.8" font-family="Sans" font-size="14.00">Block</text>
<text text-anchor="start" x="148.5" y="-83.8" font-family="Courier,monospace" font-size="14.00">4860eb18bf1b1620...688e9a8300000000</text>
<text text-anchor="start" x="89" y="-62.8" font-family="Sans" font-size="14.00">Block</text>
<text text-anchor="start" x="148.5" y="-62.8" font-family="Courier,monospace" font-size="14.00">bddd99ccfda39da1...065f626a00000000</text>
<text text-anchor="start" x="107.5" y="-42.8" font-family="Sans" font-style="italic" font-size="14.00">...............126 more inventory entries...............</text>
<polygon fill="none" stroke="black" stroke-width="2" points="77,-28 77,-286 462,-286 462,-28 77,-28"/>
</g>
<!-- ibd&#45;&gt;getdata -->
<g id="edge1" class="edge"><title>ibd&#45;&gt;getdata:f1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M54.0518,-272C59.4406,-272 64.8119,-272 69.2213,-272"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="69.5,-275.5 79.5,-272 69.5,-268.5 69.5,-275.5"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="512" y="-275.8" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="512" y="-260.8" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- getdata&#45;&gt;sync -->
<g id="edge2" class="edge"><title>getdata:f1&#45;&gt;sync</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M460.5,-272C460.5,-272 466.72,-272 474.794,-272"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="474.863,-275.5 484.862,-272 474.862,-268.5 474.863,-275.5"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

73
img/dev/en-ibd-inv.dot Normal file
View file

@ -0,0 +1,73 @@
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>Inv 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">inv</font></td>
<td border="1"><i>Size</i><br/><font face="courier">18003</font></td>
<td border="1"><i>Checksum</i><br/><font face="courier">25173c57</font></td>
</tr>
<tr>
<td colspan="4" border="0"><i>Payload</i></td>
</tr>
<tr>
<td colspan="4"><i>Number Of Inventories (Max 500 In Reply To GetBlocks) </i><br /><font face="courier">500</font></td>
</tr>
<tr>
<td colspan="4">
<table border="0">
<tr>
<td colspan="2"><i>Inventory Entries</i></td>
</tr>
<tr>
<td><i>Type</i></td>
<td><i>Unique Identifier (For Blocks, A Header Hash)</i></td>
</tr>
<tr>
<td><font face="courier">block</font></td>
<td><font face="courier">4860eb18bf1b1620...688e9a8300000000</font></td>
</tr>
<tr>
<td><font face="courier">block</font></td>
<td><font face="courier">bddd99ccfda39da1...065f626a00000000</font></td>
</tr>
<tr>
<td colspan="2"><i>...............498 more inventory entries...............</i></td>
</tr>
</table>
</td>
</tr>
</table>>];
label = "First inv message reply sent to Initial Blocks Download (IBD) node"
}

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

65
img/dev/en-ibd-inv.svg Normal file
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="234pt"
viewBox="0.00 0.00 450.00 234.41" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.783972 0.783972) rotate(0) translate(4 295)">
<title>%3</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-295 570,-295 570,4 -4,4"/>
<text text-anchor="middle" x="283" y="-7.8" font-family="Sans" font-size="14.00">First inv 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="-275.8" font-family="Sans" font-size="14.00">IBD</text>
<text text-anchor="middle" x="27" y="-260.8" font-family="Sans" font-size="14.00">Node</text>
</g>
<!-- inv -->
<g id="node2" class="node"><title>inv</title>
<text text-anchor="start" x="232.5" y="-268.8" font-family="Sans" font-weight="bold" font-size="14.00">Inv Message</text>
<text text-anchor="start" x="225.5" y="-245.8" font-family="Sans" font-style="italic" font-size="14.00">Message Header</text>
<polygon fill="none" stroke="black" points="80,-203 80,-237 221,-237 221,-203 80,-203"/>
<text text-anchor="start" x="110.5" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Start String</text>
<text text-anchor="start" x="117" y="-209.8" font-family="Courier,monospace" font-size="14.00">f9beb4d9</text>
<polygon fill="none" stroke="black" points="223,-203 223,-237 327,-237 327,-203 223,-203"/>
<text text-anchor="start" x="240" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Command</text>
<text text-anchor="start" x="262.5" y="-209.8" font-family="Courier,monospace" font-size="14.00">inv</text>
<polygon fill="none" stroke="black" points="329,-203 329,-237 391,-237 391,-203 329,-203"/>
<text text-anchor="start" x="345.5" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Size</text>
<text text-anchor="start" x="339" y="-209.8" font-family="Courier,monospace" font-size="14.00">18003</text>
<polygon fill="none" stroke="black" points="393,-203 393,-237 486,-237 486,-203 393,-203"/>
<text text-anchor="start" x="403" y="-223.8" font-family="Sans" font-style="italic" font-size="14.00">Checksum</text>
<text text-anchor="start" x="406" y="-209.8" font-family="Courier,monospace" font-size="14.00">25173c57</text>
<text text-anchor="start" x="255.5" y="-188.8" font-family="Sans" font-style="italic" font-size="14.00">Payload</text>
<polygon fill="none" stroke="black" points="80,-146 80,-180 486,-180 486,-146 80,-146"/>
<text text-anchor="start" x="86" y="-166.8" font-family="Sans" font-style="italic" font-size="14.00">Number Of Inventories (Max 500 In Reply To GetBlocks) </text>
<text text-anchor="start" x="270.5" y="-152.8" font-family="Courier,monospace" font-size="14.00">500</text>
<polygon fill="none" stroke="black" points="80,-31 80,-144 486,-144 486,-31 80,-31"/>
<text text-anchor="start" x="222.5" y="-126.8" font-family="Sans" font-style="italic" font-size="14.00">Inventory Entries</text>
<text text-anchor="start" x="98.5" y="-105.8" font-family="Sans" font-style="italic" font-size="14.00">Type</text>
<text text-anchor="start" x="156" y="-105.8" font-family="Sans" font-style="italic" font-size="14.00">Unique Identifier (For Blocks, A Header Hash)</text>
<text text-anchor="start" x="94" y="-83.8" font-family="Courier,monospace" font-size="14.00">block</text>
<text text-anchor="start" x="169.5" y="-83.8" font-family="Courier,monospace" font-size="14.00">4860eb18bf1b1620...688e9a8300000000</text>
<text text-anchor="start" x="94" y="-62.8" font-family="Courier,monospace" font-size="14.00">block</text>
<text text-anchor="start" x="169.5" y="-62.8" font-family="Courier,monospace" font-size="14.00">bddd99ccfda39da1...065f626a00000000</text>
<text text-anchor="start" x="120.5" y="-42.8" font-family="Sans" font-style="italic" font-size="14.00">...............498 more inventory entries...............</text>
<polygon fill="none" stroke="black" stroke-width="2" points="77,-28 77,-286 489,-286 489,-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,-272C72.4781,-272 79,-272 79,-272"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="64.0976,-268.5 54.0976,-272 64.0976,-275.5 64.0976,-268.5"/>
</g>
<!-- sync -->
<g id="node3" class="node"><title>sync</title>
<text text-anchor="middle" x="539" y="-275.8" font-family="Sans" font-size="14.00">Sync</text>
<text text-anchor="middle" x="539" y="-260.8" 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="M497.038,-272C501.35,-272 506.609,-272 511.902,-272"/>
<polygon fill="black" stroke="black" stroke-width="1.75" points="497,-268.5 487,-272 497,-275.5 497,-268.5"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -0,0 +1,43 @@
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" ]
subgraph cluster_mainchain {
block0 [ label = "1\n←Parent: 0" ];
block1 [ label = "2\n←Parent: 1" ];
block2 [ label = "3\n←Parent: 2" ];
style = "invis";
}
block0 -> block1 -> block2;
block0 -> block1_1;
block2 -> block5 [ style = "invis", minlen = 4 ];
block1_1 [ label = "2 (Stale)\n←Parent: 1", style = "filled" ];
block5 [ label = "5 (Orphan)\n←Parent: 4", style = "filled" ];
subgraph cluster_toplabel {
node [ style = "invis", height = 0, width = 0, label = "" ];
graph [ penwidth = 0 ];
a -> b -> c -> d -> e -> f -> g [ style = "invis" ];
label = "Orphan blocks have no known parent, so they can't be validated"
}
label = " \nStale blocks are valid but not part of the best block chain"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -0,0 +1,80 @@
<?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.26.3 (20100126.1600)
-->
<!-- Title: _anonymous_0 Pages: 1 -->
<svg width="450pt" height="196pt"
viewBox="0.00 0.00 450.00 195.85" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(0.910931 0.910931) rotate(0) translate(4 211)">
<title>_anonymous_0</title>
<polygon fill="white" stroke="white" points="-4,5 -4,-211 491,-211 491,5 -4,5"/>
<text text-anchor="middle" x="243" y="-25.4" font-family="Sans" font-size="14.00"> </text>
<text text-anchor="middle" x="243" y="-8.4" font-family="Sans" font-size="14.00">Stale blocks are valid but not part of the best block chain</text>
<g id="graph2" class="cluster"><title>cluster_mainchain</title>
</g>
<g id="graph3" class="cluster"><title>cluster_toplabel</title>
<polygon fill="none" stroke="black" stroke-width="0" points="15,-158 15,-199 478,-199 478,-158 15,-158"/>
<text text-anchor="middle" x="246.5" y="-182.4" font-family="Sans" font-size="14.00">Orphan blocks have no known parent, so they can&#39;t be validated</text>
</g>
<!-- block0 -->
<g id="node2" class="node"><title>block0</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="108,-142 16,-142 16,-100 108,-100 108,-142"/>
<text text-anchor="middle" x="62" y="-125.4" font-family="Sans" font-size="14.00">1</text>
<text text-anchor="middle" x="62" y="-108.4" font-family="Sans" font-size="14.00">←Parent: 0</text>
</g>
<!-- block1 -->
<g id="node3" class="node"><title>block1</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="214,-142 122,-142 122,-100 214,-100 214,-142"/>
<text text-anchor="middle" x="168" y="-125.4" font-family="Sans" font-size="14.00">2</text>
<text text-anchor="middle" x="168" y="-108.4" font-family="Sans" font-size="14.00">←Parent: 1</text>
</g>
<!-- block0&#45;&gt;block1 -->
<g id="edge3" class="edge"><title>block0&#45;&gt;block1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M108.185,-121C109.328,-121 110.477,-121 111.627,-121"/>
<polygon fill="black" stroke="black" points="111.977,-124.5 121.977,-121 111.977,-117.5 111.977,-124.5"/>
</g>
<!-- block1_1 -->
<g id="node7" class="node"><title>block1_1</title>
<polygon fill="lightgrey" stroke="black" stroke-width="1.75" points="214,-84 122,-84 122,-42 214,-42 214,-84"/>
<text text-anchor="middle" x="168" y="-67.4" font-family="Sans" font-size="14.00">2 (Stale)</text>
<text text-anchor="middle" x="168" y="-50.4" font-family="Sans" font-size="14.00">←Parent: 1</text>
</g>
<!-- block0&#45;&gt;block1_1 -->
<g id="edge6" class="edge"><title>block0&#45;&gt;block1_1</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M100.568,-99.8966C106.998,-96.3782 113.735,-92.692 120.359,-89.0675"/>
<polygon fill="black" stroke="black" points="122.19,-92.0555 129.283,-84.1849 118.83,-85.9146 122.19,-92.0555"/>
</g>
<!-- block2 -->
<g id="node4" class="node"><title>block2</title>
<polygon fill="none" stroke="black" stroke-width="1.75" points="320,-142 228,-142 228,-100 320,-100 320,-142"/>
<text text-anchor="middle" x="274" y="-125.4" font-family="Sans" font-size="14.00">3</text>
<text text-anchor="middle" x="274" y="-108.4" font-family="Sans" font-size="14.00">←Parent: 2</text>
</g>
<!-- block1&#45;&gt;block2 -->
<g id="edge4" class="edge"><title>block1&#45;&gt;block2</title>
<path fill="none" stroke="black" stroke-width="1.75" d="M214.185,-121C215.328,-121 216.477,-121 217.627,-121"/>
<polygon fill="black" stroke="black" points="217.977,-124.5 227.977,-121 217.977,-117.5 217.977,-124.5"/>
</g>
<!-- block5 -->
<g id="node9" class="node"><title>block5</title>
<polygon fill="lightgrey" stroke="black" stroke-width="1.75" points="476,-142 384,-142 384,-100 476,-100 476,-142"/>
<text text-anchor="middle" x="430" y="-125.4" font-family="Sans" font-size="14.00">5 (Orphan)</text>
<text text-anchor="middle" x="430" y="-108.4" font-family="Sans" font-size="14.00">←Parent: 4</text>
</g>
<!-- block2&#45;&gt;block5 -->
<!-- a -->
<!-- b -->
<!-- a&#45;&gt;b -->
<!-- c -->
<!-- b&#45;&gt;c -->
<!-- d -->
<!-- c&#45;&gt;d -->
<!-- e -->
<!-- d&#45;&gt;e -->
<!-- f -->
<!-- e&#45;&gt;f -->
<!-- g -->
<!-- f&#45;&gt;g -->
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB