Add option to disable private keys during internal wallet creation

This commit is contained in:
Jonas Schnelli
2017-05-05 08:53:39 +02:00
parent 9995a602a6
commit cebefba085
4 changed files with 95 additions and 28 deletions

View File

@@ -164,6 +164,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal)
{
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
AssertLockHeld(cs_wallet); // mapKeyMetadata
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
@@ -1465,6 +1466,7 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
CPubKey CWallet::GenerateNewSeed()
{
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
CKey key;
key.MakeNewKey(true);
return DeriveNewSeed(key);
@@ -1539,13 +1541,19 @@ bool CWallet::IsWalletFlagSet(uint64_t flag)
return (m_wallet_flags & flag);
}
void CWallet::SetWalletFlags(uint64_t overwriteFlags, bool memonly)
bool CWallet::SetWalletFlags(uint64_t overwriteFlags, bool memonly)
{
LOCK(cs_wallet);
m_wallet_flags = overwriteFlags;
if (((overwriteFlags & g_known_wallet_flags) >> 32) ^ (overwriteFlags >> 32)) {
// contains unknown non-tolerable wallet flags
return false;
}
if (!memonly && !WalletBatch(*database).WriteWalletFlags(m_wallet_flags)) {
throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
}
return true;
}
int64_t CWalletTx::GetTxTime() const
@@ -2793,6 +2801,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
// post-backup change.
// Reserve a new key pair from key pool
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
strFailReason = _("Can't generate a change-address key. Private keys are disabled for this wallet.");
return false;
}
CPubKey vchPubKey;
bool ret;
ret = reservekey.GetReservedKey(vchPubKey, true);
@@ -3193,7 +3205,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
LOCK(cs_KeyStore);
// This wallet is in its first run if all of these are empty
fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty();
fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && mapWatchKeys.empty() && setWatchOnly.empty() && mapScripts.empty() && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
}
if (nLoadWalletRet != DBErrors::LOAD_OK)
@@ -3317,6 +3329,9 @@ const std::string& CWallet::GetLabelName(const CScript& scriptPubKey) const
*/
bool CWallet::NewKeyPool()
{
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
return false;
}
{
LOCK(cs_wallet);
WalletBatch batch(*database);
@@ -3375,6 +3390,9 @@ void CWallet::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
bool CWallet::TopUpKeyPool(unsigned int kpSize)
{
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
return false;
}
{
LOCK(cs_wallet);
@@ -3499,6 +3517,10 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
{
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
return false;
}
CKeyPool keypool;
{
LOCK(cs_wallet);
@@ -4038,7 +4060,7 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
}
std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path, uint64_t wallet_creation_flags)
{
const std::string& walletFile = name;
@@ -4163,18 +4185,33 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
}
walletInstance->SetMinVersion(FEATURE_LATEST);
// generate a new seed
CPubKey seed = walletInstance->GenerateNewSeed();
if (!walletInstance->SetHDSeed(seed))
throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed");
if ((wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
//selective allow to set flags
walletInstance->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
} else {
// generate a new seed
CPubKey seed = walletInstance->GenerateNewSeed();
if (!walletInstance->SetHDSeed(seed)) {
throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed");
}
}
// Top up the keypool
if (!walletInstance->TopUpKeyPool()) {
if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !walletInstance->TopUpKeyPool()) {
InitError(_("Unable to generate initial keys") += "\n");
return nullptr;
}
walletInstance->ChainStateFlushed(chainActive.GetLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile));
return NULL;
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
LOCK(walletInstance->cs_KeyStore);
if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) {
InitWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
}
} else if (gArgs.IsArgSet("-usehd")) {
bool useHD = gArgs.GetBoolArg("-usehd", true);
if (walletInstance->IsHDEnabled() && !useHD) {