|
21 | 21 | #include "util.h"
|
22 | 22 | #include "utilstrencodings.h"
|
23 | 23 | #include "validationinterface.h"
|
| 24 | +#ifdef ENABLE_WALLET |
| 25 | +#include "wallet/wallet.h" |
| 26 | +#endif |
24 | 27 |
|
25 | 28 | #include <stdint.h>
|
26 | 29 |
|
|
31 | 34 |
|
32 | 35 | using namespace std;
|
33 | 36 |
|
| 37 | +#ifdef ENABLE_WALLET |
| 38 | +// Key used by getwork miners. |
| 39 | +// Allocated in InitRPCMining, free'd in ShutdownRPCMining |
| 40 | +static CReserveKey* pMiningKey = NULL; |
| 41 | + |
| 42 | +void InitRPCMining() |
| 43 | +{ |
| 44 | + if (!pwalletMain) |
| 45 | + return; |
| 46 | + |
| 47 | + // getwork/getblocktemplate mining rewards paid here: |
| 48 | + pMiningKey = new CReserveKey(pwalletMain); |
| 49 | +} |
| 50 | + |
| 51 | +void ShutdownRPCMining() |
| 52 | +{ |
| 53 | + if (!pMiningKey) |
| 54 | + return; |
| 55 | + |
| 56 | + delete pMiningKey; pMiningKey = NULL; |
| 57 | +} |
| 58 | +#else |
| 59 | +void InitRPCMining() |
| 60 | +{ |
| 61 | +} |
| 62 | +void ShutdownRPCMining() |
| 63 | +{ |
| 64 | +} |
| 65 | +#endif |
| 66 | + |
34 | 67 | /**
|
35 | 68 | * Return average network hashes per second based on the last 'lookup' blocks,
|
36 | 69 | * or from the last difficulty change if 'lookup' is nonpositive.
|
@@ -319,6 +352,118 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
|
319 | 352 | return s;
|
320 | 353 | }
|
321 | 354 |
|
| 355 | +#ifdef ENABLE_WALLET |
| 356 | +UniValue getwork(const UniValue& params, bool fHelp) |
| 357 | +{ |
| 358 | + if (fHelp || params.size() > 1) |
| 359 | + throw runtime_error( |
| 360 | + "getwork ( \"data\" )\n" |
| 361 | + "\nIf 'data' is not specified, it returns the formatted hash data to work on.\n" |
| 362 | + "If 'data' is specified, tries to solve the block and returns true if it was successful.\n" |
| 363 | + "\nArguments:\n" |
| 364 | + "1. \"data\" (string, optional) The hex encoded data to solve\n" |
| 365 | + "\nResult (when 'data' is not specified):\n" |
| 366 | + "{\n" |
| 367 | + " \"data\" : \"xxxxx\", (string) The block data\n" |
| 368 | + " \"target\" : \"xxxx\" (string) The little endian hash target\n" |
| 369 | + "}\n" |
| 370 | + "If [data] is specified, verifies the PoW hash against target and returns true if successful." |
| 371 | + "\nExamples:\n" |
| 372 | + + HelpExampleCli("getwork", "") |
| 373 | + + HelpExampleRpc("getwork", "") |
| 374 | + ); |
| 375 | + |
| 376 | + if (vNodes.empty()) |
| 377 | + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Trezarcoin is not connected!"); |
| 378 | + |
| 379 | + if (IsInitialBlockDownload()) |
| 380 | + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Trezarcoin is downloading blocks..."); |
| 381 | + |
| 382 | + typedef std::map<uint256, std::pair<CBlock*, CScript> > mapNewBlock_t; |
| 383 | + static mapNewBlock_t mapNewBlock; // FIXME: thread safety |
| 384 | + |
| 385 | + static boost::shared_ptr<CReserveScript> coinbaseScript; |
| 386 | + |
| 387 | + if (params.size() == 0) |
| 388 | + { |
| 389 | + // Update block |
| 390 | + static unsigned int nTransactionsUpdatedLast; |
| 391 | + static CBlockIndex* pindexPrev; |
| 392 | + static int64_t nStart; |
| 393 | + static CBlockTemplate* pblocktemplate; |
| 394 | + |
| 395 | + if (pindexPrev != chainActive.Tip() || |
| 396 | + (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)) |
| 397 | + { |
| 398 | + if (pindexPrev != chainActive.Tip()) |
| 399 | + mapNewBlock.clear(); |
| 400 | + |
| 401 | + // Clear pindexPrev so future getworks make a new block, despite any failures from here on |
| 402 | + pindexPrev = nullptr; |
| 403 | + |
| 404 | + // Store the pindexBest used before CreateNewBlock, to avoid races |
| 405 | + nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); |
| 406 | + CBlockIndex* pindexPrevNew = chainActive.Tip(); |
| 407 | + nStart = GetTime(); |
| 408 | + |
| 409 | + // Create new block |
| 410 | + GetMainSignals().ScriptForMining(coinbaseScript); |
| 411 | + pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript); |
| 412 | + if (!pblocktemplate) |
| 413 | + throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); |
| 414 | + |
| 415 | + // Need to update only after we know CreateNewBlock succeeded |
| 416 | + pindexPrev = pindexPrevNew; |
| 417 | + } |
| 418 | + CBlock* pblock = &pblocktemplate->block; // pointer for convenience |
| 419 | + |
| 420 | + // Update nTime |
| 421 | + UpdateTime(pblock, Params().GetConsensus(), pindexPrev); |
| 422 | + pblock->nNonce = 0; |
| 423 | + |
| 424 | + // Update nExtraNonce |
| 425 | + static unsigned int nExtraNonce = 0; |
| 426 | + IncrementExtraNonce(pblock, pindexPrev, nExtraNonce); |
| 427 | + |
| 428 | + // Save |
| 429 | + mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, pblock->vtx[0].vin[0].scriptSig); |
| 430 | + |
| 431 | + // Pre-build hash buffers |
| 432 | + unsigned int pdata[32]; |
| 433 | + FormatDataBuffer(pblock, pdata); |
| 434 | + |
| 435 | + arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); |
| 436 | + |
| 437 | + UniValue result(UniValue::VOBJ); |
| 438 | + result.push_back(Pair("data", HexStr(BEGIN(pdata), (char *) &pdata[20]))); |
| 439 | + result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); |
| 440 | + |
| 441 | + return result; |
| 442 | + } |
| 443 | + else |
| 444 | + { |
| 445 | + // Parse parameters |
| 446 | + vector<unsigned char> vchData = ParseHex(params[0].get_str()); |
| 447 | + if (vchData.size() < 80) |
| 448 | + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); |
| 449 | + CBlock* pdata = (CBlock*)&vchData[0]; |
| 450 | + |
| 451 | + // Get saved block |
| 452 | + if (!mapNewBlock.count(pdata->hashMerkleRoot)) |
| 453 | + return false; |
| 454 | + CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; |
| 455 | + |
| 456 | + pblock->nTime = pdata->nTime; |
| 457 | + pblock->nNonce = pdata->nNonce; |
| 458 | + pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second; |
| 459 | + pblock->hashMerkleRoot = pblock->BuildMerkleTree(); |
| 460 | + |
| 461 | + assert(pwalletMain != NULL); |
| 462 | + return CheckWork(Params(), pblock, *pwalletMain, *pMiningKey); |
| 463 | + } |
| 464 | +} |
| 465 | +#endif |
| 466 | + |
322 | 467 | UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
323 | 468 | {
|
324 | 469 | if (fHelp || params.size() > 1)
|
@@ -942,6 +1087,7 @@ static const CRPCCommand commands[] =
|
942 | 1087 | { "mining", "getmininginfo", &getmininginfo, true },
|
943 | 1088 | { "mining", "prioritisetransaction", &prioritisetransaction, true },
|
944 | 1089 | { "mining", "getblocktemplate", &getblocktemplate, true },
|
| 1090 | + { "mining", "getwork", &getwork, true }, |
945 | 1091 | { "mining", "submitblock", &submitblock, true },
|
946 | 1092 |
|
947 | 1093 | { "generating", "staking", &staking, true },
|
|
0 commit comments