mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 02:25:40 +01:00
Remove CCryptoKeyStore and move all of it's functionality into CWallet
Instead of having a separate CCryptoKeyStore that handles the encryption stuff, just roll it all into CWallet.
This commit is contained in:
parent
37a79a4fcc
commit
8f5b81e6ed
@ -476,7 +476,7 @@ public:
|
||||
}
|
||||
std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) override
|
||||
{
|
||||
return MakeHandler(m_wallet->NotifyStatusChanged.connect([fn](CCryptoKeyStore*) { fn(); }));
|
||||
return MakeHandler(m_wallet->NotifyStatusChanged.connect([fn](CWallet*) { fn(); }));
|
||||
}
|
||||
std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) override
|
||||
{
|
||||
|
@ -107,8 +107,7 @@ bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingM
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
|
||||
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext)
|
||||
{
|
||||
CCrypter cKeyCrypter;
|
||||
std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE);
|
||||
@ -118,7 +117,7 @@ static bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMateri
|
||||
return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext);
|
||||
}
|
||||
|
||||
static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
|
||||
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
|
||||
{
|
||||
CCrypter cKeyCrypter;
|
||||
std::vector<unsigned char> chIV(WALLET_CRYPTO_IV_SIZE);
|
||||
@ -128,7 +127,7 @@ static bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<u
|
||||
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
|
||||
}
|
||||
|
||||
static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
|
||||
bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
|
||||
{
|
||||
CKeyingMaterial vchSecret;
|
||||
if(!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
|
||||
@ -140,188 +139,3 @@ static bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsi
|
||||
key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
|
||||
return key.VerifyPubKey(vchPubKey);
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::SetCrypted()
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!mapKeys.empty())
|
||||
return false;
|
||||
fUseCrypto = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::IsLocked() const
|
||||
{
|
||||
if (!IsCrypted()) {
|
||||
return false;
|
||||
}
|
||||
LOCK(cs_KeyStore);
|
||||
return vMasterKey.empty();
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
bool keyPass = mapCryptedKeys.empty(); // Always pass when there are no encrypted keys
|
||||
bool keyFail = false;
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKey key;
|
||||
if (!DecryptKey(vMasterKeyIn, vchCryptedSecret, vchPubKey, key))
|
||||
{
|
||||
keyFail = true;
|
||||
break;
|
||||
}
|
||||
keyPass = true;
|
||||
if (fDecryptionThoroughlyChecked)
|
||||
break;
|
||||
}
|
||||
if (keyPass && keyFail)
|
||||
{
|
||||
LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
|
||||
throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
|
||||
}
|
||||
if (keyFail || (!keyPass && !accept_no_keys))
|
||||
return false;
|
||||
vMasterKey = vMasterKeyIn;
|
||||
fDecryptionThoroughlyChecked = true;
|
||||
}
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::AddKeyPubKey(key, pubkey);
|
||||
}
|
||||
|
||||
if (IsLocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AddCryptedKey(pubkey, vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
ImplicitlyLearnRelatedKeyScripts(vchPubKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::HaveKey(const CKeyID &address) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::HaveKey(address);
|
||||
}
|
||||
return mapCryptedKeys.count(address) > 0;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::GetKey(address, keyOut);
|
||||
}
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
vchPubKeyOut = (*mi).second.first;
|
||||
return true;
|
||||
}
|
||||
// Check for watch-only pubkeys
|
||||
return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
|
||||
}
|
||||
|
||||
std::set<CKeyID> CCryptoKeyStore::GetKeys() const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::GetKeys();
|
||||
}
|
||||
std::set<CKeyID> set_address;
|
||||
for (const auto& mi : mapCryptedKeys) {
|
||||
set_address.insert(mi.first);
|
||||
}
|
||||
return set_address;
|
||||
}
|
||||
|
||||
bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
||||
fUseCrypto = true;
|
||||
for (const KeyMap::value_type& mKey : mapKeys)
|
||||
{
|
||||
const CKey &key = mKey.second;
|
||||
CPubKey vchPubKey = key.GetPubKey();
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
mapKeys.clear();
|
||||
return true;
|
||||
}
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
|
||||
const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
|
||||
const unsigned int WALLET_CRYPTO_IV_SIZE = 16;
|
||||
@ -111,54 +109,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** Keystore which keeps the private keys encrypted.
|
||||
* It derives from the basic key store, which is used if no encryption is active.
|
||||
*/
|
||||
class CCryptoKeyStore : public FillableSigningProvider
|
||||
{
|
||||
private:
|
||||
|
||||
CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore);
|
||||
|
||||
//! if fUseCrypto is true, mapKeys must be empty
|
||||
//! if fUseCrypto is false, vMasterKey must be empty
|
||||
std::atomic<bool> fUseCrypto;
|
||||
|
||||
//! keeps track of whether Unlock has run a thorough check before
|
||||
bool fDecryptionThoroughlyChecked;
|
||||
|
||||
protected:
|
||||
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||
|
||||
bool SetCrypted();
|
||||
|
||||
//! will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false);
|
||||
CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
|
||||
|
||||
public:
|
||||
CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsCrypted() const { return fUseCrypto; }
|
||||
bool IsLocked() const;
|
||||
bool Lock();
|
||||
|
||||
virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
|
||||
bool HaveKey(const CKeyID &address) const override;
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
||||
std::set<CKeyID> GetKeys() const override;
|
||||
|
||||
/**
|
||||
* Wallet status (encrypted, locked) changed.
|
||||
* Note: Called without locks held.
|
||||
*/
|
||||
boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
|
||||
};
|
||||
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
|
||||
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
|
||||
bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key);
|
||||
|
||||
#endif // BITCOIN_WALLET_CRYPTER_H
|
||||
|
@ -294,14 +294,14 @@ bool CWallet::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& secret, const C
|
||||
// Make sure we aren't adding private keys to private key disabled wallets
|
||||
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
|
||||
|
||||
// CCryptoKeyStore has no concept of wallet databases, but calls AddCryptedKey
|
||||
// FillableSigningProvider has no concept of wallet databases, but calls AddCryptedKey
|
||||
// which is overridden below. To avoid flushes, the database handle is
|
||||
// tunneled through to it.
|
||||
bool needsDB = !encrypted_batch;
|
||||
if (needsDB) {
|
||||
encrypted_batch = &batch;
|
||||
}
|
||||
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey)) {
|
||||
if (!AddKeyPubKeyInner(secret, pubkey)) {
|
||||
if (needsDB) encrypted_batch = nullptr;
|
||||
return false;
|
||||
}
|
||||
@ -336,7 +336,7 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
|
||||
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
|
||||
const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
if (!AddCryptedKeyInner(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
@ -404,7 +404,7 @@ void CWallet::UpgradeKeyMetadata()
|
||||
|
||||
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
|
||||
return AddCryptedKeyInner(vchPubKey, vchCryptedSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,7 +431,7 @@ bool CWallet::AddCScript(const CScript& redeemScript)
|
||||
|
||||
bool CWallet::AddCScriptWithDB(WalletBatch& batch, const CScript& redeemScript)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddCScript(redeemScript))
|
||||
if (!FillableSigningProvider::AddCScript(redeemScript))
|
||||
return false;
|
||||
if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
|
||||
UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
|
||||
@ -452,12 +452,12 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
|
||||
return true;
|
||||
}
|
||||
|
||||
return CCryptoKeyStore::AddCScript(redeemScript);
|
||||
return FillableSigningProvider::AddCScript(redeemScript);
|
||||
}
|
||||
|
||||
bool CWallet::AddWatchOnlyWithDB(WalletBatch &batch, const CScript& dest)
|
||||
{
|
||||
if (!CCryptoKeyStore::AddWatchOnly(dest))
|
||||
if (!FillableSigningProvider::AddWatchOnly(dest))
|
||||
return false;
|
||||
const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)];
|
||||
UpdateTimeFirstKey(meta.nCreateTime);
|
||||
@ -490,7 +490,7 @@ bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
|
||||
bool CWallet::RemoveWatchOnly(const CScript &dest)
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
if (!CCryptoKeyStore::RemoveWatchOnly(dest))
|
||||
if (!FillableSigningProvider::RemoveWatchOnly(dest))
|
||||
return false;
|
||||
if (!HaveWatchOnly())
|
||||
NotifyWatchonlyChanged(false);
|
||||
@ -502,7 +502,7 @@ bool CWallet::RemoveWatchOnly(const CScript &dest)
|
||||
|
||||
bool CWallet::LoadWatchOnly(const CScript &dest)
|
||||
{
|
||||
return CCryptoKeyStore::AddWatchOnly(dest);
|
||||
return FillableSigningProvider::AddWatchOnly(dest);
|
||||
}
|
||||
|
||||
bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
|
||||
@ -518,7 +518,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_key
|
||||
return false;
|
||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
|
||||
continue; // try another master key
|
||||
if (CCryptoKeyStore::Unlock(_vMasterKey, accept_no_keys)) {
|
||||
if (Unlock(_vMasterKey, accept_no_keys)) {
|
||||
// Now that we've unlocked, upgrade the key metadata
|
||||
UpgradeKeyMetadata();
|
||||
return true;
|
||||
@ -544,7 +544,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||
return false;
|
||||
if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
|
||||
return false;
|
||||
if (CCryptoKeyStore::Unlock(_vMasterKey))
|
||||
if (Unlock(_vMasterKey))
|
||||
{
|
||||
int64_t nStartTime = GetTimeMillis();
|
||||
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
|
||||
@ -4588,3 +4588,188 @@ bool CWallet::AddKeyOriginWithDB(WalletBatch& batch, const CPubKey& pubkey, cons
|
||||
mapKeyMetadata[pubkey.GetID()].hdKeypath = WriteHDKeypath(info.path);
|
||||
return batch.WriteKeyMetadata(mapKeyMetadata[pubkey.GetID()], pubkey, true);
|
||||
}
|
||||
|
||||
bool CWallet::SetCrypted()
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (fUseCrypto)
|
||||
return true;
|
||||
if (!mapKeys.empty())
|
||||
return false;
|
||||
fUseCrypto = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::IsLocked() const
|
||||
{
|
||||
if (!IsCrypted()) {
|
||||
return false;
|
||||
}
|
||||
LOCK(cs_KeyStore);
|
||||
return vMasterKey.empty();
|
||||
}
|
||||
|
||||
bool CWallet::Lock()
|
||||
{
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
vMasterKey.clear();
|
||||
}
|
||||
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys)
|
||||
{
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted())
|
||||
return false;
|
||||
|
||||
bool keyPass = mapCryptedKeys.empty(); // Always pass when there are no encrypted keys
|
||||
bool keyFail = false;
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
|
||||
for (; mi != mapCryptedKeys.end(); ++mi)
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
CKey key;
|
||||
if (!DecryptKey(vMasterKeyIn, vchCryptedSecret, vchPubKey, key))
|
||||
{
|
||||
keyFail = true;
|
||||
break;
|
||||
}
|
||||
keyPass = true;
|
||||
if (fDecryptionThoroughlyChecked)
|
||||
break;
|
||||
}
|
||||
if (keyPass && keyFail)
|
||||
{
|
||||
LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n");
|
||||
throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt.");
|
||||
}
|
||||
if (keyFail || (!keyPass && !accept_no_keys))
|
||||
return false;
|
||||
vMasterKey = vMasterKeyIn;
|
||||
fDecryptionThoroughlyChecked = true;
|
||||
}
|
||||
NotifyStatusChanged(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::HaveKey(const CKeyID &address) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::HaveKey(address);
|
||||
}
|
||||
return mapCryptedKeys.count(address) > 0;
|
||||
}
|
||||
|
||||
bool CWallet::GetKey(const CKeyID &address, CKey& keyOut) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::GetKey(address, keyOut);
|
||||
}
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
const CPubKey &vchPubKey = (*mi).second.first;
|
||||
const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
|
||||
return DecryptKey(vMasterKey, vchCryptedSecret, vchPubKey, keyOut);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CWallet::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted())
|
||||
return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
|
||||
|
||||
CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
|
||||
if (mi != mapCryptedKeys.end())
|
||||
{
|
||||
vchPubKeyOut = (*mi).second.first;
|
||||
return true;
|
||||
}
|
||||
// Check for watch-only pubkeys
|
||||
return FillableSigningProvider::GetPubKey(address, vchPubKeyOut);
|
||||
}
|
||||
|
||||
std::set<CKeyID> CWallet::GetKeys() const
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::GetKeys();
|
||||
}
|
||||
std::set<CKeyID> set_address;
|
||||
for (const auto& mi : mapCryptedKeys) {
|
||||
set_address.insert(mi.first);
|
||||
}
|
||||
return set_address;
|
||||
}
|
||||
|
||||
bool CWallet::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!mapCryptedKeys.empty() || IsCrypted())
|
||||
return false;
|
||||
|
||||
fUseCrypto = true;
|
||||
for (const KeyMap::value_type& mKey : mapKeys)
|
||||
{
|
||||
const CKey &key = mKey.second;
|
||||
CPubKey vchPubKey = key.GetPubKey();
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
|
||||
return false;
|
||||
if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
|
||||
return false;
|
||||
}
|
||||
mapKeys.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!IsCrypted()) {
|
||||
return FillableSigningProvider::AddKeyPubKey(key, pubkey);
|
||||
}
|
||||
|
||||
if (IsLocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> vchCryptedSecret;
|
||||
CKeyingMaterial vchSecret(key.begin(), key.end());
|
||||
if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AddCryptedKey(pubkey, vchCryptedSecret)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CWallet::AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
if (!SetCrypted()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
|
||||
ImplicitlyLearnRelatedKeyScripts(vchPubKey);
|
||||
return true;
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
//! Explicitly unload and delete the wallet.
|
||||
//! Blocks the current thread after signaling the unload intent so that all
|
||||
//! wallet clients release the wallet.
|
||||
@ -709,9 +711,31 @@ class WalletRescanReserver; //forward declarations for ScanForWalletTransactions
|
||||
* A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
|
||||
* and provides the ability to create new transactions.
|
||||
*/
|
||||
class CWallet final : public CCryptoKeyStore, private interfaces::Chain::Notifications
|
||||
class CWallet final : public FillableSigningProvider, private interfaces::Chain::Notifications
|
||||
{
|
||||
private:
|
||||
CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore);
|
||||
|
||||
//! if fUseCrypto is true, mapKeys must be empty
|
||||
//! if fUseCrypto is false, vMasterKey must be empty
|
||||
std::atomic<bool> fUseCrypto;
|
||||
|
||||
//! keeps track of whether Unlock has run a thorough check before
|
||||
bool fDecryptionThoroughlyChecked;
|
||||
|
||||
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
|
||||
|
||||
bool SetCrypted();
|
||||
|
||||
//! will encrypt previously unencrypted keys
|
||||
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
|
||||
|
||||
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false);
|
||||
CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
|
||||
|
||||
bool AddCryptedKeyInner(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool AddKeyPubKeyInner(const CKey& key, const CPubKey &pubkey);
|
||||
|
||||
std::atomic<bool> fAbortRescan{false};
|
||||
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
|
||||
std::atomic<int64_t> m_scanning_start{0};
|
||||
@ -879,7 +903,9 @@ public:
|
||||
|
||||
/** Construct wallet with specified name and database implementation. */
|
||||
CWallet(interfaces::Chain* chain, const WalletLocation& location, std::unique_ptr<WalletDatabase> database)
|
||||
: m_chain(chain),
|
||||
: fUseCrypto(false),
|
||||
fDecryptionThoroughlyChecked(false),
|
||||
m_chain(chain),
|
||||
m_location(location),
|
||||
database(std::move(database))
|
||||
{
|
||||
@ -893,6 +919,10 @@ public:
|
||||
encrypted_batch = nullptr;
|
||||
}
|
||||
|
||||
bool IsCrypted() const { return fUseCrypto; }
|
||||
bool IsLocked() const;
|
||||
bool Lock();
|
||||
|
||||
std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
|
||||
|
||||
typedef std::multimap<int64_t, CWalletTx*> TxItems;
|
||||
@ -975,7 +1005,7 @@ public:
|
||||
//! Adds a key to the store, and saves it to disk.
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
|
||||
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return AddKeyPubKeyInner(key, pubkey); }
|
||||
//! Load metadata (used by LoadWallet)
|
||||
void LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
@ -986,9 +1016,13 @@ public:
|
||||
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! Adds an encrypted key to the store, and saves it to disk.
|
||||
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) override;
|
||||
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
//! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||
bool GetKey(const CKeyID &address, CKey& keyOut) const override;
|
||||
bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const override;
|
||||
bool HaveKey(const CKeyID &address) const override;
|
||||
std::set<CKeyID> GetKeys() const override;
|
||||
bool AddCScript(const CScript& redeemScript) override;
|
||||
bool LoadCScript(const CScript& redeemScript);
|
||||
|
||||
@ -1232,6 +1266,12 @@ public:
|
||||
/** Keypool has new keys */
|
||||
boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
|
||||
|
||||
/**
|
||||
* Wallet status (encrypted, locked) changed.
|
||||
* Note: Called without locks held.
|
||||
*/
|
||||
boost::signals2::signal<void (CWallet* wallet)> NotifyStatusChanged;
|
||||
|
||||
/** Inquire whether this wallet broadcasts transactions. */
|
||||
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
|
||||
/** Set whether this wallet broadcasts transactions. */
|
||||
|
Loading…
Reference in New Issue
Block a user