|
|
@ -24,36 +24,6 @@ |
|
|
|
using namespace json_spirit; |
|
|
|
using namespace json_spirit; |
|
|
|
using namespace std; |
|
|
|
using namespace std; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_WALLET |
|
|
|
|
|
|
|
// Key used by getwork miners.
|
|
|
|
|
|
|
|
// Allocated in InitRPCMining, free'd in ShutdownRPCMining
|
|
|
|
|
|
|
|
static CReserveKey* pMiningKey = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void InitRPCMining() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!pwalletMain) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// getwork/getblocktemplate mining rewards paid here:
|
|
|
|
|
|
|
|
pMiningKey = new CReserveKey(pwalletMain); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ShutdownRPCMining() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!pMiningKey) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
delete pMiningKey; pMiningKey = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
void InitRPCMining() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
void ShutdownRPCMining() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Return average network hashes per second based on the last 'lookup' blocks,
|
|
|
|
// Return average network hashes per second based on the last 'lookup' blocks,
|
|
|
|
// or from the last difficulty change if 'lookup' is nonpositive.
|
|
|
|
// or from the last difficulty change if 'lookup' is nonpositive.
|
|
|
|
// If 'height' is nonnegative, compute the estimate at the time when a given block was found.
|
|
|
|
// If 'height' is nonnegative, compute the estimate at the time when a given block was found.
|
|
|
@ -131,9 +101,6 @@ Value getgenerate(const Array& params, bool fHelp) |
|
|
|
+ HelpExampleRpc("getgenerate", "") |
|
|
|
+ HelpExampleRpc("getgenerate", "") |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if (!pMiningKey) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return GetBoolArg("-gen", false); |
|
|
|
return GetBoolArg("-gen", false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -279,132 +246,6 @@ Value getmininginfo(const Array& params, bool fHelp) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef ENABLE_WALLET |
|
|
|
|
|
|
|
Value getwork(const Array& params, bool fHelp) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (fHelp || params.size() > 1) |
|
|
|
|
|
|
|
throw runtime_error( |
|
|
|
|
|
|
|
"getwork ( \"data\" )\n" |
|
|
|
|
|
|
|
"\nIf 'data' is not specified, it returns the formatted hash data to work on.\n" |
|
|
|
|
|
|
|
"If 'data' is specified, tries to solve the block and returns true if it was successful.\n" |
|
|
|
|
|
|
|
"\nArguments:\n" |
|
|
|
|
|
|
|
"1. \"data\" (string, optional) The hex encoded data to solve\n" |
|
|
|
|
|
|
|
"\nResult (when 'data' is not specified):\n" |
|
|
|
|
|
|
|
"{\n" |
|
|
|
|
|
|
|
" \"midstate\" : \"xxxx\", (string) The precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
|
|
|
|
|
|
|
|
" \"data\" : \"xxxxx\", (string) The block data\n" |
|
|
|
|
|
|
|
" \"hash1\" : \"xxxxx\", (string) The formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
|
|
|
|
|
|
|
|
" \"target\" : \"xxxx\" (string) The little endian hash target\n" |
|
|
|
|
|
|
|
"}\n" |
|
|
|
|
|
|
|
"\nResult (when 'data' is specified):\n" |
|
|
|
|
|
|
|
"true|false (boolean) If solving the block specified in the 'data' was successfull\n" |
|
|
|
|
|
|
|
"\nExamples:\n" |
|
|
|
|
|
|
|
+ HelpExampleCli("getwork", "") |
|
|
|
|
|
|
|
+ HelpExampleRpc("getwork", "") |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (vNodes.empty()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (IsInitialBlockDownload()) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks..."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t; |
|
|
|
|
|
|
|
static mapNewBlock_t mapNewBlock; // FIXME: thread safety
|
|
|
|
|
|
|
|
static vector<CBlockTemplate*> vNewBlockTemplate; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (params.size() == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Update block
|
|
|
|
|
|
|
|
static unsigned int nTransactionsUpdatedLast; |
|
|
|
|
|
|
|
static CBlockIndex* pindexPrev; |
|
|
|
|
|
|
|
static int64_t nStart; |
|
|
|
|
|
|
|
static CBlockTemplate* pblocktemplate; |
|
|
|
|
|
|
|
if (pindexPrev != chainActive.Tip() || |
|
|
|
|
|
|
|
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (pindexPrev != chainActive.Tip()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// 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 = mempool.GetTransactionsUpdated(); |
|
|
|
|
|
|
|
CBlockIndex* pindexPrevNew = chainActive.Tip(); |
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
UpdateTime(*pblock, 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 = uint256().SetCompact(pblock->nBits); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object result; |
|
|
|
|
|
|
|
result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
|
|
|
|
|
|
|
|
result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); |
|
|
|
|
|
|
|
result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); // deprecated
|
|
|
|
|
|
|
|
result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); |
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Parse parameters
|
|
|
|
|
|
|
|
vector<unsigned char> vchData = ParseHex(params[0].get_str()); |
|
|
|
|
|
|
|
if (vchData.size() != 128) |
|
|
|
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); |
|
|
|
|
|
|
|
CBlock* pdata = (CBlock*)&vchData[0]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Byte reverse
|
|
|
|
|
|
|
|
for (int i = 0; i < 128/4; i++) |
|
|
|
|
|
|
|
((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get saved block
|
|
|
|
|
|
|
|
if (!mapNewBlock.count(pdata->hashMerkleRoot)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pblock->nTime = pdata->nTime; |
|
|
|
|
|
|
|
pblock->nNonce = pdata->nNonce; |
|
|
|
|
|
|
|
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; |
|
|
|
|
|
|
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(pwalletMain != NULL); |
|
|
|
|
|
|
|
return CheckWork(pblock, *pwalletMain, *pMiningKey); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Value getblocktemplate(const Array& params, bool fHelp) |
|
|
|
Value getblocktemplate(const Array& params, bool fHelp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fHelp || params.size() > 1) |
|
|
|
if (fHelp || params.size() > 1) |
|
|
|