Skip to content

Commit

Permalink
Live dex statistics
Browse files Browse the repository at this point in the history
Signed-off-by: Anthony Fieroni <[email protected]>
  • Loading branch information
bvbfan committed Apr 27, 2022
1 parent 6ed4ac9 commit 316dbc0
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/masternodes/consensus/loans.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message& obj) const {

balances.Add(CTokenAmount{loanTokenId, subAmount});
balances.Add(CTokenAmount{paybackTokenId, penalty});
attributes->attributes[liveKey] = balances;
attributes->SetValue(liveKey, std::move(balances));

LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Burning interest and loan in %s directly - total loan %lld (%lld %s), height - %d\n", paybackToken->symbol, subLoan + subInterest, subInToken, paybackToken->symbol, height);

Expand All @@ -592,7 +592,7 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message& obj) const {

balances.tokensPayback.Add(CTokenAmount{loanTokenId, subAmount});
balances.tokensFee.Add(CTokenAmount{paybackTokenId, penalty});
attributes->attributes[liveKey] = balances;
attributes->SetValue(liveKey, balances);

LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Swapping %s to DFI and burning it - total loan %lld (%lld %s), height - %d\n", paybackToken->symbol, subLoan + subInterest, subInToken, paybackToken->symbol, height);

Expand Down
2 changes: 1 addition & 1 deletion src/masternodes/consensus/smartcontracts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage& obj) const {
balances.Add(obj.source);
}

attributes->attributes[liveKey] = balances;
attributes->SetValue(liveKey, std::move(balances));
return mnview.SetVariable(*attributes);
}

Expand Down
19 changes: 16 additions & 3 deletions src/masternodes/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{EconomyKeys::DFIP2203Current, "dfip2203_current"},
{EconomyKeys::DFIP2203Burned, "dfip2203_burned"},
{EconomyKeys::DFIP2203Minted, "dfip2203_minted"},
{EconomyKeys::DexTokens, "dex"},
}
},
};
Expand Down Expand Up @@ -491,7 +492,7 @@ Res ATTRIBUTES::RefundFuturesContracts(CCustomCSView &mnview, const uint32_t hei
}
}

attributes[liveKey] = balances;
SetValue(liveKey, std::move(balances));

return Res::Ok();
}
Expand Down Expand Up @@ -519,11 +520,11 @@ Res ATTRIBUTES::Import(const UniValue & val) {
} else {
newAttr.key = TokenKeys::PaybackDFIFeePCT;
}
attributes[newAttr] = attrValue;
SetValue(newAttr, attrValue);
return Res::Ok();
}
}
attributes[attribute] = attrValue;
SetValue(attribute, attrValue);
return Res::Ok();
}
);
Expand Down Expand Up @@ -581,6 +582,18 @@ UniValue ATTRIBUTES::Export() const {
result.pushKV("paybackfees", AmountsToJSON(paybacks->tokensFee.balances));
result.pushKV("paybacktokens", AmountsToJSON(paybacks->tokensPayback.balances));
ret.pushKV(key, result);
} else if (auto balances = std::get_if<CDexBalances>(&attribute.second)) {
for (const auto& pool : *balances) {
auto& dexTokenA = pool.second.totalTokenA;
auto& dexTokenB = pool.second.totalTokenB;
auto poolkey = KeyBuilder(key, pool.first.v);
ret.pushKV(KeyBuilder(poolkey, "total_commission_a"), ValueFromUint(dexTokenA.commissions));
ret.pushKV(KeyBuilder(poolkey, "total_commission_b"), ValueFromUint(dexTokenB.commissions));
ret.pushKV(KeyBuilder(poolkey, "fee_burn_a"), ValueFromUint(dexTokenA.feeburn));
ret.pushKV(KeyBuilder(poolkey, "fee_burn_b"), ValueFromUint(dexTokenB.feeburn));
ret.pushKV(KeyBuilder(poolkey, "total_swap_a"), ValueFromUint(dexTokenA.swaps));
ret.pushKV(KeyBuilder(poolkey, "total_swap_b"), ValueFromUint(dexTokenB.swaps));
}
}
} catch (const std::out_of_range&) {
// Should not get here, that's mean maps are mismatched
Expand Down
53 changes: 50 additions & 3 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ enum EconomyKeys : uint8_t {
DFIP2203Current = 'c',
DFIP2203Burned = 'd',
DFIP2203Minted = 'e',
DexTokens = 'f',
};

enum DFIPKeys : uint8_t {
Expand Down Expand Up @@ -111,8 +112,38 @@ struct CTokenPayback {
}
};

struct CDexTokenInfo {

struct CTokenInfo {
uint64_t swaps;
uint64_t feeburn;
uint64_t commissions;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(swaps);
READWRITE(feeburn);
READWRITE(commissions);
}
};

CTokenInfo totalTokenA;
CTokenInfo totalTokenB;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(totalTokenA);
READWRITE(totalTokenB);
}
};

using CDexBalances = std::map<DCT_ID, CDexTokenInfo>;
using CAttributeType = std::variant<CDataStructureV0>;
using CAttributeValue = std::variant<bool, CAmount, CBalances, CTokenPayback, CTokenCurrencyPair>;
using CAttributeValue = std::variant<bool, CAmount, CBalances, CTokenPayback, CDexBalances, CTokenCurrencyPair>;

class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRIBUTES>
{
Expand Down Expand Up @@ -150,6 +181,21 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI
return value;
}

template<typename K, typename T>
void SetValue(const K& key, T&& value) {
static_assert(std::is_convertible_v<K, CAttributeType>);
static_assert(std::is_convertible_v<T, CAttributeValue>);
changed.insert(key);
attributes[key] = std::forward<T>(value);
}

template<typename K>
void EraseKey(const K& key) {
static_assert(std::is_convertible_v<K, CAttributeType>);
changed.insert(key);
attributes.erase(key);
}

template<typename K>
[[nodiscard]] bool CheckKey(const K& key) const {
static_assert(std::is_convertible_v<K, CAttributeType>);
Expand Down Expand Up @@ -177,16 +223,17 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI
READWRITE(attributes);
}

std::map<CAttributeType, CAttributeValue> attributes;
uint32_t time{0};

// For formatting in export
static const std::map<uint8_t, std::string>& displayVersions();
static const std::map<uint8_t, std::string>& displayTypes();
static const std::map<uint8_t, std::string>& displayParamsIDs();
static const std::map<uint8_t, std::map<uint8_t, std::string>>& displayKeys();
private:
friend class CGovView;
bool futureBlockUpdated{};
std::set<CAttributeType> changed;
std::map<CAttributeType, CAttributeValue> attributes;

// Defined allowed arguments
static const std::map<std::string, uint8_t>& allowedVersions();
Expand Down
24 changes: 23 additions & 1 deletion src/masternodes/gv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,29 @@

Res CGovView::SetVariable(GovVariable const & var)
{
return WriteBy<ByName>(var.GetName(), var) ? Res::Ok() : Res::Err("can't write to DB");
auto WriteVar = [this](GovVariable const & var) {
return WriteBy<ByName>(var.GetName(), var) ? Res::Ok() : Res::Err("can't write to DB");
};
if (var.GetName() != "ATTRIBUTES") {
return WriteVar(var);
}
auto attributes = GetAttributes();
if (!attributes) {
return WriteVar(var);
}
auto& current = dynamic_cast<const ATTRIBUTES&>(var);
if (current.changed.empty()) {
return Res::Ok();
}
for (auto& key : current.changed) {
auto it = current.attributes.find(key);
if (it == current.attributes.end()) {
attributes->attributes.erase(key);
} else {
attributes->attributes[key] = it->second;
}
}
return WriteVar(*attributes);
}

std::shared_ptr<GovVariable> CGovView::GetVariable(std::string const & name) const
Expand Down
34 changes: 34 additions & 0 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <masternodes/consensus/smartcontracts.h>
#include <masternodes/consensus/tokens.h>
#include <masternodes/consensus/vaults.h>
#include <masternodes/govvariables/attributes.h>
#include <masternodes/mn_checks.h>
#include <masternodes/res.h>
#include <masternodes/vaulthistory.h>
Expand Down Expand Up @@ -704,6 +705,14 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView& view, std::vector<DCT_ID> poolIDs, boo
mnview.Flush();
}

auto attributes = view.GetAttributes();
if (!attributes) {
attributes = std::make_shared<ATTRIBUTES>();
}

CDataStructureV0 dexKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DexTokens};
auto dexBalances = attributes->GetValue(dexKey, CDexBalances{});

// Set amount to be swapped in pool
CTokenAmount swapAmountResult{obj.idTokenFrom, obj.amountFrom};

Expand Down Expand Up @@ -745,6 +754,18 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView& view, std::vector<DCT_ID> poolIDs, boo

auto dexfeeInPct = view.GetDexFeeInPct(currentID, swapAmount.nTokenId);

auto& balances = dexBalances[currentID];
auto forward = swapAmount.nTokenId == pool->idTokenA;

auto& totalTokenA = forward ? balances.totalTokenA : balances.totalTokenB;
auto& totalTokenB = forward ? balances.totalTokenB : balances.totalTokenA;

const auto& reserveAmount = forward ? pool->reserveA : pool->reserveB;
const auto& blockCommission = forward ? pool->blockCommissionA : pool->blockCommissionB;

const auto initReserveAmount = reserveAmount;
const auto initBlockCommission = blockCommission;

// Perform swap
poolResult = pool->Swap(swapAmount, dexfeeInPct, poolPrice, [&] (const CTokenAmount& dexfeeInAmount, const CTokenAmount& tokenAmount) {
// Save swap amount for next loop
Expand Down Expand Up @@ -792,6 +813,7 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView& view, std::vector<DCT_ID> poolIDs, boo
if (!res) {
return res;
}
totalTokenA.feeburn += dexfeeInAmount.nValue;
}

// burn the dex out amount
Expand All @@ -800,6 +822,14 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView& view, std::vector<DCT_ID> poolIDs, boo
if (!res) {
return res;
}
totalTokenB.feeburn += dexfeeOutAmount.nValue;
}

totalTokenA.swaps += (reserveAmount - initReserveAmount);
totalTokenA.commissions += (blockCommission - initBlockCommission);

if (lastSwap && obj.to == Params().GetConsensus().burnAddress) {
totalTokenB.feeburn += swapAmountResult.nValue;
}

return res;
Expand All @@ -820,6 +850,10 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView& view, std::vector<DCT_ID> poolIDs, boo
}
}

if (!testOnly) {
attributes->SetValue(dexKey, std::move(dexBalances));
view.SetVariable(*attributes);
}
// Assign to result for loop testing best pool swap result
result = swapAmountResult.nValue;

Expand Down
6 changes: 3 additions & 3 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3403,11 +3403,11 @@ void CChainState::ProcessFutures(const CBlockIndex* pindex, CCustomCSView& cache
cache.EraseFuturesUserValues(key);
}

attributes->attributes[burnKey] = burned;
attributes->attributes[mintedKey] = minted;
attributes->SetValue(burnKey, std::move(burned));
attributes->SetValue(mintedKey, std::move(minted));

if (!unpaidContracts.empty()) {
attributes->attributes[liveKey] = balances;
attributes->SetValue(liveKey, std::move(balances));
}

cache.SetVariable(*attributes);
Expand Down
4 changes: 3 additions & 1 deletion test/functional/feature_loan_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,9 @@ def loan_and_collateral_token_to_govvar(self):

# Invalidate fork block
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))
assert_equal(len(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']), 0)
result = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']
for key in result.keys():
assert key.startswith('v0/live')

# Move to hard fork again
self.move_to_gw_fork()
Expand Down
Loading

0 comments on commit 316dbc0

Please sign in to comment.