aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/rpcdump.cpp104
-rw-r--r--src/wallet/rpcwallet.cpp4
-rw-r--r--src/wallet/wallet.cpp9
3 files changed, 79 insertions, 38 deletions
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 2e62a6979f..32c36ceaeb 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -134,6 +134,9 @@ UniValue importprivkey(const JSONRPCRequest& request)
},
}.ToString());
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
+ }
WalletRescanReserver reserver(pwallet);
bool fRescan = true;
@@ -587,8 +590,10 @@ UniValue importwallet(const JSONRPCRequest& request)
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
// we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
uiInterface.ShowProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
+ std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys;
+ std::vector<std::pair<CScript, int64_t>> scripts;
while (file.good()) {
- uiInterface.ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
+ uiInterface.ShowProgress("", std::max(1, std::min(50, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
std::string line;
std::getline(file, line);
if (line.empty() || line[0] == '#')
@@ -600,13 +605,6 @@ UniValue importwallet(const JSONRPCRequest& request)
continue;
CKey key = DecodeSecret(vstr[0]);
if (key.IsValid()) {
- CPubKey pubkey = key.GetPubKey();
- assert(key.VerifyPubKey(pubkey));
- CKeyID keyid = pubkey.GetID();
- if (pwallet->HaveKey(keyid)) {
- pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
- continue;
- }
int64_t nTime = DecodeDumpTime(vstr[1]);
std::string strLabel;
bool fLabel = true;
@@ -622,36 +620,67 @@ UniValue importwallet(const JSONRPCRequest& request)
fLabel = true;
}
}
- pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(keyid));
- if (!pwallet->AddKeyPubKey(key, pubkey)) {
- fGood = false;
- continue;
- }
- pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
- if (fLabel)
- pwallet->SetAddressBook(keyid, strLabel, "receive");
- nTimeBegin = std::min(nTimeBegin, nTime);
+ keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
} else if(IsHex(vstr[0])) {
- std::vector<unsigned char> vData(ParseHex(vstr[0]));
- CScript script = CScript(vData.begin(), vData.end());
- CScriptID id(script);
- if (pwallet->HaveCScript(id)) {
- pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", vstr[0]);
- continue;
- }
- if(!pwallet->AddCScript(script)) {
- pwallet->WalletLogPrintf("Error importing script %s\n", vstr[0]);
- fGood = false;
- continue;
- }
- int64_t birth_time = DecodeDumpTime(vstr[1]);
- if (birth_time > 0) {
- pwallet->m_script_metadata[id].nCreateTime = birth_time;
- nTimeBegin = std::min(nTimeBegin, birth_time);
- }
+ std::vector<unsigned char> vData(ParseHex(vstr[0]));
+ CScript script = CScript(vData.begin(), vData.end());
+ int64_t birth_time = DecodeDumpTime(vstr[1]);
+ scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
}
}
file.close();
+ // We now know whether we are importing private keys, so we can error if private keys are disabled
+ if (keys.size() > 0 && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
+ throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when private keys are disabled");
+ }
+ double total = (double)(keys.size() + scripts.size());
+ double progress = 0;
+ for (const auto& key_tuple : keys) {
+ uiInterface.ShowProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false);
+ const CKey& key = std::get<0>(key_tuple);
+ int64_t time = std::get<1>(key_tuple);
+ bool has_label = std::get<2>(key_tuple);
+ std::string label = std::get<3>(key_tuple);
+
+ CPubKey pubkey = key.GetPubKey();
+ assert(key.VerifyPubKey(pubkey));
+ CKeyID keyid = pubkey.GetID();
+ if (pwallet->HaveKey(keyid)) {
+ pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
+ continue;
+ }
+ pwallet->WalletLogPrintf("Importing %s...\n", EncodeDestination(keyid));
+ if (!pwallet->AddKeyPubKey(key, pubkey)) {
+ fGood = false;
+ continue;
+ }
+ pwallet->mapKeyMetadata[keyid].nCreateTime = time;
+ if (has_label)
+ pwallet->SetAddressBook(keyid, label, "receive");
+ nTimeBegin = std::min(nTimeBegin, time);
+ progress++;
+ }
+ for (const auto& script_pair : scripts) {
+ uiInterface.ShowProgress("", std::max(50, std::min(75, (int)((progress / total) * 100) + 50)), false);
+ const CScript& script = script_pair.first;
+ int64_t time = script_pair.second;
+ CScriptID id(script);
+ if (pwallet->HaveCScript(id)) {
+ pwallet->WalletLogPrintf("Skipping import of %s (script already present)\n", HexStr(script));
+ continue;
+ }
+ if(!pwallet->AddCScript(script)) {
+ pwallet->WalletLogPrintf("Error importing script %s\n", HexStr(script));
+ fGood = false;
+ continue;
+ }
+ if (time > 0) {
+ pwallet->m_script_metadata[id].nCreateTime = time;
+ nTimeBegin = std::min(nTimeBegin, time);
+ }
+ progress++;
+ }
uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
pwallet->UpdateTimeFirstKey(nTimeBegin);
}
@@ -785,7 +814,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD);
file << strprintf("# * Created on %s\n", FormatISO8601DateTime(GetTime()));
const Optional<int> tip_height = locked_chain->getHeight();
- file << strprintf("# * Best block at time of backup was %i (%s),\n", tip_height.value_or(-1), tip_height ? locked_chain->getBlockHash(*tip_height).ToString() : "(missing block hash)");
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", tip_height.get_value_or(-1), tip_height ? locked_chain->getBlockHash(*tip_height).ToString() : "(missing block hash)");
file << strprintf("# mined on %s\n", tip_height ? FormatISO8601DateTime(locked_chain->getBlockTime(*tip_height)) : "(missing block time)");
file << "\n";
@@ -958,6 +987,11 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false;
const std::string& label = data.exists("label") ? data["label"].get_str() : "";
+ // If private keys are disabled, abort if private keys are being imported
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
+ }
+
// Generate the script and destination for the scriptPubKey provided
CScript script;
CTxDestination dest;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 213765209c..c96a9b0aff 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -3872,6 +3872,10 @@ UniValue sethdseed(const JSONRPCRequest& request)
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download");
}
+ if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed to a wallet with private keys disabled");
+ }
+
auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 5c379aacd6..9b643be69a 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -251,6 +251,9 @@ bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const C
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
+ // 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
// which is overridden below. To avoid flushes, the database handle is
// tunneled through to it.
@@ -1717,10 +1720,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
}
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI
if (block_height && fAbortRescan) {
- WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height.value_or(0), progress_current);
+ WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height.get_value_or(0), progress_current);
result.status = ScanResult::USER_ABORT;
} else if (block_height && ShutdownRequested()) {
- WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height.value_or(0), progress_current);
+ WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height.get_value_or(0), progress_current);
result.status = ScanResult::USER_ABORT;
}
}
@@ -2581,7 +2584,7 @@ static bool IsCurrentForAntiFeeSniping(interfaces::Chain::Lock& locked_chain)
*/
static uint32_t GetLocktimeForNewTransaction(interfaces::Chain::Lock& locked_chain)
{
- uint32_t const height = locked_chain.getHeight().value_or(-1);
+ uint32_t const height = locked_chain.getHeight().get_value_or(-1);
uint32_t locktime;
// Discourage fee sniping.
//