diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index daf35988..b4b0299d 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -49,10 +49,10 @@ int64 AmountFromValue(const Value& value) { double dAmount = value.get_real(); if (dAmount <= 0.0 || dAmount > MAX_MONEY) - throw JSONRPCError(-3, "Invalid amount"); + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); int64 nAmount = roundint64(dAmount * COIN); if (!MoneyRange(nAmount)) - throw JSONRPCError(-3, "Invalid amount"); + throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); return nAmount; } @@ -288,13 +288,15 @@ Value getwork(const Array& params, bool fHelp) "If [data] is specified, tries to solve the block and returns true if it was successful."); if (vNodes.empty()) - throw JSONRPCError(-9, "Paycoin is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Paycoin is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(-10, "Paycoin is downloading blocks..."); + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Paycoin is downloading blocks..."); if (pindexBest != NULL && pindexBest->nTime > POW_END_TIME) - throw JSONRPCError(-10, "Paycoin is currently on pure PoS state"); + /* This was set to -10 but really this seems inappropriate, unsure what + * to set to instead. */ + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Paycoin is currently on pure PoS state"); typedef map > mapNewBlock_t; @@ -331,7 +333,7 @@ Value getwork(const Array& params, bool fHelp) // Create new block pblock = CreateNewBlock(*pMiningKey, pwalletMain); if (!pblock) - throw JSONRPCError(-7, "Out of memory"); + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); vNewBlock.push_back(pblock); // Need to update only after we know CreateNewBlock succeeded @@ -369,7 +371,7 @@ Value getwork(const Array& params, bool fHelp) // Parse parameters vector vchData = ParseHex(params[0].get_str()); if (vchData.size() != 128) - throw JSONRPCError(-8, "Invalid parameter"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); CBlock* pdata = (CBlock*)&vchData[0]; // Byte reverse @@ -388,6 +390,7 @@ Value getwork(const Array& params, bool fHelp) assert(pwalletMain != NULL); if (!pblock->SignBlock(*pwalletMain)) + // Should this be a defined error, if so what? throw JSONRPCError(-100, "Unable to sign block, wallet locked?"); return CheckWork(pblock, *pwalletMain, *pMiningKey); @@ -428,21 +431,22 @@ Value getblocktemplate(const Array& params, bool fHelp) /* Do nothing */ } else - throw JSONRPCError(-8, "Invalid mode"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); } if (strMode != "template") - throw JSONRPCError(-8, "Invalid mode"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); { if (vNodes.empty()) - throw JSONRPCError(-9, "Paycoin is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Paycoin is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(-10, "Paycoin is downloading blocks..."); + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Paycoin is downloading blocks..."); if (pindexBest != NULL && pindexBest->nTime > POW_END_TIME) - throw JSONRPCError(-10, "Paycoin is currently on pure PoS state"); + // Same as other instance, this feels like the wrong error code for this... + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Paycoin is currently on pure PoS state"); // Update block static unsigned int nTransactionsUpdatedLast; @@ -468,7 +472,7 @@ Value getblocktemplate(const Array& params, bool fHelp) } pblock = CreateNewBlock(*pMiningKey, pwalletMain); if (!pblock) - throw JSONRPCError(-7, "Out of memory"); + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); // Need to update only after we know CreateNewBlock succeeded pindexPrev = pindexPrevNew; @@ -570,11 +574,12 @@ Value submitblock(const Array& params, bool fHelp) ssBlock >> block; } catch (std::exception &e) { - throw JSONRPCError(-22, "Block decode failed"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); } // Paycoin: sign block if (!block.SignBlock(*pwalletMain)) + // Once again, should this be a defined error and if so what? throw JSONRPCError(-100, "Unable to sign block, wallet locked?"); bool fAccepted = CheckWork(&block, *pwalletMain, *pMiningKey); @@ -827,7 +832,7 @@ string rfc1123Time() static string HTTPReply(int nStatus, const string& strMsg) { - if (nStatus == 401) + if (nStatus == HTTP_UNAUTHORIZED) return strprintf("HTTP/1.0 401 Authorization Required\r\n" "Date: %s\r\n" "Server: paycoin-json-rpc/%s\r\n" @@ -845,11 +850,11 @@ static string HTTPReply(int nStatus, const string& strMsg) "

401 Unauthorized.

\r\n" "\r\n", rfc1123Time().c_str(), FormatFullVersion().c_str()); const char *cStatus; - if (nStatus == 200) cStatus = "OK"; - else if (nStatus == 400) cStatus = "Bad Request"; - else if (nStatus == 403) cStatus = "Forbidden"; - else if (nStatus == 404) cStatus = "Not Found"; - else if (nStatus == 500) cStatus = "Internal Server Error"; + if (nStatus == HTTP_OK) cStatus = "OK"; + else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request"; + else if (nStatus == HTTP_FORBIDDEN) cStatus = "Forbidden"; + else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found"; + else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error"; else cStatus = ""; return strprintf( "HTTP/1.1 %d %s\r\n" @@ -875,7 +880,7 @@ int ReadHTTPStatus(std::basic_istream& stream) vector vWords; boost::split(vWords, str, boost::is_any_of(" ")); if (vWords.size() < 2) - return 500; + return HTTP_INTERNAL_SERVER_ERROR; return atoi(vWords[1].c_str()); } @@ -915,7 +920,7 @@ int ReadHTTP(std::basic_istream& stream, map& mapHeadersRe // Read header int nLen = ReadHTTPHeader(stream, mapHeadersRet); if (nLen < 0 || nLen > (int)MAX_SIZE) - return 500; + return HTTP_INTERNAL_SERVER_ERROR; // Read message if (nLen > 0) @@ -978,10 +983,10 @@ string JSONRPCReply(const Value& result, const Value& error, const Value& id) void ErrorReply(std::ostream& stream, const Object& objError, const Value& id) { // Send error reply from json-rpc error object - int nStatus = 500; + int nStatus = HTTP_INTERNAL_SERVER_ERROR; int code = find_value(objError, "code").get_int(); - if (code == -32600) nStatus = 400; - else if (code == -32601) nStatus = 404; + if (code == RPC_INVALID_REQUEST) nStatus = HTTP_BAD_REQUEST; + else if (code == RPC_METHOD_NOT_FOUND) nStatus = HTTP_NOT_FOUND; string strReply = JSONRPCReply(Value::null, objError, id); stream << HTTPReply(nStatus, strReply) << std::flush; } @@ -1085,9 +1090,9 @@ static Object JSONRPCExecOne(const Value& request) // Parse method Value valMethod = find_value(req, "method"); if (valMethod.type() == null_type) - throw JSONRPCError(-32600, "Missing method"); + throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method"); if (valMethod.type() != str_type) - throw JSONRPCError(-32600, "Method must be a string"); + throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); string strMethod = valMethod.get_str(); if (strMethod != "getwork" && strMethod != "getblocktemplate") printf("ThreadRPCServer method=%s\n", strMethod.c_str()); @@ -1100,7 +1105,7 @@ static Object JSONRPCExecOne(const Value& request) else if (valParams.type() == null_type) params = Array(); else - throw JSONRPCError(-32600, "Params must be an array"); + throw JSONRPCError(RPC_INVALID_PARAMS, "Params must be an array"); Value result = tableRPC.execute(strMethod, params); rpc_result = JSONRPCReplyObj(result, Value::null, id); @@ -1111,7 +1116,7 @@ static Object JSONRPCExecOne(const Value& request) } catch (std::exception& e) { - rpc_result = JSONRPCReplyObj(Value::null, JSONRPCError(-32700, e.what()), id); + rpc_result = JSONRPCReplyObj(Value::null, JSONRPCError(RPC_PARSE_ERROR, e.what()), id); } return rpc_result; @@ -1216,7 +1221,7 @@ void ThreadRPCServer2(void* parg) { // Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake. if (!fUseSSL) - stream << HTTPReply(403, "") << std::flush; + stream << HTTPReply(HTTP_FORBIDDEN, "") << std::flush; continue; } @@ -1234,7 +1239,7 @@ void ThreadRPCServer2(void* parg) // Check authorization if (mapHeaders.count("authorization") == 0) { - stream << HTTPReply(401, "") << std::flush; + stream << HTTPReply(HTTP_UNAUTHORIZED, "") << std::flush; continue; } if (!HTTPAuthorized(mapHeaders)) @@ -1246,7 +1251,7 @@ void ThreadRPCServer2(void* parg) if (mapArgs["-rpcpassword"].size() < 20) Sleep(250); - stream << HTTPReply(401, "") << std::flush; + stream << HTTPReply(HTTP_UNAUTHORIZED, "") << std::flush; continue; } @@ -1256,7 +1261,7 @@ void ThreadRPCServer2(void* parg) // Parse request Value valRequest; if (!read_string(strRequest, valRequest)) - throw JSONRPCError(-32700, "Parse error"); + throw JSONRPCError(RPC_PARSE_ERROR, "Parse error"); string strReply; if (valRequest.type() == obj_type) { @@ -1268,10 +1273,10 @@ void ThreadRPCServer2(void* parg) // array of requests strReply = JSONRPCExecBatch(valRequest.get_array()); } else - throw JSONRPCError(-32600, "Top-level object parse error"); + throw JSONRPCError(RPC_INVALID_REQUEST, "Top-level object parse error"); // Send reply - stream << HTTPReply(200, strReply) << std::flush; + stream << HTTPReply(HTTP_OK, strReply) << std::flush; } catch (Object& objError) { @@ -1279,7 +1284,7 @@ void ThreadRPCServer2(void* parg) } catch (std::exception& e) { - ErrorReply(stream, JSONRPCError(-32700, e.what()), id); + ErrorReply(stream, JSONRPCError(RPC_PARSE_ERROR, e.what()), id); } } } @@ -1289,13 +1294,13 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s // Find method const CRPCCommand *pcmd = tableRPC[strMethod]; if (!pcmd) - throw JSONRPCError(-32601, "Method not found"); + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); // Observe safe mode string strWarning = GetWarnings("rpc"); if (strWarning != "" && !GetBoolArg("-disablesafemode") && !pcmd->okSafeMode) - throw JSONRPCError(-2, string("Safe mode: ") + strWarning); + throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning); try { @@ -1309,7 +1314,7 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s } catch (std::exception& e) { - throw JSONRPCError(-1, e.what()); + throw JSONRPCError(RPC_MISC_ERROR, e.what()); } } @@ -1331,7 +1336,7 @@ Object CallRPC(const string& strMethod, const Array& params) SSLIOStreamDevice d(sslStream, fUseSSL); iostreams::stream stream(d); if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", CBigNum(fTestNet? TESTNET_RPC_PORT : RPC_PORT).ToString().c_str()))) - throw runtime_error("couldn't connect to server"); + throw JSONRPCError(RPC_INTERNAL_ERROR, "couldn't connect to server"); // HTTP basic authentication string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]); @@ -1347,20 +1352,20 @@ Object CallRPC(const string& strMethod, const Array& params) map mapHeaders; string strReply; int nStatus = ReadHTTP(stream, mapHeaders, strReply); - if (nStatus == 401) - throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); - else if (nStatus >= 400 && nStatus != 400 && nStatus != 404 && nStatus != 500) - throw runtime_error(strprintf("server returned HTTP error %d", nStatus)); + if (nStatus == HTTP_UNAUTHORIZED) + throw JSONRPCError(RPC_INVALID_PARAMS, "incorrect rpcuser or rpcpassword (authorization failed)"); + else if (nStatus >= HTTP_BAD_REQUEST && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR) + throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("server returned HTTP error %d", nStatus)); else if (strReply.empty()) - throw runtime_error("no response from server"); + throw JSONRPCError(RPC_INTERNAL_ERROR, "no response from server"); // Parse reply Value valReply; if (!read_string(strReply, valReply)) - throw runtime_error("couldn't parse reply from server"); + throw JSONRPCError(RPC_PARSE_ERROR, "couldn't parse reply from server"); const Object& reply = valReply.get_obj(); if (reply.empty()) - throw runtime_error("expected reply to have result, error and id properties"); + throw JSONRPCError(RPC_PARSE_ERROR, "expected reply to have result, error and id properties"); return reply; } @@ -1372,7 +1377,7 @@ template void ConvertTo(Value& value) // reinterpret string as unquoted json value Value value2; if (!read_string(value.get_str(), value2)) - throw runtime_error("type mismatch"); + throw JSONRPCError(RPC_PARSE_ERROR, "type mismatch"); value = value2.get_value(); } else @@ -1430,7 +1435,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 2) ConvertTo(params[2]); @@ -1442,7 +1447,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); @@ -1451,7 +1456,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); @@ -1485,7 +1490,7 @@ int CommandLineRPC(int argc, char *argv[]) // Method if (argc < 2) - throw runtime_error("too few parameters"); + throw JSONRPCError(RPC_INVALID_PARAMS, "too few parameters"); string strMethod = argv[1]; // Parameters default to strings diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index bf0a0d4b..fc87a43f 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -17,6 +17,68 @@ class CReserveKey; #include "json/json_spirit_writer_template.h" #include "json/json_spirit_utils.h" +//! HTTP status codes +enum HTTPStatusCode +{ + HTTP_OK = 200, + HTTP_BAD_REQUEST = 400, + HTTP_UNAUTHORIZED = 401, + HTTP_FORBIDDEN = 403, + HTTP_NOT_FOUND = 404, + HTTP_BAD_METHOD = 405, + HTTP_INTERNAL_SERVER_ERROR = 500, + HTTP_SERVICE_UNAVAILABLE = 503, +}; + +//! Bitcoin RPC error codes +enum RPCErrorCode +{ + //! Standard JSON-RPC 2.0 errors + RPC_INVALID_REQUEST = -32600, + RPC_METHOD_NOT_FOUND = -32601, + RPC_INVALID_PARAMS = -32602, + RPC_INTERNAL_ERROR = -32603, + RPC_PARSE_ERROR = -32700, + + //! General application defined errors + RPC_MISC_ERROR = -1, //! std::exception thrown in command handling + RPC_FORBIDDEN_BY_SAFE_MODE = -2, //! Server is in safe mode, and command is not allowed in safe mode + RPC_TYPE_ERROR = -3, //! Unexpected type was passed as parameter + RPC_INVALID_ADDRESS_OR_KEY = -5, //! Invalid address or key + RPC_OUT_OF_MEMORY = -7, //! Ran out of memory during operation + RPC_INVALID_PARAMETER = -8, //! Invalid, missing or duplicate parameter + RPC_DATABASE_ERROR = -20, //! Database error + RPC_DESERIALIZATION_ERROR = -22, //! Error parsing or validating structure in raw format + RPC_VERIFY_ERROR = -25, //! General error during transaction or block submission + RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules + RPC_VERIFY_ALREADY_IN_CHAIN = -27, //! Transaction already in chain + RPC_IN_WARMUP = -28, //! Client still warming up + + //! Aliases for backward compatibility + RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR, + RPC_TRANSACTION_REJECTED = RPC_VERIFY_REJECTED, + RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN, + + //! P2P client errors + RPC_CLIENT_NOT_CONNECTED = -9, //! Bitcoin is not connected + RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks + RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added + RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before + RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes + RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //! Invalid IP/Subnet + + //! Wallet errors + RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.) + RPC_WALLET_INSUFFICIENT_FUNDS = -6, //! Not enough funds in wallet or account + RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //! Invalid account name + RPC_WALLET_KEYPOOL_RAN_OUT = -12, //! Keypool ran out, call keypoolrefill first + RPC_WALLET_UNLOCK_NEEDED = -13, //! Enter the wallet passphrase with walletpassphrase first + RPC_WALLET_PASSPHRASE_INCORRECT = -14, //! The wallet passphrase entered was incorrect + RPC_WALLET_WRONG_ENC_STATE = -15, //! Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + RPC_WALLET_ENCRYPTION_FAILED = -16, //! Failed to encrypt the wallet + RPC_WALLET_ALREADY_UNLOCKED = -17, //! Wallet is already unlocked +}; + void ThreadRPCServer(void* parg); int CommandLineRPC(int argc, char *argv[]); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index aeaaf03a..6c7af115 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -137,7 +137,7 @@ Value getblockhash(const Array& params, bool fHelp) int nHeight = params[0].get_int(); if (nHeight < 0 || nHeight > nBestHeight) - throw runtime_error("Block number out of range."); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block number out of range."); CBlockIndex* pblockindex = FindBlockByHeight(nHeight); return pblockindex->phashBlock->GetHex(); @@ -156,7 +156,7 @@ Value getblock(const Array& params, bool fHelp) uint256 hash(strHash); if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(-5, "Block not found"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block not found"); CBlock block; CBlockIndex* pblockindex = mapBlockIndex[hash]; diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 3acdb00d..b65ff879 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -20,8 +20,6 @@ using namespace json_spirit; using namespace std; -extern Object JSONRPCError(int code, const string& message); - class CTxDump { public: @@ -54,11 +52,11 @@ Value importprivkey(const Array& params, bool fHelp) CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(strSecret); - if (!fGood) throw JSONRPCError(-5,"Invalid private key"); + if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,"Invalid private key"); if (pwalletMain->IsLocked()) - throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); if (fWalletUnlockMintOnly) // paycoin: no importprivkey in mint-only mode - throw JSONRPCError(-102, "Wallet is unlocked for minting only (unlock with walletpassphrase)."); + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Wallet is unlocked for minting only (unlock with walletpassphrase)."); CKey key; bool fCompressed; @@ -72,7 +70,7 @@ Value importprivkey(const Array& params, bool fHelp) pwalletMain->SetAddressBookName(vchAddress, strLabel); if (!pwalletMain->AddKey(key)) - throw JSONRPCError(-4,"Error adding key to wallet"); + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true); pwalletMain->ReacceptWalletTransactions(); @@ -93,17 +91,17 @@ Value dumpprivkey(const Array& params, bool fHelp) string strAddress = params[0].get_str(); CBitcoinAddress address; if (!address.SetString(strAddress)) - throw JSONRPCError(-5, "Invalid Paycoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address"); if (pwalletMain->IsLocked()) - throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); if (fWalletUnlockMintOnly) // paycoin: no dumpprivkey in mint-only mode - throw JSONRPCError(-102, "Wallet is unlocked for minting only (unlock with walletpassphrase)."); + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Wallet is unlocked for minting only (unlock with walletpassphrase)."); CKeyID keyID; if (!address.GetKeyID(keyID)) - throw JSONRPCError(-3, "Address does not refer to a key"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address does not refer to a key"); CSecret vchSecret; bool fCompressed; if (!pwalletMain->GetSecret(keyID, vchSecret, fCompressed)) - throw JSONRPCError(-4,"Private key for address " + strAddress + " is not known"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key for address " + strAddress + " is not known"); return CBitcoinSecret(vchSecret, fCompressed).ToString(); } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 0ddcd2cc..353e9530 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -108,11 +108,9 @@ Value sendalert(const Array& params, bool fHelp) vector vchPrivKey = ParseHex(params[1].get_str()); key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) - throw runtime_error( - "Unable to sign alert, check private key?\n"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to sign alert, check private key?\n"); if(!alert.ProcessAlert()) - throw runtime_error( - "Failed to process alert.\n"); + throw JSONRPCError(RPC_MISC_ERROR, "Failed to process alert.\n"); // Relay alert { LOCK(cs_vNodes); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index c1904ce8..646e72c3 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -190,7 +190,7 @@ Value getrawtransaction(const Array& params, bool fHelp) CTransaction tx; uint256 hashBlock = 0; if (!GetTransaction(hash, tx, hashBlock)) - throw JSONRPCError(-5, "No information available about transaction"); + throw JSONRPCError(RPC_WALLET_ERROR, "No information available about transaction"); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << tx; @@ -232,9 +232,9 @@ Value listunspent(const Array& params, bool fHelp) { CBitcoinAddress address(input.get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, string("Invalid Bitcoin address: ")+input.get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Paycoin address: ")+input.get_str()); if (setAddress.count(address)) - throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+input.get_str()); + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); setAddress.insert(address); } } @@ -301,17 +301,17 @@ Value createrawtransaction(const Array& params, bool fHelp) const Value& txid_v = find_value(o, "txid"); if (txid_v.type() != str_type) - throw JSONRPCError(-8, "Invalid parameter, missing txid key"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key"); string txid = txid_v.get_str(); if (!IsHex(txid)) - throw JSONRPCError(-8, "Invalid parameter, expected hex txid"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid"); const Value& vout_v = find_value(o, "vout"); if (vout_v.type() != int_type) - throw JSONRPCError(-8, "Invalid parameter, missing vout key"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key"); int nOutput = vout_v.get_int(); if (nOutput < 0) - throw JSONRPCError(-8, "Invalid parameter, vout must be positive"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); CTxIn in(COutPoint(uint256(txid), nOutput)); rawTx.vin.push_back(in); @@ -322,10 +322,10 @@ Value createrawtransaction(const Array& params, bool fHelp) { CBitcoinAddress address(s.name_); if (!address.IsValid()) - throw JSONRPCError(-5, string("Invalid Bitcoin address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Paycoin address: ")+s.name_); if (setAddress.count(address)) - throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); setAddress.insert(address); CScript scriptPubKey; @@ -355,7 +355,7 @@ Value decoderawtransaction(const Array& params, bool fHelp) ssData >> tx; } catch (std::exception &e) { - throw JSONRPCError(-22, "TX decode failed"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); } Object result; @@ -391,12 +391,12 @@ Value signrawtransaction(const Array& params, bool fHelp) txVariants.push_back(tx); } catch (std::exception &e) { - throw JSONRPCError(-22, "TX decode failed"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); } } if (txVariants.empty()) - throw JSONRPCError(-22, "Missing transaction"); + throw JSONRPCError(RPC_WALLET_ERROR, "Missing transaction"); // mergedTx will end up with all the signatures; it // starts as a clone of the rawtx: @@ -437,7 +437,7 @@ Value signrawtransaction(const Array& params, bool fHelp) CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(k.get_str()); if (!fGood) - throw JSONRPCError(-5,"Invalid private key"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); CKey key; bool fCompressed; CSecret secret = vchSecret.GetSecret(fCompressed); @@ -446,7 +446,7 @@ Value signrawtransaction(const Array& params, bool fHelp) } } else if(pwalletMain->IsCrypted()) - throw runtime_error("The wallet must be unlocked with walletpassphrase first"); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "The wallet must be unlocked with walletpassphrase first"); // Add previous txouts given in the RPC call: if (params.size() > 1 && params[1].type() != null_type) @@ -455,23 +455,23 @@ Value signrawtransaction(const Array& params, bool fHelp) BOOST_FOREACH(Value& p, prevTxs) { if (p.type() != obj_type) - throw JSONRPCError(-22, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}"); Object prevOut = p.get_obj(); string txidHex = find_value(prevOut, "txid").get_str(); if (!IsHex(txidHex)) - throw JSONRPCError(-22, "txid must be hexadecimal"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "txid must be hexadecimal"); uint256 txid; txid.SetHex(txidHex); int nOut = find_value(prevOut, "vout").get_int(); if (nOut < 0) - throw JSONRPCError(-22, "vout must be positive"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive"); string pkHex = find_value(prevOut, "scriptPubKey").get_str(); if (!IsHex(pkHex)) - throw JSONRPCError(-22, "scriptPubKey must be hexadecimal"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "scriptPubKey must be hexadecimal"); vector pkData(ParseHex(pkHex)); CScript scriptPubKey(pkData.begin(), pkData.end()); @@ -484,7 +484,7 @@ Value signrawtransaction(const Array& params, bool fHelp) string err("Previous output scriptPubKey mismatch:\n"); err = err + mapPrevOut[outpoint].ToString() + "\nvs:\n"+ scriptPubKey.ToString(); - throw JSONRPCError(-22, err); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err); } } else @@ -523,7 +523,7 @@ Value signrawtransaction(const Array& params, bool fHelp) if (mapSigHashValues.count(strHashType)) nHashType = mapSigHashValues[strHashType]; else - throw JSONRPCError(-8, "Invalid sighash param"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid sighash param"); } bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE); @@ -583,7 +583,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) ssData >> tx; } catch (std::exception &e) { - throw JSONRPCError(-22, "TX decode failed"); + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); } uint256 hashTx = tx.GetHash(); @@ -594,7 +594,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) if (GetTransaction(hashTx, existingTx, hashBlock)) { if (hashBlock != 0) - throw JSONRPCError(-5, string("transaction already in block ")+hashBlock.GetHex()); + throw JSONRPCError(RPC_VERIFY_ALREADY_IN_CHAIN, string("transaction already in block ")+hashBlock.GetHex()); // Not in block, but already in the memory pool; will drop // through to re-relay it. } @@ -603,7 +603,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) // push to local node CTxDB txdb("r"); if (!tx.AcceptToMemoryPool(txdb, fCheckInputs)) - throw JSONRPCError(-22, "TX rejected"); + throw JSONRPCError(RPC_VERIFY_REJECTED, "TX rejected"); SyncWithWallets(tx, NULL, true); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index e5dea576..3e75fffb 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -30,7 +30,7 @@ static std::string HelpRequiringPassphrase() static inline void EnsureWalletIsUnlocked() { if (pwalletMain->IsLocked()) - throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); } void WalletTxToJSON(const CWalletTx& wtx, Object& entry) @@ -52,7 +52,7 @@ string AccountFromValue(const Value& value) { string strAccount = value.get_str(); if (strAccount == "*") - throw JSONRPCError(-11, "Invalid account name"); + throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name"); return strAccount; } @@ -106,7 +106,7 @@ Value getnewaddress(const Array& params, bool fHelp) // Generate a new key that is added to wallet CPubKey newKey; if (!pwalletMain->GetKeyFromPool(newKey, false)) - throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first"); + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); CKeyID keyID = newKey.GetID(); pwalletMain->SetAddressBookName(keyID, strAccount); @@ -143,7 +143,7 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed) { if (!pwalletMain->GetKeyFromPool(account.vchPubKey, false)) - throw JSONRPCError(-12, "Error: Keypool ran out, please call keypoolrefill first"); + throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first"); pwalletMain->SetAddressBookName(account.vchPubKey.GetID(), strAccount); walletdb.WriteAccount(strAccount, account); @@ -178,7 +178,7 @@ Value setaccount(const Array& params, bool fHelp) CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address"); string strAccount; @@ -207,7 +207,7 @@ Value getaccount(const Array& params, bool fHelp) CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address"); string strAccount; map::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); @@ -247,11 +247,12 @@ Value sendtoaddress(const Array& params, bool fHelp) CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address"); // Amount int64 nAmount = AmountFromValue(params[1]); if (nAmount < MIN_TXOUT_AMOUNT) + // Should this be a different (defined) error number? throw JSONRPCError(-101, "Send amount too small"); // Wallet comments @@ -262,11 +263,11 @@ Value sendtoaddress(const Array& params, bool fHelp) wtx.mapValue["to"] = params[3].get_str(); if (pwalletMain->IsLocked()) - throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); if (strError != "") - throw JSONRPCError(-4, strError); + throw JSONRPCError(RPC_WALLET_ERROR, strError); return wtx.GetHash().GetHex(); } @@ -285,15 +286,15 @@ Value signmessage(const Array& params, bool fHelp) CBitcoinAddress addr(strAddress); if (!addr.IsValid()) - throw JSONRPCError(-3, "Invalid address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); CKeyID keyID; if (!addr.GetKeyID(keyID)) - throw JSONRPCError(-3, "Address does not refer to key"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address does not refer to key"); CKey key; if (!pwalletMain->GetKey(keyID, key)) - throw JSONRPCError(-4, "Private key not available"); + throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); CDataStream ss(SER_GETHASH, 0); ss << strMessageMagic; @@ -301,7 +302,7 @@ Value signmessage(const Array& params, bool fHelp) vector vchSig; if (!key.SignCompact(Hash(ss.begin(), ss.end()), vchSig)) - throw JSONRPCError(-5, "Sign failed"); + throw JSONRPCError(RPC_WALLET_ERROR, "Sign failed"); return EncodeBase64(&vchSig[0], vchSig.size()); } @@ -319,17 +320,17 @@ Value verifymessage(const Array& params, bool fHelp) CBitcoinAddress addr(strAddress); if (!addr.IsValid()) - throw JSONRPCError(-3, "Invalid address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); CKeyID keyID; if (!addr.GetKeyID(keyID)) - throw JSONRPCError(-3, "Address does not refer to key"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address does not refer to key"); bool fInvalid = false; vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); if (fInvalid) - throw JSONRPCError(-5, "Malformed base64 encoding"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); CDataStream ss(SER_GETHASH, 0); ss << strMessageMagic; @@ -353,7 +354,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); CScript scriptPubKey; if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address"); scriptPubKey.SetDestination(address.Get()); if (!IsMine(*pwalletMain,scriptPubKey)) return (double)0.0; @@ -607,7 +608,7 @@ Value movecmd(const Array& params, bool fHelp) CWalletDB walletdb(pwalletMain->strWalletFile); if (!walletdb.TxnBegin()) - throw JSONRPCError(-20, "database error"); + throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); int64 nNow = GetAdjustedTime(); @@ -630,7 +631,7 @@ Value movecmd(const Array& params, bool fHelp) walletdb.WriteAccountingEntry(credit); if (!walletdb.TxnCommit()) - throw JSONRPCError(-20, "database error"); + throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); return true; } @@ -646,7 +647,7 @@ Value sendfrom(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address"); int64 nAmount = AmountFromValue(params[2]); if (nAmount < MIN_TXOUT_AMOUNT) throw JSONRPCError(-101, "Send amount too small"); @@ -666,12 +667,12 @@ Value sendfrom(const Array& params, bool fHelp) // Check funds int64 nBalance = GetAccountBalance(strAccount, nMinDepth); if (nAmount > nBalance) - throw JSONRPCError(-6, "Account has insufficient funds"); + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); if (strError != "") - throw JSONRPCError(-4, strError); + throw JSONRPCError(RPC_WALLET_ERROR, strError); return wtx.GetHash().GetHex(); } @@ -711,10 +712,10 @@ Value sendmany(const Array& params, bool fHelp) { CBitcoinAddress address(s.name_); if (!address.IsValid()) - throw JSONRPCError(-5, string("Invalid Paycoin address:")+s.name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Paycoin address:")+s.name_); if (setAddress.count(address)) - throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); setAddress.insert(address); CScript scriptPubKey; @@ -730,20 +731,20 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); if (fWalletUnlockMintOnly) - throw JSONRPCError(-13, "Error: Wallet unlocked for block minting only."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Wallet unlocked for block minting only."); // Check funds if (fFromAllAccounts) { int64 nBalance = pwalletMain->GetBalance(); if (totalAmount > nBalance) - throw JSONRPCError(-6, "Wallet has insufficient funds"); + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Wallet has insufficient funds"); } else { int64 nBalance = GetAccountBalance(strAccount, nMinDepth); if (totalAmount > nBalance) - throw JSONRPCError(-6, "Account has insufficient funds"); + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); } // Send @@ -753,11 +754,11 @@ Value sendmany(const Array& params, bool fHelp) if (!fCreated) { if (totalAmount + nFeeRequired > pwalletMain->GetBalance()) - throw JSONRPCError(-6, "Insufficient funds"); - throw JSONRPCError(-4, "Transaction creation failed"); + throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); + throw JSONRPCError(RPC_WALLET_ERROR, "Transaction creation failed"); } if (!pwalletMain->CommitTransaction(wtx, keyChange)) - throw JSONRPCError(-4, "Transaction commit failed"); + throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed"); return wtx.GetHash().GetHex(); } @@ -772,9 +773,9 @@ CScript _createmultisig(const Array& params) // Gather public keys if (nRequired < 1) - throw runtime_error("a multisignature address must require at least one key to redeem"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "a multisignature address must require at least one key to redeem"); if ((int)keys.size() < nRequired) - throw runtime_error(strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", keys.size(), nRequired)); std::vector pubkeys; pubkeys.resize(keys.size()); for (unsigned int i = 0; i < keys.size(); i++) @@ -787,12 +788,12 @@ CScript _createmultisig(const Array& params) { CKeyID keyID; if (!address.GetKeyID(keyID)) - throw runtime_error(strprintf("%s does not refer to a key",ks.c_str())); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, ks+string(" does not refer to a key")); CPubKey vchPubKey; if (!pwalletMain->GetPubKey(keyID, vchPubKey)) - throw runtime_error(strprintf("no full public key for address %s",ks.c_str())); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("no full public key for address ")+ks); if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid public key: ")+ks); pubkeys[i] = vchPubKey; } @@ -801,12 +802,12 @@ CScript _createmultisig(const Array& params) { CPubKey vchPubKey(ParseHex(ks)); if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid public key: ")+ks); pubkeys[i] = vchPubKey; } else { - throw runtime_error(" Invalid public key: "+ks); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid public key: ")+ks); } } CScript result; @@ -1124,9 +1125,9 @@ Value listtransactions(const Array& params, bool fHelp) nFrom = params[2].get_int(); if (nCount < 0) - throw JSONRPCError(-8, "Negative count"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); if (nFrom < 0) - throw JSONRPCError(-8, "Negative from"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from"); Array ret; CWalletDB walletdb(pwalletMain->strWalletFile); @@ -1315,7 +1316,7 @@ Value listsinceblock(const Array& params, bool fHelp) target_confirms = params[1].get_int(); if (target_confirms < 1) - throw JSONRPCError(-8, "Invalid parameter"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); } int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1; @@ -1368,7 +1369,7 @@ Value gettransaction(const Array& params, bool fHelp) Object entry; if (!pwalletMain->mapWallet.count(hash)) - throw JSONRPCError(-5, "Invalid or non-wallet transaction id"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or non-wallet transaction id"); const CWalletTx& wtx = pwalletMain->mapWallet[hash]; int64 nCredit = wtx.GetCredit(); @@ -1415,7 +1416,7 @@ Value keypoolrefill(const Array& params, bool fHelp) pwalletMain->TopUpKeyPool(); if (pwalletMain->GetKeyPoolSize() < GetArg("-keypool", 100)) - throw JSONRPCError(-4, "Error refreshing keypool."); + throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool."); return Value::null; } @@ -1476,10 +1477,10 @@ Value walletpassphrase(const Array& params, bool fHelp) if (fHelp) return true; if (!pwalletMain->IsCrypted()) - throw JSONRPCError(-15, "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."); if (!pwalletMain->IsLocked()) - throw JSONRPCError(-17, "Error: Wallet is already unlocked, use walletlock first if need to change unlock settings."); + throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked, use walletlock first if need to change unlock settings."); // Note that the walletpassphrase is stored in params[0] which is not mlock()ed SecureString strWalletPass; @@ -1491,7 +1492,7 @@ Value walletpassphrase(const Array& params, bool fHelp) if (strWalletPass.length() > 0) { if (!pwalletMain->Unlock(strWalletPass)) - throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect."); + throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); } else throw runtime_error( @@ -1520,7 +1521,7 @@ Value walletpassphrasechange(const Array& params, bool fHelp) if (fHelp) return true; if (!pwalletMain->IsCrypted()) - throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrasechange was called."); + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called."); // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string) // Alternately, find a way to make params[0] mlock()'d to begin with. @@ -1538,7 +1539,7 @@ Value walletpassphrasechange(const Array& params, bool fHelp) "Changes the wallet passphrase from to ."); if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) - throw JSONRPCError(-14, "Error: The wallet passphrase entered was incorrect."); + throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect."); return Value::null; } @@ -1554,7 +1555,7 @@ Value walletlock(const Array& params, bool fHelp) if (fHelp) return true; if (!pwalletMain->IsCrypted()) - throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called."); + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called."); { LOCK(cs_nWalletUnlockTime); @@ -1574,7 +1575,7 @@ Value encryptwallet(const Array& params, bool fHelp) if (fHelp) return true; if (pwalletMain->IsCrypted()) - throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called."); + throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called."); // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string) // Alternately, find a way to make params[0] mlock()'d to begin with. @@ -1588,7 +1589,7 @@ Value encryptwallet(const Array& params, bool fHelp) "Encrypts the wallet with ."); if (!pwalletMain->EncryptWallet(strWalletPass)) - throw JSONRPCError(-16, "Error: Failed to encrypt the wallet."); + throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet."); // BDB seems to have a bad habit of writing old data into // slack space in .dat files; that is bad if the old data is @@ -1678,17 +1679,17 @@ Value reservebalance(const Array& params, bool fHelp) if (fReserve) { if (params.size() == 1) - throw runtime_error("must provide amount to reserve balance.\n"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "must provide amount to reserve balance.\n"); int64 nAmount = AmountFromValue(params[1]); nAmount = (nAmount / CENT) * CENT; // round to cent if (nAmount < 0) - throw runtime_error("amount cannot be negative.\n"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "amount cannot be negative.\n"); mapArgs["-reservebalance"] = FormatMoney(nAmount).c_str(); } else { if (params.size() > 1) - throw runtime_error("cannot specify amount to turn off reserve.\n"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "cannot specify amount to turn off reserve.\n"); mapArgs["-reservebalance"] = "0"; } } @@ -1696,7 +1697,7 @@ Value reservebalance(const Array& params, bool fHelp) Object result; int64 nReserveBalance = 0; if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance)) - throw runtime_error("invalid reserve balance amount\n"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid reserve balance amount\n"); result.push_back(Pair("reserve", (nReserveBalance > 0))); result.push_back(Pair("amount", ValueFromAmount(nReserveBalance))); return result; @@ -1803,17 +1804,17 @@ Value listmicroprimedata(const Array& params, bool fHelp) CBitcoinAddress address(strAddress); if (!IsMine(*pwalletMain, address.Get())) - throw runtime_error("Address must be in wallet."); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Address must be in wallet."); if (!primeNodeDB->CheckMicroPrime(strAddress)) - throw runtime_error("Address is not a valid microprime address."); + throw JSONRPCError(RPC_WALLET_ERROR, "Address is not a valid microprime address."); int primeNodeRate; int64 group; CScript scriptMPAddress; scriptMPAddress.SetDestination(address.Get()); if (!primeNodeDB->IsMicroPrime(scriptMPAddress, primeNodeRate, group, GetTime())) - throw runtime_error("Address is not a valid microprime address."); + throw JSONRPCError(RPC_WALLET_ERROR, "Address is not a valid microprime address."); Object obj; obj.push_back(Pair("Address", strAddress)); diff --git a/src/scrapesdb.cpp b/src/scrapesdb.cpp index 828fe77c..55cb973f 100644 --- a/src/scrapesdb.cpp +++ b/src/scrapesdb.cpp @@ -21,7 +21,7 @@ Value setscrapeaddress(const Array& params, bool fHelp) } if (pwalletMain->IsLocked()) - throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); string strAddress = params[0].get_str(); CBitcoinAddress address(strAddress); @@ -29,16 +29,16 @@ Value setscrapeaddress(const Array& params, bool fHelp) CBitcoinAddress scrapeAddress(strScrapeAddress); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address."); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address."); if (address.Get() == scrapeAddress.Get()) - throw JSONRPCError(-1, "Cannot set scrape address to the same as staking address."); + throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set scrape address to the same as staking address."); if (!IsMine(*pwalletMain, address.Get())) - throw JSONRPCError(-1, "Staking address must be in wallet."); + throw JSONRPCError(RPC_WALLET_ERROR, "Staking address must be in wallet."); if (!scrapeAddress.IsValid()) - throw JSONRPCError(-5, "Invalid scrape address."); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scrape address."); string oldScrapeAddress; bool warn = false; @@ -59,7 +59,7 @@ Value setscrapeaddress(const Array& params, bool fHelp) } // This should never happen. - throw JSONRPCError(-1, "setscrapeaddress: unknown error"); + throw JSONRPCError(RPC_MISC_ERROR, "setscrapeaddress: unknown error"); } Value getscrapeaddress(const Array& params, bool fHelp) @@ -74,16 +74,16 @@ Value getscrapeaddress(const Array& params, bool fHelp) CBitcoinAddress address(strAddress); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address."); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address."); if (!IsMine(*pwalletMain, address.Get())) - throw JSONRPCError(-1, "Staking address must be in wallet."); + throw JSONRPCError(RPC_WALLET_ERROR, "Staking address must be in wallet."); string strScrapeAddress; if (!scrapesDB->ReadScrapeAddress(strAddress, strScrapeAddress)) { string ret = "No scrape address set for address "; ret += strAddress; - throw JSONRPCError(-1, ret); + throw JSONRPCError(RPC_WALLET_ERROR, ret); } Object obj; @@ -116,21 +116,21 @@ Value deletescrapeaddress(const Array& params, bool fHelp) } if (pwalletMain->IsLocked()) - throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); string strAddress = params[0].get_str(); CBitcoinAddress address(strAddress); if (!address.IsValid()) - throw JSONRPCError(-5, "Invalid Paycoin address."); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Paycoin address."); if (!IsMine(*pwalletMain, address.Get())) - throw JSONRPCError(-1, "Staking address must be in wallet."); + throw JSONRPCError(RPC_WALLET_ERROR, "Staking address must be in wallet."); if (!scrapesDB->HasScrapeAddress(strAddress)) { string ret = "No scrape address set for address "; ret += strAddress; - throw JSONRPCError(-1, ret); + throw JSONRPCError(RPC_WALLET_ERROR, ret); } return scrapesDB->EraseScrapeAddress(strAddress); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 0f9159e0..5c9ba3ca 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -46,18 +46,18 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) address.SetString(v.get_str()); BOOST_CHECK(address.IsValid() && address.IsScript()); - BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(0), false), Object); + BOOST_CHECK_THROW(addmultisig(createArgs(1), false), Object); + BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), Object); - BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error); - BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), Object); + BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), Object); string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), Object); string short2(address1Hex+2, address1Hex+sizeof(address1Hex)); // first byte missing - BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error); + BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), Object); } // Run RPC tests over RPC... @@ -104,7 +104,7 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) string strValidPrivKey = "U9nhhCCbFfY64wozUZ6ScrNNvBqhGtoi8cNHXmaLm3wi1VHtjhr8"; string strValidAddress2 = "PAjArWaTwv8P32b13iTn1bL7aN25Y9pMmJ"; - // error: {"code":-1,"message":"Staking address must be in wallet."} + // error: {"code":-4,"message":"Staking address must be in wallet."} string strMethod = "setscrapeaddress"; vector strParams; strParams.push_back(strValidAddress); @@ -114,7 +114,7 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) int error_code; BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -1); + BOOST_CHECK_EQUAL(error_code, RPC_WALLET_ERROR); strMethod = "getscrapeaddress"; strParams.clear(); @@ -123,14 +123,14 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -1); + BOOST_CHECK_EQUAL(error_code, RPC_WALLET_ERROR); strMethod = "deletescrapeaddress"; obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -1); + BOOST_CHECK_EQUAL(error_code, RPC_WALLET_ERROR); // Import a valid private key for testing on. strMethod = "importprivkey"; @@ -151,7 +151,7 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -5); + BOOST_CHECK_EQUAL(error_code, RPC_INVALID_ADDRESS_OR_KEY); strMethod = "getscrapeaddress"; strParams.clear(); @@ -160,14 +160,14 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -5); + BOOST_CHECK_EQUAL(error_code, RPC_INVALID_ADDRESS_OR_KEY); strMethod = "deletescrapeaddress"; obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -5); + BOOST_CHECK_EQUAL(error_code, RPC_INVALID_ADDRESS_OR_KEY); // error: {"code":-5,"message":"Invalid scrape address."} strMethod = "setscrapeaddress"; @@ -178,9 +178,9 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -5); + BOOST_CHECK_EQUAL(error_code, RPC_INVALID_ADDRESS_OR_KEY); - // error: {"code":-1,"message":"Cannot set scrape address to the same as staking address."} + // error: {"code":-4,"message":"Cannot set scrape address to the same as staking address."} strParams.clear(); strParams.push_back(strValidAddress); strParams.push_back(strValidAddress); @@ -188,9 +188,9 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -1); + BOOST_CHECK_EQUAL(error_code, RPC_WALLET_ERROR); - // error: ("code":-1,"message":"No scrape address set for address ") + // error: ("code":-4,"message":"No scrape address set for address ") strMethod = "getscrapeaddress"; strParams.clear(); strParams.push_back(strValidAddress); @@ -198,14 +198,14 @@ BOOST_FIXTURE_TEST_CASE(rpc_scrapes, RPCServerFixture) obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -1); + BOOST_CHECK_EQUAL(error_code, RPC_WALLET_ERROR); strMethod = "deletescrapeaddress"; obj = callRPC(strMethod, strParams); BOOST_CHECK(!readResponse(obj, error_code)); - BOOST_CHECK_EQUAL(error_code, -1); + BOOST_CHECK_EQUAL(error_code, RPC_WALLET_ERROR); // Valid setscrapeaddress strMethod = "setscrapeaddress";