<p>Bitcoin Core 0.10.0 may provide the solution you need thanks to its headers-first synchronization.  The <a href="https://bitcoin.org/en/developer-reference#getblockchaininfo" rel="nofollow"><code>getblockchaininfo</code> RPC</a> in 0.10.0 provides both a <code>blocks</code> field (the number of verified blocks) and a <code>headers</code> field (the number of partially-validated headers).</p>

<p>Any time the numbers differ, you don't have all the blocks.  During Initial Block Download (IBD), they'll be hundreds of thousands of blocks apart.  (According to a Wireshark sniff I did during IBD a few weeks ago, it took my node less than two minutes to download a complete headers chain; syncing the blocks then took another three hours.)</p>

<p>Bitcoin Core 0.10.0 has two other new fields you might find useful, both in the <a href="https://bitcoin.org/en/developer-reference#getpeerinfo" rel="nofollow"><code>getpeerinfo</code> RPC</a>.  The fields are <code>synced_headers</code> and <code>synced_blocks</code>.  The headers field is based on the last <a href="https://bitcoin.org/en/developer-reference#headers" rel="nofollow">P2P headers message</a> the remote node sent you.  The blocks field is based on the last <a href="https://bitcoin.org/en/developer-reference#inv" rel="nofollow">P2P block inv message</a> the peer sent you.  In both cases, they let you know the last header or block you have in common with the remote node (as best as can be determined).</p>

<p>I don't know how useful these <code>getpeerinfo</code> fields will be, as your node can't tell you the height of a block until it has the corresponding block header---at which point the <code>getblockchaininfo</code> RPC will already tell you that you're out of sync.  However, they are kinda fun to look at.</p>

<hr>

<blockquote>
  <p>Could I just make multiple getheaders requests and see if the peer returns any headers later than the header I have, or would the peer ban me for requesting the same headers again and again?</p>
</blockquote>

<p>As far as I know, there's no ban score there (as long as your packets are valid).  However, the remote peer should send you an <code>inv</code> message as soon as it validates an incoming block---so there's no need to poll it as long as your app handles <code>inv</code> messages with a MSG_BLOCK type.</p>

CC BY-SA 3.0
2015-01-16T00:45:21.000Z
Is it guaranteed that nodes will send you an `inv` right after they have a new best block every time? Even if you are the one who sent them the new block data?
morsecoder
CC BY-SA 3.0
2015-01-16T01:22:50.587Z
If you send them an `inv`, they shouldn't send you an `inv` for the same data.  Bitcoin Core also won't send `inv`s while they're in IBD.  For all other cases, Bitcoin Core full nodes will send you an `inv` for each new block they validate.  Based on my reading of the 0.10.0 code a few weeks ago, there is no built-in delay (like for tx `inv`s) or network partitioning (like for `addr`s) when it comes to block `inv`s. Of course, nothing is guaranteed on a P2P network.
David A. Harding
CC BY-SA 3.0
2015-01-16T02:29:31.793Z
Doesn't the bitcoin method depend on using headers first synchronization? The fields added to `getpeerinfo` may be just what I need. False negatives (reporting that the node is not sufficiently caught up to handle requests when they actually are) are fine, it's false positives that would be the real kicker. I think the methods in the new `getpeerinfo` should meet those requirements. So, thanks!
morsecoder
CC BY-SA 3.0
2015-01-16T02:48:38.417Z
Yes, headers first is required, which is why only 0.10.0 has that field.  Note that it works the same whether or not the remote node uses headers first (0.10.0 won't connect to nodes that don't support the P2P headers/getheaders messages, which were introduced in December 2010).  I'd think the headers field from `getblockchaininfo` would be more useful because it has the height of the highest of your peer connections (so you don't need to iterate over each connection).
David A. Harding
CC BY-SA 3.0
2015-01-16T03:46:03.053Z
Yes, it probably would be a faster response time and more useful, but we are working with coins other than just Bitcoin (Lite, Doge, etc), and we need the sync check for all of them. Implementing headers first synchronization in all these coins probably isn't doable in the time frame.
morsecoder
CC BY-SA 3.0
2015-01-16T00:15:00.390Z
2015-01-16T00:15:00.390Z
David A. Harding
<p>Context:</p>

<p>I'm working on an application in which we'd like to know if the current node is sufficiently synced to be able to handle RPC requests. The method we would like to use is to see if our node has at least 2-4 peers and if a majority of the peers are reporting the same best height / best block hash.</p>

<hr/>

<p>Previous research: </p>

<ul>
<li>I know the <code>version</code> network call gets the height of the peer at that time, but it isn't updated. In addition, any further <code>version</code> requests result in an increase of the ban score of a node, so this cannot be used frequently.</li>
<li><a href="https://github.com/bitcoinj/bitcoinj/blob/cd7dc3e535a06d10c010aa63d20ffeab294dd61b/core/src/main/java/org/bitcoinj/core/PeerGroup.java#L1737-L1743" rel="nofollow noreferrer">Bitcoinj</a> keeps track of the height of the best known peer by using the height given in the version message and then incrementing whenever the peer processes an <code>inv</code> message showing they have a new best-block height. This seems fast, but tricky/error prone.</li>
<li><a href="https://bitcoin.stackexchange.com/questions/32578/would-it-be-possible-to-add-an-rpc-call-to-be-able-to-determine-if-a-node-is-ful">This question</a> is similar, but it asks about how to do this with RPC calls, and it doesn't seem to want to use the same method for determining whether the node is synced as the one I've proposed.</li>
<li><a href="https://bitcoin.stackexchange.com/questions/32578/would-it-be-possible-to-add-an-rpc-call-to-be-able-to-determine-if-a-node-is-ful">This question</a> helped provide a temporary solution (calling get work and seeing if it fails), but this method is not accurate enough.</li>
</ul>

<hr/>

<p>Is there a way to just ask a peer what the height of its best block is without getting banned? </p>

<p>Could I just make multiple <code>getheaders</code> requests and see if the peer returns any headers later than the header I have, or would the peer ban me for requesting the same headers again and again?</p>

<network><synchronization><height>
How to determine custom synchronization status?
morsecoder
# How to determine custom synchronization status?

(Asked by: username_0 on 2015-01-15)

Context:

I'm working on an application in which we'd like to know if the current node is sufficiently synced to be able to handle RPC requests. The method we would like to use is to see if our node has at least 2-4 peers and if a majority of the peers are reporting the same best height / best block hash.

---

Previous research:

* I know the `version` network call gets the height of the peer at that time, but it isn't updated. In addition, any further `version` requests result in an increase of the ban score of a node, so this cannot be used frequently.
* [Bitcoinj](https://github.com/bitcoinj/bitcoinj/blob/cd7dc3e535a06d10c010aa63d20ffeab294dd61b/core/src/main/java/org/bitcoinj/core/PeerGroup.java#L1737-L1743) keeps track of the height of the best known peer by using the height given in the version message and then incrementing whenever the peer processes an `inv` message showing they have a new best-block height. This seems fast, but tricky/error prone.
* [This question](https://bitcoin.stackexchange.com/questions/32578/would-it-be-possible-to-add-an-rpc-call-to-be-able-to-determine-if-a-node-is-ful) is similar, but it asks about how to do this with RPC calls, and it doesn't seem to want to use the same method for determining whether the node is synced as the one I've proposed.
* [This question](https://bitcoin.stackexchange.com/questions/32578/would-it-be-possible-to-add-an-rpc-call-to-be-able-to-determine-if-a-node-is-ful) helped provide a temporary solution (calling get work and seeing if it fails), but this method is not accurate enough.

---

Is there a way to just ask a peer what the height of its best block is without getting banned?

Could I just make multiple `getheaders` requests and see if the peer returns any headers later than the header I have, or would the peer ban me for requesting the same headers again and again?

**Tags:** network, synchronization, height


---

## 1 answers

### Answer by username_1 on 2015-01-16. Score: 3 | Accepted answer

Bitcoin Core 0.10.0 may provide the solution you need thanks to its headers-first synchronization. The [`getblockchaininfo` RPC](https://bitcoin.org/en/developer-reference#getblockchaininfo) in 0.10.0 provides both a `blocks` field (the number of verified blocks) and a `headers` field (the number of partially-validated headers).

Any time the numbers differ, you don't have all the blocks. During Initial Block Download (IBD), they'll be hundreds of thousands of blocks apart. (According to a Wireshark sniff I did during IBD a few weeks ago, it took my node less than two minutes to download a complete headers chain; syncing the blocks then took another three hours.)

Bitcoin Core 0.10.0 has two other new fields you might find useful, both in the [`getpeerinfo` RPC](https://bitcoin.org/en/developer-reference#getpeerinfo). The fields are `synced_headers` and `synced_blocks`. The headers field is based on the last [P2P headers message](https://bitcoin.org/en/developer-reference#headers) the remote node sent you. The blocks field is based on the last [P2P block inv message](https://bitcoin.org/en/developer-reference#inv) the peer sent you. In both cases, they let you know the last header or block you have in common with the remote node (as best as can be determined).

I don't know how useful these `getpeerinfo` fields will be, as your node can't tell you the height of a block until it has the corresponding block header---at which point the `getblockchaininfo` RPC will already tell you that you're out of sync. However, they are kinda fun to look at.

---

> Could I just make multiple getheaders requests and see if the peer returns any headers later than the header I have, or would the peer ban me for requesting the same headers again and again?

As far as I know, there's no ban score there (as long as your packets are valid). However, the remote peer should send you an `inv` message as soon as it validates an incoming block---so there's no need to poll it as long as your app handles `inv` messages with a MSG\_BLOCK type.

> **Comments:**
> **username_0**: Is it guaranteed that nodes will send you an `inv` right after they have a new best block every time? Even if you are the one who sent them the new block data?  
> **username_1**: If you send them an `inv`, they shouldn't send you an `inv` for the same data.  Bitcoin Core also won't send `inv`s while they're in IBD.  For all other cases, Bitcoin Core full nodes will send you an `inv` for each new block they validate.  Based on my reading of the 0.10.0 code a few weeks ago, there is no built-in delay (like for tx `inv`s) or network partitioning (like for `addr`s) when it comes to block `inv`s. Of course, nothing is guaranteed on a P2P network.  
> **username_0**: Doesn't the bitcoin method depend on using headers first synchronization? The fields added to `getpeerinfo` may be just what I need. False negatives (reporting that the node is not sufficiently caught up to handle requests when they actually are) are fine, it's false positives that would be the real kicker. I think the methods in the new `getpeerinfo` should meet those requirements. So, thanks!  
> **username_1**: Yes, headers first is required, which is why only 0.10.0 has that field.  Note that it works the same whether or not the remote node uses headers first (0.10.0 won't connect to nodes that don't support the P2P headers/getheaders messages, which were introduced in December 2010).  I'd think the headers field from `getblockchaininfo` would be more useful because it has the height of the highest of your peer connections (so you don't need to iterate over each connection).  
> **username_0**: Yes, it probably would be a faster response time and more useful, but we are working with coins other than just Bitcoin (Lite, Doge, etc), and we need the sync check for all of them. Implementing headers first synchronization in all these coins probably isn't doable in the time frame.  

---

