New RPC "ping" command to request ping. Implemented "pong" message handler. New "pingtime" field in getpeerinfo, to provide results to user.
Added ping time measurement. #2937
pull Krellan wants to merge 1 commits into bitcoin:master from Krellan:ping changing 6 files +131 −4-
Krellan commented at 1:18 AM on August 25, 2013: contributor
-
Krellan commented at 1:39 AM on August 25, 2013: contributor
We've been having a fine discussion here: https://bitcointalk.org/index.php?topic=279652.0
-
jgarzik commented at 2:28 AM on August 25, 2013: contributor
Seems like an awful lot of code for one simple feature... no technical objection but... meh. I would rather a simple hook system (boost signals?) that delivers a pong response, to anyone who pre-registers a pong handler for nonce X. That would keep most of the code more in the RPC side of things.
-
Krellan commented at 9:40 AM on August 25, 2013: contributor
Thanks for the feedback. It did end up being more code than I thought it would. Reason is, there's 3 different protocol variations to contend with (no nonce, zero nonce, matching nonce). Also, there was no pong receiver at all, so had to add that as well.
I added a good amount of debug text in "if (fDebug) ..." blocks, which is rather verbose. I'm surprised there's no dprintf() or similar macro, perhaps there's something I missed. Every debug line adds another possible code path, because of that if statement. Probably the lowest-hanging fruit is to jettison those.
I wonder how a hook system would work? Registering a handler would seem to complicate things even more. The ping and pong messages have to be sent/received anyway, that would just add another layer of indirection to shift the processing elsewhere, unless there's something I'm missing here.
-
in src/main.cpp:None in dcb99a747d outdated
3868 | + bAcceptable = true; 3869 | + if (fDebug) { 3870 | + printf("pong %s: Recv %"PRI64x", complete\n", pfrom->addrName.c_str(), nonce); 3871 | + } 3872 | + } 3873 | + else if (0 == nonce) {
sipa commented at 2:08 PM on August 25, 2013:I think this should only be accepted if the negotiated protocol version (pnode->nVersion, AFAIK) is below BIP0031_VERSION (60000).
EDIT: Wait, pong itself was only added in BIP0031.Which clients do reply with a 0 nonce? That sounds buggy...
in src/net.h:None in dcb99a747d outdated
276 | @@ -268,6 +277,12 @@ class CNode 277 | fRelayTxes = false; 278 | setInventoryKnown.max_size(SendBufferSize() / 1000); 279 | pfilter = new CBloomFilter(); 280 | + nPingNonceQueued = 0; 281 | + nPingNonceSent = 0;
sipa commented at 2:35 PM on August 25, 2013:Indentation.
sipa commented at 2:40 PM on August 25, 2013: memberACK.
It's perhaps slightly over-complicated (rate-limiting user-requested pings?), but it's otherwise pretty much how I'd have suggested implementing it.
One nit: the ping RPC command could be a separate commit from the rest of the logic, but I don't feel strongly about this.
Krellan commented at 12:51 AM on August 26, 2013: contributorThanks for the feedback.
I will remove the ratelimit for user-requested outbound pings, since you're right, that does seem rather overcomplicated.
Also, good catch on indentation, I didn't see that. Darn editor :)
It is strange to see a ping with a valid nonce be replied to with a pong with a nonce of 0. However, this is very common on the wire, I have noticed. I looked through the history but could not find it. I'm guessing it's another implementation that has this bug?
I like the idea of only accepting these weird pong replies (nonce of zero) if that implementation can be detected. What distinguishes it? Unfortunately, I don't think its protocol version gives it away.
Krellan commented at 6:31 AM on August 26, 2013: contributorI updated the commit.
Got rid of the idea of rate-limiting user-requested RPC pings, that simplifies a chunk of code.
Cleaned up indentation.
The "pingtime" field shows only completed pings. I took the liberty of adding a second field, "pingwait", that will only appear during the time a ping is in flight. It will show you how long we have been waiting for that ping to complete. This gives a window of visibility into noticing a sudden increase in lag (perhaps a newly solved block just arrived), or a peer that is so burdened that it is having trouble responding to pings.
I could put this patch on a diet by jettisoning the debugging/error messages for various things that can happen. Good or bad idea? The messages were useful during testing but it's pretty much solid now.
gavinandresen commented at 7:13 AM on August 26, 2013: contributorWhy reinvent '/sbin/ping' ? Why not just a little shell script that calls getpeerinfo, then uses the system ping to determine ping times?
I'm a less-code-is-better kinda guy.
sipa commented at 7:23 AM on August 26, 2013: member@gavinandresen There are many factors that affect Bitcoin P2P latency which you wouldn't notice through network-level ping (application throttling, peer having an overloaded receive queue, peer being DoS'ed, implementation problems...), and it will not work for every type of connection (incoming peers that are firewalled, or onion peers for example).
Additionally, having ping statistics inside the program can be useful for future heuristics when picking peers to sync/download from.
Krellan commented at 7:44 AM on August 26, 2013: contributorThanks sipa, very well said. That's the key reasons to have a ping at the Bitcoin layer, not just at the OS networking layer.
Krellan commented at 7:44 AM on August 28, 2013: contributorI have put the ping/pong handlers in main.cpp on a diet. Removed the printf statements, they have proved their usefulness during testing, but don't need to be in there permanently.
gmaxwell commented at 8:03 AM on August 28, 2013: contributorfuture heuristics when picking peers to sync/download from.
Also for picking peers to keep/discard when our connection slots are full: Low latency is something that a sibyl attacker can't just fake— he actually has to get close to you—, so it makes sense to full to reserve some slots for the lowest latency, apparently healthy peers.
Krellan commented at 11:51 PM on August 28, 2013: contributorThanks. As talked about on IRC the other night, I restored some code that was in the before, to drop pong messages if they are received with a nonce of zero. I am unsure what clients are sending these. Their version string comes across as "0.8.99" but I haven't found any version history that would ever send a pong (not a ping!) with a nonce of zero.
While running it overnight, I noticed yet another bad client pong behavior. The peer is sending me pong messages with no payload at all (zero bytes). This causes an exception during unserialize, which is caught so nothing harmful happens, but it's unclean.
mikehearn commented at 4:57 PM on August 30, 2013: contributorWhat are the subVers of the bad clients?
Krellan commented at 6:20 AM on August 31, 2013: contributorInvestigating that now. Frustratingly, it isn't happening anymore with my current set of peers that I'm connected to.
Krellan commented at 7:12 PM on September 1, 2013: contributorMade some changes.
Added more instrumentation to catch all of the anomalies that we've seen so far, in the pong handler. Instead of previous bloat, they are all now unified into a single printf statement.
Incoming pong message size is now checked. Unfortunately, I did not find any more peers who were giving me those empty-payload pong messages, but if they show up again, they will be cleanly logged this time, instead of throwing the exception. I noticed in_avail() in serialize.h returns an int. Shouldn't it be a size_t? There are no other users of it in bitcoind, I have noticed.
I just now call RAND_bytes() for each peer, instead of trying to save random entropy by only calling it once per overall ping request and then just incrementing it for each peer. Should now never be guessable, but at the cost of burning the entropy pool. Perhaps use RAND_pseudo_bytes() instead?
Also, this pull request is getting somewhat long in the tooth. I ran it against the latest top of tree, and it still applies cleanly and works just fine. Should I close this pull request and make a new pull request from a branch closer to the very latest, or keep this pull request open?
Krellan commented at 8:53 AM on September 4, 2013: contributorTested against latest top of tree and patch still applies cleanly.
Krellan commented at 10:02 PM on September 7, 2013: contributorRebased the branch to catch up to latest master.
sipa commented at 11:19 PM on September 23, 2013: memberACK
in src/main.cpp:None in c746c3041b outdated
3891 | + bPingFinished = true; 3892 | + sProblem = "Short payload"; 3893 | + } 3894 | + 3895 | + if (!(sProblem.empty())) { 3896 | + printf("pong %s %s: %s, %"PRI64x" expected, %"PRI64x" received, %zu bytes\n"
sipa commented at 2:08 PM on September 29, 2013:This will have to become a LogPrint("net", ...) I guess.
sipa commented at 2:11 PM on September 29, 2013: member@jgarzik @gavinandresen @gmaxwell Any further comments? I'd like this merged, to be able to add some automatic latency measurement on top.
gavinandresen commented at 10:16 PM on September 30, 2013: contributors/printf(/LogPrint("net"/ and I'm OK with merging.
Krellan commented at 12:37 AM on October 1, 2013: contributorGreat idea to use LogPrint instead. Made that one-line change. Also rebased it against the latest master.
Krellan commented at 8:24 AM on October 4, 2013: contributorFixed the merge. The "ping" command doesn't require access to the wallet, of course, so the new column is false for it.
971bb3e901Added ping time measurement.
New RPC "ping" command to request ping. Implemented "pong" message handler. New "pingtime" field in getpeerinfo, to provide results to user. New "pingwait" field, to show pings still in flight, to better see newly lagging peers.
BitcoinPullTester commented at 10:25 AM on October 4, 2013: noneAutomatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/971bb3e901aad5d4f04a651e3e2a75161d3a4e2a for binaries and test log. This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/ Contact BlueMatt on freenode if something looks broken.
sipa referenced this in commit 9269d0e96e on Oct 13, 2013sipa merged this on Oct 13, 2013sipa closed this on Oct 13, 2013DrahtBot locked this on Sep 8, 2021
This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:16 UTC
More mirrored repositories can be found on mirror.b10c.me