Skip to content

Conversation

ashleyholman
Copy link
Contributor

Here is my code which adds a "Peers" tab to the debug window.

The peers table lists just a few columns of detail, and then when you click on a peer it shows all of the detail. It updates every second while the debug window is open (by doing a full scan of vNodes), and also handles the case where the selected peer gets disconnected.

If you have any suggestions on which columns should appear in the table, or how to format some of the values, I'm happy to implement them. I just chose to show Address, Subversion, and Height in the table for now. The advantage of including fields in the table is that they are sortable, so I guess the table should contain those properties which users are most likely to want to sort by.

There's a fair bit of code here, so take your time with the review.

Thanks.

@ashleyholman
Copy link
Contributor Author

github4133

@ashleyholman
Copy link
Contributor Author

Relates to issue #4133

@wtogami
Copy link
Contributor

wtogami commented May 24, 2014

Would it be complicated to add a 'Disconnect' and 'Ban' option? Either buttons or right-click menu?

@ashleyholman
Copy link
Contributor Author

@wtogami I think I'd be able to do that. I imagine that such a function should be also added as an RPC call to keep the CLI and GUI capabilities the same?

@wtogami
Copy link
Contributor

wtogami commented May 24, 2014

RPC too sounds like a great idea. Would be helpful in debugging certain things.

bannode, unbannode, disconnectnode?

The parameter could be a domain name but in the case of banning it's resolved and only the IP address is stored.

For Tor nodes I'm not sure how to handle it. You can't ban but disconnect would be possible.

@@ -4,6 +4,7 @@

#include "clientmodel.h"

#include "peertablemodel.h"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can you keep alphabetical ordering (where possible) of includes, classes etc. throughout your pull please :). Talking about just the file headers (header of .h and .cpp)...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the part about alphabetical ordering mentioned anywhere in the coding style guides? If not, it should be, as otherwise it's not realistic to expect people to do it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most likely it's not, but I remeber a big cleanup pull by someone and we liked it :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should hopefully be fixed in my new commit. Note that I have followed the format of some of the other .cpp files where they include their own .h first on a separate line, then group the others alphabetically.

@Diapolo
Copy link

Diapolo commented May 24, 2014

Pretty cool addition :), nice job!

@laanwj
Copy link
Member

laanwj commented May 24, 2014

Looks very good!

I think adding Disconnect/Ban functionality would be useful, but let's not do it in this pull request. That functionality would indeed also have to be available on RPC (and the core) first, and that's orthogonal to this nice GUI improvement. Let's aim to merge this first.

@ashleyholman
Copy link
Contributor Author

What's the process on pushing additional patches in response to feedback? If I push an amended commit, it's hard for you to see what changed. But if I commit new patches on top, the history will be a bit ugly when merged.

I guess I could make new commits on top for now, and then squash it later once it's ready for merge?

@Diapolo
Copy link

Diapolo commented May 24, 2014

@ashleyholman For such a "big" patch it's nice to add commits until you got core dev ACKs and can then squash into one.

@sipa
Copy link
Member

sipa commented May 24, 2014

Pings aren't sent automatically (yet), so the pingtime will be zero unless you explicitly request pings (using the ping RPC command).

If you run together with #2784, you'll pretty much always see ping times.

By the way, I think ping times (in that case) are more useful to show on the main screen table than startingheight (as that can be very outdated information).

@ashleyholman
Copy link
Contributor Author

Here is what it's like with #2784 merged and the Height column replaced with Ping.

guipeersping

I've pushed this to my gui_peers_ping branch, but won't include it in this pull unless #2784 is getting merged.

@laanwj
Copy link
Member

laanwj commented May 25, 2014

I did a bit of testing with this applied, works well for me; a few nits:

  • 'Ban Score' shows as 'Unavailable' for many peers. This seems confusing. It may be better to just report '0' here if the data structure for this isn't created yet.
  • When enlarging the debug window vertically, the line distance between the information entries increases. This looks a bit weird, but I suppose it's a matter of taste. I usually prefer adding a stretch at the end to avoid this.
  • Services: Maybe show the flags expanded as text here, so [NODE_]NETWORK instead of '1'. Although this leaves the question of how to show unknown service bits, maybe UNKNOWN[bit].
  • I think translators will have problems translating the word 'Subversion'. Maybe 'Sub-version'? Or just 'Version'?

@sipa
Copy link
Member

sipa commented May 25, 2014

BIP14 repurposed strSubVer as "user agent".

@ashleyholman
Copy link
Contributor Author

The ban score being "Unavailable" is because there's an extra lock required to get that info. The rest of the stats require cs_vNodes, but getting the nMisbehaviour requires cs_main. When TRY_LOCK on cs_main fails, I show "Unavailable". I could show it as 0, but then when it eventually succeeds on the lock, the value will change. If you click on another peer and then click back on the same peer, it would say 0 again until it can refetch the nMisbehaviour, because I'm only caching nMisbehaviour for the currently selected node.

As for how to make this meaningful to the user, perhaps I could just leave it blank if it can't be accessed. Or, it could say "fetching..." or something like that until it gets the value?

@leofidus
Copy link

displaying "fetching..." and periodically trying to get the information sounds like a good solution.

@ashleyholman
Copy link
Contributor Author

Pushed an update:

  • Change "Unavailable" to "Fetching..." when nMisbehaviour can't be read. If you wait some seconds, you should eventually see the ban score. It's worse when the lock is busy, such as when synchronising your chain.
  • Added a stretch element to fix up the vertical resize behaviour
  • The "Services" field is now formatted verbosely, eg. "NETWORK & UNKNOWN[2] & ..." (only scans the last 8 bits for now, as its probably overkill to check all 64 when they're not standardised yet).
  • Renamed "Subversion" to "User Agent"

@laanwj
Copy link
Member

laanwj commented May 26, 2014

@ashleyholman seems like good choices to me

ui->peerHeight->setText(QString("%1").arg(stats->nStartingHeight));
ui->peerSyncNode->setText(stats->fSyncNode ? tr("Yes") : tr("No"));

// if we can, display the peer's ban score
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason to collect the ban score here, instead of in PeerTableModel's refreshPeers()? To me it seems like this would be the responsibility of the model, not the view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the state stats, which contains the ban score, is only being retrieved for the one peer thats selected (if one is selected). The model is not aware of which one is selected, so refreshPeers() would have to get the CStateStats for every peer and store them as it does with the CNodeStats records, which I will happily do if that's cleaner. The return type of PeerTableModel::getNodeStats() would need to change in that case, so that it returns both the CNodeStats and CNodeStateStats. How would I best define a type for that?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could pass two references instead of using the one return type?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think retrieving all the data is refreshPeers is cleanest. You could define a data structure for the model that contains both a CNodeStats and a CNodeStateStats or use a std::pair if lazy :)

Unless you think this has a large impact on performance, but I don't think so, it is only a little bit extra data that gets copied.

Alternatively: add a function getNodeStateStats(id) to the PeerTableModel that retrieves this data and returns a CNodeStateStats, then just move the code and call it from here. All the code to access core data structures happens from the model then, and that's good enough for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@laanwj: my latest patch moves it into refreshPeers()

@laanwj
Copy link
Member

laanwj commented Jun 2, 2014

ACK. will merge after squash

@ashleyholman
Copy link
Contributor Author

@laanwj There you go. I avoided rebasing so that my squash can be easily diff'd against the last reviewed commit. It merges cleanly to master though.

In regards to signing, should I be doing that, or is that only needed for mainline commits (ie. your merge commit)? I don't have a PGP identity on any key servers at the moment, but it's something I've been wanting to get set up with.

@laanwj
Copy link
Member

laanwj commented Jun 2, 2014

@ashleyholman Thanks

Re: signing, I always sign the merge commits, but I think it's useful if contributors sign their uppermost commit as well, so that people can check that it's really the contributor's code that was merged and not something manipulated by a compromised github (for example). Once you have a key set up, you can sign your last commit with:

git commit --amend --gpg-sign[=<keyid>]

Then just push to github as normal.

@Azulan
Copy link

Azulan commented Jun 2, 2014

Tested with ipv6?

@laanwj
Copy link
Member

laanwj commented Jun 2, 2014

@Azulan Yes, if you could test with ipv6 that'd be helpful

@BitcoinPullTester
Copy link

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/65f78a111ff52c2212cc0a423662e7a41d1206dd 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.

@laanwj laanwj merged commit 65f78a1 into bitcoin:master Jun 3, 2014
laanwj added a commit that referenced this pull request Jun 3, 2014
65f78a1 Qt: Add GUI view of peer information. #4133 (Ashley Holman)
QModelIndex index(int row, int column, const QModelIndex &parent) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
void sort(int column, Qt::SortOrder order);
/*@}*/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Diapolo Which lines specifically? Github is highlighting a lot there so I can't tell which parts you mean.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly that line /*@}*/ and at the beginning of the comment :).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I'm not sure what the deal is with those, but they are in the other model code that I based this on.

$ git grep -F '/*@}*/'
src/qt/addresstablemodel.h:    /*@}*/
src/qt/peertablemodel.h:    /*@}*/
src/qt/recentrequeststablemodel.h:    /*@}*/

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the @name puts a descriptive name to all the code enclosed between @{ and @} in the doxygen documentation. But I think it has to be /**@}*/ to be correctly recognized.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leofidus It appears to work see https://dev.visucore.com/bitcoin/doxygen/class_peer_table_model.html, under Public Member Functions.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants