qt: allow walletpassphrase
in debug console without -server
Currently it is only possible to use `walletpassphrase` to unlock the wallet when bitcoin is started in server mode. Almost everything that manipulates the wallet in the RPC console needs the wallet to be unlocked and is thus unusable without -server. This is pretty unintuitive to me, and I'm sure it's even more confusing to users. Solve this with a very minimal change: by making the GUI start a dummy RPC thread just to handle timeouts.
This commit is contained in:
parent
08ede8ef5e
commit
a8db31c83d
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "rpcserver.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wallet.h"
|
#include "wallet.h"
|
||||||
@ -227,6 +228,13 @@ void BitcoinCore::initialize()
|
|||||||
{
|
{
|
||||||
LogPrintf("Running AppInit2 in thread\n");
|
LogPrintf("Running AppInit2 in thread\n");
|
||||||
int rv = AppInit2(threadGroup);
|
int rv = AppInit2(threadGroup);
|
||||||
|
if(rv)
|
||||||
|
{
|
||||||
|
/* Start a dummy RPC thread if no RPC thread is active yet
|
||||||
|
* to handle timeouts.
|
||||||
|
*/
|
||||||
|
StartDummyRPCThread();
|
||||||
|
}
|
||||||
emit initializeResult(rv);
|
emit initializeResult(rv);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
handleRunawayException(&e);
|
handleRunawayException(&e);
|
||||||
|
@ -49,7 +49,6 @@ enum RPCErrorCode
|
|||||||
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
|
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
|
||||||
RPC_DATABASE_ERROR = -20, // Database error
|
RPC_DATABASE_ERROR = -20, // Database error
|
||||||
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
|
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
|
||||||
RPC_SERVER_NOT_STARTED = -18, // RPC server was not started (StartRPCThreads() not called)
|
|
||||||
|
|
||||||
// P2P client errors
|
// P2P client errors
|
||||||
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected
|
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected
|
||||||
|
@ -38,6 +38,7 @@ static asio::io_service* rpc_io_service = NULL;
|
|||||||
static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
|
static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
|
||||||
static ssl::context* rpc_ssl_context = NULL;
|
static ssl::context* rpc_ssl_context = NULL;
|
||||||
static boost::thread_group* rpc_worker_group = NULL;
|
static boost::thread_group* rpc_worker_group = NULL;
|
||||||
|
static boost::asio::io_service::work *rpc_dummy_work = NULL;
|
||||||
|
|
||||||
void RPCTypeCheck(const Array& params,
|
void RPCTypeCheck(const Array& params,
|
||||||
const list<Value_type>& typesExpected,
|
const list<Value_type>& typesExpected,
|
||||||
@ -607,6 +608,19 @@ void StartRPCThreads()
|
|||||||
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
|
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StartDummyRPCThread()
|
||||||
|
{
|
||||||
|
if(rpc_io_service == NULL)
|
||||||
|
{
|
||||||
|
rpc_io_service = new asio::io_service();
|
||||||
|
/* Create dummy "work" to keep the thread from exiting when no timeouts active,
|
||||||
|
* see http://www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.stopping_the_io_service_from_running_out_of_work */
|
||||||
|
rpc_dummy_work = new asio::io_service::work(*rpc_io_service);
|
||||||
|
rpc_worker_group = new boost::thread_group();
|
||||||
|
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StopRPCThreads()
|
void StopRPCThreads()
|
||||||
{
|
{
|
||||||
if (rpc_io_service == NULL) return;
|
if (rpc_io_service == NULL) return;
|
||||||
@ -615,6 +629,7 @@ void StopRPCThreads()
|
|||||||
rpc_io_service->stop();
|
rpc_io_service->stop();
|
||||||
if (rpc_worker_group != NULL)
|
if (rpc_worker_group != NULL)
|
||||||
rpc_worker_group->join_all();
|
rpc_worker_group->join_all();
|
||||||
|
delete rpc_dummy_work; rpc_dummy_work = NULL;
|
||||||
delete rpc_worker_group; rpc_worker_group = NULL;
|
delete rpc_worker_group; rpc_worker_group = NULL;
|
||||||
delete rpc_ssl_context; rpc_ssl_context = NULL;
|
delete rpc_ssl_context; rpc_ssl_context = NULL;
|
||||||
delete rpc_io_service; rpc_io_service = NULL;
|
delete rpc_io_service; rpc_io_service = NULL;
|
||||||
|
@ -20,7 +20,14 @@
|
|||||||
|
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
|
|
||||||
|
/* Start RPC threads */
|
||||||
void StartRPCThreads();
|
void StartRPCThreads();
|
||||||
|
/* Alternative to StartRPCThreads for the GUI, when no server is
|
||||||
|
* used. The RPC thread in this case is only used to handle timeouts.
|
||||||
|
* If real RPC threads have already been started this is a no-op.
|
||||||
|
*/
|
||||||
|
void StartDummyRPCThread();
|
||||||
|
/* Stop RPC threads */
|
||||||
void StopRPCThreads();
|
void StopRPCThreads();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1562,8 +1562,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
if (fHelp)
|
if (fHelp)
|
||||||
return true;
|
return true;
|
||||||
if (!fServer)
|
|
||||||
throw JSONRPCError(RPC_SERVER_NOT_STARTED, "Error: RPC server was not started, use server=1 to change this.");
|
|
||||||
if (!pwalletMain->IsCrypted())
|
if (!pwalletMain->IsCrypted())
|
||||||
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
|
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user