Skip to content

Commit e6906fc

Browse files
aureleoulespromagryanofsky
committed
rpc: Enable wallet import on pruned nodes
Co-authored-by: João Barbosa <[email protected]> Co-authored-by: Ryan Ofsky <[email protected]>
1 parent 1801d8c commit e6906fc

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

src/wallet/rpc/backup.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver,
9393
}
9494
}
9595

96+
static void EnsureBlockDataFromTime(const CWallet& wallet, int64_t timestamp)
97+
{
98+
auto& chain{wallet.chain()};
99+
if (!chain.havePruned()) {
100+
return;
101+
}
102+
103+
int height{0};
104+
const bool found{chain.findFirstBlockWithTimeAndHeight(timestamp - TIMESTAMP_WINDOW, 0, FoundBlock().height(height))};
105+
106+
uint256 tip_hash{WITH_LOCK(wallet.cs_wallet, return wallet.GetLastBlockHash())};
107+
if (found && !chain.hasBlocks(tip_hash, height)) {
108+
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));
109+
}
110+
}
111+
96112
RPCHelpMan importprivkey()
97113
{
98114
return RPCHelpMan{"importprivkey",
@@ -504,13 +520,6 @@ RPCHelpMan importwallet()
504520

505521
EnsureLegacyScriptPubKeyMan(*pwallet, true);
506522

507-
if (pwallet->chain().havePruned()) {
508-
// Exit early and print an error.
509-
// If a block is pruned after this check, we will import the key(s),
510-
// but fail the rescan with a generic error.
511-
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when blocks are pruned");
512-
}
513-
514523
WalletRescanReserver reserver(*pwallet);
515524
if (!reserver.reserve()) {
516525
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
@@ -565,15 +574,18 @@ RPCHelpMan importwallet()
565574
fLabel = true;
566575
}
567576
}
577+
nTimeBegin = std::min(nTimeBegin, nTime);
568578
keys.push_back(std::make_tuple(key, nTime, fLabel, strLabel));
569579
} else if(IsHex(vstr[0])) {
570580
std::vector<unsigned char> vData(ParseHex(vstr[0]));
571581
CScript script = CScript(vData.begin(), vData.end());
572582
int64_t birth_time = ParseISO8601DateTime(vstr[1]);
583+
if (birth_time > 0) nTimeBegin = std::min(nTimeBegin, birth_time);
573584
scripts.push_back(std::pair<CScript, int64_t>(script, birth_time));
574585
}
575586
}
576587
file.close();
588+
EnsureBlockDataFromTime(*pwallet, nTimeBegin);
577589
// We now know whether we are importing private keys, so we can error if private keys are disabled
578590
if (keys.size() > 0 && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
579591
pwallet->chain().showProgress("", 100, false); // hide progress dialog in GUI
@@ -602,8 +614,6 @@ RPCHelpMan importwallet()
602614

603615
if (has_label)
604616
pwallet->SetAddressBook(PKHash(keyid), label, "receive");
605-
606-
nTimeBegin = std::min(nTimeBegin, time);
607617
progress++;
608618
}
609619
for (const auto& script_pair : scripts) {
@@ -616,9 +626,6 @@ RPCHelpMan importwallet()
616626
fGood = false;
617627
continue;
618628
}
619-
if (time > 0) {
620-
nTimeBegin = std::min(nTimeBegin, time);
621-
}
622629

623630
progress++;
624631
}

0 commit comments

Comments
 (0)