User can add the following into theirs bitcoin.conf:
uacomment=Prague
uacomment=BeagleBone
which will result in the following user agent:
/Satoshi:0.11.99(Prague; BeagleBone)/
User can add the following into theirs bitcoin.conf:
uacomment=Prague
uacomment=BeagleBone
which will result in the following user agent:
/Satoshi:0.11.99(Prague; BeagleBone)/
Concept ACK. Needs some sort of size limiting.
99 | @@ -99,11 +100,20 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const 100 | std::ostringstream ss; 101 | ss << "/"; 102 | ss << name << ":" << FormatVersion(nClientVersion); 103 | - if (!comments.empty()) 104 | + 105 | + const std::string key = "-uacomment";
Right now, FormatSubVersion is a pure utility function that doesn't use any global state. I think it should stay that way. E.g. by adding an const std::vector<std::string> &commentList argument. Then pass in this data at the caller side.
Also makes it easier to test this in util_tests.
Concept ACK.
Bitcoin Core will reject strings longer than 256 characters for the subser string in "version" messages.
Tested ACK. Named a few nodes.
"subversion": "/Satoshi:0.11.99(Inanna)/",
...
"subversion": "/Satoshi:0.11.99(Ishtar)/",
...
"subversion": "/Satoshi:0.11.99(Ereshkigal)/",
Names are returned both by getnetworkinfo and the version P2P message, which I verified with bitcoin-submittx:
recv msg_version(nVersion=70002 nServices=1 nTime=Fri Jul 31 15:41:00 2015 addrTo=CAddress(nTime=0 nServices=1 ip=0.0.0.0 port=0) addrFrom=CAddress(nTime=0 nServices=1 ip=0.0.0.0 port=18444) nNonce=0x95FDC41E438E8122 strSubVer=/Satoshi:0.11.99(Ishtar)/ nStartingHeight=0)
It will happily send a subversion longer than 256 bytes, though:
recv msg_version(nVersion=70002 nServices=1 nTime=Fri Jul 31 15:53:46 2015 addrTo=CAddress(nTime=0 nServices=1 ip=0.0.0.0 port=0) addrFrom=CAddress(nTime=0 nServices=1 ip=0.0.0.0 port=18333) nNonce=0x8782C2C672C750F3 strSubVer=/Satoshi:0.11.99(Ishtar; 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef)/ nStartingHeight=5178)
... which, as expected, gets me only connections to old versions. The result is quite interesting. Some nodes send me a REJECT message, which, as it arrives before full version negotiation is seen as misbehavior:
2015-07-31 13:52:46 Misbehaving: 52.1.41.179:18333 (0 -> 1)
2015-07-31 13:52:46 ProcessMessages(reject, 31 bytes) FAILED peer=1
Although not an easy to trigger issue, we should avoid sending a string longer than we accept ourselves.
I share your concern about duplicating code: but you could still define a function that calls FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, mapMultiArgs.count("-uacomment") ? mapMultiArgs["-uacomment"] : std::vector<string>())));
which can add comments to user agent as per BIP-0014
Easiest logic would be to discard all of the comments if strlen > 256.
It's a workable solution but failing silently is unexpected behavior. I'd prefer to check this in AppInit2 and fail if the subversion string is too long.
Added check to AppInit2 function. (No more than 4 comments and no longer than 40 characters allowed).
utACK.
Nit: now you can provide 4string x 40bytes. What if one likes to provide 1x50 bytes? Would it not make more sense to limit the combined string to 240 (or 255) bytes?
Reworked check to check total length of all comments altogether. If it is more than 200 characters the error is issued.
ut ACK
utACK
Reworked-By: Wladimir J. van der Laan <laanwj@gmail.com>
@prusnak I slightly reworked the last commit:
MAX_SUBVERSION_LENGTH in net.h and use where appropriateThis reduces the amount of code, and cuts down on magic values. https://github.com/laanwj/bitcoin/tree/2015_08_prusnak_uacomment Can you please take it over?
Thanks!
I can't help but wonder if this conflicts somehow with #253 and the effort there which seemed to be to not identify or associate users... what might be the long-term effects of this effort which is to associate a bitcoin address with a node? No need to answer me here.
1017 | @@ -1018,6 +1018,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) 1018 | 1019 | RegisterNodeSignals(GetNodeSignals()); 1020 | 1021 | + // format user agent, check total size 1022 | + strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, mapMultiArgs.count("-uacomment") ? mapMultiArgs["-uacomment"] : std::vector<string>()); 1023 | + if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { 1024 | + return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.",
Shouldn't that one be translatable?
No, I'd say. Apart from being a specific technical error (which we don't translate for Googlability, see translation_strings_policy.md) it's an extremely rare condition caused by almost-abuse of the configuration system. No need to waste translator time on that.
@ABISprotocol How is having this option a problem? It's not always a good idea to use it, but many people run essentially public nodes without wallet, and for those there is no need to 'hide in the crowd'.
@laanwj Since you asked, my thinking was that there might be ancillary effects on other users, a butterfly effect if you will in the privacy context. Though different functionally (and thus not comparable in the way one might consider it to be), the address reuse problem comes to mind (again, this is perhaps not relevant here because it is addressed in other ways, such as implementing stealth or confidential transactions); but at the core of this, the concern is that when you have an option which encourages or motivates users to associate a node with an address, then that will have privacy implications not only for the user who makes that choice, but for other users in the network as well.
The ability to change what software your node advertizes as is not the same as encouraging to put an address there (which is indeed a bad idea IMHO).
I might be missing something but how does this implement BIP-0014? Current master happily accepts comments containing any of the "reserved symbols" mentioned in BIP-0014 and silently drops other characters when pushing to the network.
E.g. -:
My local node:
getnetworkinfo
[...]
"subversion": "/Satoshi:0.11.99(node-bob_12);:/:)()/",
[...]
Some remote node:
getpeerinfo
[...]
"subver": "/Satoshi:0.11.99(nodebob_12);:/:)()/",
[...]