if (pindexBest == NULL)
return 1.0;
- int nShift = (pindexBest->nBits >> 24) & 0xff;
+ const CBlockIndex* pindexLastProofOfWork = GetLastBlockIndex(pindexBest, false);
+ int nShift = (pindexLastProofOfWork->nBits >> 24) & 0xff;
double dDiff =
- (double)0x0000ffff / (double)(pindexBest->nBits & 0x00ffffff);
+ (double)0x0000ffff / (double)(pindexLastProofOfWork->nBits & 0x00ffffff);
while (nShift < 29)
{
"Returns an object containing various state info.");
Object obj;
- obj.push_back(Pair("version", (int)VERSION));
+ obj.push_back(Pair("version", FormatFullVersion()));
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->IsCrypted() && (fHelp || params.size() < 2 || params.size() > 3))
throw runtime_error(
"walletpassphrase <passphrase> <timeout> [stakeonly]\n"
- "Stores the wallet decryption key in memory for <timeout> seconds."
- "stakeonly is an optional true/false allowing only stake creation.");
+ "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())
nStart = GetTime();
// Create new block
- pblock = CreateNewBlock(pwalletMain);
+ pblock = CreateNewBlock(pwalletMain, true);
if (!pblock)
throw JSONRPCError(-7, "Out of memory");
vNewBlock.push_back(pblock);
}
// Update nTime
- pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ pblock->nTime = max(pblock->GetBlockTime(), GetAdjustedTime());
pblock->nNonce = 0;
// Update nExtraNonce
pblock->nNonce = pdata->nNonce;
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
+ if (!pblock->SignBlock(*pwalletMain))
+ throw JSONRPCError(-100, "Unable to sign block");
return CheckWork(pblock, *pwalletMain, reservekey);
}
}
-// 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)
+// ppcoin: get information of sync-checkpoint
+Value getcheckpoint(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
- "getbranchpoint\n"
- "Returns height of branch point of alternative branch.\n");
+ "getcheckpoint\n"
+ "Show info of synchronized checkpoint.\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));
+ CBlockIndex* pindexCheckpoint;
+
+ result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
+ pindexCheckpoint = mapBlockIndex[Checkpoints::hashSyncCheckpoint];
+ result.push_back(Pair("height", pindexCheckpoint->nHeight));
+ result.push_back(Pair("timestamp", DateTimeStrFormat("%x %H:%M:%S", pindexCheckpoint->GetBlockTime()).c_str()));
+
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)
+{
+ if (fHelp || params.size() > 1)
+ throw runtime_error(
+ "makekeypair [prefix]\n"
+ "Make a public/private key pair.\n"
+ "[prefix] is optional preferred prefix for the public key.\n");
+
+ string strPrefix = "";
+ if (params.size() > 0)
+ strPrefix = params[0].get_str();
+
+ CKey key;
+ int nCount = 0;
+ do
+ {
+ key.MakeNewKey();
+ nCount++;
+ } while (nCount < 10000 && strPrefix != HexStr(key.GetPubKey()).substr(0, strPrefix.size()));
+
+ if (strPrefix != HexStr(key.GetPubKey()).substr(0, strPrefix.size()))
+ return Value::null;
+
+ 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;
+}
+
+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;
+}
+
+// ppcoin: send checkpoint
+Value sendcheckpoint(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2 || params.size() < 1 )
+ throw runtime_error(
+ "sendcheckpoint <privatekey> [checkpointhash]\n"
+ "<privatekey> is hex string of checkpoint master private key\n"
+ "<checkpointhash> 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");
+ }
+ else
+ {
+ checkpoint.hashCheckpoint = Checkpoints::AutoSelectSyncCheckpoint();
+ if (checkpoint.hashCheckpoint == Checkpoints::hashSyncCheckpoint)
+ throw runtime_error(
+ "Unable to select a more recent sync-checkpoint");
+ }
+
+ CDataStream sMsg;
+ sMsg << (CUnsignedSyncCheckpoint)checkpoint;
+ checkpoint.vchMsg = vector<unsigned char>(sMsg.begin(), sMsg.end());
+
+ vector<unsigned char> 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);
+
+ Object result;
+ result.push_back(Pair("checkpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
+ result.push_back(Pair("height", mapBlockIndex[Checkpoints::hashSyncCheckpoint]->nHeight));
+ result.push_back(Pair("timestamp", DateTimeStrFormat("%x %H:%M:%S", mapBlockIndex[Checkpoints::hashSyncCheckpoint]->GetBlockTime()).c_str()));
+ return result;
+}
//
make_pair("settxfee", &settxfee),
make_pair("getmemorypool", &getmemorypool),
make_pair("listsinceblock", &listsinceblock),
- make_pair("resetcheckpoint", &resetcheckpoint),
- make_pair("getbranchpoint", &getbranchpoint),
+ make_pair("getcheckpoint", &getcheckpoint),
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<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
"validateaddress",
"getwork",
"getmemorypool",
- "resetcheckpoint",
- "getbranchpoint",
+ "getcheckpoint",
};
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[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]);