[Wallet] Add simplest BIP32/deterministic key generation implementation #8035

pull jonasschnelli wants to merge 4 commits into bitcoin:master from jonasschnelli:2016/05/simplest_hd changing 6 files +173 −4
  1. jonasschnelli commented at 9:21 AM on May 10, 2016: contributor

    Probably most simplest HD implementation.

    • New wallets will use hd/bip32 (enabling hd only possible during wallet creation/first start)
    • HD can be disabled with --usehd=0
    • Only hardened key derivation
    • Fixed keypath (m/0'/0'/k')
    • Only one additional database object (CHDChain) which contains the CKeyID for the master key together with the child key counter

    I'll add some tests once there are some conceptual acks (and also to keep the diff at a very minimum).

  2. jonasschnelli added the label Wallet on May 10, 2016
  3. jonasschnelli added this to the milestone 0.13.0 on May 10, 2016
  4. slush0 commented at 10:06 AM on May 10, 2016: none

    Nice minimalistic PR. One question though. Why to use m/0'/0'/i instead of something more standard? BIP32 proposes m/0'/0/i for external chains (I suppose Core in current implementation does not need internal/change chain). Or even better - use m/0/i, which is forward compatible with BIP44 (maybe Core will make it somedays). m/0/i is subset of BIP44 - an account.

  5. in src/wallet/wallet.cpp:None in ce6332ec0a outdated
    3103 | @@ -3036,6 +3104,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
    3104 |          strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
    3105 |      strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
    3106 |      strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
    3107 | +    strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after bip32. Has only affect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET));
    


    paveljanik commented at 10:15 AM on May 10, 2016:

    No need for strprintf. See previous line.


    jonasschnelli commented at 1:11 PM on May 10, 2016:

    Hmm... I have looked at walletbroadcast, there strprintf is also used. Isn't more flexible for the translation then?


    MarcoFalke commented at 1:31 PM on May 10, 2016:

    I think you want to strprintf(_(string)) the whole string and not two separate stings, as other languages might have different grammar. but consider it a nit.


    instagibbs commented at 2:53 PM on May 12, 2016:

    s/Has only affect/Only has effect/

  6. in src/wallet/walletdb.cpp:None in ce6332ec0a outdated
     603 | +        {
     604 | +            CHDChain chain;
     605 | +            ssValue >> chain;
     606 | +            if (!pwallet->SetHDChain(chain, true))
     607 | +            {
     608 | +                strErr = "Error reading wallet database: AddChain failed";
    


    paveljanik commented at 10:17 AM on May 10, 2016:

    s/AddChain/SetHDChain/

  7. in src/wallet/walletdb.cpp:None in ce6332ec0a outdated
     598 | @@ -599,6 +599,16 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
     599 |                  return false;
     600 |              }
     601 |          }
     602 | +        else if (strType == "hdchain")
    


    paveljanik commented at 10:20 AM on May 10, 2016:

    Repeating "hdchain" several times reminds me there was some patch redefining these as constants...


    laanwj commented at 11:02 AM on May 10, 2016:

    Which one? We did the redefine-magic-strings-as-constants it in other places, but also for the wallet?


    paveljanik commented at 11:12 AM on May 10, 2016:

    Yes, because some of them are repeated several times in the file. But maybe I'm remembering some other patch.


    paveljanik commented at 11:15 AM on May 10, 2016:

    Ah, it probably was #5707.


    jonasschnelli commented at 1:09 PM on May 10, 2016:

    Yes. I did refactor out these stings into constants serval times. But this should be done in another PR and hopefully after this has been merged.


    paveljanik commented at 5:24 PM on May 10, 2016:

    Definitely not for this PR, of course.

  8. paveljanik commented at 10:25 AM on May 10, 2016: contributor

    Concept ACK

    Nice, small, elegant 👍

  9. paveljanik commented at 10:52 AM on May 10, 2016: contributor

    What should RPC dumpwallet dump after this?

  10. paveljanik commented at 10:56 AM on May 10, 2016: contributor

    Some import path needed then.

  11. laanwj commented at 11:02 AM on May 10, 2016: member

    Concept ACK

  12. jonasschnelli commented at 1:18 PM on May 10, 2016: contributor

    @slush0: One reason for the current keypath is the use hardened-only key derivation. I personally think people overestimate the switch-wallet feature. Importing a bip32 master key together with a given keypath can be tricky (lookup window).

    But I agree. If and once this PR gets merged into master, next thing I would do is writing a PR that would make the keypath flexible.

    We could discuss the default keypath and the keypath flexibility in a such follow up PR.

    This PR only intent to solve the "backup problem" by using deterministic key derivation. So we could even think of using m/k'.

  13. jonasschnelli force-pushed on May 10, 2016
  14. jonasschnelli commented at 1:56 PM on May 10, 2016: contributor

    Fixed @paveljanik nits.

  15. slush0 commented at 2:19 PM on May 10, 2016: none

    I personally think people overestimate the switch-wallet feature. @jonasschnelli It's actually quite useful feature, and it may be even for Core. I can imagine somebody who'll have Qt wallet awfully out of sync and will need to get his funds ASAP. Then loading the backup to some other software like Multibit HD will do the job. BIP44 is actually being used by most of current wallets so heading towards the same structure makes sense.

    This PR only intent to solve the "backup problem"

    Fair point and I appreciate somebody is finally addressing it.

  16. in src/wallet/wallet.cpp:None in c3b8aa5869 outdated
    1086 | @@ -1051,6 +1087,37 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
    1087 |      return nChange;
    1088 |  }
    1089 |  
    1090 | +bool CWallet::SetHDMasterKey(const CKey& key)
    1091 | +{
    1092 | +    LOCK(cs_wallet);
    1093 | +
    1094 | +    // store the key as normal "key"/"ckey" object
    1095 | +    // in the the database
    


    paveljanik commented at 5:23 PM on May 10, 2016:

    the the

  17. in src/wallet/wallet.h:None in c3b8aa5869 outdated
      56 | @@ -57,6 +57,9 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2;
      57 |  static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
      58 |  static const bool DEFAULT_WALLETBROADCAST = true;
      59 |  
      60 | +//! if set, all keys will be deriven by using BIP32
    


    paveljanik commented at 5:24 PM on May 10, 2016:

    derived

  18. in src/wallet/walletdb.h:None in c3b8aa5869 outdated
      39 | @@ -40,6 +40,34 @@ enum DBErrors
      40 |      DB_NEED_REWRITE
      41 |  };
      42 |  
      43 | +/* simple hd chain data model */
      44 | +class CHDChain
      45 | +{
      46 | +public:
      47 | +    uint32_t nExternalChainCounter;
      48 | +    CKeyID  masterKeyID; /* master key hash160 */
    


    paveljanik commented at 5:25 PM on May 10, 2016:

    two spaces


    MarcoFalke commented at 5:30 PM on May 10, 2016:

    Maybe just clang-format the diff?

  19. jonasschnelli force-pushed on May 10, 2016
  20. jonasschnelli commented at 6:12 PM on May 10, 2016: contributor

    Force push fixed @paveljanik nits. Formatted some of the code with clang-format.

  21. in src/wallet/wallet.cpp:None in c3b8aa5869 outdated
     119 | +
     120 | +        // derive m/0'/0'
     121 | +        accountKey.Derive(externalChainChildKey, 0 | 0x80000000);
     122 | +
     123 | +        // derive child key at next index
     124 | +        externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | 0x80000000);
    


    sipa commented at 6:13 PM on May 10, 2016:

    I think you should check whether the derived key already exists in the keystore, and if so, try the next chaincounter. Otheriwse you'll give out the same keys twice after a backup restore.

    EDIT: nevermind, that's not going to work. we'll also need to make keypool entries be regenerated when one is encountered in the blockchain or mempool. I think we can defer that...


    jonasschnelli commented at 12:32 PM on May 11, 2016:

    I added a loop to derive the next key as long as its not known by the wallet. I think this is required otherwise we might run into an exception if someone restores a backup or has imported a derived key of a higher child index.

  22. achow101 commented at 12:17 PM on May 11, 2016: member

    Concept ACK

    So as I understand this, it won't affect the keys already in the wallet, right? It just generates all new keys using the HD master key?

    Also there should be an RPC command to dump the master private key.

  23. jonasschnelli commented at 12:20 PM on May 11, 2016: contributor

    @achow101: for now (this PR), HD will only be enabled when you create a new wallet (first start).

    Also there should be an RPC command to dump the master private key.

    I agree. Have a look at #6265 and #7273. This is my third try to get HD into Cores wallet. I think the way to go is this extremely simple basic step. We can add RPC/API changes later.

  24. jonasschnelli force-pushed on May 11, 2016
  25. jonasschnelli force-pushed on May 11, 2016
  26. in src/wallet/wallet.h:None in cc1df8fa6f outdated
     576 | @@ -574,6 +577,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
     577 |  
     578 |      void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
     579 |  
     580 | +    /* the hd chain data model (internal and external counters) */
    


    instagibbs commented at 2:50 PM on May 12, 2016:

    external only for now? (and in the other 2 places in the PR)

  27. in src/wallet/walletdb.h:None in cc1df8fa6f outdated
      39 | @@ -40,6 +40,35 @@ enum DBErrors
      40 |      DB_NEED_REWRITE
      41 |  };
      42 |  
      43 | +/* simple hd chain data model */
      44 | +class CHDChain
      45 | +{
      46 | +public:
      47 | +    uint32_t nExternalChainCounter;
      48 | +    CKeyID masterKeyID; /* master key hash160 */
    


    MarcoFalke commented at 2:59 PM on May 12, 2016:

    Nit: I think you want to use //!< when placing a trailing comment.

    https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md#doxygen-comments

  28. in src/wallet/wallet.cpp:None in cc1df8fa6f outdated
    1095 | +
    1096 | +    // store the key as normal "key"/"ckey" object
    1097 | +    // in the database
    1098 | +    // key metadata is not required
    1099 | +    CPubKey pubkey = key.GetPubKey();
    1100 | +    if (!AddKeyPubKey(key, pubkey))
    


    instagibbs commented at 3:03 PM on May 12, 2016:

    nit: simply calling AddKey should work here nevermind, wrong function


    sipa commented at 4:56 PM on June 1, 2016:

    I'd like to know why this comment does not apply.

    EDIT: because you need pubkey below anyway, ok!

  29. instagibbs commented at 3:14 PM on May 12, 2016: member

    utACK https://github.com/bitcoin/bitcoin/pull/8035/commits/cc1df8fa6f4849b65187f60a3cb4c83da3d16788

    Glad to see a really simple PR. Baby steps better than no steps.

  30. jonasschnelli commented at 6:56 PM on May 12, 2016: contributor

    Added a squash me commit with some non-code nit fixes.

  31. in src/wallet/wallet.cpp:None in cc1df8fa6f outdated
     108 | +
     109 | +        // try to get the master key
     110 | +        if (!GetKey(hdChain.masterKeyID, key))
     111 | +            throw std::runtime_error("CWallet::GenerateNewKey(): Master key not found");
     112 | +
     113 | +        assert(key.size() == 32);
    


    pstratem commented at 5:36 AM on May 17, 2016:

    Why is this an assertion but missing the master key is an exception?


    jonasschnelli commented at 5:43 AM on May 17, 2016:

    I agree. This assertion should be removed.

  32. in src/wallet/wallet.cpp:None in cc1df8fa6f outdated
     112 | +
     113 | +        assert(key.size() == 32);
     114 | +        masterKey.SetMaster(key.begin(), key.size());
     115 | +
     116 | +        // derive m/0'
     117 | +        masterKey.Derive(accountKey, 0 | 0x80000000);
    


    pstratem commented at 5:37 AM on May 17, 2016:

    Needs comment about hardened derivation.

  33. in src/wallet/wallet.cpp:None in cc1df8fa6f outdated
     130 | +
     131 | +        // update the chain model in the database
     132 | +        if (!CWalletDB(strWalletFile).WriteHDChain(hdChain))
     133 | +            throw std::runtime_error("CWallet::GenerateNewKey(): Writing HD chain model failed");
     134 | +    } else
     135 | +        secret.MakeNewKey(fCompressed);
    


    pstratem commented at 5:42 AM on May 17, 2016:

    Please add braces here for the else block.


    jonasschnelli commented at 7:40 AM on May 17, 2016:

    our clang format script accepted that. What's wrong with it? :-)


    MarcoFalke commented at 8:17 AM on May 17, 2016:

    I think that is what clang-tidy is supposed to do ;)

  34. jonasschnelli commented at 7:42 AM on May 17, 2016: contributor

    Added another squash-me commit with minor nit fixes.

  35. sipa commented at 7:55 AM on May 17, 2016: member

    @jonasschnelli clang-format does not reject anything, it just reformats.

  36. jonasschnelli commented at 8:11 AM on May 17, 2016: contributor

    @sipa: right! Sorry. I meant it didn't reformat the else part.

  37. sipa commented at 8:13 AM on May 17, 2016: member

    @jonasschnelli It can't reformat it, because all it does is change whitespace. What we want here is more than just changing whitespace, but there is no way to make clang do that (and also not make it yell about it). Just because a whitespace formatting tool accepts the code, doesn't mean it satisfies all our style guidelines. For example, it also does not check consistency of variable names.

  38. jonasschnelli force-pushed on May 17, 2016
  39. jonasschnelli commented at 11:07 AM on May 17, 2016: contributor

    Amend force pushed last squash-me commit with the else + bracket change.

  40. jonasschnelli force-pushed on May 17, 2016
  41. in src/wallet/wallet.cpp:None in d2f3c1ded1 outdated
     112 | +
     113 | +        masterKey.SetMaster(key.begin(), key.size());
     114 | +
     115 | +        // derive m/0'
     116 | +        // use hardened derivation (child keys > 0x80000000 are hardened after bip32)
     117 | +        masterKey.Derive(accountKey, 0 | 0x80000000);
    


    jtimon commented at 9:46 AM on May 22, 2016:

    Sorry, I don't understand this | 0x80000000 from the comments...


    instagibbs commented at 10:05 AM on May 22, 2016:

    Hardened keys are >= 0x80000000, not > according to bip32


    jonasschnelli commented at 10:06 AM on May 22, 2016:

    It's specified here: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions

    You can derive 2^32 key, child keys <= 2147483648 (<=0x80000000) are non-hardened key. Derived child keys > 2147483648 are hardened keys.

    This line: masterKey.Derive(accountKey, 0 | 0x80000000); .. is equal to .. masterKey.Derive(accountKey, 0 + 2147483648)


    MarcoFalke commented at 10:09 AM on May 22, 2016:

    I think the comment has a typo?


    jtimon commented at 10:27 AM on May 22, 2016:

    Oh, I forgot about this, thanks. IIRC, pycoin (what I've used for bip32 so far) used an asterisk in its interface for hardened keys. I wouldn't complain if the link was added to the comment, but maybe an appropriately named constant for 0x80000000 would be enough.


    sipa commented at 4:49 PM on June 1, 2016:

    Agree about adding a named constant.

  42. jtimon commented at 10:21 AM on May 22, 2016: contributor

    I still have limited knowledge of the wallet, but thanks to this being so simple I was able to review it and everything looks good. something-between-concept-and-ut ACK

  43. arowser commented at 8:43 AM on May 25, 2016: contributor

    Can one of the admins verify this patch?

  44. jonasschnelli force-pushed on May 31, 2016
  45. jonasschnelli commented at 8:45 AM on May 31, 2016: contributor

    Rebased. Squashed squash-me commits.

  46. fanquake commented at 8:57 AM on May 31, 2016: member

    This needs to be added to doc/bips.md. I can add it to #8121 if you'd rather not add additional commits.

  47. paveljanik commented at 11:44 AM on May 31, 2016: contributor

    Doesn't build here:

    wallet/wallet.cpp:3219:9: error: use of undeclared identifier 'RandAddSeedPerfmon'
    

    See #7891, it should be enough to remove it.

  48. MarcoFalke commented at 11:50 AM on May 31, 2016: member

    I don't think this should be added to doc/bips.md, as this pull does not add any interface at all. Though, the release notes should be updated.

  49. [Wallet] Add simplest BIP32/deterministic key generation implementation f19025106d
  50. in src/wallet/wallet.cpp:None in d89e8d5664 outdated
     111 | +            throw std::runtime_error("CWallet::GenerateNewKey(): Master key not found");
     112 | +
     113 | +        masterKey.SetMaster(key.begin(), key.size());
     114 | +
     115 | +        // derive m/0'
     116 | +        // use hardened derivation (child keys > 0x80000000 are hardened after bip32)
    


    MarcoFalke commented at 11:51 AM on May 31, 2016:

    comment-nit: It is >= 0x80000000

  51. jonasschnelli force-pushed on May 31, 2016
  52. jonasschnelli commented at 12:47 PM on May 31, 2016: contributor

    Fixed and force pushed the rebase issue RandAddSeedPerfmon (#7891).

  53. sipa commented at 5:03 PM on June 1, 2016: member

    utACK, will test. There are a few nits left to address.

  54. [Wallet] use constant for bip32 hardened key limit c022e5b15d
  55. jonasschnelli commented at 6:33 PM on June 1, 2016: contributor

    Added a commit that...

    • ... uses a constant for 0x80000000 (hardened child index range limit)
    • ... extend the source code comment
    • ... simplify 0 | 0x80000000 in 0x80000000 (and is now a const)
  56. laanwj commented at 8:24 AM on June 9, 2016: member

    This is a high-profile feature. Definitely needs mention in release notes.

  57. jonasschnelli commented at 8:24 AM on June 9, 2016: contributor

    Okay. I'll write something for the release notes.

  58. jonasschnelli force-pushed on Jun 10, 2016
  59. jonasschnelli force-pushed on Jun 10, 2016
  60. jonasschnelli commented at 9:09 AM on June 10, 2016: contributor

    Added a part in the release-notes.md (thanks for lang review). Updated the bips.md.

  61. in doc/release-notes.md:None in e9ec7b2aa0 outdated
     116 | +-----------------------------------------
     117 | +Newly created wallets will use hierarchical deterministic key generation
     118 | +according to BIP32 (keypath m/0'/0'/k').
     119 | +Existing wallets will still use traditional key generation.
     120 | +
     121 | +Backups, regardless of when they have been created, can therefore be
    


    MarcoFalke commented at 9:26 AM on June 10, 2016:

    Nit: Let's call it "Backups of HD wallets"?

  62. in doc/release-notes.md:None in e9ec7b2aa0 outdated
     117 | +Newly created wallets will use hierarchical deterministic key generation
     118 | +according to BIP32 (keypath m/0'/0'/k').
     119 | +Existing wallets will still use traditional key generation.
     120 | +
     121 | +Backups, regardless of when they have been created, can therefore be
     122 | +used to re-generate all possible private keys, even the ones who hasn't
    


    MarcoFalke commented at 9:28 AM on June 10, 2016:

    "even the ones which haven't already"?

  63. jonasschnelli force-pushed on Jun 10, 2016
  64. [Docs] Add release notes and bip update for Bip32/HD wallets 17c0131fad
  65. jonasschnelli force-pushed on Jun 10, 2016
  66. in src/wallet/wallet.cpp:None in e9ec7b2aa0 outdated
    3131 | @@ -3058,6 +3132,7 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
    3132 |          strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
    3133 |      strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
    3134 |      strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
    3135 | +    strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after bip32. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET));
    


    MarcoFalke commented at 9:31 AM on June 10, 2016:

    Nit: Might as well call this -createhdwallet or similar. Using a lengthy and more verbose option does not hurt if it is expected to be changed from its default only very rarely.


    jonasschnelli commented at 9:32 AM on June 10, 2016:

    Agree that -createhdwallet would make more sense.

  67. sipa commented at 2:40 PM on June 11, 2016: member

    I prefer -usehd, but adding a check that if it is given in case there already exists a wallet, we verify that it matches that wallet. That way you won't ever get any surprises, just set -usehd, and you're sure you'll always use HD derivation, set -usehd=0 and you're sure you'll never.

    That's similar to how -txindex works: if given, it must match the existing tree.

  68. MarcoFalke commented at 10:51 AM on June 12, 2016: member

    @sipa If you add the check that your wallet must match with -usehd you can't set the default to true, I assume. Otherwise the a user switching from 0.12.1 to 0.13 would see a InitError or InitWarning pop up on every start.

  69. sipa commented at 10:55 AM on June 12, 2016: member

    If -usehd is not explicitly given, default to whatever is the current wallet (or true for new wallets). if it is explicitly given, it must match the existing wallet.

  70. MarcoFalke commented at 11:35 AM on June 12, 2016: member

    Ok makes sense. (But that is different from txindex, as I remember you can't set -txindex=1 once and then remove it, to make it default to true. I may be mistaken but I should better not hijack this pull's discussion.)

  71. instagibbs commented at 11:39 AM on June 12, 2016: member

    @MarcoFalke it's slightly different, yes, but txindex behavior wouldn't make sense since you can't "reindex" your HD wallet to legacy.

  72. jonasschnelli commented at 2:30 PM on June 13, 2016: contributor

    Added a commit. Now the PR detects if a user likes to disabled hd (with -usehd=0) when using a hd wallet.dat file. The PR also detects if a user likes to enable hd (with -usehd=1) when using a non hd wallet.dat file.

    The node will shutdown/stop init in a such mismatch situation.

  73. MarcoFalke commented at 3:45 PM on June 13, 2016: member

    utACK 71ff55fcc2245e03c786d7e0312755e812d9de8e

  74. Detect -usehd mismatches when wallet.dat already exists afcd77e179
  75. in src/wallet/wallet.cpp:None in 71ff55fcc2 outdated
    3235 | @@ -3236,6 +3236,14 @@ bool CWallet::InitLoadWallet()
    3236 |  
    3237 |          walletInstance->SetBestChain(chainActive.GetLocator());
    3238 |      }
    3239 | +    else
    


    laanwj commented at 6:45 AM on June 14, 2016:

    Can be simplified a bit:

    else if (mapArgs.count("-usehd")) {
        bool useHd = GetBoolArg("-usehd", DEFAULT_USEHD);
        if (!walletInstance->hdChain.masterKeyID.IsNull() && !useHD)
            return InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), walletFile));
        if (walletInstance->hdChain.masterKeyID.IsNull() && useHD)
            return InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), walletFile));
    }
    

    (also please introduce a DEFAULT_USEHD constant)


    jonasschnelli commented at 6:56 AM on June 14, 2016:

    Thanks. Much simpler. Force push updated last commit.

  76. jonasschnelli force-pushed on Jun 14, 2016
  77. laanwj commented at 9:44 AM on June 14, 2016: member

    utACK afcd77e

    Even though this wallet change is reasonably risky, I think this has received enough review for correctness, and it should be merged now to make sure it gets more actual testing.

  78. laanwj merged this on Jun 14, 2016
  79. laanwj closed this on Jun 14, 2016

  80. laanwj referenced this in commit b67a4726df on Jun 14, 2016
  81. gmaxwell commented at 9:40 AM on June 15, 2016: contributor

    Post merge utACK. Will also test.

  82. schildbach commented at 6:22 PM on June 15, 2016: contributor

    Just found out about this PR. Would like to clarify the keypath: It's purpose number is 0' not 0? ((m/0'/0'/k') not (m/0/0'/k'))

    I'm asking because otherwise it could be incompatible to how bitcoinj derives addresses.

  83. jonasschnelli commented at 2:12 PM on June 17, 2016: contributor

    @schildbach: We have decided to go with a "hardened only derivation" version for the first implementation. Using m/0/0'/k' would introduce the risk of revealing extended pubkey m/0 together with a non extended child privatekey resulting in revealing the whole chain of keys.

    On top of that, I personally think importing a xpriv into another wallet in order to "reconstruct everything" is not a very good concept.

  84. schildbach commented at 7:42 PM on June 17, 2016: contributor

    @jonasschnelli Yes that's fine. I just wanted to make sure there is no "partial overlap" with the bitcoinj impl.

  85. rebroad commented at 3:54 PM on June 25, 2016: contributor

    So, how does one import a BIP32 master key into an existing wallet?

  86. diegoviola commented at 4:10 PM on June 25, 2016: contributor

    I'm switching to Core (from Electrum) after this lands in 0.13, thanks for your efforts.

  87. laanwj commented at 12:27 PM on June 27, 2016: member

    So, how does one import a BIP32 master key into an existing wallet?

    That functionality currently doesn't exist. Please read the OP: this is the smallest possible change to introduce BIP32 into Bitcoin Core. This made it realistic to get it reviewed and merged in a small timespan. More functionality can be added later.

  88. in src/wallet/wallet.cpp:None in afcd77e179
    1099 | +    // store the key as normal "key"/"ckey" object
    1100 | +    // in the database
    1101 | +    // key metadata is not required
    1102 | +    CPubKey pubkey = key.GetPubKey();
    1103 | +    if (!AddKeyPubKey(key, pubkey))
    1104 | +        throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
    


    MarcoFalke commented at 5:20 PM on July 8, 2016:

    Nit: Wrong function name

  89. TheBlueMatt commented at 1:48 AM on July 19, 2016: member

    Post-merge review comments, sorry :/ (continued from IRC): There is also a comment on #8324 and other related PRs here.

    • The use of an ECDSA private key (stored as such) as the master seed is somewhat strange...While not strictly an issue, I'm concerned about the ability of users to dump this as a regular key, potentially causing some interesting behavior.
    • The way I read the current code, every time we go to GenerateNewKey() we will iterate over every key we have already generated before generating a new one (as we never call SetHDChain to store the updated counter on disk)....anyone with a test hd wallet lying around want to see what their disk-counter is?
    • I think IsKeyType should be changed to include hdchain, not add an explicit hdchain check in ::Recover, since we probably definitely want it in ::LoadWallet as well.
    • The duplication of the old CTransaction READWRITE(this->nVersion); nVersion = this->nVersion; logic seems strange to me. I always found that a kinda funny way to do things and was glad to see it go in SegWit...Its "hidden functionality" and I'd prefer if we handled that very explicitly instead of via this strange hack.

    I think all but the first could easily be fixed even now, if we decide they are, indeed, issues.

  90. jonasschnelli commented at 5:32 AM on July 19, 2016: contributor

    Thanks for the post-merge review Matt.

    The use of an ECDSA private key (stored as such) as the master seed is somewhat strange...While not strictly an issue, I'm concerned about the ability of users to dump this as a regular key, potentially causing some interesting behavior.

    Yes. Agree. This was done after two of my former PR did not made it into the master (https://github.com/bitcoin/bitcoin/pull/6265 #7273) and I was looking for a simpler solutions. There is a PR to identify the seed when dumping (https://github.com/bitcoin/bitcoin/pull/8206).

    The way I read the current code, every time we go to GenerateNewKey() we will iterate over every key we have already generated before generating a new one (as we never call SetHDChain to store the updated counter on disk)....anyone with a test hd wallet lying around want to see what their disk-counter is?

    This is to ensure we don't re-generate an already existing key (there are some cases where this would be possible otherwise). The iteration should be painless. It's a std::map count() of an in memory map of all the key.

  91. TheBlueMatt commented at 11:51 PM on July 19, 2016: member

    re: GenerateNewKey(): Not sure what your response was about (seems to be communication failure there), but it was pointed out to me that I missed the save line and was incorrect.

  92. zihad944 commented at 9:10 PM on August 11, 2018: none

    I foget my sceond wallet passwor. Thats why i cant get backup. I need help

  93. jeandudey commented at 9:16 PM on August 11, 2018: none

    @zihad944 what problem do you have specifically, what do you mean by "my second wallet password"?

  94. sorawee1970 commented at 2:42 PM on May 16, 2019: none

    src/wallet/walletdb.h

  95. fanquake deleted a comment on May 16, 2019
  96. DrahtBot locked this on Dec 16, 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: 2026-04-13 18:15 UTC

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