Skip to content

Commit a8db31c

Browse files
committed
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.
1 parent 08ede8e commit a8db31c

File tree

5 files changed

+30
-3
lines changed

5 files changed

+30
-3
lines changed

src/qt/bitcoin.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "init.h"
2323
#include "main.h"
24+
#include "rpcserver.h"
2425
#include "ui_interface.h"
2526
#include "util.h"
2627
#include "wallet.h"
@@ -227,6 +228,13 @@ void BitcoinCore::initialize()
227228
{
228229
LogPrintf("Running AppInit2 in thread\n");
229230
int rv = AppInit2(threadGroup);
231+
if(rv)
232+
{
233+
/* Start a dummy RPC thread if no RPC thread is active yet
234+
* to handle timeouts.
235+
*/
236+
StartDummyRPCThread();
237+
}
230238
emit initializeResult(rv);
231239
} catch (std::exception& e) {
232240
handleRunawayException(&e);

src/rpcprotocol.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ enum RPCErrorCode
4949
RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter
5050
RPC_DATABASE_ERROR = -20, // Database error
5151
RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format
52-
RPC_SERVER_NOT_STARTED = -18, // RPC server was not started (StartRPCThreads() not called)
5352

5453
// P2P client errors
5554
RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected

src/rpcserver.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static asio::io_service* rpc_io_service = NULL;
3838
static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
3939
static ssl::context* rpc_ssl_context = NULL;
4040
static boost::thread_group* rpc_worker_group = NULL;
41+
static boost::asio::io_service::work *rpc_dummy_work = NULL;
4142

4243
void RPCTypeCheck(const Array& params,
4344
const list<Value_type>& typesExpected,
@@ -607,6 +608,19 @@ void StartRPCThreads()
607608
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
608609
}
609610

611+
void StartDummyRPCThread()
612+
{
613+
if(rpc_io_service == NULL)
614+
{
615+
rpc_io_service = new asio::io_service();
616+
/* Create dummy "work" to keep the thread from exiting when no timeouts active,
617+
* 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 */
618+
rpc_dummy_work = new asio::io_service::work(*rpc_io_service);
619+
rpc_worker_group = new boost::thread_group();
620+
rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
621+
}
622+
}
623+
610624
void StopRPCThreads()
611625
{
612626
if (rpc_io_service == NULL) return;
@@ -615,6 +629,7 @@ void StopRPCThreads()
615629
rpc_io_service->stop();
616630
if (rpc_worker_group != NULL)
617631
rpc_worker_group->join_all();
632+
delete rpc_dummy_work; rpc_dummy_work = NULL;
618633
delete rpc_worker_group; rpc_worker_group = NULL;
619634
delete rpc_ssl_context; rpc_ssl_context = NULL;
620635
delete rpc_io_service; rpc_io_service = NULL;

src/rpcserver.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@
2020

2121
class CBlockIndex;
2222

23+
/* Start RPC threads */
2324
void StartRPCThreads();
25+
/* Alternative to StartRPCThreads for the GUI, when no server is
26+
* used. The RPC thread in this case is only used to handle timeouts.
27+
* If real RPC threads have already been started this is a no-op.
28+
*/
29+
void StartDummyRPCThread();
30+
/* Stop RPC threads */
2431
void StopRPCThreads();
2532

2633
/*

src/rpcwallet.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,8 +1562,6 @@ Value walletpassphrase(const Array& params, bool fHelp)
15621562

15631563
if (fHelp)
15641564
return true;
1565-
if (!fServer)
1566-
throw JSONRPCError(RPC_SERVER_NOT_STARTED, "Error: RPC server was not started, use server=1 to change this.");
15671565
if (!pwalletMain->IsCrypted())
15681566
throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
15691567

0 commit comments

Comments
 (0)