diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 59705edb9f..fafbd6e0ce 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1759,6 +1759,71 @@ UniValue getspentinfo(const JSONRPCRequest& request) return obj; } +CAmount getzerocoinpoolbalance() +{ + CAmount nTotalAmount = 0; + + // Iterate over all mints + std::vector > addressIndex; + if (GetAddressIndex(uint160(), AddressType::zerocoinMint, addressIndex)) { + for (auto& it : addressIndex) { + nTotalAmount += it.second; + } + } + addressIndex.clear(); + + // Iterate over all spends + if (GetAddressIndex(uint160(), AddressType::zerocoinSpend, addressIndex)) { + for (auto& it : addressIndex) { + nTotalAmount += it.second; + } + } + + return nTotalAmount; +} + +CAmount getCVE17144amount() +{ + // CVE-2018-17144 was a critical bug that allowed double-spending of inputs + // in the same transaction. This function calculates the total amount of coins + // that were created due to this vulnerability at block 293526. + LOCK(cs_main); + if (chainActive.Height() < 293526) { + throw std::runtime_error("Chain height is less than 293,526."); + } + + if (!Params().GetConsensus().IsMain()) { + throw std::runtime_error("Attack only occurred on mainnet"); + } + + CBlockIndex *atackedBlock = chainActive[293526]; + CBlock block; + if (!ReadBlockFromDisk(block, atackedBlock, ::Params().GetConsensus())) { + throw std::runtime_error("Failed to read block 293526 from disk"); + } + CAmount amount = 0; + for (CTransactionRef tx : block.vtx) { + if (!tx->IsCoinBase() && !tx->HasNoRegularInputs()) { + std::set vInOutPoints; + for (const auto& txin : tx->vin) + { + if (!vInOutPoints.insert(txin.prevout).second) { + CTransactionRef tx; + uint256 hashBlock; + if (!GetTransaction(txin.prevout.hash, tx, Params().GetConsensus(), hashBlock, true)) { + continue; + } + if (txin.prevout.n >= tx->vout.size()) { + continue; // Skip if output index is out of bounds + } + amount += tx->vout[txin.prevout.n].nValue; + } + } + } + } + return amount; +} + UniValue gettotalsupply(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) @@ -1780,12 +1845,53 @@ UniValue gettotalsupply(const JSONRPCRequest& request) if(!pblocktree->ReadTotalSupply(total)) throw JSONRPCError(RPC_DATABASE_ERROR, "Cannot read the total supply from the database. This functionality requires -addressindex to be enabled. Enabling -addressindex requires reindexing."); + total -= getzerocoinpoolbalance(); //498,397.00000000 The actual amount of coins forged during the Zerocoin attacks (the negative balance after the pool closed), + total += getCVE17144amount(); //320,841.99803185 The cmount of forged coins during CVE-2018-17144 attacks, + total -= 16810168037465;// burnt Coins sent to unrecoverable address https://explorer.firo.org/tx/0b53178c1b22bae4c04ef943ee6d6d30f2483327fe9beb54952951592e8ce368 UniValue result(UniValue::VOBJ); result.push_back(Pair("total", total)); return result; } +UniValue getzerocoinpoolbalance(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 0) + throw std::runtime_error( + "getzerocoinpoolbalance\n" + "\nReturns the total coin amount, which remains after zerocoin pool closed.\n" + "\nArguments: none\n" + "\nResult:\n" + "{\n" + " \"total\" (string) The total balance\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getzerocoinpoolbalance", "") + + HelpExampleRpc("getzerocoinpoolbalance", "") + ); + + return getzerocoinpoolbalance(); +} + +UniValue getCVE17144amount(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 0) + throw std::runtime_error( + "getCVE17144amount\n" + "\nReturns the total amount of forged coins during CVE-2018-17144 attacks.\n" + "\nArguments: none\n" + "\nResult:\n" + "{\n" + " \"total\" (string) The total balance\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getCVE17144amount", "") + + HelpExampleRpc("getCVE17144amount", "") + ); + + return getCVE17144amount(); +} + UniValue getinfoex(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) @@ -1911,7 +2017,8 @@ static const CRPCCommand commands[] = /* Not shown in help */ { "hidden", "getinfoex", &getinfoex, false }, { "addressindex", "gettotalsupply", &gettotalsupply, false }, - + { "addressindex", "getzerocoinpoolbalance", &getzerocoinpoolbalance, false }, + { "addressindex", "getCVE17144amount", &getCVE17144amount, false }, /* Mobile related */ { "mobile", "getanonymityset", &getanonymityset, false }, { "mobile", "getmintmetadata", &getmintmetadata, true },