Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

manage names tab merged against current master #187

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

brandonrobertz
Copy link

I've finally completed the merge to namecoin-core/master. I had to refactor several things, due to upstream changed in the internal APIs, so there may be some bugs that didn't exist in the previous version. I also fixed the following bugs:

  • pending registration bug, where the client requests unlock over and over and then errors with name registered
  • names not showing up in the manage names list properly until client has been restarted

I know domob said he had some stylistic critiques, so I'd like to work through some of those as well once I know what they are.

@brandonrobertz
Copy link
Author

Paging @randy-waterhouse and @domob1812

@domob1812 domob1812 self-requested a review October 18, 2017 16:48
@domob1812
Copy link

Thanks a lot for finishing this work - this will be great once launched!

I'll take a look at the code now - and am already sorry for probably a lot of pedantic comments I'll have. ;)

BTW, in the future, I think you should try to have fewer (or just one) commit in a PR - git rebase is your friend here. I think that the code history of a project is important, and having only few commits of logically coherent changes helps a lot (rather than a long list of commits as the code evolved in your local branch). I don't expect you to rebase or squash this PR now, though.

@brandonrobertz
Copy link
Author

I know it's annoying to go through a million commits. I can squash it before we merge, if that's OK. Thanks for looking.

Copy link

@domob1812 domob1812 left a comment

Choose a reason for hiding this comment

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

Looks very good, I'm just very pedantic -- thanks for your hard work on this!

@@ -6,6 +6,8 @@

#include "script/names.h"

std::map<std::string, NameNewReturn > pendingNameFirstUpdate;

Choose a reason for hiding this comment

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

Formatting nit: I would remove the space between NameNewReturn and the closing >.

@@ -10,6 +10,8 @@
#include "script/script.h"
#include "serialize.h"

#include <univalue.h>

Choose a reason for hiding this comment

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

Why do you need this include? I don't see anything in your additions that would require it - or is it required for something existing in the file and currently missing? Please either remove or briefly reply here with the explanation why you need the include.


/* Here is where we store our pending name_firstupdates (see above)
while we're waiting for name_new to confirm. */
extern std::map<std::string, NameNewReturn > pendingNameFirstUpdate;

Choose a reason for hiding this comment

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

If I understand your code correctly, you need this here rather than just in the UI code because it is part of the wallet, right? In that case, however, it should also be stored in the wallet and not in a global variable -- especially in light of the recent upstream changes to support multiple wallets in a single running client.

Copy link
Author

Choose a reason for hiding this comment

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

For this one, what do you think about this refactor strategy:

  • move pendingNameFirstUpdate map to walletdb
  • move reads, writes, exists checks on pendingNameFirstUpdate to methods in walletdb
  • in the UI do the interaction through walletmodel (QT model) which wraps function calls to walletdb

Choose a reason for hiding this comment

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

Yes, basically. I think you should add the variable to CWallet, where for instance also mapWallet is (since it is very similar in spirit, IMHO). Access should be through CWallet, not walletdb, though. (The walletdb is the backing BDB, but from there you load it into memory just like you do now - except that you keep it in CWallet and ideally do all access to it through the wallet. Do not access walletdb directly, let the wallet do it; at least that's how I think it works for transactions.)

I don't know how the UI typically interacts with the wallet, but I guess walletmodel is the correct way, yes. (In general, I think you should just follow how the wallet transactions are stored and handled, for instance.)

@@ -15,9 +15,12 @@ class BitcoinAddressEntryValidator : public QValidator
Q_OBJECT

public:
explicit BitcoinAddressEntryValidator(QObject *parent);
explicit BitcoinAddressEntryValidator(QObject *parent, bool fAllowEmpty = false);

Choose a reason for hiding this comment

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

Why do you need this change? I've not yet finished reading your code, but my guess is that you want an "allow empty" address field for name updates - is that correct, or do you need it for something else? (Apart from that, though, I have no idea how this could be related to adding the name UI.) Please briefly explain here for my understanding. Thanks!


State validate(QString &input, int &pos) const;

private:
bool allowEmpty;

Choose a reason for hiding this comment

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

Nit: I think you can mark this as const.

NameNewReturn ret;
ret.hex = txid;
ret.rand = rand;
ret.data = pendingData;

Choose a reason for hiding this comment

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

This has me wonder about the serialisation of NameNewReturn. You could actually define "proper" serialisation of the struct in the same way that other stuff in the code is serialised (e. g., transactions). That would fit better into the existing code here than using JSON.

Copy link
Author

Choose a reason for hiding this comment

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

I agree and I'll add this to the list.


BOOST_FIXTURE_TEST_SUITE(wallet_name_pending_tests, WalletTestingSetup)

BOOST_AUTO_TEST_CASE(wallet_name_pending_tests)

Choose a reason for hiding this comment

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

Thanks for writing a unit test! :)

std::string nameBad = "test/baddata";
std::string txid = "9f73e1dfa3cbae23d008307e42e72beb8c010546ea2a7b9ff32619676a9c64a6";
std::string rand = "092abbca8a938103abcc";
std::string data = "{\"foo\": \"bar\"}";

Choose a reason for hiding this comment

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

Can all these be const?


// make sure we've added our pending name
BOOST_CHECK(pendingNameFirstUpdate.size() == 1);
BOOST_CHECK(pendingNameFirstUpdate.find(nameGood) != pendingNameFirstUpdate.end());

Choose a reason for hiding this comment

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

Nit: I personally would write the check as pendingNameFirstUpdate.count(nameGood) > 0, but that's probably just a matter of taste. I find that version easier to read.

BOOST_CHECK(CWalletDB(dbw).EraseNameFirstUpdate(nameBad));
}
}

Choose a reason for hiding this comment

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

Bonus points: Can you also add a unit test for the auto-updating logic? That would be even better to have, I think -- but may be complicated to write (I don't know how unit testing in Qt works).

Copy link
Author

Choose a reason for hiding this comment

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

Writing Qt unit tests is pretty complicated, but it's been on my list for a while now. I tried a while back but couldn't get it to work correctly basing from the existing Qt tests. I'll definitely give it another stab, though.

Choose a reason for hiding this comment

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

Yes, I agree. That's certainly not required for merging this IMHO - but if you do find time to work on it later, it would be much appreciated! (And I feel your pain in writing the Qt tests!)

@domob1812
Copy link

I would prefer to squash the commits if you don't mind -- but I'm also fine with keeping it as it is, if that would be a lot of extra work and complication for you. (Just wanted to point this out for the future.)

@domob1812
Copy link

Thanks for the updates! Please let me know when you are ready for a second round of review - and please note that I'll be busy the next couple of weekends, so I can't promise how much time I'll have for Namecoin-related work. But I should probably also be able to do a follow-up review in a couple of evenings during the week.

@brandonrobertz
Copy link
Author

Alright. I've worked through all your comments @domob1812 and made lots of improvements. Your review comments were extremely helpful, so thanks for going through everything. Let me know if you get a chance to go through my revisions.

One thing I noticed is that the first test (https://travis-ci.org/namecoin/namecoin-core/jobs/295544697) seems to always fail in Travis, but it succeeds local. Something about not being able to find certain Namecoin commands? I've fixed all the other test issues, though. Maybe @JeremyRand knows more about this?

@domob1812
Copy link

Thanks, I'll take another look - although I won't have time until next Monday to do so, unfortunately. In the meantime, @JeremyRand and others: feel free to take a look also, and to test.

@brandonrobertz
Copy link
Author

I replaced the JSON serialization with a more standard CNamePendingData serializable class. Note that this change is incompatible with any old beta wallets that have old-style pending names in them.

Copy link

@domob1812 domob1812 left a comment

Choose a reason for hiding this comment

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

I've added a few more comments, but now everything are just minor things - no bigger refactorings as last time. Thanks for all your work on this!

(But note again that I've not reviewed the Qt-specific stuff too closely, as I don't know much about it anyway. This is particularly true about the .ui files.)

class CNamePendingData
{
private:
std::vector<unsigned char> vchToAddress;

Choose a reason for hiding this comment

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

Please use vchType as elsewhere in the names/* code.

inline const std::string getToAddress() { return ValtypeToString(vchToAddress); }
inline const std::string getHex() { return ValtypeToString(vchHex); }
inline const std::string getRand() { return ValtypeToString(vchRand); }
inline const std::string getData() { return ValtypeToString(vchData); }

Choose a reason for hiding this comment

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

If I understand the code correctly, you are actually storing the address in its string representation in the vchType. Similarly for hex and rand, which are stored as hex strings, right?

I think since you have this wrapper class and already need to convert between string and vchType, you should actually encode the data properly: The address can be a CScript, and hex/rand can be the actual binary data in vchType, not the hex string.

Copy link
Author

Choose a reason for hiding this comment

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

I'm down to this last one before I start doing more testing, but I'm a little confused. Do you want me to not return std::string and instead return standard internal types like CScript etc? Or are you saying I can leave it accepting/returning std::string but encode internally and serialize to the reference types (CScript, etc)?

Copy link
Author

Choose a reason for hiding this comment

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

I've got it working the first way, accepting/returning std::string but serializing toAddress, txid, rand to CScript, uint256, uint160 respectively. If you had something different in mind, let me know. For the way the UI code is using the wallet, it's easier for me to just use strings and it allows me to not have to mess with internal types in the Qt code. But I can change if required.

Choose a reason for hiding this comment

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

Thanks! Yes, that's exactly what I meant - storing and serialising as raw data. Interfacing to the UI as strings is certainly fine.


explicit ConfigureNameDialog(const PlatformStyle *platformStyle,
const QString &_name, const QString &data,
bool _firstUpdate, QWidget *parent = 0);

Choose a reason for hiding this comment

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

Nit: nullptr instead of 0.

void on_pasteButton_clicked();

private:
Ui::ConfigureNameDialog *ui;

Choose a reason for hiding this comment

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

Sounds good.

QString returnTransferTo;
WalletModel *walletModel;
QString name;
bool firstUpdate;

Choose a reason for hiding this comment

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

Nit: I think a couple of these variables can actually be const (e. g., firstUpdate).


std::vector<std::reference_wrapper<std::string>> WalletModel::sendPendingNameFirstUpdates()
{
std::vector<std::reference_wrapper<std::string>> successfulNames;

Choose a reason for hiding this comment

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

Do you really need a reference_wrapper<string> here? I think just having a vector<string> would make the code simpler and easier to read, besides avoiding any potential issues with references to strings that go out of scope. Of course, a vector of references is smaller and faster, but is that really important here vs code simplicity and clarity?

const int confirms = val.get_int ();
LogPrintf ("Pending Name FirstUpdate Confirms: %d\n", confirms);

if ((unsigned int)confirms < MIN_FIRSTUPDATE_DEPTH)

Choose a reason for hiding this comment

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

Nit: Prefer static_cast over C-style casts.

completedResult = this->completePendingNameFirstUpdate(name, rand, txid, data, toaddress);

// Locks wallet
unlock_ctx.reset(nullptr);

Choose a reason for hiding this comment

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

I think you can just reset() without passing nullptr.

LOCK(cs_wallet);
std::map<std::string, CNamePendingData> pn = namePendingMap;
std::map<std::string, CNamePendingData>::iterator it = pn.find(name);
return it->second;

Choose a reason for hiding this comment

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

How can your caller know if the name was not found? (Since namePendingMap.end() is presumably private, if you have this access function defined.)

@@ -17,6 +18,7 @@
#include "wallet/wallet.h"

#include <atomic>
#include <univalue.h>

Choose a reason for hiding this comment

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

For what do you need this?

@domob1812
Copy link

@JeremyRand Yes that's fine with me, and sounds indeed like a useful start.

JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Jun 4, 2020
Based on namecoin#187
by Brandon Roberts.

TODO: Untested.
@JeremyRand
Copy link
Member

@domob1812 Does the internal tableRPC interface have problems if I pass binary data that isn't valid UTF-8? Trying to figure out if I need to convert things to hex and back, or if the UTF-8 constraint is solely for the external HTTP server.

@domob1812
Copy link

Does the internal tableRPC interface have problems if I pass binary data that isn't valid UTF-8? Trying to figure out if I need to convert things to hex and back, or if the UTF-8 constraint is solely for the external HTTP server.

I'm not entirely sure, but from a quick look it seems that the main thing you need is passing a UniValue. So if you can convert your data into UniValue, it should be fine. This may involve converting the binary string to "corresponding" UTF-8, though, as if by using escape codes in the JSON string literals.

JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Jun 27, 2020
Based on namecoin#187
by Brandon Roberts.

TODO: Untested.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 8, 2020
Based on namecoin#187
by Brandon Roberts.

TODO: Untested.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 8, 2020
Based on namecoin#187
by Brandon Roberts.

TODO: Untested.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 9, 2020
Based on namecoin#187
by Brandon Roberts.

TODO: Untested.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 18, 2020
Based on namecoin#187
by Brandon Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 18, 2020
Depends on #353 and #373, do not merge this until those are merged and
this PR is rebased.

TODO: Untested.

Based on namecoin#187 by Brandon
Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 22, 2020
Based on namecoin#187
by Brandon Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 22, 2020
Depends on #353, do not merge this until that PR is merged and this PR
is rebased.

Based on namecoin#187 by Brandon
Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 22, 2020
Depends on #353, do not merge this until that PR is merged and this PR
is rebased.

Fixes namecoin#377

Based on namecoin#187 by Brandon
Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Oct 22, 2020
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Nov 23, 2020
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Nov 23, 2020
Depends on #353, do not merge this until that PR is merged and this PR
is rebased.

Fixes namecoin#377

Based on namecoin#187 by Brandon
Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Dec 14, 2020
Depends on #353, do not merge this until that PR is merged and this PR
is rebased.

Fixes namecoin#377

Based on namecoin#187 by Brandon
Roberts.
JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Dec 14, 2020
@JeremyRand
Copy link
Member

@domob1812 Is it okay if we allocate up to 1 week of dev time from the Handshake funds to getting the name_list portion of the name tab GUI merged to Namecoin Core master branch? (I.e. the read-only parts of the name tab, so it shows name inventory but doesn't allow updating or registering.) I'd probably be up for attempting it. AFAICT that piece of the GUI doesn't need any new RPC functionality since it's basically just a GUI wrapper for name_list. (It's part of the NLnet proposal we submitted, but that's taking longer to approve than we were hoping, and we can redirect the NLnet funds to other tasks.)

The name_autoregister RPC command is worth doing as well, but I don't see any reason why it has to be done before the GUI for name_list.

@JeremyRand Yes that's fine with me, and sounds indeed like a useful start.

@domob1812 We are almost at the 1 week mark here. Things were unexpectedly productive: not only did we get the name_list GUI merged, but the name renewal GUI is ready for review too.

If a 2nd week of dev on this front is approved, I plan to focus on the Renew Name button (should be easy), the name_update GUI, and perhaps porting some UX improvements from Electrum-NMC (e.g. friendlier representations of names), and maybe fix the GUI bugs that currently occur with non-ASCII names/values (they're currently hidden from the GUI completely).

@domob1812
Copy link

If a 2nd week of dev on this front is approved, I plan to focus on the Renew Name button (should be easy), the name_update GUI, and perhaps porting some UX improvements from Electrum-NMC (e.g. friendlier representations of names), and maybe fix the GUI bugs that currently occur with non-ASCII names/values (they're currently hidden from the GUI completely).

Seems fine with me. :)

@JeremyRand
Copy link
Member

Week 1 has completed. Although this was projected to only cover the name_list GUI, we were also able to get most of the name renewal GUI (including multiple renewals at once) implemented and ready for review. Also threw in a Cirrus bugfix and an AuxPoW bug report, since those were in my way.

@domob1812 Is it okay to pay out for Week 1?

If a 2nd week of dev on this front is approved, I plan to focus on the Renew Name button (should be easy), the name_update GUI, and perhaps porting some UX improvements from Electrum-NMC (e.g. friendlier representations of names), and maybe fix the GUI bugs that currently occur with non-ASCII names/values (they're currently hidden from the GUI completely).

@domob1812 Is it okay to authorize funding of Week 2? (Wasn't sure if your previous comment was a yes, figured I should verify rather than assume.)

@domob1812
Copy link

@JeremyRand Yes to both. It is fine for me to pay out week 1, and fine to work on week 2 with Handshake funds.

JeremyRand added a commit to JeremyRand/namecoin-core that referenced this pull request Jan 22, 2021
@JeremyRand
Copy link
Member

@domob1812 Is there any convenience function that takes a CTransaction as input and returns an interable of CNameScripts, where a returned size of 0 indicates it's not a name transaction, and a returned size of 1 indicates the name operation that exists? If there's no such function, is it okay if I add one somewhere in the src/names directory? This would make some of the Namecoin-Qt code that I'm porting a bit more readable. (Pretty sure Electrum-NMC has such a convenience function already.)

@domob1812
Copy link

@JeremyRand I don't think there is such a function, but there are a couple of places that iterate over the vout's and search for the name operation. If you feel such a function is useful to have, I think it is perfectly fine to add it.

I think instead of an iterable, you should return Optional<CNameScript> (from optional.h, which internally uses C++17's std::optional).

@JeremyRand
Copy link
Member

@JeremyRand Yes to both. It is fine for me to pay out week 1, and fine to work on week 2 with Handshake funds.

@domob1812 We are nearing the end of Week 2. Here's what's been accomplished:

Also threw in a few Cirrus failure bug reports and a few Gitian-related fixes, which were getting in my way. Also threw in a Gitian build of nc0.21.0.1.

If a 3rd week of funding is approved, I will probably focus on finishing up the DNS builder dialog and the namespace-specific name_list GUI functionality, and maybe adding GUI support for non-ASCII names/values.

@JeremyRand
Copy link
Member

@domob1812 We are nearing the end of Week 2.

@domob1812 Week 2 has been completed. Is it okay to pay out for Week 2?

If a 3rd week of funding is approved, I will probably focus on finishing up the DNS builder dialog and the namespace-specific name_list GUI functionality, and maybe adding GUI support for non-ASCII names/values.

@domob1812 Is it okay to allocate Handshake funds for Week 3?

@domob1812
Copy link

Sounds good to me. Will week 3 wrap it all up, or will then there still be something outstanding that we should work on?

domob1812 added a commit that referenced this pull request Sep 1, 2021
befa241 Namecoin / Qt: Add name_firstupdate GUI (Jeremy Rand)

Pull request description:

  This PR adds a GUI for `name_firstupdate`, based on Brandon's port of Mikhail's GUI.  AFAICT, once #436 is merged, patching this GUI to use `name_autoregister` instead should be roughly a one-liner.  Until then, it's still a UX improvement over the status quo, even though the user needs to run `name_new` themselves.

  Refs #187

ACKs for top commit:
  domob1812:
    ACK befa241.

Tree-SHA512: 044e2daf0b67992013703fe3e4e6fe255585fa0268b5b084a92c6eff0027f662891adb9633b1a4c1fef7a39de2e796b8aa713b0f901558ce016a00318e5b602a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants