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, "cyphers is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "cyphers 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; }