|
|
@ -100,6 +100,29 @@ CPubKey CWallet::GenerateNewKey() |
|
|
|
|
|
|
|
|
|
|
|
// use HD key derivation if HD was enabled during wallet creation
|
|
|
|
// use HD key derivation if HD was enabled during wallet creation
|
|
|
|
if (IsHDEnabled()) { |
|
|
|
if (IsHDEnabled()) { |
|
|
|
|
|
|
|
DeriveNewChildKey(metadata, secret); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
secret.MakeNewKey(fCompressed); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Compressed public keys were introduced in version 0.6.0
|
|
|
|
|
|
|
|
if (fCompressed) |
|
|
|
|
|
|
|
SetMinVersion(FEATURE_COMPRPUBKEY); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CPubKey pubkey = secret.GetPubKey(); |
|
|
|
|
|
|
|
assert(secret.VerifyPubKey(pubkey)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mapKeyMetadata[pubkey.GetID()] = metadata; |
|
|
|
|
|
|
|
if (!nTimeFirstKey || nCreationTime < nTimeFirstKey) |
|
|
|
|
|
|
|
nTimeFirstKey = nCreationTime; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!AddKeyPubKey(secret, pubkey)) |
|
|
|
|
|
|
|
throw std::runtime_error(std::string(__func__) + ": AddKey failed"); |
|
|
|
|
|
|
|
return pubkey; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CWallet::DeriveNewChildKey(CKeyMetadata& metadata, CKey& secret) |
|
|
|
|
|
|
|
{ |
|
|
|
// for now we use a fixed keypath scheme of m/0'/0'/k
|
|
|
|
// for now we use a fixed keypath scheme of m/0'/0'/k
|
|
|
|
CKey key; //master key seed (256bit)
|
|
|
|
CKey key; //master key seed (256bit)
|
|
|
|
CExtKey masterKey; //hd master key
|
|
|
|
CExtKey masterKey; //hd master key
|
|
|
@ -121,40 +144,21 @@ CPubKey CWallet::GenerateNewKey() |
|
|
|
accountKey.Derive(externalChainChildKey, BIP32_HARDENED_KEY_LIMIT); |
|
|
|
accountKey.Derive(externalChainChildKey, BIP32_HARDENED_KEY_LIMIT); |
|
|
|
|
|
|
|
|
|
|
|
// derive child key at next index, skip keys already known to the wallet
|
|
|
|
// derive child key at next index, skip keys already known to the wallet
|
|
|
|
do |
|
|
|
do { |
|
|
|
{ |
|
|
|
|
|
|
|
// always derive hardened keys
|
|
|
|
// always derive hardened keys
|
|
|
|
// childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
|
|
|
|
// childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
|
|
|
|
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
|
|
|
|
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
|
|
|
|
externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT); |
|
|
|
externalChainChildKey.Derive(childKey, hdChain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT); |
|
|
|
metadata.hdKeypath = "m/0'/0'/"+std::to_string(hdChain.nExternalChainCounter)+"'"; |
|
|
|
metadata.hdKeypath = "m/0'/0'/" + std::to_string(hdChain.nExternalChainCounter) + "'"; |
|
|
|
metadata.hdMasterKeyID = hdChain.masterKeyID; |
|
|
|
metadata.hdMasterKeyID = hdChain.masterKeyID; |
|
|
|
// increment childkey index
|
|
|
|
// increment childkey index
|
|
|
|
hdChain.nExternalChainCounter++; |
|
|
|
hdChain.nExternalChainCounter++; |
|
|
|
} while(HaveKey(childKey.key.GetPubKey().GetID())); |
|
|
|
} while (HaveKey(childKey.key.GetPubKey().GetID())); |
|
|
|
secret = childKey.key; |
|
|
|
secret = childKey.key; |
|
|
|
|
|
|
|
|
|
|
|
// update the chain model in the database
|
|
|
|
// update the chain model in the database
|
|
|
|
if (!CWalletDB(strWalletFile).WriteHDChain(hdChain)) |
|
|
|
if (!CWalletDB(strWalletFile).WriteHDChain(hdChain)) |
|
|
|
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); |
|
|
|
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); |
|
|
|
} else { |
|
|
|
|
|
|
|
secret.MakeNewKey(fCompressed); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Compressed public keys were introduced in version 0.6.0
|
|
|
|
|
|
|
|
if (fCompressed) |
|
|
|
|
|
|
|
SetMinVersion(FEATURE_COMPRPUBKEY); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CPubKey pubkey = secret.GetPubKey(); |
|
|
|
|
|
|
|
assert(secret.VerifyPubKey(pubkey)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mapKeyMetadata[pubkey.GetID()] = metadata; |
|
|
|
|
|
|
|
if (!nTimeFirstKey || nCreationTime < nTimeFirstKey) |
|
|
|
|
|
|
|
nTimeFirstKey = nCreationTime; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!AddKeyPubKey(secret, pubkey)) |
|
|
|
|
|
|
|
throw std::runtime_error(std::string(__func__) + ": AddKey failed"); |
|
|
|
|
|
|
|
return pubkey; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) |
|
|
|
bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) |
|
|
|