From 2304a52d4ff59a45336b65d95efa13be788bb332 Mon Sep 17 00:00:00 2001 From: thephez Date: Tue, 24 Apr 2018 10:53:32 -0400 Subject: [PATCH] [Content] - P2P - Compact block addition (#64) * content - Add compact block inventory * content - p2p - Compact Block messages - Start adding `blocktxn`, `cmpctblock`, `getblocktxn`, and `sendcmpct` messages - blocktxn and getblocktxn description and format added - Placeholders for cmpctblock and sendcmpct * content - p2p - Sendcmpct message - Add details of `sendcmpct` including hex dump * content - p2p - CmpctBlock message - Add hexdump - Update description * content - Minor formatting updates * content - p2p - Update control and data message drawings - Add compact block related commands * content - p2p - Update compact block messages - Add info about protocol version when implemented - Add info to cmpctblock * content - p2p - Update compact block messages - Add some info from bitcoin-dot-org/bitcoin.org#2092 - Add detail to cmpctblock, sendcmpct, getblocktxn, blocktxn messages - Add reference terms * content - p2p - Comment out blocktxn and getblocktxn hexdump for now Closes #59 --- _autocrossref.yaml | 8 + _includes/devdoc/ref_p2p_networking.md | 255 ++++++++++++++++++++++++- _includes/references.md | 9 + img/dev/en-p2p-control-messages.dot | 2 + img/dev/en-p2p-control-messages.png | Bin 4863 -> 8533 bytes img/dev/en-p2p-control-messages.svg | 75 ++++---- img/dev/en-p2p-data-messages.dot | 2 + img/dev/en-p2p-data-messages.png | Bin 7637 -> 24436 bytes img/dev/en-p2p-data-messages.svg | 142 +++++++------- 9 files changed, 391 insertions(+), 102 deletions(-) diff --git a/_autocrossref.yaml b/_autocrossref.yaml index bd7b88bd..ac1ba50c 100644 --- a/_autocrossref.yaml +++ b/_autocrossref.yaml @@ -20,7 +20,11 @@ bitcoin QR codes: URI QR code bitcoinj: '`block` message': block message '`block` messages': block message +'`blocktxn` message': blocktxn message +'`blocktxn` messages': blocktxn message certificate chain: +'`cmpctblock` message': cmpctblock message +'`cmpctblock` messages': cmpctblock message DER: DER format: der DER-formatted: der @@ -57,6 +61,8 @@ fiat: '`filterload` messages': filterload message '`getblocks` message': getblocks message '`getblocks` messages': getblocks message +'`getblocktxn` message': getblocktxn message +'`getblocktxn` messages': getblocktxn message '`getdata` message': getdata message '`getdata` messages': getdata message '`getheaders` message': getheaders message @@ -172,6 +178,8 @@ RPC: RPCs: rpc '`script`': DO NOT AUTOCROSSREF secp256k1: +'`sendcmpct` message': sendcmpct message +'`sendcmpct` messages': sendcmpct message '`spork` message': spork message '`spork` messages': spork message '`ssc` message': ssc message diff --git a/_includes/devdoc/ref_p2p_networking.md b/_includes/devdoc/ref_p2p_networking.md index 0b56aa95..62448ada 100644 --- a/_includes/devdoc/ref_p2p_networking.md +++ b/_includes/devdoc/ref_p2p_networking.md @@ -172,8 +172,9 @@ The currently-available type identifiers are: | 17 | [`MSG_GOVERNANCE_OBJECT`][msg_governance_object]{:#term-msg_governance_object}{:.term} | The hash is a Governance Object. | 18 | [`MSG_GOVERNANCE_OBJECT_VOTE`][msg_governance_object_vote]{:#term-msg_governance_object_vote}{:.term} | The hash is a Governance Object Vote. | 19 | [`MSG_MASTERNODE_VERIFY`][msg_masternode_verify]{:#term-msg_masternode_verify}{:.term} | The hash is a Masternode Verify. +| 20 | [`MSG_CMPCT_BLOCK`][msg_cmpct_block]{:#term-msg_cmpct_block}{:.term} | The hash is of a block header; identical to `MSG_BLOCK`. When used in a `getdata` message, this indicates the response should be a `cmpctblock` message. **Only for use in `getdata` messages.** -Type identifier zero and type identifiers greater than nineteen are reserved +Type identifier zero and type identifiers greater than twenty are reserved for future implementations. Dash Core ignores all inventories with one of these unknown types. @@ -202,6 +203,166 @@ different reasons: {% endautocrossref %} +#### Blocktxn +{% include helpers/subhead-links.md %} + +{% autocrossref %} + +*Added in protocol version 70209 of Dash Core as described by BIP152* + +The `blocktxn` message sends requested block transactions to a node which +previously requested them with a `getblocktxn` message. It is defined as a message +containing a serialized `BlockTransactions` message. + +Upon receipt of a properly-formatted requested `blocktxn` message, nodes should: + +1. Attempt to reconstruct the full block by taking the prefilledtxn transactions from the original `cmpctblock` message and placing them in the marked positions +2. For each short transaction ID from the original `cmpctblock` message, in order, find the corresponding transaction (from either the `blocktxn` message or from other sources) +3. Place each short transaction ID in the first available position in the block +4. Once the block has been reconstructed, it shall be processed as normal. + +**Short transaction IDs are expected to occasionally collide. Nodes must +not be penalized for such collisions.** + +The structure of `BlockTransactions` is defined below. + +| Bytes | Name | Data Type | Encoding | Description| +|----------|----------------------|----------------------|----------|------------| +| 32 | blockhash | Binary blob | The output from a double-SHA256 of the block header, as used elsewhere | The blockhash of the block which the transactions being provided are in +| 1 or 3 | transactions
_length | CompactSize | As used to encode array lengths elsewhere | The number of transactions provided +| *Varies* | transactions | List of transactions | As encoded in `tx` messages in response to `getdata MSG_TX` | The transactions provided + + + +{% endautocrossref %} + +#### CmpctBlock +{% include helpers/subhead-links.md %} + +{% autocrossref %} + +*Added in protocol version 70209 of Dash Core as described by BIP152* + +The `cmpctblock` message is a reply to a `getdata` message which +requested a block using the inventory type `MSG_CMPCT_BLOCK`. If the +requested block was recently announced and is close to the tip of the +best chain of the receiver and after having sent the requesting peer +a `sendcmpct` message, nodes respond with a `cmpctblock` message containing +data for the block. + +**If the requested block is too old, the node responds with a *full non-compact block*** + +Upon receipt of a `cmpctblock` message, after sending a `sendcmpct` message, +nodes should calculate the short transaction ID for each unconfirmed +transaction they have available (i.e. in their mempool) and compare each +to each short transaction ID in the `cmpctblock` message. After finding +already-available transactions, nodes which do not have all transactions +available to reconstruct the full block should request the missing transactions +using a `getblocktxn` message. + +A node must not send a `cmpctblock` message unless they are able to respond to +a `getblocktxn` message which requests every transaction in the block. A node +must not send a `cmpctblock` message without having validated that the header properly +commits to each transaction in the block, and properly builds on top of the existing, +fully-validated chain with a valid proof-of-work either as a part of the current most-work +valid chain, or building directly on top of it. A node may send a `cmpctblock` message before +validating that each transaction in the block validly spends existing UTXO set entries. + +The `cmpctblock` message contains a vector of `PrefilledTransaction` whose +structure is defined below. A `PrefilledTransaction` is used in `HeaderAndShortIDs` +to provide a list of a few transactions explicitly. + +| Bytes | Name | Data Type | Encoding | Description| +|----------|----------------------|----------------------|----------|------------| +| 1 or 3 | index | CompactSize | Compact Size, differentially encoded since the last PrefilledTransaction in a list | The index into the block at which this transaction is +| *Varies* | tx | Transaction | As encoded in `tx` messages sent in response to `getdata MSG_TX` | Transaction which is in the block at index `index` + +The `cmpctblock` message is compromised of a serialized `HeaderAndShortIDs` +structure which is defined below. A `HeaderAndShortIDs` structure is used to +relay a block header, the short transactions IDs used for matching +already-available transactions, and a select few transactions which +we expect a peer may be missing. + +| Bytes | Name | Data Type | Encoding | Description| +|----------|----------------------|----------------------|----------|------------| +| 80 | header | Block header | First 80 bytes of the block as defined by the encoding used by `block` messages | The header of the block being provided +| 8 | nonce | uint64_t | Little Endian | A nonce for use in short transaction ID calculations +| 1 or 3 | shortids_
length | CompactSize | As used to encode array lengths elsewhere | The number of short transaction IDs in `shortids` (i.e. block tx count - `prefilledtxn`
`_length`) +| *Varies* | shortids | List of 6-byte integers | Little Endian | The short transaction IDs calculated from the transactions which were not provided explicitly in `prefilledtxn` +| 1 or 3 | prefilledtxn
_length | CompactSize | As used to encode array lengths elsewhere | The number of prefilled transactions in `prefilledtxn` (i.e. block tx count - `shortids`
`_length`) +| *Varies* | prefilledtxn | List of Prefilled
Transactions | As defined by `Prefilled`
`Transaction` definition below | Used to provide the coinbase transaction and a select few which we expect a peer may be missing + +**Short Transaction ID calculation** + +Short transaction IDs are used to represent a transaction without sending a full 256-bit hash. They are calculated as follows, + +* A single-SHA256 hashing the block header with the nonce appended (in little-endian) +* Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) set to the first two little-endian 64-bit integers from the above hash, respectively. +* Dropping the 2 most significant bytes from the SipHash output to make it 6 bytes. + + +The following annotated hexdump shows a `cmpctblock` message. (The +message header has been omitted.) + +{% highlight text %} +00000020981178a4342cec6316296b2ad84c9b7cdf9f +2688e5d0fe1a0003cd0000000000f64870f52a3d0125 +1336c9464961216732b25fbf288a51f25a0e81bffb20 +e9600194d85a64a50d1cc02b0181 ................ Block Header + +3151b67e5b418b9d ............................ Nonce + +00 .......................................... Short IDs Length: 0 +............................................. Short IDs: None + +01 .......................................... Prefilled Transaction Length: 1 + +Prefilled Transactions +| 00 ........................................ Index: 0 +| +| Transaction 1 (Coinbase) +| | 01000000 ................................ Transaction Version: 1 +| | 01 ...................................... Input count: 1 +| | +| | Transaction input #1 +| | | +| | | 00000000000000000000000000000000 +| | | 00000000000000000000000000000000 ..... Outpoint TXID +| | | ffffffff ............................. Outpoint index number: UINT32_MAX +| | | +| | | 13 ................................... Bytes in sig. script: 19 +| | | 03daaf010e2f5032506f6f6c2d74444153482f Secp256k1 signature +| | | +| | | ffffffff ............................. Sequence number: UINT32_MAX +| | +| | 04 ..................................... Number of outputs: 04 +| | +| | Transaction output #1 +| | | ffe5654200000000 ..................... Duffs (11.13974271 Dash) +| | | +| | | 19 ................................... Bytes in pubkey script: 25 +| | | | 76 ................................. OP_DUP +| | | | a9 ................................. OP_HASH160 +| | | | 14 ................................. Push 20 bytes as data +| | | | | b885cb21ad12e593c1a46d814df47ccb +| | | | | 450a7d84 ......................... PubKey hash +| | | | 88 ................................. OP_EQUALVERIFY +| | | | ac ................................. OP_CHECKSIG +| | +| | [...] .................................. 3 more tx outputs omitted +| | +| | 00000000 ............................... locktime: 0 (a block height) +{% endhighlight %} + +{% endautocrossref %} + #### GetBlocks {% include helpers/subhead-links.md %} @@ -254,6 +415,44 @@ d39f608a7775b537729884d4e6633bb2 {% endautocrossref %} +#### GetBlockTxn +{% include helpers/subhead-links.md %} + +{% autocrossref %} + +*Added in protocol version 70209 of Dash Core as described by BIP152* + +The `getblocktxn` message requests a `blocktxn` message for any transactions +that it has not seen after a compact block is received. It is defined as a +message containing a serialized `BlockTransactionsRequest` message. Upon receipt +of a properly-formatted `getblocktxn` message, nodes which recently provided the +sender of such a message with a `cmpctblock` message for the block hash +identified in this message must respond with either an appropriate +`blocktxn` message, or a full block message. + +A `blocktxn` message response must contain exactly and only each transaction +which is present in the appropriate block at the index specified in the +`getblocktxn` message indexes list, in the order requested. + +The structure of `BlockTransactionsRequest` is defined below. + +| Bytes | Name | Data Type | Encoding | Description| +|----------|-----------------|----------------------|----------|------| +| 32 | blockhash | Binary blob | The output from a double-SHA256 of the block header, as used elsewhere | The blockhash of the block which the transactions being requested are in +| *Varies* | indexes_length | CompactSize uint | As used to encode array lengths elsewhere | The number of transactions requested +| *Varies* | indexes | CompactSize uint[] | Differentially encoded | Vector of compactSize containing the indexes of the transactions being requested in the block. + + + +{% endautocrossref %} + #### GetData {% include helpers/subhead-links.md %} @@ -266,7 +465,7 @@ node typically previously received by way of an `inv` message. The response to a `getdata` message can be a `tx` message, `block` message, `merkleblock` message, `ix` message, `txlvote` message, `mnw` message, `mnb` message, `mnp` message, `dstx` message, `govobj` message, -`govobjvote` message, `mnv` message, or `notfound` message. +`govobjvote` message, `mnv` message, `notfound` message, or `cmpctblock` message. This message cannot be used to request arbitrary data, such as historic transactions no longer in the memory pool or relay set. Full nodes may @@ -1289,6 +1488,57 @@ header has been omitted.) {% endautocrossref %} +#### SendCmpct +{% include helpers/subhead-links.md %} + +{% autocrossref %} + +*Added in protocol version 70209 of Dash Core as described by BIP152* + +The `sendcmpct` message tells the receiving peer whether or not to announce new +blocks using a `cmpctblock` message. It also sends the compact block protocol +version it supports. The `sendcmpct` message is defined as a message containing +a 1-byte integer followed by a 8-byte integer. The first integer is interpreted +as a boolean and should have a value of either 1 or 0. The second integer +is be interpreted as a little-endian version number. + +Upon receipt of a `sendcmpct` message with the first and second integers +set to 1, the node should announce new blocks by sending a `cmpctblock` message. + +Upon receipt of a `sendcmpct` message with the first integer set to 0, the node +shouldn't announce new blocks by sending a `cmpctblock` message, but instead announce +new blocks by sending invs or headers, as defined by [BIP130][]. + +Upon receipt of a `sendcmpct` message with the second integer set to something +other than 1, nodes should treat the peer as if they had not received the message +(as it indicates the peer will provide an unexpected encoding in `cmpctblock` messages, +and/or other, messages). This allows future versions to send duplicate +`sendcmpct` messages with different versions as a part of a version handshake. + +Nodes should check for a protocol version of >= 70209 before sending `sendcmpct` +messages. Nodes shouldn't send a request for a `MSG_CMPCT_BLOCK` object to a peer +before having received a `sendcmpct` message from that peer. Nodes shouldn't +request a `MSG_CMPCT_BLOCK` object before having sent all `sendcmpct` messages +to that peer which they intend to send, as the peer cannot know what protocol +version to use in the response. + +The structure of a `sendcmpct` message is defined below. + +| Bytes | Name | Data Type | Description +|----------|---------------|------------------|-------------- +| 1 | announce | bool | 0 - Announce blocks via `headers` message or `inv` message
1 - Announce blocks via `cmpctblock` message +| 8 | version | uint64_t | The compact block protocol version number + +The annotated hexdump below shows a `sendcmpct` message. (The message +header has been omitted.) + +{% highlight text %} +01 ................................. Block announce type: Compact Blocks +0100000000000000 ................... Compact block version: 1 +{% endhighlight %} + +{% endautocrossref %} + #### SendHeaders {% include helpers/subhead-links.md %} @@ -1302,7 +1552,6 @@ section][section message header] for an example of a message without a payload. {% endautocrossref %} - #### Spork {% include helpers/subhead-links.md %} diff --git a/_includes/references.md b/_includes/references.md index 10a9c515..e602cc5f 100644 --- a/_includes/references.md +++ b/_includes/references.md @@ -4,8 +4,11 @@ http://opensource.org/licenses/MIT. {% endcomment %} {% comment %}{% endcomment %} +[blocktransactions]: /en/developer-reference#blocktxn "A P2P Networking data structure used to provide some of the transactions in a block as requested" +[blocktransactionsrequest]: /en/developer-reference#getblocktxn "A P2P Networking data structure used to list transaction indexes in a block being requested by a peer" [coinbase block height]: /en/developer-reference#term-coinbase-block-height "The current block's height encoded into the first bytes of the coinbase field" [data-pushing opcode]: https://en.bitcoin.it/wiki/Script#Constants "Any opcode from 0x01 to 0x4e which pushes data on to the script evaluation stack" +[headerandshortids]: /en/developer-reference#cmpctblock "A P2P Networking data structure used to relay a block header, the short transactions IDs used for matching already-available transactions, and a select few transactions which a peer may be missing" [key index]: /en/developer-guide#term-key-index "An index number used in the HD wallet formula to generate child keys from a parent key" [key pair]: /en/developer-guide#term-key-pair "A private key and its derived public key" @@ -29,6 +32,7 @@ http://opensource.org/licenses/MIT. [msg_governance_object]: /en/developer-reference#term-msg_governance_object "Governance object data type identifier of an inventory on the P2P network" [msg_governance_object_vote]: /en/developer-reference#term-msg_governance_object_vote "Governance object vote data type identifier of an inventory on the P2P network" [msg_masternode_verify]: /en/developer-reference#term-msg_masternode_verify "Masternode Verify data type identifier of an inventory on the P2P network" +[msg_cmpct_block]: /en/developer-reference#term-msg_cmpct_block "An alternative to the block header hash data type identifier of an inventory on the P2P network used to request a compact block" [network]: /en/developer-guide#term-network "The Dash P2P network which broadcasts transactions and blocks" [op_checkmultisig]: /en/developer-reference#term-op-checkmultisig "Opcode which returns true if one or more provided signatures (m) sign the correct parts of a transaction and match one or more provided public keys (n)" @@ -41,6 +45,7 @@ http://opensource.org/licenses/MIT. [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)" [output index]: /en/developer-guide#term-output-index "The sequentially-numbered index of outputs in a single transaction starting from 0" [point function]: /en/developer-guide#term-point-function "The ECDSA function used to create a public key from a private key" +[prefilledtransaction]: /en/developer-reference#cmpctblock "A P2P Networking data structure used to represent a vector of a few transactions" [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" [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" [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" @@ -205,6 +210,8 @@ http://opensource.org/licenses/MIT. [addr message]: /en/developer-reference#addr "The P2P network message which relays IP addresses and port numbers of active nodes to other nodes and clients, allowing decentralized peer discovery." [alert message]: /en/developer-reference#alert "The P2P network message which sends alerts in case of major software problems." [block message]: /en/developer-reference#block "The P2P network message which sends a serialized block" +[blocktxn message]: /en/developer-reference#blocktxn "The P2P network message which sends a list of requested transactions from a compact block" +[cmpctblock message]: /en/developer-reference#cmpctblock "The P2P network message which sends a serialized compact block" [dsa message]: /en/developer-reference#dsa "A P2P network message used to join a mixing pool" [dsc message]: /en/developer-reference#dsc "A P2P network message used to indicates a PrivateSend mixing session is complete" [dsf message]: /en/developer-reference#dsf "A P2P network message sent as the final mixing transaction in a session asking users to sign the final mixing TX messages" @@ -220,6 +227,7 @@ http://opensource.org/licenses/MIT. [filterload message]: /en/developer-reference#filterclear "A P2P protocol message used to send a filter to a remote peer, requesting that they only send transactions which match the filter." [getaddr message]: /en/developer-reference#getaddr "A P2P protool message used to request an addr message containing connection information for other nodes" [getblocks message]: /en/developer-reference#getblocks "A P2P protocol message used to request an inv message containing a range of block header hashes" +[getblocktxn message]: /en/developer-reference#getblocktxn "A P2P protocol message used to request transactions from a compact block" [getdata message]: /en/developer-reference#getdata "A P2P protocol message used to request one or more transactions, blocks, or merkle blocks" [getheaders message]: /en/developer-reference#getheaders "A P2P protocol message used to request a range of block headers" [getsporks message]: /en/developer-reference#getsporks "A P2P network message used to request the status of sporks" @@ -240,6 +248,7 @@ http://opensource.org/licenses/MIT. [ping message]: /en/developer-reference#ping "A P2P network message used to see if the remote host is still connected" [pong message]: /en/developer-reference#pong "A P2P network message used to reply to a P2P network ping message" [reject message]: /en/developer-reference#reject "A P2P network message used to indicate a previously-received message was rejected for some reason" +[sendcmpct message]: /en/developer-reference#sendcmpct "A P2P network message used to request new blocks be announced as compact blocks" [sendheaders message]: /en/developer-reference#sendheaders "A P2P network message used to request new blocks be announced through headers messages rather than inv messages" [spork message]: /en/developer-reference#spork "A P2P network message used to send the activation status of a spork" [ssc message]: /en/developer-reference#ssc "A P2P network message used to track the sync status of masternode objects ()" diff --git a/img/dev/en-p2p-control-messages.dot b/img/dev/en-p2p-control-messages.dot index ddb35231..2c9e41c1 100644 --- a/img/dev/en-p2p-control-messages.dot +++ b/img/dev/en-p2p-control-messages.dot @@ -22,6 +22,8 @@ sendheaders; ERROR [ style = "invis" ]; ERROR -> reject [ style = "invis" ]; +sendcmpct; + label = " \nOverview Of P2P Protocol Control And Advisory Messages" } diff --git a/img/dev/en-p2p-control-messages.png b/img/dev/en-p2p-control-messages.png index f9b69d2c7425f24ad69b33c0a6d52dd27196b935..8443f697c6b6e66f45218f8bb511a15223dcfb6a 100644 GIT binary patch literal 8533 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 W*_doM!K$|}dw>Q^N2N*$5&mB`MJ_V{ diff --git a/img/dev/en-p2p-control-messages.svg b/img/dev/en-p2p-control-messages.svg index eab70122..d603fbac 100644 --- a/img/dev/en-p2p-control-messages.svg +++ b/img/dev/en-p2p-control-messages.svg @@ -4,94 +4,99 @@ - - + + %3 - - -Overview Of P2P Protocol Control And Advisory Messages + + +Overview Of P2P Protocol Control And Advisory Messages version - -version + +version verack - -verack + +verack version->verack - + ping - -ping + +ping pong - -pong + +pong ping->pong - + getaddr - -getaddr + +getaddr addr - -addr + +addr getaddr->addr - + filterload - -filterload + +filterload filteradd - -filteradd + +filteradd filterload->filteradd - + filterclear - -filterclear + +filterclear filterload->filterclear - + alert - -alert + +alert sendheaders - -sendheaders + +sendheaders reject - -reject + +reject + +sendcmpct + +sendcmpct + diff --git a/img/dev/en-p2p-data-messages.dot b/img/dev/en-p2p-data-messages.dot index 7f9fd575..2e47a418 100644 --- a/img/dev/en-p2p-data-messages.dot +++ b/img/dev/en-p2p-data-messages.dot @@ -10,6 +10,8 @@ edge [ penwidth = 1.75, fontname="Sans", dir="none" ] node [ penwidth = 1.75, shape = "box", fontname="Sans", ] graph [ penwidth = 1.75, fontname="Sans" ] +getblocktxn -> blocktxn [ minlen = 3 ]; + getblocks -> inv; mempool -> inv; diff --git a/img/dev/en-p2p-data-messages.png b/img/dev/en-p2p-data-messages.png index 7b54c6959f66356bc7adcf3ca98544def20488ab..39ada9342adfe9a875d97cf826f722aa4139a007 100644 GIT binary patch literal 24436 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 literal 7637 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 diff --git a/img/dev/en-p2p-data-messages.svg b/img/dev/en-p2p-data-messages.svg index d7ce75f6..73699941 100644 --- a/img/dev/en-p2p-data-messages.svg +++ b/img/dev/en-p2p-data-messages.svg @@ -1,117 +1,131 @@ - - - - -_anonymous_0 - -Overview Of P2P Protocol Data Request And Reply Messages + + + +%3 + +Overview Of P2P Protocol Data Request And Reply Messages + +getblocktxn + +getblocktxn + + +blocktxn + +blocktxn + + +getblocktxn->blocktxn + + -getblocks - -getblocks +getblocks + +getblocks -inv - -inv +inv + +inv getblocks->inv - + -getdata - -getdata +getdata + +getdata -inv->getdata - +inv->getdata + -mempool - -mempool +mempool + +mempool -mempool->inv - +mempool->inv + -tx - -tx +tx + +tx -getdata->tx - +getdata->tx + -block - -block +block + +block -getdata->block - +getdata->block + -merkleblock - -merkleblock +merkleblock + +merkleblock -getdata->merkleblock - +getdata->merkleblock + -notfound - -notfound +notfound + +notfound -getdata->notfound - +getdata->notfound + -getheaders - -getheaders +getheaders + +getheaders -headers - -headers +headers + +headers -getheaders->headers - +getheaders->headers + -label1 -Request For Help -Getting Up To Date +label1 +Request For Help +Getting Up To Date -label2 -Reply With -Inventory +label2 +Reply With +Inventory -label3 -Request For Specific Data +label3 +Request For Specific Data -label4 -Reply With -Requested Data +label4 +Reply With +Requested Data