RPC: creates possibility to preserve labels on importprivkey #13381

pull marcoagner wants to merge 1 commits into bitcoin:master from marcoagner:feature_preserve_labels_on_import changing 4 files +172 −3
  1. marcoagner commented at 2:59 pm on June 3, 2018: contributor

    Closes #13087.

    As discussed in the issue, this is a feature request instead of a bug report since the behaviour was as intended (i.e. label with default: ''). With this, the old behaviour is kept while the possibility to achieve the preservation of labels, as expected in the open issue, is added.

  2. fanquake added the label Wallet on Jun 3, 2018
  3. fanquake added the label RPC/REST/ZMQ on Jun 3, 2018
  4. promag commented at 4:30 pm on June 3, 2018: member
    There is no need for a new parameter, check if label is null instead - this means that the default is to preserve if it exists otherwise “”.
  5. promag commented at 5:29 pm on June 3, 2018: member
    Concept ACK, a test would be nice.
  6. marcoagner commented at 9:16 pm on June 3, 2018: contributor
    Thank you, @promag. I added some functional tests for this specific behavior between importaddress and importprivkey. If everything is alright, I’ll squash and rebase as necessary.
  7. marcoagner renamed this:
    [WIP] RPC: creates preserve parameter for importprivkey call
    RPC: creates preserve parameter for importprivkey call
    on Jun 3, 2018
  8. in src/wallet/rpcdump.cpp:157 in c74740701d outdated
    150@@ -151,9 +151,12 @@ UniValue importprivkey(const JSONRPCRequest& request)
    151         CKeyID vchAddress = pubkey.GetID();
    152         {
    153             pwallet->MarkDirty();
    154-            // We don't know which corresponding address will be used; label them all
    155+
    156+            // We don't know which corresponding address will be used; label all new addresses and preserve the rest
    157             for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
    158-                pwallet->SetAddressBook(dest, strLabel, "receive");
    159+                bool has_label = pwallet->mapAddressBook.find(dest) != pwallet->mapAddressBook.end() && !pwallet->mapAddressBook[dest].name.empty();
    


    promag commented at 9:42 pm on June 3, 2018:

    I was thinking in something like

    0if (request.params[1].isNull()) {
    1    const auto& it = pwallet->mapAddressBook.find(dest);
    2    if (it != pwallet->mapAddressBook.end()) strLabel = it->second;
    3}
    4pwallet->SetAddressBook(dest, strLabel, "receive");
    

    marcoagner commented at 11:52 pm on June 3, 2018:
    Hm, I see. Yeah.. this behavior seems better. Thanks! Updating this and the test.
  9. marcoagner commented at 11:57 pm on June 3, 2018: contributor
    Updated with the right behavior. I will squash and rebase it as necessary in the morning, thanks.
  10. in test/functional/wallet_import_with_label.py:2 in 75e46d2c2d outdated
    0@@ -0,0 +1,93 @@
    1+#!/usr/bin/env python3
    2+# Copyright (c) 2017 The Bitcoin Core developers
    


    promag commented at 0:12 am on June 4, 2018:
    2018
  11. in src/wallet/rpcdump.cpp:155 in 75e46d2c2d outdated
    150@@ -151,8 +151,13 @@ UniValue importprivkey(const JSONRPCRequest& request)
    151         CKeyID vchAddress = pubkey.GetID();
    152         {
    153             pwallet->MarkDirty();
    154-            // We don't know which corresponding address will be used; label them all
    155+
    156+            // We don't know which corresponding address will be used; label all new addresses and preserve the rest
    


    promag commented at 0:17 am on June 4, 2018:
    Comment is inacurate.
  12. promag commented at 9:51 am on June 4, 2018: member
    Update PR title.
  13. marcoagner renamed this:
    RPC: creates preserve parameter for importprivkey call
    RPC: creates possibility to preserve labels on importprivkey
    on Jun 4, 2018
  14. harding commented at 5:58 pm on June 4, 2018: contributor
    Tested ACK 74877f3b10072e1975c931bb296212e008cd8c58 . This is exactly the behavior I desired, thanks @marcoagner!
  15. in src/wallet/rpcdump.cpp:161 in 74877f3b10 outdated
    157+            // label all new addresses, and label existing addresses if a
    158+            // label was passed.
    159             for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
    160+                if (request.params[1].isNull()) {
    161+                    const auto& it = pwallet->mapAddressBook.find(dest);
    162+                    if (it != pwallet->mapAddressBook.end()) strLabel = it->second.name;
    


    Empact commented at 7:24 am on June 8, 2018:
    Is it problematic that this will apply the label for a given destination over all following destinations, provided they aren’t found on lookup? I suspect you’ll want another destination-specific local to prevent that.

    promag commented at 12:18 pm on June 8, 2018:

    Good catch! Suggestion:

    0if (it == pwallet->mapAddressBook.end() || !request.params[1].isNull()) {
    1    pwallet->SetAddressBook(dest, strLabel, "receive")
    2}
    

    promag commented at 12:19 pm on June 8, 2018:
    There should be a test ensuring the correct behaviour.

    marcoagner commented at 12:48 pm on June 8, 2018:
    Yes, makes sense. I will update it and add a test for the correct behaviour as soon as I can.
  16. marcoagner commented at 11:16 am on June 10, 2018: contributor
    I’m back to this. The new commit keeps the already tested behaviour (passing tests added on this PR et al) and passes new test for the multiple destinations bug spotted by @Empact.
  17. luke-jr commented at 9:44 pm on June 12, 2018: member

    This still changes behaviour: the default is now null (ie, current label) instead of "".

    I don’t particularly care what the default is (null makes more sense), but the change should be documented and noted in release notes.

  18. promag commented at 0:01 am on June 13, 2018: member
    Agree with @luke-jr regarding the behaviour change.
  19. marcoagner commented at 12:03 pm on June 13, 2018: contributor
    I added a release-notes-pr13381.md file documenting the change. Let me know if I missed something or should document this somewhere else. Thanks!
  20. harding commented at 1:31 pm on June 13, 2018: contributor

    @marcoagner Thanks for adding the release notes! I thought maybe the behavior change could be described more simply with the addition of a few examples; see below from some proposed text. I also changed the heading so that it’s clear that only a small part of the importprivkey API is being changed (I also removed the code style from the heading as those don’t display well in headings on parts of BitcoinCore.org, but that’s a local problem so feel free to add back the backtics if you like them).

     0RPC importprivkey: new label behavior
     1-------------------------------------
     2
     3Previously, `importprivkey`automatically added the default empty label
     4("") to all addresses associated with imported private keys.  Now it
     5defaults to using any existing label for those addresses.  For example:
     6
     7- Old behavior: you import a watch-only address with the label "cold
     8  wallet".  Later, you import the corresponding private key using the
     9  default settings.  The address's label is changed from "cold wallet"
    10  to "".
    11
    12- New behavior: you import a watch-only address with the label "cold
    13  wallet".  Later, you import the corresponding private key using the
    14  default settings.  The address's label remains "cold wallet".
    15
    16In both the previous and current case, if you directly specify a label
    17during the import, that label will override whatever previous label the
    18addresses may have had.  Also in both cases, if none of the addresses
    19previously had a label, they will still receive the default empty label
    20("").  Examples:
    21
    22- You import a watch-only address with the label "temporary".  Later you
    23  import the corresponding private key with the label "final".  The
    24  address's label will be changed to "final".
    25
    26- You import a private key for an address that was not previously in the
    27  wallet.  It's addresses will receive the default empty label ("").
    
  21. marcoagner commented at 1:57 pm on June 13, 2018: contributor

    @harding That’s much better, thanks. I’m changing to that on the next commit with some small (nit) differences. Here’s the diff so it’s easier to spot my edits:

     04,5c4,5
     1< Previously, `importprivkey`automatically added the default empty label
     2< ("") to all addresses associated with imported private keys.  Now it
     3---
     4> Previously, `importprivkey` automatically added the default empty label
     5> ("") to all addresses associated with the imported private keys.  Now it
     621c21
     7< ("").  Examples:
     8---
     9> ("") as default.  Examples:
    1028c28,29
    11<   wallet.  It's addresses will receive the default empty label ("").
    12---
    13>   wallet using the default settings.  Its addresses will receive the
    14>   default empty label ("").
    

    Seems good?

  22. harding commented at 2:30 pm on June 13, 2018: contributor

    @marcoagner LGTM, although the two uses of ‘default’ in this clause is a tiny bit awkward IMO (but, it’s clear, which is all that really matters):

    they will still receive the default empty label ("") as default.

    Maybe that second-to-last sentence could have its adverbial phrase “using the default settings” moved next to the verb it modifies, “import”, e.g.:

    You use the default settings to import a private key for an address that was not previously in the wallet.

    Thanks for updating, and thanks especially for catching my misuse of the apostrophe in the possessive its. :man_facepalming:

  23. marcoagner commented at 3:22 pm on June 13, 2018: contributor
    @harding I changed both parts pointed in your last comment. Thanks for the attention and help with this; I think we’ve now nailed this part. :)
  24. marcoagner commented at 10:12 pm on July 19, 2018: contributor
    Could anybody review 6115b5231954a38c400fa4808627dbb8e239ea68, please? One month in the freezer and is (hopefully) simple. :) @promag @Empact
  25. in src/wallet/rpcdump.cpp:159 in 6115b52319 outdated
    156+            // We don't know which corresponding address will be used;
    157+            // label all new addresses, and label existing addresses if a
    158+            // label was passed.
    159             for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
    160-                pwallet->SetAddressBook(dest, strLabel, "receive");
    161+                const auto& it = pwallet->mapAddressBook.find(dest);
    


    sipa commented at 10:59 pm on July 19, 2018:
    Nit: It’s slightly confusing to use a reference type here; find returns an iterator by value.
  26. sipa commented at 10:59 pm on July 19, 2018: member

    utACK 6115b5231954a38c400fa4808627dbb8e239ea68. Didn’t review the tests.

    Non-blocking nit only.

  27. in doc/release-notes-pr13381.md:5 in 6115b52319 outdated
    0@@ -0,0 +1,29 @@
    1+RPC importprivkey: new label behavior
    2+-------------------------------------
    3+
    4+Previously, `importprivkey` automatically added the default empty label
    5+("") to all addresses associated with the imported private keys.  Now it
    


    promag commented at 0:37 am on July 20, 2018:
    Should be ... imported private key. (singular)?
  28. in src/wallet/rpcdump.cpp:105 in 6115b52319 outdated
    101@@ -102,7 +102,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
    102             "Hint: use importmulti to import more than one private key.\n"
    103             "\nArguments:\n"
    104             "1. \"privkey\"          (string, required) The private key (see dumpprivkey)\n"
    105-            "2. \"label\"            (string, optional, default=\"\") An optional label\n"
    106+            "2. \"label\"            (string, optional, default=current label if watch-only address exists, otherwise \"\") An optional label\n"
    


    promag commented at 0:43 am on July 20, 2018:
    Could drop watch-only since the code below does’t validate that, it only checks if the label exists for each associated address. So default=current label if exists, otherwise \"\".

    marcoagner commented at 10:19 am on July 20, 2018:
    Yes. Just leaving address between if and exists: default=current label if address exists, otherwise \"\". (I know it was probably just a typo; I’m commenting to make sure)
  29. in src/wallet/rpcdump.cpp:160 in 6115b52319 outdated
    157+            // label all new addresses, and label existing addresses if a
    158+            // label was passed.
    159             for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
    160-                pwallet->SetAddressBook(dest, strLabel, "receive");
    161+                const auto& it = pwallet->mapAddressBook.find(dest);
    162+                if (it == pwallet->mapAddressBook.end() || !request.params[1].isNull()) {
    


    promag commented at 0:59 am on July 20, 2018:

    Nit, maybe make it clear that params[1] has precedence — prevents a lookup if it does? Also, updating with the same label could be avoided, or am I missing something? Suggestion:

    0for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
    1    if (!request.params[1].isNull()) {
    2        pwallet->SetAddressBook(dest, strLabel, "receive")
    3    } else if (pwallet->mapAddressBook.count(dest) == 0) {
    4        pwallet->SetAddressBook(dest, strLabel, "receive");
    5    }
    6}
    

    marcoagner commented at 10:19 am on July 20, 2018:
    Yes, it seems right to me. Thank you again! I thought I had to somehow guarantee purpose was now “receive” for all dests, but it doesn’t seem to be the case now I looked.
  30. in test/functional/wallet_import_with_label.py:6 in 6115b52319 outdated
    0@@ -0,0 +1,126 @@
    1+#!/usr/bin/env python3
    2+# Copyright (c) 2018 The Bitcoin Core developers
    3+# Distributed under the MIT software license, see the accompanying
    4+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
    5+"""Test the behavior of RPC importprivkey on set and unset labels of
    6+watch-only addresses.
    


    promag commented at 1:00 am on July 20, 2018:
    Drop watch-only?
  31. in test/functional/wallet_import_with_label.py:24 in 6115b52319 outdated
    19+class ImportWithLabel(BitcoinTestFramework):
    20+    def set_test_params(self):
    21+        self.num_nodes = 2
    22+        self.setup_clean_chain = True
    23+
    24+    def setup_network(self):
    


    promag commented at 1:02 am on July 20, 2018:
    Can be removed.
  32. marcoagner commented at 10:20 am on July 20, 2018: contributor
    Thank you all for reviewing again. Updated with 1d4fdb33349a60cac1926f83586826ba62b1a451.
  33. promag commented at 10:27 am on July 20, 2018: member
    Maybe @harding could re-test?
  34. in src/wallet/rpcdump.cpp:161 in 1d4fdb3334 outdated
    158+            // label was passed.
    159             for (const auto& dest : GetAllDestinationsForKey(pubkey)) {
    160-                pwallet->SetAddressBook(dest, strLabel, "receive");
    161+                if (!request.params[1].isNull()) {
    162+                    pwallet->SetAddressBook(dest, strLabel, "receive");
    163+                } else if (pwallet->mapAddressBook.count(dest) == 0) {
    


    sipa commented at 6:46 am on July 21, 2018:
    Given that the branches for the two if statements are identical, why not write it as a single if (!request.params[1].isNull() || pwallet->mapAddressBook.count(dest)) { ?

    marcoagner commented at 8:30 am on July 21, 2018:
    Just to try to make it obvious in the code that the request.params[1] has precedence. Bad idea? Both work.

    marcoagner commented at 8:32 am on July 21, 2018:
    No reason besides it since AFAIK putting the look up as second condition in the || statement (like your suggestion) will not call it if there is a params[1] in the first condition.
  35. sipa commented at 6:47 am on July 21, 2018: member
    utACK 1d4fdb33349a60cac1926f83586826ba62b1a451
  36. in test/functional/wallet_import_with_label.py:25 in a84fb66ba4 outdated
    19+class ImportWithLabel(BitcoinTestFramework):
    20+    def set_test_params(self):
    21+        self.num_nodes = 2
    22+        self.setup_clean_chain = True
    23+
    24+    def run_test(self):
    


    MarcoFalke commented at 10:16 pm on September 13, 2018:
    The skip-if-no-wallet might have to be added to this test?

    marcoagner commented at 0:31 am on September 28, 2018:
    You’re right. I was not aware, thanks.
  37. MarcoFalke commented at 10:16 pm on September 13, 2018: member
    Lets see what travis says
  38. MarcoFalke closed this on Sep 13, 2018

  39. MarcoFalke reopened this on Sep 13, 2018

  40. DrahtBot commented at 2:21 pm on September 15, 2018: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    No conflicts as of last run.

  41. in test/functional/wallet_import_with_label.py:117 in 8972e273aa outdated
    112+
    113+        assert(address_assert4.get('embedded'))
    114+
    115+        bcaddress_assert = self.nodes[1].getaddressinfo(
    116+                address_assert4['embedded']['address']
    117+                )
    


    practicalswift commented at 7:25 am on October 5, 2018:
    Since this is a new file - please run it through black to get it auto-formatted in accordance with PEP-8 :-)

    marcoagner commented at 12:40 pm on October 5, 2018:
    Hm, nice. Didn’t know this black, thanks. I was using Flake8. Besides the double-quotes for strings, it seems that black has a longer default line length, but I’m okay with (actually prefer) that. :) I will just rebase, re-run tests, and provide a new commit.
  42. rpc: creates possibility to preserve labels on importprivkey
    - changes importprivkey behavior to overwrite existent label if one
    is passed and keep existing ones if no label is passed
    
    - tests behavior of importprivkey on existing address labels and
    different same key destination
    a6b5ec18ff
  43. marcoagner commented at 1:39 pm on October 5, 2018: contributor
    wallet_basic.py passed locally but seems to have failed on appveyor :thinking:
  44. sipa commented at 3:10 am on November 11, 2018: member
    utACK a6b5ec18ff39ef3ccd19ec0e6db9ae00602d8938
  45. Empact commented at 6:25 am on November 13, 2018: member
    utACK a6b5ec1
  46. jonasschnelli commented at 7:51 am on November 13, 2018: contributor
    utACK a6b5ec18ff39ef3ccd19ec0e6db9ae00602d8938
  47. jonasschnelli merged this on Nov 13, 2018
  48. jonasschnelli closed this on Nov 13, 2018

  49. jonasschnelli referenced this in commit b60f4e3f09 on Nov 13, 2018
  50. deadalnix referenced this in commit e9e95047ac on May 21, 2020
  51. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

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: 2024-12-19 00:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me