#include "db.h"
#include "net.h"
#include "init.h"
+#include "checkpoints.h"
#undef printf
#include <boost/asio.hpp>
#include <boost/iostreams/concepts.hpp>
Object obj;
obj.push_back(Pair("version", (int)VERSION));
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
+ obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint())));
obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake())));
obj.push_back(Pair("blocks", (int)nBestHeight));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
+ obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP()));
obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
if (pwalletMain->IsLocked())
throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+ if (fWalletUnlockStakeOnly)
+ throw JSONRPCError(-13, "Error: Wallet unlocked for coinstake only.");
// Check funds
int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
Value walletpassphrase(const Array& params, bool fHelp)
{
- if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
+ if (pwalletMain->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 3))
throw runtime_error(
- "walletpassphrase <passphrase> <timeout>\n"
- "Stores the wallet decryption key in memory for <timeout> seconds.");
+ "walletpassphrase <passphrase> <timeout> [stakeonly]\n"
+ "Stores the wallet decryption key in memory for <timeout> seconds.\n"
+ "stakeonly is optional true/false allowing only stake creation.");
if (fHelp)
return true;
if (!pwalletMain->IsCrypted())
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
if (!pwalletMain->IsLocked())
- throw JSONRPCError(-17, "Error: Wallet is already unlocked.");
+ throw JSONRPCError(-17, "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;
int* pnSleepTime = new int(params[1].get_int());
CreateThread(ThreadCleanWalletPassphrase, pnSleepTime);
+ // ppcoin: if user OS account compromised prevent trivial sendmoney commands
+ if (params.size() > 2)
+ fWalletUnlockStakeOnly = params[2].get_bool();
+ else
+ fWalletUnlockStakeOnly = false;
+
return Value::null;
}
}
+// ppcoin: reset auto checkpoint
+Value resetcheckpoint(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 1)
+ throw runtime_error(
+ "resetcheckpoint <checkpointheight>\n"
+ "Reset automatic checkpoint to specified height.\n"
+ "<checkpointheight> is the height of the new checkpoint block.\n");
+
+ int nCheckpoint = params[0].get_int();
+ if (nCheckpoint <= 0 || nCheckpoint >= nBestHeight)
+ throw runtime_error(
+ "invalid checkpoint height.\n"
+ );
+ if (nCheckpoint >= Checkpoints::nAutoCheckpoint)
+ throw runtime_error(
+ "new checkpoint must be earlier than current auto checkpoint.\n"
+ );
+ if (!Checkpoints::ResetAutoCheckpoint(nCheckpoint))
+ throw runtime_error(
+ "internal error - reset checkpoint failed.\n"
+ );
+
+ return Value::null;
+}
+
+
+// ppcoin: get branch point of alternative branch
+Value getbranchpoint(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "getbranchpoint\n"
+ "Returns height of branch point of alternative branch.\n");
+
+ Object result;
+ if (Checkpoints::nBranchPoint > 0)
+ result.push_back(Pair("branchpoint", Checkpoints::nBranchPoint));
+ else
+ result.push_back(Pair("branchpoint", "none"));
+ result.push_back(Pair("checkpoint", Checkpoints::nAutoCheckpoint));
+ return result;
+}
+
+
+// ppcoin: reserve balance from being staked for network protection
+Value reservebalance(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2)
+ throw runtime_error(
+ "reservebalance [<reserve> [amount]]\n"
+ "<reserve> is true or false to turn balance reserve on or off.\n"
+ "<amount> is a real and rounded to cent.\n"
+ "Set reserve amount not participating in network protection.\n"
+ "If no parameters provided current setting is printed.\n");
+
+ if (params.size() > 0)
+ {
+ bool fReserve = params[0].get_bool();
+ if (fReserve)
+ {
+ if (params.size() == 1)
+ throw runtime_error("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");
+ WriteSetting("nBalanceReserve", nBalanceReserve = nAmount);
+ }
+ else
+ {
+ if (params.size() > 1)
+ throw runtime_error("cannot specify amount to turn off reserve.\n");
+ WriteSetting("nBalanceReserve", nBalanceReserve = 0);
+ }
+ }
+
+ Object result;
+ result.push_back(Pair("reserve", (nBalanceReserve > 0)));
+ result.push_back(Pair("amount", ValueFromAmount(nBalanceReserve)));
+ return result;
+}
+
+
+// ppcoin: check wallet integrity
+Value checkwallet(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 0)
+ throw runtime_error(
+ "checkwallet\n"
+ "Check wallet for integrity.\n");
+
+ int nMismatchSpent;
+ int64 nBalanceInQuestion;
+ if (!pwalletMain->CheckSpentCoins(nMismatchSpent, nBalanceInQuestion))
+ {
+ Object result;
+ result.push_back(Pair("mismatched spent coins", nMismatchSpent));
+ result.push_back(Pair("amount in question", ValueFromAmount(nBalanceInQuestion)));
+ return result;
+ }
+ return Value::null;
+}
+
+// ppcoin: repair wallet
+Value repairwallet(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 0)
+ throw runtime_error(
+ "repairwallet\n"
+ "Repair wallet if checkwallet reports any problem.\n");
+
+ int nMismatchSpent;
+ int64 nBalanceInQuestion;
+ pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion);
+ Object result;
+ if (nMismatchSpent == 0)
+ {
+ result.push_back(Pair("wallet check passed", true));
+ }
+ else
+ {
+ result.push_back(Pair("mismatched spent coins", nMismatchSpent));
+ result.push_back(Pair("amount affected by repair", ValueFromAmount(nBalanceInQuestion)));
+ }
+ return result;
+}
+extern CCriticalSection cs_mapAlerts;
+extern map<uint256, CAlert> mapAlerts;
+// ppcoin: send alert.
+// There is a known deadlock situation with ThreadMessageHandler
+// ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages()
+// ThreadRPCServer: holds cs_main and acquiring cs_vSend in alert.RelayTo()/PushMessage()/BeginMessage()
+Value sendalert(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() < 5)
+ throw runtime_error(
+ "sendalert <message> <privatekey> <minver> <maxver> <id> [cancelupto]\n"
+ "<message> is the alert text message\n"
+ "<privatekey> is hex string of alert master private key\n"
+ "<minver> is the minimum applicable client version\n"
+ "<maxver> is the maximum applicable client version\n"
+ "<id> is the alert id\n"
+ "[cancelupto] cancels all alert id's up to this number\n"
+ "Returns true or false.");
+ CAlert alert;
+ CKey key;
+ alert.strStatusBar = params[0].get_str();
+ alert.nMinVer = params[2].get_int();
+ alert.nMaxVer = params[3].get_int();
+ alert.nID = params[4].get_int();
+ if (params.size() > 5)
+ alert.nCancel = params[5].get_int();
+ alert.nVersion = VERSION;
+ alert.nRelayUntil = GetAdjustedTime() + 365*24*60*60;
+ alert.nExpiration = GetAdjustedTime() + 365*24*60*60;
+ alert.nPriority = 1;
+
+ CDataStream sMsg;
+ sMsg << (CUnsignedAlert)alert;
+ alert.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end());
+
+ vector<unsigned char> 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");
+ if(!alert.ProcessAlert())
+ throw runtime_error(
+ "Failed to process alert.\n");
+ // Relay alert
+ CRITICAL_BLOCK(cs_vNodes)
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ alert.RelayTo(pnode);
+ Object result;
+ result.push_back(Pair("strStatusBar", alert.strStatusBar));
+ result.push_back(Pair("nVersion", alert.nVersion));
+ result.push_back(Pair("nMinVer", alert.nMinVer));
+ result.push_back(Pair("nMaxVer", alert.nMaxVer));
+ result.push_back(Pair("nID", alert.nID));
+ if (alert.nCancel > 0)
+ result.push_back(Pair("nCancel", alert.nCancel));
+ return result;
+}
+Value makekeypair(const Array& params, bool fHelp)
+{
+ CKey key;
+ key.MakeNewKey();
+ CPrivKey vchPrivKey = key.GetPrivKey();
+ Object result;
+ result.push_back(Pair("PrivateKey", HexStr<CPrivKey::iterator>(vchPrivKey.begin(), vchPrivKey.end())));
+ result.push_back(Pair("PublicKey", HexStr(key.GetPubKey())));
+ return result;
+}
//
// Call Table
make_pair("settxfee", &settxfee),
make_pair("getmemorypool", &getmemorypool),
make_pair("listsinceblock", &listsinceblock),
+ make_pair("resetcheckpoint", &resetcheckpoint),
+ make_pair("getbranchpoint", &getbranchpoint),
+ make_pair("reservebalance", &reservebalance),
+ make_pair("checkwallet", &checkwallet),
+ make_pair("repairwallet", &repairwallet),
+ make_pair("sendalert", &sendalert),
+ make_pair("makekeypair", &makekeypair),
};
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
"validateaddress",
"getwork",
"getmemorypool",
+ "resetcheckpoint",
+ "getbranchpoint",
};
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
if (strMethod == "listtransactions" && n > 2) ConvertTo<boost::int64_t>(params[2]);
if (strMethod == "listaccounts" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "walletpassphrase" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "walletpassphrase" && n > 2) ConvertTo<bool>(params[2]);
if (strMethod == "listsinceblock" && n > 1) ConvertTo<boost::int64_t>(params[1]);
+ if (strMethod == "sendalert" && n > 2) ConvertTo<boost::int64_t>(params[2]);
+ if (strMethod == "sendalert" && n > 3) ConvertTo<boost::int64_t>(params[3]);
+ if (strMethod == "sendalert" && n > 4) ConvertTo<boost::int64_t>(params[4]);
+ if (strMethod == "sendalert" && n > 5) ConvertTo<boost::int64_t>(params[5]);
if (strMethod == "sendmany" && n > 1)
{
string s = params[1].get_str();
params[1] = v.get_obj();
}
if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
+ if (strMethod == "resetcheckpoint" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "reservebalance" && n > 0) ConvertTo<bool>(params[0]);
+ if (strMethod == "reservebalance" && n > 1) ConvertTo<double>(params[1]);
// Execute
Object reply = CallRPC(strMethod, params);