Support absence of wallet (pwalletMain==NULL) in several locations,

notably RPC.
This commit is contained in:
Jeff Garzik 2013-08-25 00:00:02 -04:00
parent 19c415b1cf
commit b0730874d9
6 changed files with 123 additions and 92 deletions

View File

@ -160,6 +160,9 @@ string CRPCTable::help(string strCommand) const
continue; continue;
if (strCommand != "" && strMethod != strCommand) if (strCommand != "" && strMethod != strCommand)
continue; continue;
if (pcmd->reqWallet && !pwalletMain)
continue;
try try
{ {
Array params; Array params;
@ -218,77 +221,77 @@ Value stop(const Array& params, bool fHelp)
static const CRPCCommand vRPCCommands[] = static const CRPCCommand vRPCCommands[] =
{ // name actor (function) okSafeMode threadSafe { // name actor (function) okSafeMode threadSafe reqWallet
// ------------------------ ----------------------- ---------- ---------- // ------------------------ ----------------------- ---------- ---------- ---------
{ "help", &help, true, true }, { "help", &help, true, true, false },
{ "stop", &stop, true, true }, { "stop", &stop, true, true, false },
{ "getblockcount", &getblockcount, true, false }, { "getblockcount", &getblockcount, true, false, false },
{ "getbestblockhash", &getbestblockhash, true, false }, { "getbestblockhash", &getbestblockhash, true, false, false },
{ "getconnectioncount", &getconnectioncount, true, false }, { "getconnectioncount", &getconnectioncount, true, false, false },
{ "getpeerinfo", &getpeerinfo, true, false }, { "getpeerinfo", &getpeerinfo, true, false, false },
{ "addnode", &addnode, true, true }, { "addnode", &addnode, true, true, false },
{ "getaddednodeinfo", &getaddednodeinfo, true, true }, { "getaddednodeinfo", &getaddednodeinfo, true, true, false },
{ "getdifficulty", &getdifficulty, true, false }, { "getdifficulty", &getdifficulty, true, false, false },
{ "getnetworkhashps", &getnetworkhashps, true, false }, { "getnetworkhashps", &getnetworkhashps, true, false, false },
{ "getgenerate", &getgenerate, true, false }, { "getgenerate", &getgenerate, true, false, false },
{ "setgenerate", &setgenerate, true, false }, { "setgenerate", &setgenerate, true, false, true },
{ "gethashespersec", &gethashespersec, true, false }, { "gethashespersec", &gethashespersec, true, false, false },
{ "getinfo", &getinfo, true, false }, { "getinfo", &getinfo, true, false, false },
{ "getmininginfo", &getmininginfo, true, false }, { "getmininginfo", &getmininginfo, true, false, false },
{ "getnewaddress", &getnewaddress, true, false }, { "getnewaddress", &getnewaddress, true, false, true },
{ "getaccountaddress", &getaccountaddress, true, false }, { "getaccountaddress", &getaccountaddress, true, false, true },
{ "getrawchangeaddress", &getrawchangeaddress, true, false }, { "getrawchangeaddress", &getrawchangeaddress, true, false, true },
{ "setaccount", &setaccount, true, false }, { "setaccount", &setaccount, true, false, true },
{ "getaccount", &getaccount, false, false }, { "getaccount", &getaccount, false, false, true },
{ "getaddressesbyaccount", &getaddressesbyaccount, true, false }, { "getaddressesbyaccount", &getaddressesbyaccount, true, false, true },
{ "sendtoaddress", &sendtoaddress, false, false }, { "sendtoaddress", &sendtoaddress, false, false, true },
{ "getreceivedbyaddress", &getreceivedbyaddress, false, false }, { "getreceivedbyaddress", &getreceivedbyaddress, false, false, true },
{ "getreceivedbyaccount", &getreceivedbyaccount, false, false }, { "getreceivedbyaccount", &getreceivedbyaccount, false, false, true },
{ "listreceivedbyaddress", &listreceivedbyaddress, false, false }, { "listreceivedbyaddress", &listreceivedbyaddress, false, false, true },
{ "listreceivedbyaccount", &listreceivedbyaccount, false, false }, { "listreceivedbyaccount", &listreceivedbyaccount, false, false, true },
{ "backupwallet", &backupwallet, true, false }, { "backupwallet", &backupwallet, true, false, true },
{ "keypoolrefill", &keypoolrefill, true, false }, { "keypoolrefill", &keypoolrefill, true, false, true },
{ "walletpassphrase", &walletpassphrase, true, false }, { "walletpassphrase", &walletpassphrase, true, false, true },
{ "walletpassphrasechange", &walletpassphrasechange, false, false }, { "walletpassphrasechange", &walletpassphrasechange, false, false, true },
{ "walletlock", &walletlock, true, false }, { "walletlock", &walletlock, true, false, true },
{ "encryptwallet", &encryptwallet, false, false }, { "encryptwallet", &encryptwallet, false, false, true },
{ "validateaddress", &validateaddress, true, false }, { "validateaddress", &validateaddress, true, false, false },
{ "getbalance", &getbalance, false, false }, { "getbalance", &getbalance, false, false, true },
{ "move", &movecmd, false, false }, { "move", &movecmd, false, false, true },
{ "sendfrom", &sendfrom, false, false }, { "sendfrom", &sendfrom, false, false, true },
{ "sendmany", &sendmany, false, false }, { "sendmany", &sendmany, false, false, true },
{ "addmultisigaddress", &addmultisigaddress, false, false }, { "addmultisigaddress", &addmultisigaddress, false, false, true },
{ "createmultisig", &createmultisig, true, true }, { "createmultisig", &createmultisig, true, true , false },
{ "getrawmempool", &getrawmempool, true, false }, { "getrawmempool", &getrawmempool, true, false, false },
{ "getblock", &getblock, false, false }, { "getblock", &getblock, false, false, false },
{ "getblockhash", &getblockhash, false, false }, { "getblockhash", &getblockhash, false, false, false },
{ "gettransaction", &gettransaction, false, false }, { "gettransaction", &gettransaction, false, false, true },
{ "listtransactions", &listtransactions, false, false }, { "listtransactions", &listtransactions, false, false, true },
{ "listaddressgroupings", &listaddressgroupings, false, false }, { "listaddressgroupings", &listaddressgroupings, false, false, true },
{ "signmessage", &signmessage, false, false }, { "signmessage", &signmessage, false, false, true },
{ "verifymessage", &verifymessage, false, false }, { "verifymessage", &verifymessage, false, false, false },
{ "getwork", &getwork, true, false }, { "getwork", &getwork, true, false, true },
{ "listaccounts", &listaccounts, false, false }, { "listaccounts", &listaccounts, false, false, true },
{ "settxfee", &settxfee, false, false }, { "settxfee", &settxfee, false, false, true },
{ "getblocktemplate", &getblocktemplate, true, false }, { "getblocktemplate", &getblocktemplate, true, false, false },
{ "submitblock", &submitblock, false, false }, { "submitblock", &submitblock, false, false, false },
{ "listsinceblock", &listsinceblock, false, false }, { "listsinceblock", &listsinceblock, false, false, true },
{ "dumpprivkey", &dumpprivkey, true, false }, { "dumpprivkey", &dumpprivkey, true, false, true },
{ "dumpwallet", &dumpwallet, true, false }, { "dumpwallet", &dumpwallet, true, false, true },
{ "importprivkey", &importprivkey, false, false }, { "importprivkey", &importprivkey, false, false, true },
{ "importwallet", &importwallet, false, false }, { "importwallet", &importwallet, false, false, true },
{ "listunspent", &listunspent, false, false }, { "listunspent", &listunspent, false, false, true },
{ "getrawtransaction", &getrawtransaction, false, false }, { "getrawtransaction", &getrawtransaction, false, false, false },
{ "createrawtransaction", &createrawtransaction, false, false }, { "createrawtransaction", &createrawtransaction, false, false, false },
{ "decoderawtransaction", &decoderawtransaction, false, false }, { "decoderawtransaction", &decoderawtransaction, false, false, false },
{ "decodescript", &decodescript, false, false }, { "decodescript", &decodescript, false, false, false },
{ "signrawtransaction", &signrawtransaction, false, false }, { "signrawtransaction", &signrawtransaction, false, false, false },
{ "sendrawtransaction", &sendrawtransaction, false, false }, { "sendrawtransaction", &sendrawtransaction, false, false, false },
{ "gettxoutsetinfo", &gettxoutsetinfo, true, false }, { "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
{ "gettxout", &gettxout, true, false }, { "gettxout", &gettxout, true, false, false },
{ "lockunspent", &lockunspent, false, false }, { "lockunspent", &lockunspent, false, false, true },
{ "listlockunspent", &listlockunspent, false, false }, { "listlockunspent", &listlockunspent, false, false, true },
{ "verifychain", &verifychain, true, false }, { "verifychain", &verifychain, true, false, false },
}; };
CRPCTable::CRPCTable() CRPCTable::CRPCTable()
@ -1065,6 +1068,8 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
const CRPCCommand *pcmd = tableRPC[strMethod]; const CRPCCommand *pcmd = tableRPC[strMethod];
if (!pcmd) if (!pcmd)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
if (pcmd->reqWallet && !pwalletMain)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
// Observe safe mode // Observe safe mode
string strWarning = GetWarnings("rpc"); string strWarning = GetWarnings("rpc");
@ -1079,7 +1084,10 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
{ {
if (pcmd->threadSafe) if (pcmd->threadSafe)
result = pcmd->actor(params, false); result = pcmd->actor(params, false);
else { else if (!pwalletMain) {
LOCK(cs_main);
result = pcmd->actor(params, false);
} else {
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
result = pcmd->actor(params, false); result = pcmd->actor(params, false);
} }

View File

@ -104,6 +104,7 @@ public:
rpcfn_type actor; rpcfn_type actor;
bool okSafeMode; bool okSafeMode;
bool threadSafe; bool threadSafe;
bool reqWallet;
}; };
/** /**

View File

@ -108,7 +108,8 @@ void Shutdown()
nTransactionsUpdated++; nTransactionsUpdated++;
StopRPCThreads(); StopRPCThreads();
ShutdownRPCMining(); ShutdownRPCMining();
bitdb.Flush(false); if (pwalletMain)
bitdb.Flush(false);
GenerateBitcoins(false, NULL); GenerateBitcoins(false, NULL);
StopNode(); StopNode();
{ {
@ -123,10 +124,12 @@ void Shutdown()
delete pcoinsdbview; pcoinsdbview = NULL; delete pcoinsdbview; pcoinsdbview = NULL;
delete pblocktree; pblocktree = NULL; delete pblocktree; pblocktree = NULL;
} }
bitdb.Flush(true); if (pwalletMain)
bitdb.Flush(true);
boost::filesystem::remove(GetPidFile()); boost::filesystem::remove(GetPidFile());
UnregisterAllWallets(); UnregisterAllWallets();
delete pwalletMain; if (pwalletMain)
delete pwalletMain;
} }
// //
@ -981,9 +984,9 @@ bool AppInit2(boost::thread_group& threadGroup)
//// debug print //// debug print
LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size()); LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
LogPrintf("nBestHeight = %d\n", nBestHeight); LogPrintf("nBestHeight = %d\n", nBestHeight);
LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain->setKeyPool.size()); LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain->mapWallet.size()); LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain->mapAddressBook.size()); LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
StartNode(threadGroup); StartNode(threadGroup);
@ -993,17 +996,20 @@ bool AppInit2(boost::thread_group& threadGroup)
StartRPCThreads(); StartRPCThreads();
// Generate coins in the background // Generate coins in the background
GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain); if (pwalletMain)
GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
// ********************************************************* Step 12: finished // ********************************************************* Step 12: finished
uiInterface.InitMessage(_("Done loading")); uiInterface.InitMessage(_("Done loading"));
// Add wallet transactions that aren't already in a block to mapTransactions if (pwalletMain) {
pwalletMain->ReacceptWalletTransactions(); // Add wallet transactions that aren't already in a block to mapTransactions
pwalletMain->ReacceptWalletTransactions();
// Run a thread to flush wallet periodically // Run a thread to flush wallet periodically
threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile))); threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile)));
}
return !fRequestShutdown; return !fRequestShutdown;
} }

View File

@ -18,12 +18,18 @@ static CReserveKey* pMiningKey = NULL;
void InitRPCMining() void InitRPCMining()
{ {
if (!pwalletMain)
return;
// getwork/getblocktemplate mining rewards paid here: // getwork/getblocktemplate mining rewards paid here:
pMiningKey = new CReserveKey(pwalletMain); pMiningKey = new CReserveKey(pwalletMain);
} }
void ShutdownRPCMining() void ShutdownRPCMining()
{ {
if (!pMiningKey)
return;
delete pMiningKey; pMiningKey = NULL; delete pMiningKey; pMiningKey = NULL;
} }
@ -87,6 +93,9 @@ Value getgenerate(const Array& params, bool fHelp)
"getgenerate\n" "getgenerate\n"
"Returns true or false."); "Returns true or false.");
if (!pMiningKey)
return false;
return GetBoolArg("-gen", false); return GetBoolArg("-gen", false);
} }
@ -112,6 +121,7 @@ Value setgenerate(const Array& params, bool fHelp)
} }
mapArgs["-gen"] = (fGenerate ? "1" : "0"); mapArgs["-gen"] = (fGenerate ? "1" : "0");
assert(pwalletMain != NULL);
GenerateBitcoins(fGenerate, pwalletMain); GenerateBitcoins(fGenerate, pwalletMain);
return Value::null; return Value::null;
} }
@ -143,7 +153,7 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("errors", GetWarnings("statusbar")));
obj.push_back(Pair("generate", GetBoolArg("-gen", false))); obj.push_back(Pair("generate", getgenerate(params, false)));
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1))); obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
obj.push_back(Pair("hashespersec", gethashespersec(params, false))); obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("networkhashps", getnetworkhashps(params, false))); obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
@ -261,6 +271,7 @@ Value getwork(const Array& params, bool fHelp)
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->hashMerkleRoot = pblock->BuildMerkleTree();
assert(pwalletMain != NULL);
return CheckWork(pblock, *pwalletMain, *pMiningKey); return CheckWork(pblock, *pwalletMain, *pMiningKey);
} }
} }

View File

@ -171,6 +171,7 @@ Value listunspent(const Array& params, bool fHelp)
Array results; Array results;
vector<COutput> vecOutputs; vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
pwalletMain->AvailableCoins(vecOutputs, false); pwalletMain->AvailableCoins(vecOutputs, false);
BOOST_FOREACH(const COutput& out, vecOutputs) BOOST_FOREACH(const COutput& out, vecOutputs)
{ {
@ -458,7 +459,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
} }
} }
const CKeyStore& keystore = (fGivenKeys ? tempKeystore : *pwalletMain); const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
int nHashType = SIGHASH_ALL; int nHashType = SIGHASH_ALL;
if (params.size() > 3 && params[3].type() != null_type) if (params.size() > 3 && params[3].type() != null_type)

View File

@ -21,7 +21,7 @@ static CCriticalSection cs_nWalletUnlockTime;
std::string HelpRequiringPassphrase() std::string HelpRequiringPassphrase()
{ {
return pwalletMain->IsCrypted() return pwalletMain && pwalletMain->IsCrypted()
? "\nrequires wallet passphrase to be set with walletpassphrase first" ? "\nrequires wallet passphrase to be set with walletpassphrase first"
: ""; : "";
} }
@ -72,18 +72,22 @@ Value getinfo(const Array& params, bool fHelp)
Object obj; Object obj;
obj.push_back(Pair("version", (int)CLIENT_VERSION)); obj.push_back(Pair("version", (int)CLIENT_VERSION));
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); if (pwalletMain) {
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
}
obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("blocks", (int)nBestHeight));
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("testnet", TestNet())); obj.push_back(Pair("testnet", TestNet()));
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); if (pwalletMain) {
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
}
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
if (pwalletMain->IsCrypted()) if (pwalletMain && pwalletMain->IsCrypted())
obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj; return obj;
@ -738,7 +742,7 @@ static CScript _createmultisig(const Array& params)
// Case 1: Bitcoin address and we have full public key: // Case 1: Bitcoin address and we have full public key:
CBitcoinAddress address(ks); CBitcoinAddress address(ks);
if (address.IsValid()) if (pwalletMain && address.IsValid())
{ {
CKeyID keyID; CKeyID keyID;
if (!address.GetKeyID(keyID)) if (!address.GetKeyID(keyID))