rpc: Add unloadwallet RPC
This commit is contained in:
parent
537efe19e6
commit
6608c369b1
3 changed files with 68 additions and 4 deletions
|
@ -3076,7 +3076,7 @@ static UniValue listwallets(const JSONRPCRequest& request)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue loadwallet(const JSONRPCRequest& request)
|
static UniValue loadwallet(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() != 1)
|
if (request.fHelp || request.params.size() != 1)
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
|
@ -3123,7 +3123,7 @@ UniValue loadwallet(const JSONRPCRequest& request)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue createwallet(const JSONRPCRequest& request)
|
static UniValue createwallet(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() != 1) {
|
if (request.fHelp || request.params.size() != 1) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
|
@ -3170,6 +3170,55 @@ UniValue createwallet(const JSONRPCRequest& request)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UniValue unloadwallet(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
if (request.fHelp || request.params.size() > 1) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"unloadwallet ( \"wallet_name\" )\n"
|
||||||
|
"Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
|
||||||
|
"Specifying the wallet name on a wallet endpoint is invalid."
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"wallet_name\" (string, optional) The name of the wallet to unload.\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli("unloadwallet", "wallet_name")
|
||||||
|
+ HelpExampleRpc("unloadwallet", "wallet_name")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string wallet_name;
|
||||||
|
if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
|
||||||
|
if (!request.params[0].isNull()) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wallet_name = request.params[0].get_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<CWallet> wallet = GetWallet(wallet_name);
|
||||||
|
if (!wallet) {
|
||||||
|
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release the "main" shared pointer and prevent further notifications.
|
||||||
|
// Note that any attempt to load the same wallet would fail until the wallet
|
||||||
|
// is destroyed (see CheckUniqueFileid).
|
||||||
|
if (!RemoveWallet(wallet)) {
|
||||||
|
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
|
||||||
|
}
|
||||||
|
UnregisterValidationInterface(wallet.get());
|
||||||
|
|
||||||
|
// The wallet can be in use so it's not possible to explicitly unload here.
|
||||||
|
// Just notify the unload intent so that all shared pointers are released.
|
||||||
|
// The wallet will be destroyed once the last shared pointer is released.
|
||||||
|
wallet->NotifyUnload();
|
||||||
|
|
||||||
|
// There's no point in waiting for the wallet to unload.
|
||||||
|
// At this point this method should never fail. The unloading could only
|
||||||
|
// fail due to an unexpected error which would cause a process termination.
|
||||||
|
|
||||||
|
return NullUniValue;
|
||||||
|
}
|
||||||
|
|
||||||
static UniValue resendwallettransactions(const JSONRPCRequest& request)
|
static UniValue resendwallettransactions(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||||
|
@ -4405,6 +4454,7 @@ static const CRPCCommand commands[] =
|
||||||
{ "wallet", "settxfee", &settxfee, {"amount"} },
|
{ "wallet", "settxfee", &settxfee, {"amount"} },
|
||||||
{ "wallet", "signmessage", &signmessage, {"address","message"} },
|
{ "wallet", "signmessage", &signmessage, {"address","message"} },
|
||||||
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
|
{ "wallet", "signrawtransactionwithwallet", &signrawtransactionwithwallet, {"hexstring","prevtxs","sighashtype"} },
|
||||||
|
{ "wallet", "unloadwallet", &unloadwallet, {"wallet_name"} },
|
||||||
{ "wallet", "walletlock", &walletlock, {} },
|
{ "wallet", "walletlock", &walletlock, {} },
|
||||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
|
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, {"oldpassphrase","newpassphrase"} },
|
||||||
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
|
{ "wallet", "walletpassphrase", &walletpassphrase, {"passphrase","timeout"} },
|
||||||
|
|
|
@ -79,6 +79,15 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom deleter for shared_ptr<CWallet>.
|
||||||
|
static void ReleaseWallet(CWallet* wallet)
|
||||||
|
{
|
||||||
|
LogPrintf("Releasing wallet %s\n", wallet->GetName());
|
||||||
|
wallet->BlockUntilSyncedToCurrentChain();
|
||||||
|
wallet->Flush();
|
||||||
|
delete wallet;
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
|
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
|
||||||
|
|
||||||
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||||
|
@ -1294,7 +1303,7 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
const CBlockIndex* initialChainTip = chainActive.Tip();
|
const CBlockIndex* initialChainTip = chainActive.Tip();
|
||||||
|
|
||||||
if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
|
if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4057,7 +4066,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name,
|
||||||
|
|
||||||
int64_t nStart = GetTimeMillis();
|
int64_t nStart = GetTimeMillis();
|
||||||
bool fFirstRun = true;
|
bool fFirstRun = true;
|
||||||
std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
|
// TODO: Can't use std::make_shared because we need a custom deleter but
|
||||||
|
// should be possible to use std::allocate_shared.
|
||||||
|
std::shared_ptr<CWallet> walletInstance(new CWallet(name, WalletDatabase::Create(path)), ReleaseWallet);
|
||||||
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
|
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
|
||||||
if (nLoadWalletRet != DBErrors::LOAD_OK)
|
if (nLoadWalletRet != DBErrors::LOAD_OK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1097,6 +1097,9 @@ public:
|
||||||
//! Flush wallet (bitdb flush)
|
//! Flush wallet (bitdb flush)
|
||||||
void Flush(bool shutdown=false);
|
void Flush(bool shutdown=false);
|
||||||
|
|
||||||
|
/** Wallet is about to be unloaded */
|
||||||
|
boost::signals2::signal<void ()> NotifyUnload;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address book entry changed.
|
* Address book entry changed.
|
||||||
* @note called with lock cs_wallet held.
|
* @note called with lock cs_wallet held.
|
||||||
|
|
Loading…
Reference in a new issue