rpc: Enable wallet import on pruned nodes

Co-authored-by: João Barbosa <joao.paulo.barbosa@gmail.com>
Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
Aurèle Oulès 2022-10-02 18:21:11 +02:00
parent 1801d8c3c9
commit e6906fcf9e
No known key found for this signature in database
GPG Key ID: 55F3976F7001D998

View File

@ -93,6 +93,22 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver,
} }
} }
static void EnsureBlockDataFromTime(const CWallet& wallet, int64_t timestamp)
{
auto& chain{wallet.chain()};
if (!chain.havePruned()) {
return;
}
int height{0};
const bool found{chain.findFirstBlockWithTimeAndHeight(timestamp - TIMESTAMP_WINDOW, 0, FoundBlock().height(height))};
uint256 tip_hash{WITH_LOCK(wallet.cs_wallet, return wallet.GetLastBlockHash())};
if (found && !chain.hasBlocks(tip_hash, height)) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Pruned blocks from height %d required to import keys. Use RPC call getblockchaininfo to determine your pruned height.", height));
}
}
RPCHelpMan importprivkey() RPCHelpMan importprivkey()
{ {
return RPCHelpMan{"importprivkey", return RPCHelpMan{"importprivkey",
@ -504,13 +520,6 @@ RPCHelpMan importwallet()
EnsureLegacyScriptPubKeyMan(*pwallet, true); EnsureLegacyScriptPubKeyMan(*pwallet, true);
if (pwallet->chain().havePruned()) {
// Exit early and print an error.
// If a block is pruned after this check, we will import the key(s),
// but fail the rescan with a generic error.
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when blocks are pruned");
}
WalletRescanReserver reserver(*pwallet); WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) { if (!reserver.reserve()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
@ -565,15 +574,18 @@ RPCHelpMan importwallet()
fLabel = true; fLabel = true;
} }
} }
nTimeBegin = std::min(nTimeBegin, nTime);
keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel)); keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
} else if(IsHex(vstr[0])) { } else if(IsHex(vstr[0])) {
std::vector<unsigned char> vData(ParseHex(vstr[0])); std::vector<unsigned char> vData(ParseHex(vstr[0]));
CScript script = CScript(vData.begin(), vData.end()); CScript script = CScript(vData.begin(), vData.end());
int64_t birth_time = ParseISO8601DateTime(vstr[1]); int64_t birth_time = ParseISO8601DateTime(vstr[1]);
if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
scripts.push_back(std::pair<CScript, int64_t>(script, birth_time)); scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
} }
} }
file.close(); file.close();
EnsureBlockDataFromTime(*pwallet, nTimeBegin);
// We now know whether we are importing private keys, so we can error if private keys are disabled // 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)) { if (keys.size() > 0 && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
@ -602,8 +614,6 @@ RPCHelpMan importwallet()
if (has_label) if (has_label)
pwallet->SetAddressBook(PKHash(keyid), label, "receive"); pwallet->SetAddressBook(PKHash(keyid), label, "receive");
nTimeBegin = std::min(nTimeBegin, time);
progress++; progress++;
} }
for (const auto& script_pair : scripts) { for (const auto& script_pair : scripts) {
@ -616,9 +626,6 @@ RPCHelpMan importwallet()
fGood = false; fGood = false;
continue; continue;
} }
if (time > 0) {
nTimeBegin = std::min(nTimeBegin, time);
}
progress++; progress++;
} }