X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fbitcoinrpc.cpp;h=033250fe84ea5602a931c9fd8b906966712e69c9;hb=d56fde1346ccd32ca6a6e98d9a0a84c8fa9939e7;hp=5be876c84f3238b333e1f2c9634f52724641e842;hpb=928d604ce64ea9be9adba61d0198faec36e2dd8f;p=novacoin.git diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 5be876c..033250f 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2011 The Bitcoin developers -// Copyright (c) 2011 The PPCoin developers +// Copyright (c) 2011-2012 The PPCoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. @@ -8,6 +8,7 @@ #include "db.h" #include "net.h" #include "init.h" +#include "checkpoints.h" #undef printf #include #include @@ -307,9 +308,12 @@ Value getinfo(const Array& params, bool fHelp) 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())); @@ -623,7 +627,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (wtx.IsCoinBase() || !wtx.IsFinal()) + if (wtx.IsCoinBase() || wtx.IsCoinStake() || !wtx.IsFinal()) continue; BOOST_FOREACH(const CTxOut& txout, wtx.vout) @@ -670,7 +674,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (wtx.IsCoinBase() || !wtx.IsFinal()) + if (wtx.IsCoinBase() || wtx.IsCoinStake() || !wtx.IsFinal()) continue; BOOST_FOREACH(const CTxOut& txout, wtx.vout) @@ -907,6 +911,8 @@ Value sendmany(const Array& params, bool fHelp) 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); @@ -958,7 +964,7 @@ Value ListReceived(const Array& params, bool fByAccounts) for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = (*it).second; - if (wtx.IsCoinBase() || !wtx.IsFinal()) + if (wtx.IsCoinBase() || wtx.IsCoinStake() || !wtx.IsFinal()) continue; int nDepth = wtx.GetDepthInMainChain(); @@ -1440,17 +1446,18 @@ void ThreadCleanWalletPassphrase(void* parg) 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 \n" - "Stores the wallet decryption key in memory for seconds."); + "walletpassphrase [stakeonly]\n" + "Stores the wallet decryption key in memory for 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; @@ -1473,6 +1480,12 @@ Value walletpassphrase(const Array& params, bool fHelp) 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; } @@ -1643,7 +1656,7 @@ Value getwork(const Array& params, bool fHelp) nStart = GetTime(); // Create new block - pblock = CreateNewBlock(reservekey); + pblock = CreateNewBlock(pwalletMain); if (!pblock) throw JSONRPCError(-7, "Out of memory"); vNewBlock.push_back(pblock); @@ -1741,7 +1754,7 @@ Value getmemorypool(const Array& params, bool fHelp) // Create new block if(pblock) delete pblock; - pblock = CreateNewBlock(reservekey); + pblock = CreateNewBlock(pwalletMain); if (!pblock) throw JSONRPCError(-7, "Out of memory"); } @@ -1752,7 +1765,7 @@ Value getmemorypool(const Array& params, bool fHelp) Array transactions; BOOST_FOREACH(CTransaction tx, pblock->vtx) { - if(tx.IsCoinBase()) + if(tx.IsCoinBase() || tx.IsCoinStake()) continue; CDataStream ssTx; @@ -1789,13 +1802,251 @@ Value getmemorypool(const Array& params, bool fHelp) } +// ppcoin: reset auto checkpoint +Value resetcheckpoint(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 1) + throw runtime_error( + "resetcheckpoint \n" + "Reset automatic checkpoint to specified height.\n" + " 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 [ [amount]]\n" + " is true or false to turn balance reserve on or off.\n" + " 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; +} + +// ppcoin: make a public-private key pair +Value makekeypair(const Array& params, bool fHelp) +{ + CKey key; + key.MakeNewKey(); + CPrivKey vchPrivKey = key.GetPrivKey(); + + Object result; + result.push_back(Pair("PrivateKey", HexStr(vchPrivKey.begin(), vchPrivKey.end()))); + result.push_back(Pair("PublicKey", HexStr(key.GetPubKey()))); + return result; +} + +extern CCriticalSection cs_mapAlerts; +extern map 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 [cancelupto]\n" + " is the alert text message\n" + " is hex string of alert master private key\n" + " is the minimum applicable client version\n" + " is the maximum applicable client version\n" + " 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(sMsg.begin(), sMsg.end()); + + 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"); + 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; +} + +// ppcoin: send checkpoint +Value sendcheckpoint(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2 || params.size() < 1 ) + throw runtime_error( + "sendcheckpoint [checkpointhash]\n" + " is hex string of checkpoint master private key\n" + " is the hash of checkpoint block\n"); + CSyncCheckpoint checkpoint; + CKey key; + // TODO: omit checkpointhash parameter + if (params.size() > 1) + { + checkpoint.hashCheckpoint = uint256(params[1].get_str()); + if (!mapBlockIndex.count(checkpoint.hashCheckpoint)) + throw runtime_error( + "Provided checkpoint block is not on main chain\n"); + } + CDataStream sMsg; + sMsg << (CUnsignedSyncCheckpoint)checkpoint; + checkpoint.vchMsg = vector(sMsg.begin(), sMsg.end()); + vector vchPrivKey = ParseHex(params[0].get_str()); + key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end())); // if key is not correct openssl may crash + if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig)) + throw runtime_error( + "Unable to sign checkpoint, check private key?\n"); + if(!checkpoint.ProcessSyncCheckpoint(NULL)) + throw runtime_error( + "Failed to process checkpoint.\n"); + // Relay checkpoint + CRITICAL_BLOCK(cs_vNodes) + BOOST_FOREACH(CNode* pnode, vNodes) + checkpoint.RelayTo(pnode); + return Value::null; +} // @@ -1844,6 +2095,14 @@ pair pCallTable[] = 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("makekeypair", &makekeypair), + make_pair("sendalert", &sendalert), + make_pair("sendcheckpoint", &sendcheckpoint), }; map mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); @@ -1870,6 +2129,8 @@ string pAllowInSafeMode[] = "validateaddress", "getwork", "getmemorypool", + "resetcheckpoint", + "getbranchpoint", }; set setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0])); @@ -2466,7 +2727,12 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "listtransactions" && n > 2) ConvertTo(params[2]); if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); if (strMethod == "walletpassphrase" && n > 1) ConvertTo(params[1]); + if (strMethod == "walletpassphrase" && n > 2) ConvertTo(params[2]); if (strMethod == "listsinceblock" && n > 1) ConvertTo(params[1]); + if (strMethod == "sendalert" && n > 2) ConvertTo(params[2]); + if (strMethod == "sendalert" && n > 3) ConvertTo(params[3]); + if (strMethod == "sendalert" && n > 4) ConvertTo(params[4]); + if (strMethod == "sendalert" && n > 5) ConvertTo(params[5]); if (strMethod == "sendmany" && n > 1) { string s = params[1].get_str(); @@ -2476,6 +2742,9 @@ int CommandLineRPC(int argc, char *argv[]) params[1] = v.get_obj(); } if (strMethod == "sendmany" && n > 2) ConvertTo(params[2]); + if (strMethod == "resetcheckpoint" && n > 0) ConvertTo(params[0]); + if (strMethod == "reservebalance" && n > 0) ConvertTo(params[0]); + if (strMethod == "reservebalance" && n > 1) ConvertTo(params[1]); // Execute Object reply = CallRPC(strMethod, params);