Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gettotalsupply #1502

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
194 changes: 193 additions & 1 deletion src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,154 @@ UniValue getspentinfo(const JSONRPCRequest& request)
return obj;
}

CAmount getzerocoinpoolbalance()
{
CAmount nTotalAmount = 0;

// Iterate over all mints
std::vector<std::pair<CAddressIndexKey, CAmount> > 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;
}
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved

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<COutPoint> 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;
}

// another way to calculate the forged amount
CAmount getCVE17144amountNew()
{
// 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");
}

std::unordered_map<uint160, AddressType> addresses;
for (CTransactionRef tx : block.vtx) {
if (!tx->IsCoinBase() && !tx->HasNoRegularInputs()) {
for (const auto& txout : tx->vout)
{
CTxDestination addr;
if (!ExtractDestination(txout.scriptPubKey, addr))
continue;
CBitcoinAddress address(addr);
uint160 hashBytes;
AddressType type = AddressType::unknown;
if (!address.GetIndexKey(hashBytes, type)) {
continue;
}
addresses.insert({hashBytes, type});
}

for (const auto& txin : tx->vin)
{
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
}

CTxDestination addr;
if (!ExtractDestination(tx->vout[txin.prevout.n].scriptPubKey, addr))
continue;
CBitcoinAddress address(addr);
uint160 hashBytes;
AddressType type = AddressType::unknown;
if (!address.GetIndexKey(hashBytes, type)) {
continue;
}
addresses.insert({hashBytes, type});
}
}
}

CAmount result = 0;
for (const auto& it : addresses) {
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex;
if (!GetAddressIndex(it.first, it.second, addressIndex)) {
continue;
}
CAmount amount = 0;
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) {
amount += it->second;
}

if (amount < 0)
result += amount;
}



return result;
}

UniValue gettotalsupply(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
Expand All @@ -1780,12 +1928,55 @@ 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
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved
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();
}
levonpetrosyan93 marked this conversation as resolved.
Show resolved Hide resolved

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", "")
);
UniValue results(UniValue::VOBJ);
results.push_back(Pair("firstWay",getCVE17144amount()));
results.push_back(Pair("secondWay",getCVE17144amountNew()));
return results;
}

UniValue getinfoex(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
Expand Down Expand Up @@ -1911,7 +2102,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 },
Expand Down
Loading