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

Multi-threaded getburninfo #1762

Merged
merged 7 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 114 additions & 58 deletions src/masternodes/rpc_accounts.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
#include <masternodes/accountshistory.h>
#include <masternodes/govvariables/attributes.h>
#include <masternodes/mn_rpc.h>
#include <masternodes/validation.h>

#include <boost/asio.hpp>

struct BalanceResults {
CAmount burntDFI{};
CAmount burntFee{};
CAmount auctionFee{};
CBalances burntTokens;
CBalances nonConsortiumTokens;
CBalances dexfeeburn;
CBalances paybackFee;
};

std::string tokenAmountString(CTokenAmount const& amount, AmountFormat format = AmountFormat::Symbol) {
const auto token = pcustomcsview->GetToken(amount.nTokenId);
Expand Down Expand Up @@ -1958,7 +1971,6 @@ UniValue getburninfo(const JSONRPCRequest& request) {
auto fortCanningHeight = Params().GetConsensus().FortCanningHeight;
auto burnAddress = Params().GetConsensus().burnAddress;
auto view = *pcustomcsview;
auto &burnView = pburnHistoryDB;
auto attributes = view.GetAttributes();

if (attributes) {
Expand Down Expand Up @@ -1991,67 +2003,111 @@ UniValue getburninfo(const JSONRPCRequest& request) {
}
}

auto calculateBurnAmounts = [&](AccountHistoryKey const& key, AccountHistoryValue value) {
// UTXO burn
if (value.category == uint8_t(CustomTxType::None)) {
for (auto const & diff : value.diff) {
burntDFI += diff.second;
}
return true;
}
// Fee burn
if (value.category == uint8_t(CustomTxType::CreateMasternode)
|| value.category == uint8_t(CustomTxType::CreateToken)
|| value.category == uint8_t(CustomTxType::Vault)
|| value.category == uint8_t(CustomTxType::CreateCfp)
|| value.category == uint8_t(CustomTxType::CreateVoc)) {
for (auto const & diff : value.diff) {
burntFee += diff.second;
}
return true;
}
// withdraw burn
if (value.category == uint8_t(CustomTxType::PaybackLoan)
|| value.category == uint8_t(CustomTxType::PaybackLoanV2)
|| value.category == uint8_t(CustomTxType::PaybackWithCollateral)) {
for (const auto& [id, amount] : value.diff) {
paybackFee.Add({id, amount});
}
return true;
}
// auction burn
if (value.category == uint8_t(CustomTxType::AuctionBid)) {
for (auto const & diff : value.diff) {
auctionFee += diff.second;
}
return true;
}
// dex fee burn
if (value.category == uint8_t(CustomTxType::PoolSwap)
|| value.category == uint8_t(CustomTxType::PoolSwapV2)) {
for (auto const & diff : value.diff) {
dexfeeburn.Add({diff.first, diff.second});
}
return true;
}
const auto nWorkers = RewardConsolidationWorkersCount();
const auto currentHeight = ChainActive().Height();
const auto chunks = currentHeight / nWorkers;
const auto chunksRemainder = currentHeight % nWorkers;

// token burn with burnToken tx
if (value.category == uint8_t(CustomTxType::BurnToken))
{
for (auto const & diff : value.diff) {
nonConsortiumTokens.Add({diff.first, diff.second});
}
return true;
}
std::vector<std::shared_ptr<BalanceResults>> workerResults;
boost::asio::thread_pool workerPool{nWorkers};

for (size_t i{}; i < nWorkers; ++i) {
uint32_t startHeight = (i + 1) * chunks;
uint32_t stopHeight = startHeight - chunks;

// Token burn
for (auto const & diff : value.diff) {
burntTokens.Add({diff.first, diff.second});
if (i + 1 == nWorkers) {
startHeight += chunksRemainder;
stopHeight -= chunksRemainder;
}
return true;
};

burnView->ForEachAccountHistory(calculateBurnAmounts);
auto result = std::make_shared<BalanceResults>();
workerResults.push_back(result);

boost::asio::post(workerPool, [result, startHeight, stopHeight]{
pburnHistoryDB->ForEachAccountHistory([result, stopHeight](const AccountHistoryKey &key, const AccountHistoryValue &value) {

// Stop on chunk range for worker
if (key.blockHeight <= stopHeight) {
return false;
}

// UTXO burn
if (value.category == uint8_t(CustomTxType::None)) {
for (auto const & diff : value.diff) {
result->burntDFI += diff.second;
}
return true;
}

// Fee burn
if (value.category == uint8_t(CustomTxType::CreateMasternode)
|| value.category == uint8_t(CustomTxType::CreateToken)
|| value.category == uint8_t(CustomTxType::Vault)
|| value.category == uint8_t(CustomTxType::CreateCfp)
|| value.category == uint8_t(CustomTxType::CreateVoc)) {
for (auto const & diff : value.diff) {
result->burntFee += diff.second;
}
return true;
}

// withdraw burn
if (value.category == uint8_t(CustomTxType::PaybackLoan)
|| value.category == uint8_t(CustomTxType::PaybackLoanV2)
|| value.category == uint8_t(CustomTxType::PaybackWithCollateral)) {
for (const auto& [id, amount] : value.diff) {
result->paybackFee.Add({id, amount});
}
return true;
}

// auction burn
if (value.category == uint8_t(CustomTxType::AuctionBid)) {
for (auto const & diff : value.diff) {
result->auctionFee += diff.second;
}
return true;
}

// dex fee burn
if (value.category == uint8_t(CustomTxType::PoolSwap)
|| value.category == uint8_t(CustomTxType::PoolSwapV2)) {
for (auto const & diff : value.diff) {
result->dexfeeburn.Add({diff.first, diff.second});
}
return true;
}

// token burn with burnToken tx
if (value.category == uint8_t(CustomTxType::BurnToken))
{
for (auto const & diff : value.diff) {
result->nonConsortiumTokens.Add({diff.first, diff.second});
}
return true;
}

// Token burn
for (auto const & diff : value.diff) {
result->burntTokens.Add({diff.first, diff.second});
}

return true;
}, {}, startHeight, std::numeric_limits<uint32_t>::max());
});
}

workerPool.join();

for (const auto &result : workerResults) {
burntDFI += result->burntDFI;
burntFee += result->burntFee;
auctionFee += result->auctionFee;
burntTokens.AddBalances(result->burntTokens.balances);
nonConsortiumTokens.AddBalances(result->nonConsortiumTokens.balances);
dexfeeburn.AddBalances(result->dexfeeburn.balances);
paybackFee.AddBalances(result->paybackFee.balances);
}

CDataStructureV0 liveKey = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::ConsortiumMinted};
auto balances = attributes->GetValue(liveKey, CConsortiumGlobalMinted{});
Expand Down
2 changes: 2 additions & 0 deletions src/masternodes/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ using CreationTxs = std::map<uint32_t, std::pair<uint256, std::vector<std::pair<
void ProcessDeFiEvent(const CBlock &block, const CBlockIndex* pindex, CCustomCSView& mnview, const CCoinsViewCache& view, const CChainParams& chainparams, const CreationTxs &creationTxs);
std::vector<CAuctionBatch> CollectAuctionBatches(const CCollateralLoans& collLoan, const TAmounts& collBalances, const TAmounts& loanBalances);

size_t RewardConsolidationWorkersCount();

#endif // DEFI_MASTERNODES_VALIDATION_H