Value getworkex(const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( "getworkex [data, coinbase]\n" "If [data, coinbase] is not specified, returns extended work data.\n" ); if (vNodes.empty()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Thepandacoin is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Thepandacoin is downloading blocks..."); typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t; static mapNewBlock_t mapNewBlock; // FIXME: thread safety static vector<CBlockTemplate*> vNewBlockTemplate; static CReserveKey reservekey(pwalletMain); if (params.size() == 0) { // Update block static unsigned int nTransactionsUpdatedLast; static CBlockIndex* pindexPrev; static int64 nStart; static CBlockTemplate* pblocktemplate; if (pindexPrev != pindexBest || (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)) { if (pindexPrev != pindexBest) { // Deallocate old blocks since they're obsolete now mapNewBlock.clear(); BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate) delete pblocktemplate; vNewBlockTemplate.clear(); } // Clear pindexPrev so future getworks make a new block, despite any failures from here on pindexPrev = NULL; // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = nTransactionsUpdated; CBlockIndex* pindexPrevNew = pindexBest; nStart = GetTime(); // Create new block pblocktemplate = CreateNewBlockWithKey(*pMiningKey); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); vNewBlockTemplate.push_back(pblocktemplate); // Need to update only after we know CreateNewBlock succeeded pindexPrev = pindexPrevNew; } CBlock* pblock = &pblocktemplate->block; // pointer for convenience // Update nTime pblock->UpdateTime(pindexPrev); pblock->nNonce = 0; // Update nExtraNonce static unsigned int nExtraNonce = 0; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); // Save mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); // Pre-build hash buffers char pmidstate[32]; char pdata[128]; char phash1[64]; FormatHashBuffers(pblock, pmidstate, pdata, phash1); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); CTransaction coinbaseTx = pblock->vtx[0]; std::vector<uint256> merkle = pblock->GetMerkleBranch(0); Object result; result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << coinbaseTx; result.push_back(Pair("coinbase", HexStr(ssTx.begin(), ssTx.end()))); Array merkle_arr; BOOST_FOREACH(uint256 merkleh, merkle) { printf("%s\n", merkleh.ToString().c_str()); merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh))); } result.push_back(Pair("merkle", merkle_arr)); return result; }
Value getworkex(const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( "getworkex [data, coinbase]\n" "If [data, coinbase] is not specified, returns extended work data.\n" ); if (vNodes.empty()) throw JSONRPCError(-9, "SSVCoin is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(-10, "SSVCoin is downloading blocks..."); typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t; static mapNewBlock_t mapNewBlock; static vector<CBlock*> vNewBlock; static CReserveKey reservekey(pwalletMain); if (params.size() == 0) { // Update block static unsigned int nTransactionsUpdatedLast; static CBlockIndex* pindexPrev; static int64 nStart; static CBlock* pblock; if (pindexPrev != pindexBest || (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)) { if (pindexPrev != pindexBest) { // Deallocate old blocks since they're obsolete now mapNewBlock.clear(); BOOST_FOREACH(CBlock* pblock, vNewBlock) delete pblock; vNewBlock.clear(); } nTransactionsUpdatedLast = nTransactionsUpdated; pindexPrev = pindexBest; nStart = GetTime(); // Create new block pblock = CreateNewBlock(pwalletMain); if (!pblock) throw JSONRPCError(-7, "Out of memory"); vNewBlock.push_back(pblock); } // Update nTime pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); pblock->nNonce = 0; // Update nExtraNonce static unsigned int nExtraNonce = 0; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); // Save mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); // Prebuild hash buffers char pmidstate[32]; char pdata[128]; char phash1[64]; FormatHashBuffers(pblock, pmidstate, pdata, phash1); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); CTransaction coinbaseTx = pblock->vtx[0]; std::vector<uint256> merkle = pblock->GetMerkleBranch(0); Object result; result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << coinbaseTx; result.push_back(Pair("coinbase", HexStr(ssTx.begin(), ssTx.end()))); Array merkle_arr; BOOST_FOREACH(uint256 merkleh, merkle) { merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh))); } result.push_back(Pair("merkle", merkle_arr)); return result; }
// TODO: allow to query for future blocks Value getsubsidy(const Array& params, bool fHelp) { if (fHelp || params.size() > 2) { throw runtime_error( "getsubsidy [height] [height]\n" "If no height is provided, return subsidy of current block.\n" "Returns the pow reward for block at height or from one to the other.\n" "Biggest height should be no more than the last pow block."); } Object ret; #if PROOF_MODEL == PURE_POS static const int nLastPoWBlock = GetLastPoWBlock(); #endif if (params.size() == 0) { struct AMOUNT subsidy = GetPoWSubsidy(pindexBest); ret.push_back(Pair("blockvalue", subsidy.nValue)); ret.push_back(Pair("currency", COLOR_TICKER[subsidy.nColor])); } else if (params.size() == 1) { int nHeight = (int) params[0].get_int(); #if PROOF_MODEL == PURE_POS if (nHeight > GetLastPoWBlock() || nHeight < 1) #else if (nHeight > (int) nBestHeight + 1 || nHeight < 1) #endif { throw runtime_error( "getsubsidy [height] [height]\n" "If no height is provided, return subsidy of current block.\n" "Returns the pow reward for block at height or from one to the other.\n" "Biggest height should be no more than the last pow block."); } CBlockIndex *pindexPrev; if (nHeight == (int) nBestHeight + 1) { pindexPrev = pindexBest; } else { pindexPrev = GetBlockIndexByNumber(nHeight)->pprev; } struct AMOUNT subsidy = GetPoWSubsidy(pindexPrev); ret.push_back(Pair("blockvalue", subsidy.nValue)); ret.push_back(Pair("currency", COLOR_TICKER[subsidy.nColor])); } else { int p1, p2; p1 = params[0].get_int(); p2 = params[1].get_int(); #if PROOF_MODEL == PURE_POS if ((p1 < 1) || (p2 < 1) || (p1 > nLastPoWBlock) || (p2 > nLastPoWBlock)) { #else if ((p1 < 1) || (p2 < 1) || (p1 > (int) nBestHeight) || (p2 > (int) nBestHeight)) { #endif throw runtime_error( "getsubsidy [height] [height]\n" "If no height is provided, return subsidy of current block.\n" "Returns the pow reward for block at height or from one to the other.\n" "Biggest height should be no more than the last pow block."); } int first, last; if (p1 > p2) { first = p2; last = p1; } else { first = p1; last = p2; } for (int i = first; i <= last; i++) { Object obj; CBlockIndex *pindex = GetBlockIndexByNumber(i); struct AMOUNT subsidy = GetPoWSubsidy(pindex->pprev); obj.push_back(Pair("blockvalue", subsidy.nValue)); obj.push_back(Pair("currency", COLOR_TICKER[subsidy.nColor])); ret.push_back(Pair(boost::lexical_cast<string>(i), obj)); } } return ret; } Value getmininginfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( "getmininginfo\n" "Returns an object containing mining-related information."); bool hasPoS = (nNumberOfStakingCurrencies > 0); uint64_t nWeight = 0; if (hasPoS) { pwalletMain->GetStakeWeight(*pwalletMain, nWeight); } Object obj, diff, weight; obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("currentblocksize",(uint64_t)nLastBlockSize)); obj.push_back(Pair("currentblocktx",(uint64_t)nLastBlockTx)); diff.push_back(Pair("proof-of-work", GetDifficulty())); if (hasPoS) { diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); diff.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); } obj.push_back(Pair("difficulty", diff)); struct AMOUNT subsidy = GetPoWSubsidy(pindexBest); obj.push_back(Pair("blockvalue", subsidy.nValue)); obj.push_back(Pair("currency", COLOR_TICKER[subsidy.nColor])); obj.push_back(Pair("netmhashps", GetPoWMHashPS())); if (hasPoS) { obj.push_back(Pair("netstakeweight", GetPoSKernelPS())); } obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); if (hasPoS) { weight.push_back(Pair("combined", (uint64_t)nWeight)); obj.push_back(Pair("stakeweight", weight)); // IMPORTANT: if you use interest stake, then fix this stuff Object stakeObj; for (int nStakeColor = 1; nStakeColor < N_COLORS; ++nStakeColor) { struct AMOUNT subsidy = GetProofOfStakeReward(pindexBest, nStakeColor); if (subsidy.nValue > 0) { Object mintObj; mintObj.push_back(Pair(COLOR_TICKER[subsidy.nColor], (uint64_t) subsidy.nValue)); stakeObj.push_back(Pair(COLOR_TICKER[nStakeColor], mintObj)); } } obj.push_back(Pair("stakereward", stakeObj)); } obj.push_back(Pair("testnet", fTestNet)); return obj; } Value getstakinginfo(const Array& params, bool fHelp) { if (nNumberOfStakingCurrencies == 0) { throw runtime_error("No staking currencies.\n"); } if (fHelp || params.size() != 0) throw runtime_error( "getstakinginfo\n" "Returns an object containing staking-related information."); int nTargetSpacing = GetTargetSpacing(true, pindexBest->nTime); uint64_t nWeight = 0; pwalletMain->GetStakeWeight(*pwalletMain, nWeight); uint64_t nNetworkWeight = GetPoSKernelPS(); bool staking = nLastCoinStakeSearchInterval && nWeight; int nExpectedTime = staking ? (nTargetSpacing * nNetworkWeight / nWeight) : -1; Object obj; obj.push_back(Pair("enabled", GetBoolArg("-staking", true))); obj.push_back(Pair("staking", staking)); obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize)); obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx)); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("difficulty", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); obj.push_back(Pair("weight", (uint64_t)nWeight)); obj.push_back(Pair("netstakeweight", (uint64_t)nNetworkWeight)); obj.push_back(Pair("expectedtime", nExpectedTime)); return obj; } Value getworkex(const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( "getworkex [data, coinbase]\n" "If [data, coinbase] is not specified, returns extended work data.\n" ); if (vNodes.empty()) throw JSONRPCError(-9, "breakout is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(-10, "breakout is downloading blocks..."); #if PROOF_MODEL == PURE_POS static const int nLastPoWBlock = GetLastPoWBlock(); if (pindexBest->nHeight >= nLastPoWBlock) throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); #endif typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t; static mapNewBlock_t mapNewBlock; static vector<CBlock*> vNewBlock; static CReserveKey reservekey(pwalletMain); if (params.size() == 0) { // Update block static unsigned int nTransactionsUpdatedLast; static CBlockIndex* pindexPrev; static int64_t nStart; static CBlock* pblock; if (pindexPrev != pindexBest || (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)) { if (pindexPrev != pindexBest) { // Deallocate old blocks since they're obsolete now mapNewBlock.clear(); BOOST_FOREACH(CBlock* pblock, vNewBlock) delete pblock; vNewBlock.clear(); } nTransactionsUpdatedLast = nTransactionsUpdated; pindexPrev = pindexBest; nStart = GetTime(); // Create new block pblock = CreateNewBlock(pwalletMain); if (!pblock) throw JSONRPCError(-7, "Out of memory"); vNewBlock.push_back(pblock); } // Update nTime pblock->nTime = max(pindexPrev->GetPastTimeLimit()+1, GetAdjustedTime()); pblock->nNonce = 0; // Update nExtraNonce static unsigned int nExtraNonce = 0; IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); // Save mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); // Prebuild hash buffers char pmidstate[32]; char pdata[128]; char phash1[64]; FormatHashBuffers(pblock, pmidstate, pdata, phash1); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); CTransaction coinbaseTx = pblock->vtx[0]; std::vector<uint256> merkle = pblock->GetMerkleBranch(0); Object result; result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << coinbaseTx; result.push_back(Pair("coinbase", HexStr(ssTx.begin(), ssTx.end()))); Array merkle_arr; BOOST_FOREACH(uint256 merkleh, merkle) { merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh))); } result.push_back(Pair("merkle", merkle_arr)); return result; } else {