@@ -87,6 +87,18 @@ bool ScriptPubKeyMan::GetKeyFromPool(CPubKey& result, bool internal)
8787 return true ;
8888}
8989
90+ bool ScriptPubKeyMan::GetReservedKey (bool internal, int64_t & index, CKeyPool& keypool)
91+ {
92+ if (!CanGetAddresses (internal)) {
93+ return false ;
94+ }
95+
96+ if (!ReserveKeyFromKeyPool (index, keypool, internal)) {
97+ return false ;
98+ }
99+ return true ;
100+ }
101+
90102bool ScriptPubKeyMan::ReserveKeyFromKeyPool (int64_t & nIndex, CKeyPool& keypool, bool fRequestedInternal )
91103{
92104 nIndex = -1 ;
@@ -238,7 +250,6 @@ bool ScriptPubKeyMan::TopUp(unsigned int kpSize)
238250 }
239251 if (missingInternal + missingExternal > 0 ) {
240252 LogPrintf (" keypool added %d keys (%d internal), size=%u (%u internal)\n " , missingInternal + missingExternal, missingInternal, setInternalKeyPool.size () + setExternalKeyPool.size () + set_pre_split_keypool.size (), setInternalKeyPool.size ());
241- // LogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size());
242253 }
243254 }
244255 // TODO: Implement this.
@@ -305,13 +316,14 @@ const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
305316void ScriptPubKeyMan::DeriveNewChildKey (CWalletDB &batch, CKeyMetadata& metadata, CKey& secret, bool internal)
306317{
307318 AssertLockHeld (wallet->cs_wallet );
308- // For now we use a fixed keypath scheme of m/0'/0'/k
309- // TODO: Change it to bip44.
319+ // Use BIP44 keypath scheme i.e. m / purpose' / coin_type' / account' / change / address_index
310320 CKey seed; // seed (256bit)
311321 CExtKey masterKey; // hd master key
312- CExtKey accountKey; // key at m/0'
313- CExtKey chainChildKey; // key at m/0'/0' (external) or m/0'/1' (internal)
314- CExtKey childKey; // key at m/0'/0'/<n>'
322+ CExtKey purposeKey; // key at m/purpose' --> key at m/44'
323+ CExtKey cointypeKey; // key at m/purpose'/coin_type' --> key at m/44'/119'
324+ CExtKey accountKey; // key at m/purpose'/coin_type'/account' ---> key at m/44'/119'/account_num
325+ CExtKey changeKey; // key at m/purpose'/coin_type'/account'/change ---> key at m/44'/119'/account_num/change', external = 0' or internal = 1'.
326+ CExtKey childKey; // key at m/purpose'/coin_type'/account'/change/address_index ---> key at m/44'/119'/account_num/change'/<n>'
315327
316328 // try to get the seed
317329 if (!wallet->GetKey (hdChain.GetID (), seed))
@@ -321,27 +333,30 @@ void ScriptPubKeyMan::DeriveNewChildKey(CWalletDB &batch, CKeyMetadata& metadata
321333
322334 // derive m/0'
323335 // use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
324- masterKey.Derive (accountKey, BIP32_HARDENED_KEY_LIMIT);
325-
326- // derive m/0'/0' (external chain) OR m/0'/1' (internal chain)
336+ masterKey.Derive (purposeKey, 44 | BIP32_HARDENED_KEY_LIMIT);
337+ // derive m/purpose'/coin_type'
338+ purposeKey.Derive (cointypeKey, 119 | BIP32_HARDENED_KEY_LIMIT);
339+ // derive m/purpose'/coin_type'/account' // Hardcoded to account 0 for now.
340+ cointypeKey.Derive (accountKey, 0 | BIP32_HARDENED_KEY_LIMIT);
341+ // derive m/purpose'/coin_type'/account'/change
327342 assert (internal ? wallet->CanSupportFeature (FEATURE_HD_SPLIT) : true );
328- accountKey.Derive (chainChildKey , BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0 ));
343+ accountKey.Derive (changeKey , BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0 ));
329344
330345 // derive child key at next index, skip keys already known to the wallet
331346 do {
332347 // always derive hardened keys
333348 // childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
334349 // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
335350 if (internal) {
336- chainChildKey .Derive (childKey, hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
351+ changeKey .Derive (childKey, hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
337352 // metadata.hdKeypath = "m/0'/1'/" + std::to_string(hdChain.nInternalChainCounter) + "'";
338353 metadata.key_origin .path .push_back (0 | BIP32_HARDENED_KEY_LIMIT);
339354 metadata.key_origin .path .push_back (1 | BIP32_HARDENED_KEY_LIMIT);
340355 metadata.key_origin .path .push_back (hdChain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
341356 hdChain.nInternalChainCounter ++;
342357 }
343358 else {
344- chainChildKey .Derive (childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
359+ changeKey .Derive (childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
345360 // metadata.hdKeypath = "m/0'/0'/" + std::to_string(hdChain.nExternalChainCounter) + "'";
346361 metadata.key_origin .path .push_back (0 | BIP32_HARDENED_KEY_LIMIT);
347362 metadata.key_origin .path .push_back (0 | BIP32_HARDENED_KEY_LIMIT);
0 commit comments