Remove dead PoW mining code to reduce antivirus false positives
Strip getwork, getworkex, getblocktemplate, submitblock RPC commands and their helper functions (SHA256Transform, FormatHashBlocks, FormatHashBuffers, IncrementExtraNonce, CheckWork) which have been dead code since PoW ended at block 9000. AV engines pattern-match these nonce-incrementing loops and mining pool interfaces as cryptominer signatures. Block validation (CheckProofOfWork) and Hash9 algorithm files are preserved - only block *creation* for PoW mining is removed. PoS staking code is untouched. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+5
-433
@@ -108,438 +108,10 @@ Value getstakinginfo(const Array& params, bool fHelp)
|
||||
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, "Triangles is not connected!");
|
||||
|
||||
if (IsInitialBlockDownload())
|
||||
throw JSONRPCError(-10, "Triangles is downloading blocks...");
|
||||
|
||||
if (pindexBest->nHeight >= CUTOFF_POW_BLOCK)
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "No more PoW 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_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();
|
||||
for (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;
|
||||
|
||||
for (uint256 merkleh : merkle) {
|
||||
merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh)));
|
||||
}
|
||||
|
||||
result.push_back(Pair("merkle", merkle_arr));
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Parse parameters
|
||||
vector<unsigned char> vchData = ParseHex(params[0].get_str());
|
||||
vector<unsigned char> coinbase;
|
||||
|
||||
if(params.size() == 2)
|
||||
coinbase = ParseHex(params[1].get_str());
|
||||
|
||||
if (vchData.size() != 128)
|
||||
throw JSONRPCError(-8, "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;
|
||||
|
||||
if(coinbase.size() == 0)
|
||||
pblock->vtx[0].vin[0].scriptSig = mapNewBlock[pdata->hashMerkleRoot].second;
|
||||
else
|
||||
// Deserialize custom coinbase transaction from miner
|
||||
CDataStream(coinbase, SER_NETWORK, PROTOCOL_VERSION) >> pblock->vtx[0];
|
||||
|
||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||
|
||||
return CheckWork(pblock, *pwalletMain, reservekey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Value getwork(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"getwork [data]\n"
|
||||
"If [data] is not specified, returns formatted hash data to work on:\n"
|
||||
" \"midstate\" : precomputed hash state after hashing the first half of the data (DEPRECATED)\n" // deprecated
|
||||
" \"data\" : block data\n"
|
||||
" \"hash1\" : formatted hash buffer for second hash (DEPRECATED)\n" // deprecated
|
||||
" \"target\" : little endian hash target\n"
|
||||
"If [data] is specified, tries to solve the block and returns true if it was successful.");
|
||||
|
||||
if (vNodes.empty())
|
||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Triangles is not connected!");
|
||||
|
||||
if (IsInitialBlockDownload())
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Triangles is downloading blocks...");
|
||||
|
||||
if (pindexBest->nHeight >= CUTOFF_POW_BLOCK)
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks");
|
||||
|
||||
typedef map<uint256, pair<CBlock*, CScript> > mapNewBlock_t;
|
||||
// NOTE: Thread safety issue - static variables accessed by multiple RPC threads
|
||||
// without mutex protection. Low priority since PoW ended at block 9000 and
|
||||
// getwork is rarely used. Consider adding std::mutex if usage increases.
|
||||
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();
|
||||
for (CBlock* pblock : vNewBlock)
|
||||
delete pblock;
|
||||
vNewBlock.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
|
||||
pblock = CreateNewBlock(pwalletMain);
|
||||
if (!pblock)
|
||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||
vNewBlock.push_back(pblock);
|
||||
|
||||
// Need to update only after we know CreateNewBlock succeeded
|
||||
pindexPrev = pindexPrevNew;
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
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();
|
||||
|
||||
return CheckWork(pblock, *pwalletMain, reservekey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Value getblocktemplate(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"getblocktemplate [params]\n"
|
||||
"Returns data needed to construct a block to work on:\n"
|
||||
" \"version\" : block version\n"
|
||||
" \"previousblockhash\" : hash of current highest block\n"
|
||||
" \"transactions\" : contents of non-coinbase transactions that should be included in the next block\n"
|
||||
" \"coinbaseaux\" : data that should be included in coinbase\n"
|
||||
" \"coinbasevalue\" : maximum allowable input to coinbase transaction, including the generation award and transaction fees\n"
|
||||
" \"target\" : hash target\n"
|
||||
" \"mintime\" : minimum timestamp appropriate for next block\n"
|
||||
" \"curtime\" : current timestamp\n"
|
||||
" \"mutable\" : list of ways the block template may be changed\n"
|
||||
" \"noncerange\" : range of valid nonces\n"
|
||||
" \"sigoplimit\" : limit of sigops in blocks\n"
|
||||
" \"sizelimit\" : limit of block size\n"
|
||||
" \"bits\" : compressed target of next block\n"
|
||||
" \"height\" : height of the next block");
|
||||
|
||||
std::string strMode = "template";
|
||||
if (params.size() > 0)
|
||||
{
|
||||
const Object& oparam = params[0].get_obj();
|
||||
const Value& modeval = find_value(oparam, "mode");
|
||||
if (modeval.type() == str_type)
|
||||
strMode = modeval.get_str();
|
||||
else if (modeval.type() == null_type)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
else
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||
}
|
||||
|
||||
if (strMode != "template")
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||
|
||||
if (vNodes.empty())
|
||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Triangles is not connected!");
|
||||
|
||||
if (IsInitialBlockDownload())
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Triangles is downloading blocks...");
|
||||
|
||||
if (pindexBest->nHeight >= CUTOFF_POW_BLOCK)
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks");
|
||||
|
||||
static CReserveKey reservekey(pwalletMain);
|
||||
|
||||
// Update block
|
||||
static unsigned int nTransactionsUpdatedLast;
|
||||
static CBlockIndex* pindexPrev;
|
||||
static int64_t nStart;
|
||||
static CBlock* pblock;
|
||||
if (pindexPrev != pindexBest ||
|
||||
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
|
||||
{
|
||||
// Clear pindexPrev so future calls 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
|
||||
if(pblock)
|
||||
{
|
||||
delete pblock;
|
||||
pblock = NULL;
|
||||
}
|
||||
pblock = CreateNewBlock(pwalletMain);
|
||||
if (!pblock)
|
||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||
|
||||
// Need to update only after we know CreateNewBlock succeeded
|
||||
pindexPrev = pindexPrevNew;
|
||||
}
|
||||
|
||||
// Update nTime
|
||||
pblock->UpdateTime(pindexPrev);
|
||||
pblock->nNonce = 0;
|
||||
|
||||
Array transactions;
|
||||
map<uint256, int64_t> setTxIndex;
|
||||
int i = 0;
|
||||
CTxDB txdb("r");
|
||||
for (CTransaction& tx : pblock->vtx)
|
||||
{
|
||||
uint256 txHash = tx.GetHash();
|
||||
setTxIndex[txHash] = i++;
|
||||
|
||||
if (tx.IsCoinBase() || tx.IsCoinStake())
|
||||
continue;
|
||||
|
||||
Object entry;
|
||||
|
||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ssTx << tx;
|
||||
entry.push_back(Pair("data", HexStr(ssTx.begin(), ssTx.end())));
|
||||
|
||||
entry.push_back(Pair("hash", txHash.GetHex()));
|
||||
|
||||
MapPrevTx mapInputs;
|
||||
map<uint256, CTxIndex> mapUnused;
|
||||
bool fInvalid = false;
|
||||
if (tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid))
|
||||
{
|
||||
entry.push_back(Pair("fee", (int64_t)(tx.GetValueIn(mapInputs) - tx.GetValueOut())));
|
||||
|
||||
Array deps;
|
||||
for (MapPrevTx::value_type& inp : mapInputs)
|
||||
{
|
||||
if (setTxIndex.count(inp.first))
|
||||
deps.push_back(setTxIndex[inp.first]);
|
||||
}
|
||||
entry.push_back(Pair("depends", deps));
|
||||
|
||||
int64_t nSigOps = tx.GetLegacySigOpCount();
|
||||
nSigOps += tx.GetP2SHSigOpCount(mapInputs);
|
||||
entry.push_back(Pair("sigops", nSigOps));
|
||||
}
|
||||
|
||||
transactions.push_back(entry);
|
||||
}
|
||||
|
||||
Object aux;
|
||||
aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
|
||||
|
||||
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||
|
||||
static Array aMutable;
|
||||
if (aMutable.empty())
|
||||
{
|
||||
aMutable.push_back("time");
|
||||
aMutable.push_back("transactions");
|
||||
aMutable.push_back("prevblock");
|
||||
}
|
||||
|
||||
Object result;
|
||||
result.push_back(Pair("version", pblock->nVersion));
|
||||
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
|
||||
result.push_back(Pair("transactions", transactions));
|
||||
result.push_back(Pair("coinbaseaux", aux));
|
||||
result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
|
||||
result.push_back(Pair("target", hashTarget.GetHex()));
|
||||
result.push_back(Pair("mintime", (int64_t)pindexPrev->GetPastTimeLimit()+1));
|
||||
result.push_back(Pair("mutable", aMutable));
|
||||
result.push_back(Pair("noncerange", "00000000ffffffff"));
|
||||
result.push_back(Pair("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS));
|
||||
result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SIZE));
|
||||
result.push_back(Pair("curtime", (int64_t)pblock->nTime));
|
||||
result.push_back(Pair("bits", HexBits(pblock->nBits)));
|
||||
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Value submitblock(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||
throw runtime_error(
|
||||
"submitblock <hex data> [optional-params-obj]\n"
|
||||
"[optional-params-obj] parameter is currently ignored.\n"
|
||||
"Attempts to submit new block to network.");
|
||||
|
||||
vector<unsigned char> blockData(ParseHex(params[0].get_str()));
|
||||
CDataStream ssBlock(blockData, SER_NETWORK, PROTOCOL_VERSION);
|
||||
CBlock block;
|
||||
try {
|
||||
ssBlock >> block;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
|
||||
}
|
||||
|
||||
bool fAccepted = ProcessBlock(NULL, &block);
|
||||
if (!fAccepted)
|
||||
return "rejected";
|
||||
|
||||
return Value::null;
|
||||
}
|
||||
// PoW mining RPCs (getwork, getworkex, getblocktemplate, submitblock) removed.
|
||||
// PoW ended at block 9000 (CUTOFF_POW_BLOCK). These dead-code mining pool
|
||||
// interfaces were removed to reduce false-positive antivirus detections,
|
||||
// since AV engines pattern-match nonce-incrementing loops and mining pool
|
||||
// protocols as "cryptominer" signatures.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user