wallet: addhdkey RPC to add just keys to wallets via new void(KEY) descriptor #29136

pull achow101 wants to merge 6 commits into bitcoin:master from achow101:sethdseed-void-descriptor changing 9 files +308 −1
  1. achow101 commented at 11:40 pm on December 22, 2023: member

    It is sometimes useful for the wallet to have keys that it can sign with but are not (initially) involved in any scripts, e.g. for setting up a multisig. Ryanofsky suggested A void(KEY) descriptor which allows for a key to be specified, but produces no scripts. These can be imported into the wallet, and subsequently retrieved with gethdkeys. Additionally, listdescriptors will output these descriptors so that they can be easily backed up.

    In order to make it easier for people to add HD keys to their wallet, and to generate a new one if they want to rotate their descriptors, an addhdkey RPC is also added. Without arguments, it will generate a new HD key and add it to the wallet via a void(KEY) descriptor. If provided a private key, it will construct the descriptor and add it to the wallet.

    See also: #26728 (comment)

    Based on #29130 as gethdkeys is useful for testing this.

  2. DrahtBot commented at 11:40 pm on December 22, 2023: contributor

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

    Code Coverage

    For detailed information about the code coverage, see the test coverage report.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #30343 (wallet, logging: Replace WalletLogPrintf() with LogInfo() by ryanofsky)
    • #30243 (Tr partial descriptors by Eunovo)
    • #28710 (Remove the legacy wallet and BDB dependency by achow101)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  3. DrahtBot added the label Wallet on Dec 22, 2023
  4. DrahtBot added the label CI failed on Dec 23, 2023
  5. ryanofsky commented at 4:40 am on December 23, 2023: contributor

    This is great, amazed you could implement this so quickly!

    I was thinking about the void(KEY) idea more today, and think it would be good to make 3 tweaks:

    1 - rename “void(KEY)” to “unused(KEY)” 2 - add logic to importdescriptors and generatewalletdescriptor to delete any unused(KEY) descriptor as soon as the KEY which it references is used by an new descriptor (taking into account both public and private parts of the key) 3 - add logic to importdescriptors to disallow importing an unused(KEY) if KEY is used by another descriptor.

    I think these changes would help make these descriptors easier to understand and also enhance backwards compatibility, because IIUC wallets containing unknown descriptor types can’t be opened by older software. Also keeping redundant descriptors in the wallet that were only temporarily needed is confusing.

    If making these tweaks isn’t possible or is not a good idea. I still think probably we should rename void(KEY) to data(KEY) or something like that. I think while “void” makes a certain amount of sense as programming jargon, it’s not really a familiar term and doesn’t describe the purpose of these descriptors, which is just to hold an inert piece of data, and not be used for generating or matching scriptpubkeys.

    I also have a number of ideas to improve the RPC interface for generating keys and descriptors, and will try to post them soon. (EDIT: now posted #29130 (review)). But this seems like a very good start and very functional.

  6. achow101 force-pushed on Jan 3, 2024
  7. DrahtBot removed the label CI failed on Jan 3, 2024
  8. achow101 force-pushed on Jan 4, 2024
  9. achow101 commented at 8:03 pm on January 4, 2024: member

    1 - rename “void(KEY)” to “unused(KEY)” 3 - add logic to importdescriptors to disallow importing an unused(KEY) if KEY is used by another descriptor.

    Done these. I’ve also added a further restriction that unused() cannot be import to a wallet without private keys. It isn’t useful in such wallets so I think it makes sense to disallow their import.

    2 - add logic to importdescriptors and generatewalletdescriptor to delete any unused(KEY) descriptor as soon as the KEY which it references is used by an new descriptor (taking into account both public and private parts of the key)

    Still working and thinking on this. However we’ve generally held to the policy of not deleting any records from the wallet since that could result in private keys being accidentally deleted. The only exception to that was adding encryption.

  10. achow101 force-pushed on Jan 4, 2024
  11. achow101 force-pushed on Jan 4, 2024
  12. DrahtBot added the label CI failed on Jan 4, 2024
  13. DrahtBot removed the label CI failed on Jan 4, 2024
  14. ryanofsky commented at 5:41 pm on January 8, 2024: contributor

    However we’ve generally held to the policy of not deleting any records from the wallet since that could result in private keys being accidentally deleted. The only exception to that was adding encryption.

    Oh, I didn’t know that but it makes sense.

    One approach you could take would just be to delete the descriptor from memory without actually deleting it from the database, and ignore it the next time the wallet is loaded. But a drawback of this would be that once addhdkey was used the wallet would be forever incompatible with older versions of the software, when one of the benefits of deleting the descriptor was to make wallets backward compatible.

    Another approach that might be acceptable could be to add a DatabaseBatch::MarkErased method to call instead of DatabaseBatch::Erase. This could just prepend a serialized string like const std::string TOMBSTONE{"tombstone"} to the key and otherwise leave the record unchanged.

    Or maybe just decide in this case that it is ok to delete a record after verifying all the information it contains is present in other records.

    Would also want to think about it more, though.

  15. DrahtBot added the label CI failed on Jan 15, 2024
  16. DrahtBot added the label Needs rebase on Feb 20, 2024
  17. achow101 force-pushed on Feb 20, 2024
  18. DrahtBot removed the label Needs rebase on Feb 20, 2024
  19. DrahtBot removed the label CI failed on Feb 20, 2024
  20. DrahtBot added the label Needs rebase on Mar 29, 2024
  21. achow101 force-pushed on Mar 29, 2024
  22. achow101 marked this as ready for review on Mar 29, 2024
  23. DrahtBot removed the label Needs rebase on Mar 29, 2024
  24. DrahtBot added the label Needs rebase on Aug 28, 2024
  25. achow101 force-pushed on Aug 29, 2024
  26. DrahtBot removed the label Needs rebase on Aug 29, 2024
  27. DrahtBot commented at 4:27 am on August 30, 2024: contributor

    🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/29446941801

    Make sure to run all tests locally, according to the documentation.

    The failure may happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  28. DrahtBot added the label CI failed on Aug 30, 2024
  29. achow101 force-pushed on Sep 3, 2024
  30. descriptor: Add unused(KEY) descriptor
    unused() descriptors do not have scriptPubKeys. Instead, the wallet uses
    them to store keys without having any scripts to watch for.
    1e951bfe19
  31. test: Simple test for importing unused(KEY) 187c9fc1ef
  32. achow101 force-pushed on Sep 10, 2024
  33. wallet: Add addhdkey RPC 43779af0f9
  34. test: Test for addhdkey 6317a72adb
  35. wallet, rpc: Disallow import of unused() if key already exists 5c4a0a3a5c
  36. wallet, rpc: Disallow importing unused() to wallets without privkeys 17de9e6f63
  37. achow101 force-pushed on Sep 18, 2024
  38. DrahtBot removed the label CI failed on Sep 18, 2024
  39. DrahtBot added the label CI failed on Oct 20, 2024
  40. DrahtBot removed the label CI failed on Oct 24, 2024

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-21 15:12 UTC

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