Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 311 Lines • ▼ Show 20 Lines | do { | ||||
// child-index-range | // child-index-range | ||||
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649 | // example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649 | ||||
if (internal) { | if (internal) { | ||||
chainChildKey.Derive(childKey, hdChain.nInternalChainCounter | | chainChildKey.Derive(childKey, hdChain.nInternalChainCounter | | ||||
BIP32_HARDENED_KEY_LIMIT); | BIP32_HARDENED_KEY_LIMIT); | ||||
metadata.hdKeypath = "m/0'/1'/" + | metadata.hdKeypath = "m/0'/1'/" + | ||||
std::to_string(hdChain.nInternalChainCounter) + | std::to_string(hdChain.nInternalChainCounter) + | ||||
"'"; | "'"; | ||||
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT); | |||||
metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT); | |||||
metadata.key_origin.path.push_back(hdChain.nInternalChainCounter | | |||||
BIP32_HARDENED_KEY_LIMIT); | |||||
hdChain.nInternalChainCounter++; | hdChain.nInternalChainCounter++; | ||||
} else { | } else { | ||||
chainChildKey.Derive(childKey, hdChain.nExternalChainCounter | | chainChildKey.Derive(childKey, hdChain.nExternalChainCounter | | ||||
BIP32_HARDENED_KEY_LIMIT); | BIP32_HARDENED_KEY_LIMIT); | ||||
metadata.hdKeypath = "m/0'/0'/" + | metadata.hdKeypath = "m/0'/0'/" + | ||||
std::to_string(hdChain.nExternalChainCounter) + | std::to_string(hdChain.nExternalChainCounter) + | ||||
"'"; | "'"; | ||||
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT); | |||||
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT); | |||||
metadata.key_origin.path.push_back(hdChain.nExternalChainCounter | | |||||
BIP32_HARDENED_KEY_LIMIT); | |||||
hdChain.nExternalChainCounter++; | hdChain.nExternalChainCounter++; | ||||
} | } | ||||
} while (HaveKey(childKey.key.GetPubKey().GetID())); | } while (HaveKey(childKey.key.GetPubKey().GetID())); | ||||
secret = childKey.key; | secret = childKey.key; | ||||
metadata.hd_seed_id = hdChain.seed_id; | metadata.hd_seed_id = hdChain.seed_id; | ||||
CKeyID master_id = masterKey.key.GetPubKey().GetID(); | |||||
std::copy(master_id.begin(), master_id.begin() + 4, | |||||
metadata.key_origin.fingerprint); | |||||
metadata.has_key_origin = true; | |||||
// update the chain model in the database | // update the chain model in the database | ||||
if (!batch.WriteHDChain(hdChain)) { | if (!batch.WriteHDChain(hdChain)) { | ||||
throw std::runtime_error(std::string(__func__) + | throw std::runtime_error(std::string(__func__) + | ||||
": Writing HD chain model failed"); | ": Writing HD chain model failed"); | ||||
} | } | ||||
} | } | ||||
bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret, | bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret, | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | |||||
// Writes a keymetadata for a public key. overwrite specifies whether to | // Writes a keymetadata for a public key. overwrite specifies whether to | ||||
// overwrite an existing metadata for that key if there exists one. | // overwrite an existing metadata for that key if there exists one. | ||||
bool CWallet::WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, | bool CWallet::WriteKeyMetadata(const CKeyMetadata &meta, const CPubKey &pubkey, | ||||
const bool overwrite) { | const bool overwrite) { | ||||
return WalletBatch(*database).WriteKeyMetadata(meta, pubkey, overwrite); | return WalletBatch(*database).WriteKeyMetadata(meta, pubkey, overwrite); | ||||
} | } | ||||
void CWallet::UpgradeKeyMetadata() { | |||||
// mapKeyMetadata | |||||
AssertLockHeld(cs_wallet); | |||||
if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) { | |||||
return; | |||||
} | |||||
for (auto &meta_pair : mapKeyMetadata) { | |||||
CKeyMetadata &meta = meta_pair.second; | |||||
// If the hdKeypath is "s", that's the seed and it doesn't have a key | |||||
// origin | |||||
if (!meta.hd_seed_id.IsNull() && !meta.has_key_origin && | |||||
meta.hdKeypath != "s") { | |||||
CKey key; | |||||
GetKey(meta.hd_seed_id, key); | |||||
CExtKey masterKey; | |||||
masterKey.SetSeed(key.begin(), key.size()); | |||||
// Add to map | |||||
CKeyID master_id = masterKey.key.GetPubKey().GetID(); | |||||
std::copy(master_id.begin(), master_id.begin() + 4, | |||||
meta.key_origin.fingerprint); | |||||
if (!ParseHDKeypath(meta.hdKeypath, meta.key_origin.path)) { | |||||
throw std::runtime_error("Invalid stored hdKeypath"); | |||||
} | |||||
meta.has_key_origin = true; | |||||
if (meta.nVersion < CKeyMetadata::VERSION_WITH_KEY_ORIGIN) { | |||||
meta.nVersion = CKeyMetadata::VERSION_WITH_KEY_ORIGIN; | |||||
} | |||||
// Write meta to wallet | |||||
CPubKey pubkey; | |||||
if (GetPubKey(meta_pair.first, pubkey)) { | |||||
WriteKeyMetadata(meta, pubkey, true); | |||||
} | |||||
} | |||||
} | |||||
SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA); | |||||
} | |||||
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, | bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, | ||||
const std::vector<uint8_t> &vchCryptedSecret) { | const std::vector<uint8_t> &vchCryptedSecret) { | ||||
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); | return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); | ||||
} | } | ||||
/** | /** | ||||
* Update wallet first key creation time. This should be called whenever keys | * Update wallet first key creation time. This should be called whenever keys | ||||
* are added to the wallet, with the oldest key creation time. | * are added to the wallet, with the oldest key creation time. | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | CKeyingMaterial _vMasterKey; | ||||
return false; | return false; | ||||
} | } | ||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, | if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, | ||||
_vMasterKey)) { | _vMasterKey)) { | ||||
// try another master key | // try another master key | ||||
continue; | continue; | ||||
} | } | ||||
if (CCryptoKeyStore::Unlock(_vMasterKey, accept_no_keys)) { | if (CCryptoKeyStore::Unlock(_vMasterKey, accept_no_keys)) { | ||||
// Now that we've unlocked, upgrade the key metadata | |||||
UpgradeKeyMetadata(); | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,015 Lines • ▼ Show 20 Lines | CPubKey CWallet::DeriveNewSeed(const CKey &key) { | ||||
CKeyMetadata metadata(nCreationTime); | CKeyMetadata metadata(nCreationTime); | ||||
// Calculate the seed | // Calculate the seed | ||||
CPubKey seed = key.GetPubKey(); | CPubKey seed = key.GetPubKey(); | ||||
assert(key.VerifyPubKey(seed)); | assert(key.VerifyPubKey(seed)); | ||||
// Set the hd keypath to "s" -> Seed, refers the seed to itself | // Set the hd keypath to "s" -> Seed, refers the seed to itself | ||||
metadata.hdKeypath = "s"; | metadata.hdKeypath = "s"; | ||||
metadata.has_key_origin = false; | |||||
metadata.hd_seed_id = seed.GetID(); | metadata.hd_seed_id = seed.GetID(); | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
// mem store the metadata | // mem store the metadata | ||||
mapKeyMetadata[seed.GetID()] = metadata; | mapKeyMetadata[seed.GetID()] = metadata; | ||||
// Write the key&metadata to the database | // Write the key&metadata to the database | ||||
▲ Show 20 Lines • Show All 3,330 Lines • ▼ Show 20 Lines | bool CWallet::GetKeyOrigin(const CKeyID &keyID, KeyOriginInfo &info) const { | ||||
CKeyMetadata meta; | CKeyMetadata meta; | ||||
{ | { | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
auto it = mapKeyMetadata.find(keyID); | auto it = mapKeyMetadata.find(keyID); | ||||
if (it != mapKeyMetadata.end()) { | if (it != mapKeyMetadata.end()) { | ||||
meta = it->second; | meta = it->second; | ||||
} | } | ||||
} | } | ||||
if (!meta.hdKeypath.empty()) { | if (meta.has_key_origin) { | ||||
if (!ParseHDKeypath(meta.hdKeypath, info.path)) { | std::copy(meta.key_origin.fingerprint, meta.key_origin.fingerprint + 4, | ||||
return false; | info.fingerprint); | ||||
} | info.path = meta.key_origin.path; | ||||
// Get the proper master key id | |||||
CKey key; | |||||
GetKey(meta.hd_seed_id, key); | |||||
CExtKey masterKey; | |||||
masterKey.SetSeed(key.begin(), key.size()); | |||||
// Compute identifier | |||||
CKeyID masterid = masterKey.key.GetPubKey().GetID(); | |||||
std::copy(masterid.begin(), masterid.begin() + 4, info.fingerprint); | |||||
} else { | } else { | ||||
// Single pubkeys get the master fingerprint of themselves | // Single pubkeys get the master fingerprint of themselves | ||||
std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint); | std::copy(keyID.begin(), keyID.begin() + 4, info.fingerprint); | ||||
} | } | ||||
return true; | return true; | ||||
} | } |