diff --git a/src/Makefile.am b/src/Makefile.am index 1d823f97df..065695d7a1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -184,6 +184,7 @@ DEFI_CORE_H = \ dfi/evm.h \ dfi/factory.h \ dfi/govvariables/attributes.h \ + dfi/govvariables/attributetypes.h \ dfi/govvariables/icx_takerfee_per_btc.h \ dfi/govvariables/loan_daily_reward.h \ dfi/govvariables/loan_liquidation_penalty.h \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index dc4cdc6cff..dc17edc2ea 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -8,7 +8,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/src/dfi/accountshistory.cpp b/src/dfi/accountshistory.cpp index 7c4fba9e4f..e34e71793c 100644 --- a/src/dfi/accountshistory.cpp +++ b/src/dfi/accountshistory.cpp @@ -102,7 +102,12 @@ CAccountsHistoryWriter::CAccountsHistoryWriter(CCustomCSView &storage, txn(txn), txid(txid), type(type), - writers(storage.GetHistoryWriters()) {} + writers(storage.GetHistoryWriters()) { + if (storage.HasAttributes()) { + attributes = storage.GetAttributes(); + } + persistentAttributes = true; +} CAccountsHistoryWriter::~CAccountsHistoryWriter() { writers.ClearState(); diff --git a/src/dfi/consensus/governance.cpp b/src/dfi/consensus/governance.cpp index d03d8bdb6c..332307ec5b 100644 --- a/src/dfi/consensus/governance.cpp +++ b/src/dfi/consensus/governance.cpp @@ -18,20 +18,16 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { const auto time = txCtx.GetTime(); auto &mnview = blockCtx.GetView(); - for (const auto &gov : obj.govs) { - if (!gov.second) { - return Res::Err("'%s': variable does not registered", gov.first); + for (const auto &[name, var] : obj.govs) { + if (!var) { + return Res::Err("'%s': variable does not registered", name); } - auto var = gov.second; Res res{}; if (var->GetName() == "ATTRIBUTES") { // Add to existing ATTRIBUTES instead of overwriting. - auto govVar = mnview.GetAttributes(); - - govVar->time = time; - govVar->evmTemplate = blockCtx.GetEVMTemplate(); + mnview.SetAttributesMembers(time, blockCtx.GetEVMTemplate()); auto newVar = std::dynamic_pointer_cast(var); if (!newVar) { @@ -54,7 +50,7 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { auto memberRemoval = newVar->GetValue(key, std::set{}); if (!memberRemoval.empty()) { - auto existingMembers = govVar->GetValue(key, std::set{}); + auto existingMembers = mnview.GetValue(key, std::set{}); for (auto &member : memberRemoval) { if (member.empty()) { @@ -85,23 +81,21 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { } } - govVar->SetValue(key, existingMembers); + mnview.SetValue(key, existingMembers); // Remove this key and apply any other changes newVar->EraseKey(key); - if (!(res = govVar->Import(newVar->Export())) || !(res = govVar->Validate(mnview)) || - !(res = govVar->Apply(mnview, height))) { + if (!(res = mnview.ImportAttributes(newVar->Export())) || !(res = mnview.ValidateAttributes()) || + !(res = mnview.ApplyAttributes(height))) { return Res::Err("%s: %s", var->GetName(), res.msg); } } else { // Validate as complete set. Check for future conflicts between key pairs. - if (!(res = govVar->Import(var->Export())) || !(res = govVar->Validate(mnview)) || - !(res = govVar->Apply(mnview, height))) { + if (!(res = mnview.ImportAttributes(var->Export())) || !(res = mnview.ValidateAttributes()) || + !(res = mnview.ApplyAttributes(height))) { return Res::Err("%s: %s", var->GetName(), res.msg); } } - - var = govVar; } else { // After GW, some ATTRIBUTES changes require the context of its map to validate, // moving this Validate() call to else statement from before this conditional. @@ -115,7 +109,7 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { const auto diff = height % mnview.GetIntervalBlock(); if (diff != 0) { // Store as pending change - StoreGovVars({gov.first, var, height + mnview.GetIntervalBlock() - diff}, mnview); + StoreGovVars({name, var, height + mnview.GetIntervalBlock() - diff}, mnview); continue; } } @@ -124,11 +118,11 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { if (!res) { return Res::Err("%s: %s", var->GetName(), res.msg); } - } - res = mnview.SetVariable(*var); - if (!res) { - return Res::Err("%s: %s", var->GetName(), res.msg); + res = mnview.SetVariable(*var); + if (!res) { + return Res::Err("%s: %s", var->GetName(), res.msg); + } } } return Res::Ok(); @@ -142,26 +136,32 @@ Res CGovernanceConsensus::operator()(const CGovernanceUnsetMessage &obj) const { const auto height = txCtx.GetHeight(); auto &mnview = blockCtx.GetView(); - const auto attributes = mnview.GetAttributes(); CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovUnset}; - if (!attributes->GetValue(key, false)) { + if (!mnview.GetValue(key, false)) { return Res::Err("Unset Gov variables not currently enabled in attributes."); } - for (const auto &gov : obj.govs) { - auto var = mnview.GetVariable(gov.first); + for (const auto &[name, keys] : obj.govs) { + auto var = mnview.GetVariable(name); if (!var) { - return Res::Err("'%s': variable does not registered", gov.first); + return Res::Err("'%s': variable does not registered", name); } - auto res = var->Erase(mnview, height, gov.second); - if (!res) { - return Res::Err("%s: %s", var->GetName(), res.msg); - } - - if (!(res = mnview.SetVariable(*var))) { - return Res::Err("%s: %s", var->GetName(), res.msg); + Res res = Res::Ok(); + if (var->GetName() == "ATTRIBUTES") { + res = mnview.EraseAttributes(height, keys); + if (!res) { + return Res::Err("%s: %s", var->GetName(), res.msg); + } + } else { + res = var->Erase(mnview, height, keys); + if (!res) { + return Res::Err("%s: %s", var->GetName(), res.msg); + } + if (!(res = mnview.SetVariable(*var))) { + return Res::Err("%s: %s", var->GetName(), res.msg); + } } } return Res::Ok(); @@ -188,8 +188,6 @@ Res CGovernanceConsensus::operator()(const CGovernanceHeightMessage &obj) const // Validate GovVariables before storing if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && obj.govVar->GetName() == "ATTRIBUTES") { - auto govVar = mnview.GetAttributes(); - if (height >= static_cast(consensus.DF22MetachainHeight)) { auto newVar = std::dynamic_pointer_cast(obj.govVar); if (!newVar) { @@ -207,13 +205,13 @@ Res CGovernanceConsensus::operator()(const CGovernanceHeightMessage &obj) const } } - auto storedGovVars = mnview.GetStoredVariablesRange(height, obj.startHeight); - Res res{}; - CCustomCSView govCache(mnview); + CCustomCSView discardCache(mnview); + auto storedGovVars = discardCache.GetStoredVariablesRange(height, obj.startHeight); + for (const auto &[varHeight, var] : storedGovVars) { if (var->GetName() == "ATTRIBUTES") { - if (res = govVar->Import(var->Export()); !res) { + if (res = discardCache.ImportAttributes(var->Export()); !res) { return Res::Err("%s: Failed to import stored vars: %s", obj.govVar->GetName(), res.msg); } } @@ -221,25 +219,28 @@ Res CGovernanceConsensus::operator()(const CGovernanceHeightMessage &obj) const // After GW exclude TokenSplit if split will have already been performed by startHeight if (height >= static_cast(consensus.DF20GrandCentralHeight)) { - if (const auto attrVar = std::dynamic_pointer_cast(govVar); attrVar) { - const auto attrMap = attrVar->GetAttributesMap(); - std::vector keysToErase; - for (const auto &[key, value] : attrMap) { - if (const auto attrV0 = std::get_if(&key); attrV0) { - if (attrV0->type == AttributeTypes::Oracles && attrV0->typeId == OracleIDs::Splits && - attrV0->key < obj.startHeight) { - keysToErase.push_back(*attrV0); - } + std::vector keysToErase; + discardCache.ForEachAttribute( + [&](const CDataStructureV0 &attr, const CAttributeValue &value) { + if (attr.type != AttributeTypes::Oracles) { + return false; } - } - for (const auto &key : keysToErase) { - attrVar->EraseKey(key); - } + + if (attr.typeId == OracleIDs::Splits && attr.key < obj.startHeight) { + keysToErase.push_back(attr); + } + + return true; + }, + CDataStructureV0{AttributeTypes::Oracles}); + + for (const auto &key : keysToErase) { + discardCache.EraseKey(key); } } - if (!(res = govVar->Import(obj.govVar->Export())) || !(res = govVar->Validate(govCache)) || - !(res = govVar->Apply(govCache, obj.startHeight))) { + if (!(res = discardCache.ImportAttributes(obj.govVar->Export())) || + !(res = discardCache.ValidateAttributes()) || !(res = discardCache.ApplyAttributes(obj.startHeight))) { return Res::Err("%s: Cumulative application of Gov vars failed: %s", obj.govVar->GetName(), res.msg); } } else { diff --git a/src/dfi/consensus/icxorders.cpp b/src/dfi/consensus/icxorders.cpp index 503c43ed13..ddc347dc3e 100644 --- a/src/dfi/consensus/icxorders.cpp +++ b/src/dfi/consensus/icxorders.cpp @@ -8,11 +8,10 @@ #include #include -bool IsICXEnabled(const int height, const CCustomCSView &view, const Consensus::Params &consensus) { +bool IsICXEnabled(const int height, CCustomCSView &view, const Consensus::Params &consensus) { if (height >= consensus.DF22MetachainHeight) { const CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::ICXEnabled}; - auto attributes = view.GetAttributes(); - return attributes->GetValue(enabledKey, false); + return view.GetValue(enabledKey, false); } // ICX transactions allowed before NextNetwrokUpgrade and some of these conditions else if (height < consensus.DF13FortCanningParkHeight || IsRegtestNetwork() || diff --git a/src/dfi/consensus/loans.cpp b/src/dfi/consensus/loans.cpp index 808b934ed8..d37f7b02d8 100644 --- a/src/dfi/consensus/loans.cpp +++ b/src/dfi/consensus/loans.cpp @@ -29,15 +29,13 @@ static Res PaybackWithCollateral(CCustomCSView &view, const CVaultId &vaultId, uint32_t height, uint64_t time) { - const auto attributes = view.GetAttributes(); - const auto dUsdToken = view.GetToken("DUSD"); if (!dUsdToken) { return DeFiErrors::TokenInvalidForName("DUSD"); } CDataStructureV0 activeKey{AttributeTypes::Token, dUsdToken->first.v, TokenKeys::LoanPaybackCollateral}; - if (!attributes->GetValue(activeKey, false)) { + if (!view.GetValue(activeKey, false)) { return DeFiErrors::LoanPaybackWithCollateralDisable(); } @@ -189,8 +187,7 @@ Res CLoansConsensus::operator()(const CLoanSetCollateralTokenMessage &obj) const if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) { const auto &tokenId = obj.idToken.v; - auto attributes = mnview.GetAttributes(); - attributes->time = time; + mnview.SetAttributesMembers(time, blockCtx.GetEVMTemplate()); CDataStructureV0 collateralEnabled{AttributeTypes::Token, tokenId, TokenKeys::LoanCollateralEnabled}; CDataStructureV0 collateralFactor{AttributeTypes::Token, tokenId, TokenKeys::LoanCollateralFactor}; @@ -210,17 +207,16 @@ Res CLoansConsensus::operator()(const CLoanSetCollateralTokenMessage &obj) const var->SetValue(collateralFactor, obj.factor); var->SetValue(pairKey, obj.fixedIntervalPriceId); - if (auto res = attributes->Import(var->Export()); !res) { + if (auto res = mnview.ImportAttributes(var->Export()); !res) { return res; } - if (auto res = attributes->Validate(mnview); !res) { + if (auto res = mnview.ValidateAttributes(); !res) { return res; } - if (auto res = attributes->Apply(mnview, height); !res) { + if (auto res = mnview.ApplyAttributes(height); !res) { return res; } - - return mnview.SetVariable(*attributes); + return Res::Ok(); } CLoanSetCollateralTokenImplementation collToken; @@ -309,9 +305,7 @@ Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) { const auto &id = tokenId.val->v; - auto attributes = mnview.GetAttributes(); - attributes->time = time; - attributes->evmTemplate = blockCtx.GetEVMTemplate(); + mnview.SetAttributesMembers(time, blockCtx.GetEVMTemplate()); CDataStructureV0 mintEnabled{AttributeTypes::Token, id, TokenKeys::LoanMintingEnabled}; CDataStructureV0 mintInterest{AttributeTypes::Token, id, TokenKeys::LoanMintingInterest}; @@ -331,16 +325,16 @@ Res CLoansConsensus::operator()(const CLoanSetLoanTokenMessage &obj) const { var->SetValue(mintInterest, obj.interest); var->SetValue(pairKey, obj.fixedIntervalPriceId); - if (auto res = attributes->Import(var->Export()); !res) { + if (auto res = mnview.ImportAttributes(var->Export()); !res) { return res; } - if (auto res = attributes->Validate(mnview); !res) { + if (auto res = mnview.ValidateAttributes(); !res) { return res; } - if (auto res = attributes->Apply(mnview, height); !res) { + if (auto res = mnview.ApplyAttributes(height); !res) { return res; } - return mnview.SetVariable(*attributes); + return Res::Ok(); } CLoanSetLoanTokenImplementation loanToken; @@ -437,8 +431,7 @@ Res CLoansConsensus::operator()(const CLoanUpdateLoanTokenMessage &obj) const { if (height >= static_cast(consensus.DF16FortCanningCrunchHeight) && IsTokensMigratedToGovVar()) { const auto &id = pair->first.v; - auto attributes = mnview.GetAttributes(); - attributes->time = time; + mnview.SetAttributesMembers(time, blockCtx.GetEVMTemplate()); CDataStructureV0 mintEnabled{AttributeTypes::Token, id, TokenKeys::LoanMintingEnabled}; CDataStructureV0 mintInterest{AttributeTypes::Token, id, TokenKeys::LoanMintingInterest}; @@ -458,16 +451,16 @@ Res CLoansConsensus::operator()(const CLoanUpdateLoanTokenMessage &obj) const { var->SetValue(mintInterest, obj.interest); var->SetValue(pairKey, obj.fixedIntervalPriceId); - if (auto res = attributes->Import(var->Export()); !res) { + if (auto res = mnview.ImportAttributes(var->Export()); !res) { return res; } - if (auto res = attributes->Validate(mnview); !res) { + if (auto res = mnview.ValidateAttributes(); !res) { return res; } - if (auto res = attributes->Apply(mnview, height); !res) { + if (auto res = mnview.ApplyAttributes(height); !res) { return res; } - return mnview.SetVariable(*attributes); + return Res::Ok(); } if (obj.fixedIntervalPriceId != loanToken->fixedIntervalPriceId) { @@ -896,9 +889,6 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { return PaybackWithCollateral(mnview, *vault, obj.vaultId, height, time); } - auto shouldSetVariable = false; - auto attributes = mnview.GetAttributes(); - for (const auto &[loanTokenId, paybackAmounts] : obj.loans) { const auto loanToken = mnview.GetLoanTokenByID(loanTokenId); if (!loanToken) { @@ -931,21 +921,21 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { if (paybackTokenId != DCT_ID{0}) { CDataStructureV0 activeKey{ AttributeTypes::Token, loanTokenId.v, TokenKeys::LoanPayback, paybackTokenId.v}; - if (!attributes->GetValue(activeKey, false)) { + if (!mnview.GetValue(activeKey, false)) { return DeFiErrors::LoanPaybackDisabled(paybackToken->symbol); } CDataStructureV0 penaltyKey{ AttributeTypes::Token, loanTokenId.v, TokenKeys::LoanPaybackFeePCT, paybackTokenId.v}; - penaltyPct -= attributes->GetValue(penaltyKey, CAmount{0}); + penaltyPct -= mnview.GetValue(penaltyKey, CAmount{0}); } else { CDataStructureV0 activeKey{AttributeTypes::Token, loanTokenId.v, TokenKeys::PaybackDFI}; - if (!attributes->GetValue(activeKey, false)) { + if (!mnview.GetValue(activeKey, false)) { return DeFiErrors::LoanPaybackDisabled(paybackToken->symbol); } CDataStructureV0 penaltyKey{AttributeTypes::Token, loanTokenId.v, TokenKeys::PaybackDFIFeePCT}; - penaltyPct -= attributes->GetValue(penaltyKey, COIN / 100); + penaltyPct -= mnview.GetValue(penaltyKey, COIN / 100); } // Get token price in USD @@ -1125,21 +1115,19 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { subInToken = kv.second; } - shouldSetVariable = true; - auto penalty = MultiplyAmounts(subInToken, COIN - penaltyPct); if (paybackTokenId == DCT_ID{0}) { CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::PaybackDFITokens}; - auto balances = attributes->GetValue(liveKey, CBalances{}); + auto balances = mnview.GetValue(liveKey, CBalances{}); balances.Add({loanTokenId, subAmount}); balances.Add({paybackTokenId, penalty}); - attributes->SetValue(liveKey, balances); + mnview.SetValue(liveKey, balances); liveKey.key = EconomyKeys::PaybackDFITokensPrincipal; - balances = attributes->GetValue(liveKey, CBalances{}); + balances = mnview.GetValue(liveKey, CBalances{}); balances.Add({loanTokenId, subLoan}); - attributes->SetValue(liveKey, balances); + mnview.SetValue(liveKey, balances); LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Burning interest and loan in %s directly - total loan " @@ -1156,11 +1144,11 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { } } else { CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::PaybackTokens}; - auto balances = attributes->GetValue(liveKey, CTokenPayback{}); + auto balances = mnview.GetValue(liveKey, CTokenPayback{}); balances.tokensPayback.Add(CTokenAmount{loanTokenId, subAmount}); balances.tokensFee.Add(CTokenAmount{paybackTokenId, penalty}); - attributes->SetValue(liveKey, balances); + mnview.SetValue(liveKey, balances); LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Swapping %s to DFI and burning it - total loan %lld (%lld " @@ -1172,7 +1160,7 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { height); CDataStructureV0 directBurnKey{AttributeTypes::Param, ParamIDs::DFIP2206A, DFIPKeys::DUSDLoanBurn}; - auto directLoanBurn = attributes->GetValue(directBurnKey, false); + auto directLoanBurn = mnview.GetValue(directBurnKey, false); res = SwapToDFIorDUSD(mnview, paybackTokenId, @@ -1190,7 +1178,7 @@ Res CLoansConsensus::operator()(const CLoanPaybackLoanV2Message &obj) const { } } - return shouldSetVariable ? mnview.SetVariable(*attributes) : Res::Ok(); + return Res::Ok(); } Res CLoansConsensus::operator()(const CPaybackWithCollateralMessage &obj) const { diff --git a/src/dfi/consensus/masternodes.cpp b/src/dfi/consensus/masternodes.cpp index 2c1b16741d..16f6d97de9 100644 --- a/src/dfi/consensus/masternodes.cpp +++ b/src/dfi/consensus/masternodes.cpp @@ -163,14 +163,12 @@ Res CMasternodesConsensus::operator()(const CUpdateMasterNodeMessage &obj) const return DeFiErrors::MNStateNotEnabled(obj.mnId.ToString()); } - const auto attributes = mnview.GetAttributes(); - bool ownerType{}, operatorType{}, rewardType{}; for (const auto &[type, addressPair] : obj.updates) { const auto &[addressType, rawAddress] = addressPair; if (type == static_cast(UpdateMasternodeType::OwnerAddress)) { CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::MNSetOwnerAddress}; - if (!attributes->GetValue(key, false)) { + if (!mnview.GetValue(key, false)) { return Res::Err("Updating masternode owner address not currently enabled in attributes."); } if (ownerType) { @@ -232,7 +230,7 @@ Res CMasternodesConsensus::operator()(const CUpdateMasterNodeMessage &obj) const mnview.UpdateMasternodeCollateral(obj.mnId, *node, tx.GetHash(), height); } else if (type == static_cast(UpdateMasternodeType::OperatorAddress)) { CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::MNSetOperatorAddress}; - if (!attributes->GetValue(key, false)) { + if (!mnview.GetValue(key, false)) { return Res::Err("Updating masternode operator address not currently enabled in attributes."); } if (operatorType) { @@ -257,7 +255,7 @@ Res CMasternodesConsensus::operator()(const CUpdateMasterNodeMessage &obj) const mnview.UpdateMasternodeOperator(obj.mnId, *node, addressType, keyID, height); } else if (type == static_cast(UpdateMasternodeType::SetRewardAddress)) { CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::MNSetRewardAddress}; - if (!attributes->GetValue(key, false)) { + if (!mnview.GetValue(key, false)) { return Res::Err("Updating masternode reward address not currently enabled in attributes."); } if (rewardType) { @@ -296,7 +294,7 @@ Res CMasternodesConsensus::operator()(const CUpdateMasterNodeMessage &obj) const } } else if (type == static_cast(UpdateMasternodeType::RemRewardAddress)) { CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::MNSetRewardAddress}; - if (!attributes->GetValue(key, false)) { + if (!mnview.GetValue(key, false)) { return Res::Err("Updating masternode reward address not currently enabled in attributes."); } if (rewardType) { diff --git a/src/dfi/consensus/proposals.cpp b/src/dfi/consensus/proposals.cpp index 2c3416ac80..3bbfdc04e3 100644 --- a/src/dfi/consensus/proposals.cpp +++ b/src/dfi/consensus/proposals.cpp @@ -23,9 +23,8 @@ Res CProposalsConsensus::IsOnChainGovernanceEnabled() const { CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovernanceEnabled}; auto &mnview = blockCtx.GetView(); - auto attributes = mnview.GetAttributes(); - if (!attributes->GetValue(enabledKey, false)) { + if (!mnview.GetValue(enabledKey, false)) { return Res::Err("Cannot create tx, on-chain governance is not enabled"); } @@ -96,9 +95,8 @@ Res CProposalsConsensus::operator()(const CCreateProposalMessage &obj) const { const auto &tx = txCtx.GetTransaction(); auto &mnview = blockCtx.GetView(); - auto attributes = mnview.GetAttributes(); CDataStructureV0 cfpMaxCycles{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::CFPMaxCycles}; - auto maxCycles = attributes->GetValue(cfpMaxCycles, static_cast(MAX_CYCLES)); + auto maxCycles = mnview.GetValue(cfpMaxCycles, static_cast(MAX_CYCLES)); if (obj.nCycles < 1 || obj.nCycles > maxCycles) { return Res::Err("proposal cycles can be between 1 and %d", maxCycles); diff --git a/src/dfi/consensus/smartcontracts.cpp b/src/dfi/consensus/smartcontracts.cpp index 95b59edba6..726d0d4e7f 100644 --- a/src/dfi/consensus/smartcontracts.cpp +++ b/src/dfi/consensus/smartcontracts.cpp @@ -15,11 +15,10 @@ Res CSmartContractsConsensus::HandleDFIP2201Contract(const CSmartContractMessage const auto &consensus = txCtx.GetConsensus(); const auto height = txCtx.GetHeight(); auto &mnview = blockCtx.GetView(); - const auto attributes = mnview.GetAttributes(); CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2201, DFIPKeys::Active}; - if (!attributes->GetValue(activeKey, false)) { + if (!mnview.GetValue(activeKey, false)) { return Res::Err("DFIP2201 smart contract is not enabled"); } @@ -48,7 +47,7 @@ Res CSmartContractsConsensus::HandleDFIP2201Contract(const CSmartContractMessage } CDataStructureV0 minSwapKey{AttributeTypes::Param, ParamIDs::DFIP2201, DFIPKeys::MinSwap}; - auto minSwap = attributes->GetValue(minSwapKey, CAmount{0}); + auto minSwap = mnview.GetValue(minSwapKey, CAmount{0}); if (amount < minSwap) { return DeFiErrors::ICXBTCBelowMinSwap(amount, minSwap); @@ -81,7 +80,7 @@ Res CSmartContractsConsensus::HandleDFIP2201Contract(const CSmartContractMessage } CDataStructureV0 premiumKey{AttributeTypes::Param, ParamIDs::DFIP2201, DFIPKeys::Premium}; - auto premium = attributes->GetValue(premiumKey, CAmount{2500000}); + auto premium = mnview.GetValue(premiumKey, CAmount{2500000}); const auto &btcPrice = MultiplyAmounts(*resVal.val, premium + COIN); @@ -133,7 +132,6 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { const auto height = txCtx.GetHeight(); const auto txn = txCtx.GetTxn(); auto &mnview = blockCtx.GetView(); - const auto attributes = mnview.GetAttributes(); bool dfiToDUSD = !obj.source.nTokenId.v; const auto paramID = dfiToDUSD ? ParamIDs::DFIP2206F : ParamIDs::DFIP2203; @@ -142,13 +140,12 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { CDataStructureV0 blockKey{AttributeTypes::Param, paramID, DFIPKeys::BlockPeriod}; CDataStructureV0 rewardKey{AttributeTypes::Param, paramID, DFIPKeys::RewardPct}; - if (!attributes->GetValue(activeKey, false) || !attributes->CheckKey(blockKey) || - !attributes->CheckKey(rewardKey)) { + if (!mnview.GetValue(activeKey, false) || !mnview.CheckKey(blockKey) || !mnview.CheckKey(rewardKey)) { return Res::Err("%s not currently active", dfiToDUSD ? "DFIP2206F" : "DFIP2203"); } CDataStructureV0 startKey{AttributeTypes::Param, paramID, DFIPKeys::StartBlock}; - if (const auto startBlock = attributes->GetValue(startKey, CAmount{})) { + if (const auto startBlock = mnview.GetValue(startKey, CAmount{})) { if (height < startBlock) { return Res::Err("%s not active until block %d", dfiToDUSD ? "DFIP2206F" : "DFIP2203", startBlock); } @@ -165,7 +162,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { if (!dfiToDUSD && source->symbol == "DUSD") { CDataStructureV0 tokenKey{AttributeTypes::Token, obj.destination, TokenKeys::DFIP2203Enabled}; - const auto enabled = attributes->GetValue(tokenKey, true); + const auto enabled = mnview.GetValue(tokenKey, true); if (!enabled) { return Res::Err("DFIP2203 currently disabled for token %d", obj.destination); } @@ -189,7 +186,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { } CDataStructureV0 tokenKey{AttributeTypes::Token, obj.source.nTokenId.v, TokenKeys::DFIP2203Enabled}; - const auto enabled = attributes->GetValue(tokenKey, true); + const auto enabled = mnview.GetValue(tokenKey, true); if (!enabled) { return Res::Err("DFIP2203 currently disabled for token %s", obj.source.nTokenId.ToString()); } @@ -218,7 +215,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { const auto economyKey = dfiToDUSD ? EconomyKeys::DFIP2206FCurrent : EconomyKeys::DFIP2203Current; CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, economyKey}; - auto balances = attributes->GetValue(liveKey, CBalances{}); + auto balances = mnview.GetValue(liveKey, CBalances{}); if (height >= static_cast(consensus.DF16FortCanningCrunchHeight)) { CalculateOwnerRewards(obj.owner); @@ -291,7 +288,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { } else { if (height >= static_cast(consensus.DF23Height) && !dfiToDUSD) { CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2211F, DFIPKeys::Active}; - const auto dfip11fEnabled = attributes->GetValue(activeKey, false); + const auto dfip11fEnabled = mnview.GetValue(activeKey, false); const auto dusdToken = mnview.GetToken("DUSD"); if (!dusdToken) { return Res::Err("No DUSD token defined"); @@ -303,7 +300,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { CDataStructureV0 averageKey{ AttributeTypes::Param, ParamIDs::DFIP2211F, DFIPKeys::AverageLiquidityPercentage}; const auto averageLiquidityPercentage = - attributes->GetValue(averageKey, DEFAULT_AVERAGE_LIQUIDITY_PERCENTAGE); + mnview.GetValue(averageKey, DEFAULT_AVERAGE_LIQUIDITY_PERCENTAGE); const auto maxSwapAmount = MultiplyAmounts(*averageLiquidity, averageLiquidityPercentage); @@ -352,9 +349,7 @@ Res CSmartContractsConsensus::operator()(const CFutureSwapMessage &obj) const { balances.Add(obj.source); } - attributes->SetValue(liveKey, balances); - - mnview.SetVariable(*attributes); + mnview.SetValue(liveKey, balances); return Res::Ok(); } diff --git a/src/dfi/consensus/tokens.cpp b/src/dfi/consensus/tokens.cpp index b19a2d4c6b..0efed48618 100644 --- a/src/dfi/consensus/tokens.cpp +++ b/src/dfi/consensus/tokens.cpp @@ -167,11 +167,9 @@ Res CTokensConsensus::operator()(const CUpdateTokenMessage &obj) const { // check auth, depends from token's "origins" const Coin &auth = coins.AccessCoin(COutPoint(token.creationTx, 1)); // always n=1 output - const auto attributes = mnview.GetAttributes(); std::set databaseMembers; - if (attributes->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, - false)) { - databaseMembers = attributes->GetValue( + if (mnview.GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, false)) { + databaseMembers = mnview.GetValue( CDataStructureV0{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}, std::set{}); } bool isFoundersToken = !databaseMembers.empty() ? databaseMembers.count(auth.out.scriptPubKey) > 0 @@ -218,8 +216,7 @@ Res CTokensConsensus::operator()(const CMintTokensMessage &obj) const { const auto anybodyCanMint = IsRegtestNetwork() && !isRegTestSimulateMainnet; CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::MintTokens}; - const auto attributes = mnview.GetAttributes(); - const auto toAddressEnabled = attributes->GetValue(enabledKey, false); + const auto toAddressEnabled = mnview.GetValue(enabledKey, false); if (!toAddressEnabled && !obj.to.empty()) { return Res::Err("Mint tokens to address is not enabled"); diff --git a/src/dfi/consensus/txvisitor.cpp b/src/dfi/consensus/txvisitor.cpp index 08a8a5442e..58fdf04124 100644 --- a/src/dfi/consensus/txvisitor.cpp +++ b/src/dfi/consensus/txvisitor.cpp @@ -117,11 +117,9 @@ Res CCustomTxVisitor::HasFoundationAuth() const { const auto &tx = txCtx.GetTransaction(); auto members = consensus.foundationMembers; - const auto attributes = mnview.GetAttributes(); - if (attributes->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, - false)) { - if (const auto databaseMembers = attributes->GetValue( + if (mnview.GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, false)) { + if (const auto databaseMembers = mnview.GetValue( CDataStructureV0{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}, std::set{}); !databaseMembers.empty()) { members = databaseMembers; @@ -316,9 +314,7 @@ Res CCustomTxVisitor::CollateralPctCheck(const bool hasDUSDLoans, if (isPostNext) { const CDataStructureV0 enabledKey{AttributeTypes::Vaults, VaultIDs::DUSDVault, VaultKeys::DUSDVaultEnabled}; - auto attributes = mnview.GetAttributes(); - - auto DUSDVaultsAllowed = attributes->GetValue(enabledKey, false); + auto DUSDVaultsAllowed = mnview.GetValue(enabledKey, false); if (DUSDVaultsAllowed && hasDUSDColl && !hasOtherColl) { return Res::Ok(); // every loan ok when DUSD loops allowed and 100% DUSD collateral } diff --git a/src/dfi/consensus/vaults.cpp b/src/dfi/consensus/vaults.cpp index c3c463a278..7ea834e48b 100644 --- a/src/dfi/consensus/vaults.cpp +++ b/src/dfi/consensus/vaults.cpp @@ -15,10 +15,9 @@ Res CVaultsConsensus::operator()(const CVaultMessage &obj) const { const auto &tx = txCtx.GetTransaction(); auto &mnview = blockCtx.GetView(); auto &height = blockCtx.GetHeight(); - auto attributes = mnview.GetAttributes(); const CDataStructureV0 creationFeeKey{AttributeTypes::Vaults, VaultIDs::Parameters, VaultKeys::CreationFee}; - const auto vaultCreationFee = attributes->GetValue(creationFeeKey, consensus.vaultCreationFee); + const auto vaultCreationFee = mnview.GetValue(creationFeeKey, consensus.vaultCreationFee); if (tx.vout[0].nValue != vaultCreationFee || tx.vout[0].nTokenId != DCT_ID{0}) { return Res::Err("Malformed tx vouts, creation vault fee is %s DFI", GetDecimalString(vaultCreationFee)); } @@ -235,8 +234,7 @@ Res CVaultsConsensus::operator()(const CDepositToVaultMessage &obj) const { // If collateral token exist make sure it is enabled. if (mnview.GetCollateralTokenFromAttributes(obj.amount.nTokenId)) { CDataStructureV0 collateralKey{AttributeTypes::Token, obj.amount.nTokenId.v, TokenKeys::LoanCollateralEnabled}; - const auto attributes = mnview.GetAttributes(); - if (!attributes->GetValue(collateralKey, false)) { + if (!mnview.GetValue(collateralKey, false)) { return Res::Err("Collateral token (%d) is disabled", obj.amount.nTokenId.v); } } diff --git a/src/dfi/consensus/xvm.cpp b/src/dfi/consensus/xvm.cpp index 93085051ca..ef01f4da46 100644 --- a/src/dfi/consensus/xvm.cpp +++ b/src/dfi/consensus/xvm.cpp @@ -16,14 +16,13 @@ constexpr uint32_t MAX_TRANSFERDOMAIN_EVM_DATA_LEN = 1024; -static bool IsTransferDomainEnabled(const int height, const CCustomCSView &view, const Consensus::Params &consensus) { +static bool IsTransferDomainEnabled(const int height, CCustomCSView &view, const Consensus::Params &consensus) { if (height < consensus.DF22MetachainHeight) { return false; } const CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::TransferDomain}; - auto attributes = view.GetAttributes(); - return attributes->GetValue(enabledKey, false); + return view.GetValue(enabledKey, false); } static XVmAddressFormatTypes FromTxDestType(const size_t index) { @@ -191,7 +190,7 @@ static Res ValidateTransferDomainEdge(const CTransaction &tx, static Res ValidateTransferDomain(const CTransaction &tx, uint32_t height, const CCoinsViewCache &coins, - const CCustomCSView &mnview, + CCustomCSView &mnview, const Consensus::Params &consensus, const CTransferDomainMessage &obj, const bool isEvmEnabledForBlock, @@ -242,8 +241,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { return res; } - auto attributes = mnview.GetAttributes(); - auto stats = attributes->GetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); + auto stats = mnview.GetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); std::string evmTxHash; CrossBoundaryResult result; @@ -420,13 +418,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { LogPrintf("Failed to store EVMToDVM TX hash for DFI TX %s\n", txHash); } - attributes->SetValue(CTransferDomainStatsLive::Key, stats); - res = mnview.SetVariable(*attributes); - if (!res) { - evm_try_unsafe_remove_txs_above_hash_in_template( - result, evmTemplate->GetTemplate(), tx.GetHash().GetByteArray()); - return res; - } + mnview.SetValue(CTransferDomainStatsLive::Key, stats); return Res::Ok(); } diff --git a/src/dfi/govvariables/attributes.cpp b/src/dfi/govvariables/attributes.cpp index a3fc4e7e58..a937ee8d53 100644 --- a/src/dfi/govvariables/attributes.cpp +++ b/src/dfi/govvariables/attributes.cpp @@ -881,10 +881,8 @@ static void TrackLiveBalance(CCustomCSView &mnview, const CTokenAmount &amount, const EconomyKeys dataKey, const bool add) { - auto attributes = mnview.GetAttributes(); - CDataStructureV0 key{AttributeTypes::Live, ParamIDs::Economy, dataKey}; - auto balances = attributes->GetValue(key, CBalances{}); + auto balances = mnview.GetValue(key, CBalances{}); Res res{}; if (add) { res = balances.Add(amount); @@ -892,8 +890,7 @@ static void TrackLiveBalance(CCustomCSView &mnview, res = balances.Sub(amount); } if (res) { - attributes->SetValue(key, balances); - mnview.SetVariable(*attributes); + mnview.SetValue(key, balances); } } @@ -913,30 +910,17 @@ void TrackDUSDSub(CCustomCSView &mnview, const CTokenAmount &amount) { } void TrackLiveBalances(CCustomCSView &mnview, const CBalances &balances, const uint8_t key) { - auto attributes = mnview.GetAttributes(); - const CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Auction, key}; - auto storedBalances = attributes->GetValue(liveKey, CBalances{}); + auto storedBalances = mnview.GetValue(liveKey, CBalances{}); for (const auto &[tokenID, amount] : balances.balances) { storedBalances.balances[tokenID] += amount; } - attributes->SetValue(liveKey, storedBalances); - mnview.SetVariable(*attributes); + mnview.SetValue(liveKey, storedBalances); } -bool IsEVMEnabled(const std::shared_ptr attributes) { - if (!attributes) { - return false; - } - +bool IsEVMEnabled(CCustomCSView &view) { const CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::EVMEnabled}; - return attributes->GetValue(enabledKey, false); -} - -bool IsEVMEnabled(const CCustomCSView &view) { - auto attributes = view.GetAttributes(); - - return IsEVMEnabled(attributes); + return view.GetValue(enabledKey, false); } Res StoreGovVars(const CGovernanceHeightMessage &obj, CCustomCSView &view) { @@ -1431,19 +1415,6 @@ Res ATTRIBUTES::RefundFuturesDUSD(CCustomCSView &mnview, const uint32_t height) return Res::Ok(); } -template -static Res SetOracleSplit(ATTRIBUTES &attributes, const CAttributeType &attribute, const T &splitValue) { - if (splitValue->size() != 1) { - return Res::Err("Invalid number of token splits, allowed only one per height!"); - } - - const auto &[id, multiplier] = *(splitValue->begin()); - attributes.AddTokenSplit(id); - attributes.SetValue(attribute, *splitValue); - - return Res::Ok(); -} - Res ATTRIBUTES::Import(const UniValue &val) { if (!val.isObject()) { return DeFiErrors::GovVarImportObjectExpected(); @@ -1468,9 +1439,9 @@ Res ATTRIBUTES::Import(const UniValue &val) { if (!splitValue64) { return Res::Err("Failed to get Oracle split value"); } - return SetOracleSplit(*this, attribute, splitValue64); + return SetOracleSplit(attribute, splitValue64); } - return SetOracleSplit(*this, attribute, splitValue); + return SetOracleSplit(attribute, splitValue); } else if (attrV0->type == AttributeTypes::Param && attrV0->typeId == ParamIDs::Foundation && attrV0->key == DFIPKeys::Members) { const auto members = std::get_if>(&value); @@ -1802,19 +1773,42 @@ UniValue ATTRIBUTES::Export() const { return ExportFiltered(GovVarsFilter::All, ""); } -template -static Res ValidateOracleSplits(const ATTRIBUTES &attributes, - const CCustomCSView &view, - const bool checkFractional, - const T &splitMap) { +Res ATTRIBUTES::ValidateOracleSplits(const CCustomCSView &view, const OracleSplits &splitMap) const { + for (const auto &[tokenId, multiplier] : splitMap) { + if (tokenId == 0) { + return DeFiErrors::GovVarValidateSplitDFI(); + } + const auto id = DCT_ID{tokenId}; + if (view.HasPoolPair(id)) { + return DeFiErrors::GovVarValidateSplitPool(); + } + const auto token = view.GetToken(id); + if (!token) { + return DeFiErrors::GovVarValidateTokenExist(tokenId); + } + if (!token->IsDAT()) { + return DeFiErrors::GovVarValidateSplitDAT(); + } + if (!view.GetLoanTokenByIDFromStore(id) && !GetLoanTokenByID(view, id)) { + return DeFiErrors::GovVarValidateLoanTokenID(tokenId); + } + } + + return Res::Ok(); +} + +Res ATTRIBUTES::ValidateOracleSplits64(const CCustomCSView &view, + const bool checkFractional, + const OracleSplits64 &splitMap) const { CDataStructureV0 fractionalKey{AttributeTypes::Oracles, OracleIDs::Splits, OracleKeys::FractionalSplits}; - const auto fractionalEnabled = attributes.GetValue(fractionalKey, bool{}); + const auto fractionalEnabled = GetValue(fractionalKey, bool{}); - for (const auto &[tokenId, multiplier] : *splitMap) { + for (const auto &[tokenId, multiplier] : splitMap) { if (tokenId == 0) { return DeFiErrors::GovVarValidateSplitDFI(); } - if (view.HasPoolPair({tokenId})) { + const auto id = DCT_ID{tokenId}; + if (view.HasPoolPair(id)) { return DeFiErrors::GovVarValidateSplitPool(); } const auto token = view.GetToken(DCT_ID{tokenId}); @@ -1824,7 +1818,7 @@ static Res ValidateOracleSplits(const ATTRIBUTES &attributes, if (!token->IsDAT()) { return DeFiErrors::GovVarValidateSplitDAT(); } - if (!view.GetLoanTokenByID({tokenId})) { + if (!view.GetLoanTokenByIDFromStore(id) && !GetLoanTokenByID(view, id)) { return DeFiErrors::GovVarValidateLoanTokenID(tokenId); } if (checkFractional) { @@ -1861,7 +1855,8 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { [[fallthrough]]; case TokenKeys::PaybackDFI: case TokenKeys::PaybackDFIFeePCT: - if (!view.GetLoanTokenByID({attrV0->typeId})) { + if (!view.GetLoanTokenByIDFromStore({attrV0->typeId}) && + !GetLoanTokenByID(view, {attrV0->typeId})) { return DeFiErrors::GovVarValidateLoanToken(attrV0->typeId); } break; @@ -1870,7 +1865,8 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { if (view.GetLastHeight() < Params().GetConsensus().DF15FortCanningRoadHeight) { return DeFiErrors::GovVarValidateFortCanningRoad(); } - if (!view.GetLoanTokenByID({attrV0->typeId})) { + if (!view.GetLoanTokenByIDFromStore({attrV0->typeId}) && + !GetLoanTokenByID(view, {attrV0->typeId})) { return DeFiErrors::GovVarValidateLoanToken(attrV0->typeId); } if (!view.GetToken(DCT_ID{attrV0->keyId})) { @@ -1963,7 +1959,8 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { if (view.GetLastHeight() < Params().GetConsensus().DF15FortCanningRoadHeight) { return DeFiErrors::GovVarValidateFortCanningRoad(); } - if (!view.GetLoanTokenByID({attrV0->typeId})) { + if (!view.GetLoanTokenByIDFromStore({attrV0->typeId}) && + !GetLoanTokenByID(view, {attrV0->typeId})) { return DeFiErrors::GovVarValidateLoanToken(attrV0->typeId); } break; @@ -1988,7 +1985,7 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { } else { const auto splitMap = std::get_if(&value); if (splitMap) { - if (auto res = ValidateOracleSplits(*this, view, false, splitMap); !res) { + if (auto res = ValidateOracleSplits(view, *splitMap); !res) { return res; } } else { @@ -1996,7 +1993,7 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { if (!splitMap64) { return DeFiErrors::GovVarUnsupportedValue(); } - if (auto res = ValidateOracleSplits(*this, view, true, splitMap64); !res) { + if (auto res = ValidateOracleSplits64(view, true, *splitMap64); !res) { return res; } } @@ -2084,17 +2081,19 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { case AttributeTypes::Live: break; - case AttributeTypes::Locks: + case AttributeTypes::Locks: { if (view.GetLastHeight() < Params().GetConsensus().DF16FortCanningCrunchHeight) { return Res::Err("Cannot be set before FortCanningCrunch"); } if (attrV0->typeId != ParamIDs::TokenID) { return Res::Err("Unrecognised locks id"); } - if (!view.GetLoanTokenByID(DCT_ID{attrV0->key}).has_value()) { - return Res::Err("No loan token with id (%d)", attrV0->key); + const DCT_ID tokenId{attrV0->key}; + if (!view.GetLoanTokenByIDFromStore(tokenId) && !GetLoanTokenByID(view, tokenId)) { + return DeFiErrors::GovVarValidateLoanTokenID(attrV0->key); } break; + } case AttributeTypes::Governance: if (view.GetLastHeight() < Params().GetConsensus().DF20GrandCentralHeight) { @@ -2462,7 +2461,7 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { return Res::Ok(); } -Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t, const std::vector &keys) { +Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t height, const std::vector &keys) { for (const auto &key : keys) { auto res = ProcessVariable(key, {}, [&](const CAttributeType &attribute, const CAttributeValue &) { auto attrV0 = std::get_if(&attribute); @@ -2502,3 +2501,28 @@ Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t, const std::vector &setEvmTemplate) { + time = setTime; + evmTemplate = setEvmTemplate; +} + +std::optional ATTRIBUTES::GetLoanTokenByID(const CCustomCSView &view, + const DCT_ID &id) const { + CDataStructureV0 pairKey{AttributeTypes::Token, id.v, TokenKeys::FixedIntervalPriceId}; + CDataStructureV0 interestKey{AttributeTypes::Token, id.v, TokenKeys::LoanMintingInterest}; + CDataStructureV0 mintableKey{AttributeTypes::Token, id.v, TokenKeys::LoanMintingEnabled}; + + if (const auto token = view.GetToken(id); + token && CheckKey(pairKey) && CheckKey(interestKey) && CheckKey(mintableKey)) { + CLoanView::CLoanSetLoanTokenImpl loanToken; + loanToken.fixedIntervalPriceId = GetValue(pairKey, CTokenCurrencyPair{}); + loanToken.interest = GetValue(interestKey, CAmount{}); + loanToken.mintable = GetValue(mintableKey, false); + loanToken.symbol = token->symbol; + loanToken.name = token->name; + return loanToken; + } + + return {}; +} diff --git a/src/dfi/govvariables/attributes.h b/src/dfi/govvariables/attributes.h index a1b0d920f5..65da87a265 100644 --- a/src/dfi/govvariables/attributes.h +++ b/src/dfi/govvariables/attributes.h @@ -5,401 +5,22 @@ #ifndef DEFI_DFI_GOVVARIABLES_ATTRIBUTES_H #define DEFI_DFI_GOVVARIABLES_ATTRIBUTES_H -#include -#include -#include +#include /// DeFiErrors #include -#include +class CBlockIndex; namespace Consensus { struct Params; } -enum VersionTypes : uint8_t { - v0 = 0, -}; - -enum AttributeTypes : uint8_t { - Live = 'l', - Oracles = 'o', - Param = 'a', - Token = 't', - Poolpairs = 'p', - Locks = 'L', - Governance = 'g', - Transfer = 'b', - EVMType = 'e', - Vaults = 'v', - Rules = 'r', -}; - -enum ParamIDs : uint8_t { - DFIP2201 = 'a', - DFIP2203 = 'b', - TokenID = 'c', - Economy = 'e', - DFIP2206A = 'f', - DFIP2206F = 'g', - Feature = 'h', - Auction = 'i', - Foundation = 'j', - DFIP2211F = 'k', -}; - -enum OracleIDs : uint8_t { - Splits = 'a', -}; - -enum EVMIDs : uint8_t { - Block = 'a', -}; - -enum EVMKeys : uint8_t { - Finalized = 'a', - GasLimit = 'b', - GasTargetFactor = 'c', - RbfIncrementMinPct = 'd', -}; - -enum GovernanceIDs : uint8_t { - Global = 'a', - Proposals = 'b', -}; - -enum TransferIDs : uint8_t { - DVMToEVM = 'a', - EVMToDVM = 'b', -}; - -enum VaultIDs : uint8_t { - DUSDVault = 'a', - Parameters = 'b', -}; - -enum RulesIDs : uint8_t { - TXRules = 'a', -}; - -enum EconomyKeys : uint8_t { - PaybackDFITokens = 'a', - PaybackTokens = 'b', - DFIP2203Current = 'c', - DFIP2203Burned = 'd', - DFIP2203Minted = 'e', - DFIP2206FCurrent = 'f', - DFIP2206FBurned = 'g', - DFIP2206FMinted = 'h', - DexTokens = 'i', - NegativeInt = 'j', - NegativeIntCurrent = 'k', - BatchRoundingExcess = 'n', // Extra added to loan amounts on auction creation due to round errors. - ConsolidatedInterest = 'o', // Amount added to loan amounts after auction with no bids. - PaybackDFITokensPrincipal = 'p', // Same as PaybackDFITokens but without interest. - Loans = 'q', - TransferDomainStatsLive = 'r', - EVMBlockStatsLive = 's', -}; - -enum DFIPKeys : uint8_t { - Active = 'a', - Premium = 'b', - MinSwap = 'c', - RewardPct = 'd', - BlockPeriod = 'e', - DUSDInterestBurn = 'g', - DUSDLoanBurn = 'h', - StartBlock = 'i', - GovUnset = 'j', - GovFoundation = 'k', - MNSetRewardAddress = 'l', - MNSetOperatorAddress = 'm', - MNSetOwnerAddress = 'n', - Members = 'p', - GovernanceEnabled = 'q', - CFPPayout = 'r', - EmissionUnusedFund = 's', - MintTokens = 't', - EVMEnabled = 'u', - ICXEnabled = 'v', - TransferDomain = 'w', - LiquidityCalcSamplingPeriod = 'x', - AverageLiquidityPercentage = 'y', -}; - -enum GovernanceKeys : uint8_t { - FeeRedistribution = 'a', - FeeBurnPct = 'b', - CFPFee = 'd', - CFPApprovalThreshold = 'e', - VOCFee = 'f', - VOCEmergencyFee = 'g', - VOCEmergencyPeriod = 'h', - VOCApprovalThreshold = 'i', - Quorum = 'j', - VotingPeriod = 'k', - VOCEmergencyQuorum = 'l', - CFPMaxCycles = 'm', -}; - -enum TokenKeys : uint8_t { - PaybackDFI = 'a', - PaybackDFIFeePCT = 'b', - LoanPayback = 'c', - LoanPaybackFeePCT = 'd', - DexInFeePct = 'e', - DexOutFeePct = 'f', - DFIP2203Enabled = 'g', - FixedIntervalPriceId = 'h', - LoanCollateralEnabled = 'i', - LoanCollateralFactor = 'j', - LoanMintingEnabled = 'k', - LoanMintingInterest = 'l', - Ascendant = 'm', - Descendant = 'n', - Epitaph = 'o', - LoanPaybackCollateral = 'p', -}; - -enum PoolKeys : uint8_t { - TokenAFeePCT = 'a', - TokenBFeePCT = 'b', - TokenAFeeDir = 'c', - TokenBFeeDir = 'd', -}; - -enum TransferKeys : uint8_t { - TransferEnabled = 'a', - SrcFormats = 'b', - DestFormats = 'c', - AuthFormats = 'd', - NativeEnabled = 'e', - DATEnabled = 'f', - Disallowed = 'g', -}; - -enum VaultKeys : uint8_t { - CreationFee = 'a', - DUSDVaultEnabled = 'w', -}; - -enum OracleKeys : uint8_t { - FractionalSplits = 0, -}; - -enum RulesKeys : uint8_t { - CoreOPReturn = 'a', - DVMOPReturn = 'b', - EVMOPReturn = 'c', -}; - -struct CDataStructureV0 { - uint8_t type; - uint32_t typeId; - uint32_t key; - uint32_t keyId; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(type); - READWRITE(typeId); - READWRITE(VARINT(key)); - if (IsExtendedSize()) { - READWRITE(keyId); - } else { - keyId = 0; - } - } - - bool IsExtendedSize() const { - return type == AttributeTypes::Token && (key == TokenKeys::LoanPayback || key == TokenKeys::LoanPaybackFeePCT); - } - - bool operator<(const CDataStructureV0 &o) const { - return std::tie(type, typeId, key, keyId) < std::tie(o.type, o.typeId, o.key, o.keyId); - } -}; - -// for future use -struct CDataStructureV1 { - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) {} - - bool operator<(const CDataStructureV1 &o) const { return false; } -}; - -struct CTokenPayback { - CBalances tokensFee; - CBalances tokensPayback; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(tokensFee); - READWRITE(tokensPayback); - } -}; - -struct CFeeDir { - uint8_t feeDir; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(feeDir); - } -}; - -ResVal GetFutureSwapContractAddress(const std::string &contract); - -struct CDexTokenInfo { - struct CTokenInfo { - uint64_t swaps; - uint64_t feeburn; - uint64_t commissions; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(swaps); - READWRITE(feeburn); - READWRITE(commissions); - } - }; - - CTokenInfo totalTokenA; - CTokenInfo totalTokenB; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(totalTokenA); - READWRITE(totalTokenB); - } -}; - -enum FeeDirValues : uint8_t { Both, In, Out }; - -struct CTransferDomainStatsLive { - CStatsTokenBalances dvmEvmTotal; - CStatsTokenBalances evmDvmTotal; - CStatsTokenBalances dvmIn; - CStatsTokenBalances evmIn; - CStatsTokenBalances dvmOut; - CStatsTokenBalances evmOut; - CStatsTokenBalances dvmCurrent; - CStatsTokenBalances evmCurrent; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(dvmEvmTotal); - READWRITE(evmDvmTotal); - READWRITE(dvmIn); - READWRITE(evmIn); - READWRITE(dvmOut); - READWRITE(evmOut); - READWRITE(dvmCurrent); - READWRITE(evmCurrent); - } - - static constexpr CDataStructureV0 Key = {AttributeTypes::Live, - ParamIDs::Economy, - EconomyKeys::TransferDomainStatsLive}; -}; - -enum XVmAddressFormatTypes : uint8_t { - None, - Bech32, - Bech32ProxyErc55, - PkHash, - PkHashProxyErc55, - Erc55, -}; - -struct CEvmBlockStatsLive { - CAmount feeBurnt; - CAmount feeBurntMin = std::numeric_limits::max(); - uint256 feeBurntMinHash; - CAmount feeBurntMax = std::numeric_limits::min(); - uint256 feeBurntMaxHash; - CAmount feePriority; - CAmount feePriorityMin = std::numeric_limits::max(); - uint256 feePriorityMinHash; - CAmount feePriorityMax = std::numeric_limits::min(); - uint256 feePriorityMaxHash; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream &s, Operation ser_action) { - READWRITE(feeBurnt); - READWRITE(feeBurntMin); - READWRITE(feeBurntMinHash); - READWRITE(feeBurntMax); - READWRITE(feeBurntMaxHash); - READWRITE(feePriority); - READWRITE(feePriorityMin); - READWRITE(feePriorityMinHash); - READWRITE(feePriorityMax); - READWRITE(feePriorityMaxHash); - } - - static constexpr CDataStructureV0 Key = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::EVMBlockStatsLive}; -}; - -using CDexBalances = std::map; -using OracleSplits = std::map; -using OracleSplits64 = std::map; -using DescendantValue = std::pair; -using AscendantValue = std::pair; -using CAttributeType = std::variant; - -// Unused legacy types but can be changed and update for future use. -// Required for sync to maintain consistent variant indexing. -using LegacyEntry1 = std::map; -using LegacyEntry2 = std::map; -using LegacyEntry3 = std::map; - -using CAttributeValue = std::variant, - std::set, - LegacyEntry1, - LegacyEntry2, - LegacyEntry3, - int32_t, - uint32_t, - uint64_t, - XVmAddressFormatItems, - CTransferDomainStatsLive, - CEvmBlockStatsLive, - OracleSplits64>; - void TrackNegativeInterest(CCustomCSView &mnview, const CTokenAmount &amount); void TrackLiveBalances(CCustomCSView &mnview, const CBalances &balances, const uint8_t key); void TrackDUSDAdd(CCustomCSView &mnview, const CTokenAmount &amount); void TrackDUSDSub(CCustomCSView &mnview, const CTokenAmount &amount); -bool IsEVMEnabled(const std::shared_ptr attributes); -bool IsEVMEnabled(const CCustomCSView &view); +bool IsEVMEnabled(CCustomCSView &view); Res StoreGovVars(const CGovernanceHeightMessage &obj, CCustomCSView &view); +ResVal GetFutureSwapContractAddress(const std::string &contract); enum GovVarsFilter { All, @@ -429,6 +50,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator static void GetIf(std::optional &opt, const CAttributeValue &var) { if (auto value = std::get_if(&var)) { @@ -443,6 +65,10 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator evmTemplate{}; + +public: template [[nodiscard]] T GetValue(const K &key, T value) const { static_assert(std::is_convertible_v); @@ -490,8 +116,6 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &GetAttributesMap() const { return attributes; } - ADD_OVERRIDE_VECTOR_SERIALIZE_METHODS ADD_OVERRIDE_SERIALIZE_METHODS(CDataStream) @@ -500,9 +124,6 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator evmTemplate{}; - // For formatting in export static const std::map &displayVersions(); static const std::map &displayTypes(); @@ -517,14 +138,9 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &displayRulesIDs(); static const std::map> &displayKeys(); - Res RefundFuturesContracts(CCustomCSView &mnview, - const uint32_t height, - const uint32_t tokenID = std::numeric_limits::max()); - - void AddTokenSplit(const uint32_t tokenID) { tokenSplits.insert(tokenID); } - private: friend class CGovView; + friend class CCustomCSView; bool futureUpdated{}; bool futureDUSDUpdated{}; std::set tokenSplits{}; @@ -551,6 +167,30 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &value, std::function applyVariable); Res RefundFuturesDUSD(CCustomCSView &mnview, const uint32_t height); + Res RefundFuturesContracts(CCustomCSView &mnview, + const uint32_t height, + const uint32_t tokenID = std::numeric_limits::max()); + void SetAttributesMembers(const int64_t setTime, const std::shared_ptr &setEvmTemplate); + [[nodiscard]] std::optional GetLoanTokenByID(const CCustomCSView &view, + const DCT_ID &id) const; + [[nodiscard]] bool IsChanged() const { return !changed.empty(); } + void AddTokenSplit(const uint32_t tokenID) { tokenSplits.insert(tokenID); } + + Res ValidateOracleSplits(const CCustomCSView &view, const OracleSplits &splitMap) const; + Res ValidateOracleSplits64(const CCustomCSView &view, + const bool checkFractional, + const OracleSplits64 &splitMap) const; + + template + Res SetOracleSplit(const CAttributeType &key, const T &splitValue) { + if (splitValue->size() != 1) { + return Res::Err("Invalid number of token splits, allowed only one per height!"); + } + const auto &[id, multiplier] = *(splitValue->begin()); + AddTokenSplit(id); + SetValue(key, *splitValue); + return Res::Ok(); + } }; #endif // DEFI_DFI_GOVVARIABLES_ATTRIBUTES_H diff --git a/src/dfi/govvariables/attributetypes.h b/src/dfi/govvariables/attributetypes.h new file mode 100644 index 0000000000..40afb5f504 --- /dev/null +++ b/src/dfi/govvariables/attributetypes.h @@ -0,0 +1,390 @@ +// Copyright (c) 2020 The DeFi Foundation +// Distributed under the MIT software license, see the accompanying +// file LICENSE or http://www.opensource.org/licenses/mit-license.php. + +#ifndef DEFI_DFI_GOVVARIABLES_ATTRIBUTETYPES_H +#define DEFI_DFI_GOVVARIABLES_ATTRIBUTETYPES_H + +#include +#include +#include +#include +#include + +enum VersionTypes : uint8_t { + v0 = 0, +}; + +enum AttributeTypes : uint8_t { + Live = 'l', + Oracles = 'o', + Param = 'a', + Token = 't', + Poolpairs = 'p', + Locks = 'L', + Governance = 'g', + Transfer = 'b', + EVMType = 'e', + Vaults = 'v', + Rules = 'r', +}; + +enum ParamIDs : uint8_t { + DFIP2201 = 'a', + DFIP2203 = 'b', + TokenID = 'c', + Economy = 'e', + DFIP2206A = 'f', + DFIP2206F = 'g', + Feature = 'h', + Auction = 'i', + Foundation = 'j', + DFIP2211F = 'k', +}; + +enum OracleIDs : uint8_t { + Splits = 'a', +}; + +enum EVMIDs : uint8_t { + Block = 'a', +}; + +enum EVMKeys : uint8_t { + Finalized = 'a', + GasLimit = 'b', + GasTargetFactor = 'c', + RbfIncrementMinPct = 'd', +}; + +enum GovernanceIDs : uint8_t { + Global = 'a', + Proposals = 'b', +}; + +enum TransferIDs : uint8_t { + DVMToEVM = 'a', + EVMToDVM = 'b', +}; + +enum VaultIDs : uint8_t { + DUSDVault = 'a', + Parameters = 'b', +}; + +enum RulesIDs : uint8_t { + TXRules = 'a', +}; + +enum EconomyKeys : uint8_t { + PaybackDFITokens = 'a', + PaybackTokens = 'b', + DFIP2203Current = 'c', + DFIP2203Burned = 'd', + DFIP2203Minted = 'e', + DFIP2206FCurrent = 'f', + DFIP2206FBurned = 'g', + DFIP2206FMinted = 'h', + DexTokens = 'i', + NegativeInt = 'j', + NegativeIntCurrent = 'k', + BatchRoundingExcess = 'n', // Extra added to loan amounts on auction creation due to round errors. + ConsolidatedInterest = 'o', // Amount added to loan amounts after auction with no bids. + PaybackDFITokensPrincipal = 'p', // Same as PaybackDFITokens but without interest. + Loans = 'q', + TransferDomainStatsLive = 'r', + EVMBlockStatsLive = 's', +}; + +enum DFIPKeys : uint8_t { + Active = 'a', + Premium = 'b', + MinSwap = 'c', + RewardPct = 'd', + BlockPeriod = 'e', + DUSDInterestBurn = 'g', + DUSDLoanBurn = 'h', + StartBlock = 'i', + GovUnset = 'j', + GovFoundation = 'k', + MNSetRewardAddress = 'l', + MNSetOperatorAddress = 'm', + MNSetOwnerAddress = 'n', + Members = 'p', + GovernanceEnabled = 'q', + CFPPayout = 'r', + EmissionUnusedFund = 's', + MintTokens = 't', + EVMEnabled = 'u', + ICXEnabled = 'v', + TransferDomain = 'w', + LiquidityCalcSamplingPeriod = 'x', + AverageLiquidityPercentage = 'y', +}; + +enum GovernanceKeys : uint8_t { + FeeRedistribution = 'a', + FeeBurnPct = 'b', + CFPFee = 'd', + CFPApprovalThreshold = 'e', + VOCFee = 'f', + VOCEmergencyFee = 'g', + VOCEmergencyPeriod = 'h', + VOCApprovalThreshold = 'i', + Quorum = 'j', + VotingPeriod = 'k', + VOCEmergencyQuorum = 'l', + CFPMaxCycles = 'm', +}; + +enum TokenKeys : uint8_t { + PaybackDFI = 'a', + PaybackDFIFeePCT = 'b', + LoanPayback = 'c', + LoanPaybackFeePCT = 'd', + DexInFeePct = 'e', + DexOutFeePct = 'f', + DFIP2203Enabled = 'g', + FixedIntervalPriceId = 'h', + LoanCollateralEnabled = 'i', + LoanCollateralFactor = 'j', + LoanMintingEnabled = 'k', + LoanMintingInterest = 'l', + Ascendant = 'm', + Descendant = 'n', + Epitaph = 'o', + LoanPaybackCollateral = 'p', +}; + +enum PoolKeys : uint8_t { + TokenAFeePCT = 'a', + TokenBFeePCT = 'b', + TokenAFeeDir = 'c', + TokenBFeeDir = 'd', +}; + +enum TransferKeys : uint8_t { + TransferEnabled = 'a', + SrcFormats = 'b', + DestFormats = 'c', + AuthFormats = 'd', + NativeEnabled = 'e', + DATEnabled = 'f', + Disallowed = 'g', +}; + +enum VaultKeys : uint8_t { + CreationFee = 'a', + DUSDVaultEnabled = 'w', +}; + +enum OracleKeys : uint8_t { + FractionalSplits = 0, +}; + +enum RulesKeys : uint8_t { + CoreOPReturn = 'a', + DVMOPReturn = 'b', + EVMOPReturn = 'c', +}; + +struct CDataStructureV0 { + uint8_t type; + uint32_t typeId; + uint32_t key; + uint32_t keyId; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(type); + READWRITE(typeId); + READWRITE(VARINT(key)); + if (IsExtendedSize()) { + READWRITE(keyId); + } else { + keyId = 0; + } + } + + bool IsExtendedSize() const { + return type == AttributeTypes::Token && (key == TokenKeys::LoanPayback || key == TokenKeys::LoanPaybackFeePCT); + } + + bool operator<(const CDataStructureV0 &o) const { + return std::tie(type, typeId, key, keyId) < std::tie(o.type, o.typeId, o.key, o.keyId); + } +}; + +// for future use +struct CDataStructureV1 { + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) {} + + bool operator<(const CDataStructureV1 &o) const { return false; } +}; + +struct CTokenPayback { + CBalances tokensFee; + CBalances tokensPayback; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(tokensFee); + READWRITE(tokensPayback); + } +}; + +struct CFeeDir { + uint8_t feeDir; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(feeDir); + } +}; + +struct CDexTokenInfo { + struct CTokenInfo { + uint64_t swaps; + uint64_t feeburn; + uint64_t commissions; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(swaps); + READWRITE(feeburn); + READWRITE(commissions); + } + }; + + CTokenInfo totalTokenA; + CTokenInfo totalTokenB; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(totalTokenA); + READWRITE(totalTokenB); + } +}; + +enum FeeDirValues : uint8_t { Both, In, Out }; + +struct CTransferDomainStatsLive { + CStatsTokenBalances dvmEvmTotal; + CStatsTokenBalances evmDvmTotal; + CStatsTokenBalances dvmIn; + CStatsTokenBalances evmIn; + CStatsTokenBalances dvmOut; + CStatsTokenBalances evmOut; + CStatsTokenBalances dvmCurrent; + CStatsTokenBalances evmCurrent; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(dvmEvmTotal); + READWRITE(evmDvmTotal); + READWRITE(dvmIn); + READWRITE(evmIn); + READWRITE(dvmOut); + READWRITE(evmOut); + READWRITE(dvmCurrent); + READWRITE(evmCurrent); + } + + static constexpr CDataStructureV0 Key = {AttributeTypes::Live, + ParamIDs::Economy, + EconomyKeys::TransferDomainStatsLive}; +}; + +enum XVmAddressFormatTypes : uint8_t { + None, + Bech32, + Bech32ProxyErc55, + PkHash, + PkHashProxyErc55, + Erc55, +}; + +struct CEvmBlockStatsLive { + CAmount feeBurnt; + CAmount feeBurntMin = std::numeric_limits::max(); + uint256 feeBurntMinHash; + CAmount feeBurntMax = std::numeric_limits::min(); + uint256 feeBurntMaxHash; + CAmount feePriority; + CAmount feePriorityMin = std::numeric_limits::max(); + uint256 feePriorityMinHash; + CAmount feePriorityMax = std::numeric_limits::min(); + uint256 feePriorityMaxHash; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream &s, Operation ser_action) { + READWRITE(feeBurnt); + READWRITE(feeBurntMin); + READWRITE(feeBurntMinHash); + READWRITE(feeBurntMax); + READWRITE(feeBurntMaxHash); + READWRITE(feePriority); + READWRITE(feePriorityMin); + READWRITE(feePriorityMinHash); + READWRITE(feePriorityMax); + READWRITE(feePriorityMaxHash); + } + + static constexpr CDataStructureV0 Key = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::EVMBlockStatsLive}; +}; + +using CDexBalances = std::map; +using OracleSplits = std::map; +using OracleSplits64 = std::map; +using DescendantValue = std::pair; +using AscendantValue = std::pair; +using CAttributeType = std::variant; +using XVmAddressFormatItems = std::set; + +// Unused legacy types but can be changed and update for future use. +// Required for sync to maintain consistent variant indexing. +using LegacyEntry1 = std::map; +using LegacyEntry2 = std::map; +using LegacyEntry3 = std::map; + +using CAttributeValue = std::variant, + std::set, + LegacyEntry1, + LegacyEntry2, + LegacyEntry3, + int32_t, + uint32_t, + uint64_t, + XVmAddressFormatItems, + CTransferDomainStatsLive, + CEvmBlockStatsLive, + OracleSplits64>; + +#endif // DEFI_DFI_GOVVARIABLES_ATTRIBUTETYPES_H \ No newline at end of file diff --git a/src/dfi/gv.cpp b/src/dfi/gv.cpp index 315768f4ac..e194d62c89 100644 --- a/src/dfi/gv.cpp +++ b/src/dfi/gv.cpp @@ -14,7 +14,7 @@ #include #include -Res CGovView::SetVariable(const GovVariable &var) { +Res CGovView::SetVariable(GovVariable &var) { auto WriteOrEraseVar = [this](const GovVariable &var) { if (var.IsEmpty()) { EraseBy(var.GetName()); @@ -26,20 +26,24 @@ Res CGovView::SetVariable(const GovVariable &var) { if (var.GetName() != "ATTRIBUTES") { return WriteOrEraseVar(var); } - auto attributes = GetAttributes(); - auto ¤t = dynamic_cast(var); + auto attr = GetAttributesFromStore(); + auto ¤t = dynamic_cast(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); + attr->attributes.erase(key); } else { - attributes->attributes[key] = it->second; + attr->attributes[key] = it->second; } } - return WriteOrEraseVar(*attributes); + + // Wipe changed set. + current.changed.clear(); + + return WriteOrEraseVar(*attr); } std::shared_ptr CGovView::GetVariable(const std::string &name) const { @@ -116,10 +120,10 @@ void CGovView::EraseStoredVariables(const uint32_t height) { } } -std::shared_ptr CGovView::GetAttributes() const { +std::shared_ptr CGovView::GetAttributesFromStore() const { const auto var = GetVariable("ATTRIBUTES"); assert(var); - auto attributes = std::dynamic_pointer_cast(var); - assert(attributes); - return attributes; + auto attr = std::dynamic_pointer_cast(var); + assert(attr); + return attr; } diff --git a/src/dfi/gv.h b/src/dfi/gv.h index 173060804b..b72488661e 100644 --- a/src/dfi/gv.h +++ b/src/dfi/gv.h @@ -13,8 +13,6 @@ class ATTRIBUTES; class CCustomCSView; -using XVmAddressFormatItems = std::set; - template class GvOptional : public std::optional { public: @@ -106,9 +104,12 @@ struct CGovernanceUnsetMessage { }; class CGovView : public virtual CStorageView { +protected: + [[nodiscard]] std::shared_ptr GetAttributesFromStore() const; + public: - Res SetVariable(const GovVariable &var); - std::shared_ptr GetVariable(const std::string &govKey) const; + Res SetVariable(GovVariable &var); + [[nodiscard]] std::shared_ptr GetVariable(const std::string &govKey) const; Res SetStoredVariables(const std::set> &govVars, const uint32_t height); std::set> GetStoredVariables(const uint32_t height); @@ -117,9 +118,7 @@ class CGovView : public virtual CStorageView { std::map>> GetAllStoredVariables(); void EraseStoredVariables(const uint32_t height); - std::shared_ptr GetAttributes() const; - - [[nodiscard]] virtual bool AreTokensLocked(const std::set &tokenIds) const = 0; + [[nodiscard]] virtual bool AreTokensLocked(const std::set &tokenIds) = 0; struct ByHeightVars { static constexpr uint8_t prefix() { return 'G'; } diff --git a/src/dfi/loan.cpp b/src/dfi/loan.cpp index 48cc952ace..77c44dc595 100644 --- a/src/dfi/loan.cpp +++ b/src/dfi/loan.cpp @@ -55,14 +55,14 @@ std::optional CLoanView::HasLoanCollater std::optional CLoanView::GetLoanToken(const uint256 &txid) const { auto id = ReadBy(txid); if (id) { - return GetLoanTokenByID(*id); + return GetLoanTokenByIDFromStore(*id); } return {}; } Res CLoanView::SetLoanToken(const CLoanSetLoanTokenImpl &loanToken, DCT_ID const &id) { // this should not happen, but for sure - if (GetLoanTokenByID(id)) { + if (GetLoanTokenByIDFromStore(id)) { return Res::Err("setLoanToken with creation tx %s already exists!", loanToken.creationTx.GetHex()); } diff --git a/src/dfi/loan.h b/src/dfi/loan.h index 1191068db6..4260b19586 100644 --- a/src/dfi/loan.h +++ b/src/dfi/loan.h @@ -412,8 +412,9 @@ class CLoanView : public virtual CStorageView { const CollateralTokenKey &start = {DCT_ID{0}, UINT_MAX}); std::optional HasLoanCollateralToken(const CollateralTokenKey &key); - std::optional GetLoanToken(const uint256 &txid) const; - [[nodiscard]] virtual std::optional GetLoanTokenByID(DCT_ID const &id) const = 0; + [[nodiscard]] std::optional GetLoanToken(const uint256 &txid) const; + [[nodiscard]] virtual std::optional GetLoanTokenByIDFromStore(const DCT_ID &id) const = 0; + [[nodiscard]] virtual std::optional GetLoanTokenByID(const DCT_ID &id) = 0; Res SetLoanToken(const CLoanSetLoanTokenImpl &loanToken, DCT_ID const &id); Res UpdateLoanToken(const CLoanSetLoanTokenImpl &loanToken, DCT_ID const &id); Res EraseLoanToken(const DCT_ID &id); @@ -479,9 +480,9 @@ class CLoanView : public virtual CStorageView { CAmount GetLoanLiquidationPenalty(); [[nodiscard]] virtual std::optional GetLoanTokenFromAttributes( - const DCT_ID &id) const = 0; + const DCT_ID &id) = 0; [[nodiscard]] virtual std::optional GetCollateralTokenFromAttributes( - const DCT_ID &id) const = 0; + const DCT_ID &id) = 0; struct LoanSetCollateralTokenCreationTx { static constexpr uint8_t prefix() { return 0x10; } diff --git a/src/dfi/masternodes.cpp b/src/dfi/masternodes.cpp index 94d86e4dbb..b8b942259e 100644 --- a/src/dfi/masternodes.cpp +++ b/src/dfi/masternodes.cpp @@ -74,10 +74,9 @@ CAmount GetTokenCreationFee(int) { return Params().GetConsensus().token.creationFee; } -CAmount GetProposalCreationFee(int, const CCustomCSView &view, const CCreateProposalMessage &msg) { +CAmount GetProposalCreationFee(int, CCustomCSView &view, const CCreateProposalMessage &msg) { auto type = static_cast(msg.type); auto options = static_cast(msg.options); - auto attributes = view.GetAttributes(); CDataStructureV0 CFPKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::CFPFee}; CDataStructureV0 VOCKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::VOCFee}; @@ -88,15 +87,15 @@ CAmount GetProposalCreationFee(int, const CCustomCSView &view, const CCreateProp CAmount cfpFee; switch (type) { case CProposalType::CommunityFundProposal: { - cfpFee = MultiplyAmounts(msg.nAmount, attributes->GetValue(CFPKey, Params().GetConsensus().props.cfp.fee)); + cfpFee = MultiplyAmounts(msg.nAmount, view.GetValue(CFPKey, Params().GetConsensus().props.cfp.fee)); auto minimumFee = Params().GetConsensus().props.cfp.minimumFee; return minimumFee > cfpFee ? minimumFee : cfpFee; } case CProposalType::VoteOfConfidence: if (emergency) { - return attributes->GetValue(VOCEmergencyKey, Params().GetConsensus().props.voc.emergencyFee); + return view.GetValue(VOCEmergencyKey, Params().GetConsensus().props.voc.emergencyFee); } else { - return attributes->GetValue(VOCKey, Params().GetConsensus().props.voc.fee); + return view.GetValue(VOCKey, Params().GetConsensus().props.voc.fee); } } return -1; @@ -790,7 +789,11 @@ CCustomCSView::CCustomCSView(std::unique_ptr &st, const MapKV & // cache-upon-a-cache (not a copy!) constructor CCustomCSView::CCustomCSView(CCustomCSView &other) : CStorageView(new CFlushableStorageKV(other.DB())), + persistentAttributes(true), writers(other.GetHistoryWriters()) { + if (other.HasAttributes()) { + attributes = other.GetAttributes(); + } CheckPrefixes(); } @@ -799,7 +802,11 @@ CCustomCSView::CCustomCSView(CCustomCSView &other, CBurnHistoryStorage *burnView, CVaultHistoryStorage *vaultView) : CStorageView(new CFlushableStorageKV(other.DB())), + persistentAttributes(true), writers(historyView, burnView, vaultView) { + if (other.HasAttributes()) { + attributes = other.GetAttributes(); + } CheckPrefixes(); } @@ -1200,12 +1207,10 @@ uint256 CCustomCSView::MerkleRoot() { return ComputeMerkleRoot(std::move(hashes)); } -bool CCustomCSView::AreTokensLocked(const std::set &tokenIds) const { - const auto attributes = GetAttributes(); - +bool CCustomCSView::AreTokensLocked(const std::set &tokenIds) { for (const auto &tokenId : tokenIds) { CDataStructureV0 lockKey{AttributeTypes::Locks, ParamIDs::TokenID, tokenId}; - if (attributes->GetValue(lockKey, false)) { + if (GetValue(lockKey, false)) { return true; } } @@ -1241,8 +1246,12 @@ std::optional CCustomCSView::GetTokenGuessId(const std: return {}; } -std::optional CCustomCSView::GetLoanTokenByID(DCT_ID const &id) const { - auto loanToken = ReadBy(id); +std::optional CCustomCSView::GetLoanTokenByIDFromStore(DCT_ID const &id) const { + return ReadBy(id); +} + +std::optional CCustomCSView::GetLoanTokenByID(DCT_ID const &id) { + auto loanToken = GetLoanTokenByIDFromStore(id); if (loanToken) { return loanToken; } @@ -1279,37 +1288,20 @@ std::map AmISignerNow(int height, const CAnchorData::CTeam &team) return operatorDetails; } -std::optional CCustomCSView::GetLoanTokenFromAttributes(const DCT_ID &id) const { - const auto attributes = GetAttributes(); - CDataStructureV0 pairKey{AttributeTypes::Token, id.v, TokenKeys::FixedIntervalPriceId}; - CDataStructureV0 interestKey{AttributeTypes::Token, id.v, TokenKeys::LoanMintingInterest}; - CDataStructureV0 mintableKey{AttributeTypes::Token, id.v, TokenKeys::LoanMintingEnabled}; - - if (const auto token = GetToken(id); token && attributes->CheckKey(pairKey) && attributes->CheckKey(interestKey) && - attributes->CheckKey(mintableKey)) { - CLoanView::CLoanSetLoanTokenImpl loanToken; - loanToken.fixedIntervalPriceId = attributes->GetValue(pairKey, CTokenCurrencyPair{}); - loanToken.interest = attributes->GetValue(interestKey, CAmount{}); - loanToken.mintable = attributes->GetValue(mintableKey, false); - loanToken.symbol = token->symbol; - loanToken.name = token->name; - return loanToken; - } - - return {}; +std::optional CCustomCSView::GetLoanTokenFromAttributes(const DCT_ID &id) { + return GetAttributes().GetLoanTokenByID(*this, id); } std::optional CCustomCSView::GetCollateralTokenFromAttributes( - const DCT_ID &id) const { - const auto attributes = GetAttributes(); + const DCT_ID &id) { CLoanSetCollateralTokenImplementation collToken; CDataStructureV0 pairKey{AttributeTypes::Token, id.v, TokenKeys::FixedIntervalPriceId}; CDataStructureV0 factorKey{AttributeTypes::Token, id.v, TokenKeys::LoanCollateralFactor}; - if (attributes->CheckKey(pairKey) && attributes->CheckKey(factorKey)) { - collToken.fixedIntervalPriceId = attributes->GetValue(pairKey, CTokenCurrencyPair{}); - collToken.factor = attributes->GetValue(factorKey, CAmount{0}); + if (CheckKey(pairKey) && CheckKey(factorKey)) { + collToken.fixedIntervalPriceId = GetValue(pairKey, CTokenCurrencyPair{}); + collToken.factor = GetValue(factorKey, CAmount{0}); collToken.idToken = id; auto token = GetToken(id); @@ -1323,53 +1315,114 @@ std::optional CCustomCSView::GetCollater return {}; } -uint32_t CCustomCSView::GetVotingPeriodFromAttributes() const { - const auto attributes = GetAttributes(); +uint32_t CCustomCSView::GetVotingPeriodFromAttributes() { CDataStructureV0 votingKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::VotingPeriod}; - return attributes->GetValue(votingKey, Params().GetConsensus().props.votingPeriod); + return GetValue(votingKey, Params().GetConsensus().props.votingPeriod); } -uint32_t CCustomCSView::GetEmergencyPeriodFromAttributes(const CProposalType &type) const { - const auto attributes = GetAttributes(); +uint32_t CCustomCSView::GetEmergencyPeriodFromAttributes(const CProposalType &type) { CDataStructureV0 VOCKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::VOCEmergencyPeriod}; - return attributes->GetValue(VOCKey, Params().GetConsensus().props.emergencyPeriod); + return GetValue(VOCKey, Params().GetConsensus().props.emergencyPeriod); } -CAmount CCustomCSView::GetApprovalThresholdFromAttributes(const CProposalType &type) const { - const auto attributes = GetAttributes(); +CAmount CCustomCSView::GetApprovalThresholdFromAttributes(const CProposalType &type) { CDataStructureV0 CFPKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::CFPApprovalThreshold}; CDataStructureV0 VOCKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::VOCApprovalThreshold}; switch (type) { case CProposalType::CommunityFundProposal: - return attributes->GetValue(CFPKey, Params().GetConsensus().props.cfp.approvalThreshold) / 10000; + return GetValue(CFPKey, Params().GetConsensus().props.cfp.approvalThreshold) / 10000; case CProposalType::VoteOfConfidence: - return attributes->GetValue(VOCKey, Params().GetConsensus().props.voc.approvalThreshold) / 10000; + return GetValue(VOCKey, Params().GetConsensus().props.voc.approvalThreshold) / 10000; } return 0; } -CAmount CCustomCSView::GetQuorumFromAttributes(const CProposalType &type, bool emergency) const { - const auto attributes = GetAttributes(); - +CAmount CCustomCSView::GetQuorumFromAttributes(const CProposalType &type, bool emergency) { CDataStructureV0 quorumKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::Quorum}; CDataStructureV0 vocEmergencyQuorumKey{ AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::VOCEmergencyQuorum}; if (type == CProposalType::VoteOfConfidence && emergency) { - return attributes->GetValue(vocEmergencyQuorumKey, COIN / 10) / 10000; + return GetValue(vocEmergencyQuorumKey, COIN / 10) / 10000; } - return attributes->GetValue(quorumKey, Params().GetConsensus().props.quorum) / 10000; + return GetValue(quorumKey, Params().GetConsensus().props.quorum) / 10000; } -CAmount CCustomCSView::GetFeeBurnPctFromAttributes() const { - const auto attributes = GetAttributes(); - +CAmount CCustomCSView::GetFeeBurnPctFromAttributes() { CDataStructureV0 feeBurnPctKey{AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::FeeBurnPct}; + return GetValue(feeBurnPctKey, Params().GetConsensus().props.feeBurnPct); +} + +Res CCustomCSView::RefundFuturesContracts(const uint32_t height, const uint32_t tokenID) { + return GetAttributes().RefundFuturesContracts(*this, height, tokenID); +} + +void CCustomCSView::SetAttributesMembers(const int64_t setTime, + const std::shared_ptr &setEvmTemplate) { + GetAttributes().SetAttributesMembers(setTime, setEvmTemplate); +} + +Res CCustomCSView::ImportAttributes(const UniValue &val) { + return GetAttributes().Import(val); +} + +Res CCustomCSView::ValidateAttributes() { + return GetAttributes().Validate(*this); +} + +Res CCustomCSView::EraseAttributes(const uint32_t height, const std::vector &keys) { + return GetAttributes().Erase(*this, height, keys); +} + +Res CCustomCSView::ApplyAttributes(const int height) { + if (!attributes) { + // No attributes loaded indicates that there are no updates to be applied. + return Res::Err("No attributes in view to apply changes to"); + } + + return GetAttributes().Apply(*this, height); +} + +UniValue CCustomCSView::ExportFiltered(GovVarsFilter filter, const std::string &prefix) { + return GetAttributes().ExportFiltered(filter, prefix); +} + +ATTRIBUTES &CCustomCSView::GetAttributes() { + std::lock_guard lock(attributesMutex); + if (persistentAttributes) { + if (!attributes) { + attributes = *GetAttributesFromStore(); + } + return *attributes; + } + + // Update from store on every call. Not persistent. + discardableAttributes = *GetAttributesFromStore(); + return *discardableAttributes; +} + +bool CCustomCSView::SetAttributes() { + if (!HasAttributes() || !GetAttributes().IsChanged()) { + return false; + } + SetVariable(GetAttributes()); + return true; +} + +void CCustomCSView::ClearAttributes() { + attributes.reset(); +} + +bool CCustomCSView::HasAttributes() const { + return attributes.has_value(); +} - return attributes->GetValue(feeBurnPctKey, Params().GetConsensus().props.feeBurnPct); +bool CCustomCSView::Flush() { + SetAttributes(); + return CStorageView::Flush(); } void CalcMissingRewardTempFix(CCustomCSView &mnview, const uint32_t targetHeight, const CWallet &wallet) { diff --git a/src/dfi/masternodes.h b/src/dfi/masternodes.h index 6d2b573372..efc73ec29e 100644 --- a/src/dfi/masternodes.h +++ b/src/dfi/masternodes.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,7 @@ CAmount GetTokenCollateralAmount(); CAmount GetMnCreationFee(int height); CAmount GetTokenCreationFee(int height); CAmount GetMnCollateralAmount(int height); -CAmount GetProposalCreationFee(int height, const CCustomCSView &view, const CCreateProposalMessage &msg); +CAmount GetProposalCreationFee(int height, CCustomCSView &view, const CCreateProposalMessage &msg); // Update owner rewards for MNs missing call to CalculateOwnerRewards after voter fee distributions. // Missing call fixed in: https://github.com/DeFiCh/ain/pull/1766 @@ -525,6 +526,18 @@ class CCustomCSView : public CMasternodesView, // clang-format on private: + // Protect setting of attributes when called via thread pools + mutable std::mutex attributesMutex; + + // Updated on each use and returned when called from global view + std::optional discardableAttributes; + + // Not exposed to outside of class and friends + ATTRIBUTES &GetAttributes(); + + // Allow access to private members and methods + friend class CAccountsHistoryWriter; + Res PopulateLoansData(CVaultAssets &result, const CVaultId &vaultId, uint32_t height, @@ -540,6 +553,8 @@ class CCustomCSView : public CMasternodesView, bool requireLivePrice); protected: + std::optional attributes; + bool persistentAttributes{}; CHistoryWriters writers; public: @@ -596,13 +611,13 @@ class CCustomCSView : public CMasternodesView, bool useNextPrice, bool requireLivePrice); - [[nodiscard]] bool AreTokensLocked(const std::set &tokenIds) const override; + [[nodiscard]] bool AreTokensLocked(const std::set &tokenIds) override; [[nodiscard]] std::optional GetTokenGuessId(const std::string &str, DCT_ID &id) const override; - [[nodiscard]] std::optional GetLoanTokenByID(DCT_ID const &id) const override; - [[nodiscard]] std::optional GetLoanTokenFromAttributes( - const DCT_ID &id) const override; + [[nodiscard]] std::optional GetLoanTokenByIDFromStore(DCT_ID const &id) const override; + [[nodiscard]] std::optional GetLoanTokenByID(DCT_ID const &id) override; + [[nodiscard]] std::optional GetLoanTokenFromAttributes(const DCT_ID &id) override; [[nodiscard]] std::optional GetCollateralTokenFromAttributes( - const DCT_ID &id) const override; + const DCT_ID &id) override; void SetDbVersion(int version); @@ -615,11 +630,56 @@ class CCustomCSView : public CMasternodesView, // we construct it as it CFlushableStorageKV &GetStorage() { return static_cast(DB()); } - uint32_t GetVotingPeriodFromAttributes() const override; - uint32_t GetEmergencyPeriodFromAttributes(const CProposalType &type) const override; - CAmount GetApprovalThresholdFromAttributes(const CProposalType &type) const override; - CAmount GetQuorumFromAttributes(const CProposalType &type, bool emergency = false) const override; - CAmount GetFeeBurnPctFromAttributes() const override; + uint32_t GetVotingPeriodFromAttributes() override; + uint32_t GetEmergencyPeriodFromAttributes(const CProposalType &type) override; + CAmount GetApprovalThresholdFromAttributes(const CProposalType &type) override; + CAmount GetQuorumFromAttributes(const CProposalType &type, bool emergency = false) override; + CAmount GetFeeBurnPctFromAttributes() override; + + bool SetAttributes(); + void ClearAttributes(); + [[nodiscard]] bool HasAttributes() const; + Res ApplyAttributes(const int height); + Res ImportAttributes(const UniValue &val); + Res ValidateAttributes(); + Res EraseAttributes(const uint32_t height, const std::vector &keys); + UniValue ExportFiltered(GovVarsFilter filter, const std::string &prefix); + Res RefundFuturesContracts(const uint32_t height, const uint32_t tokenID); + void SetAttributesMembers(const int64_t setTime, const std::shared_ptr &setEvmTemplate); + + template + [[nodiscard]] T GetValue(const K &key, T value) { + return GetAttributes().GetValue(key, value); + } + + template + void SetValue(const K &key, T &&value) { + if (!persistentAttributes) { + // Do not make changes on global + return; + } + + GetAttributes().SetValue(key, value); + } + + template + bool EraseKey(const K &key) { + if (!persistentAttributes) { + // Do not make changes on global + return false; + } + + return GetAttributes().EraseKey(key); + } + + [[nodiscard]] bool CheckKey(const CAttributeType &key) { return GetAttributes().CheckKey(key); } + + template + void ForEachAttribute(const C &callback, const K &key) { + GetAttributes().ForEach(callback, key); + } + + bool Flush() override; struct DbVersion { static constexpr uint8_t prefix() { return 'D'; } diff --git a/src/dfi/mn_checks.cpp b/src/dfi/mn_checks.cpp index d416f4170f..1a9db4a362 100644 --- a/src/dfi/mn_checks.cpp +++ b/src/dfi/mn_checks.cpp @@ -528,14 +528,12 @@ Res ApplyCustomTx(BlockContext &blockCtx, TransactionContext &txCtx) { } const auto txType = txCtx.GetTxType(); - auto attributes = mnview.GetAttributes(); - if ((txType == CustomTxType::EvmTx || txType == CustomTxType::TransferDomain) && !isEvmEnabledForBlock) { return Res::ErrCode(CustomTxErrCodes::Fatal, "EVM is not enabled on this block"); } // Check OP_RETURN sizes - const auto opReturnLimits = OpReturnLimits::From(height, consensus, *attributes); + const auto opReturnLimits = OpReturnLimits::From(height, consensus, mnview); if (opReturnLimits.shouldEnforce) { if (r = opReturnLimits.Validate(tx, txType); !r) { return r; @@ -577,9 +575,7 @@ Res ApplyCustomTx(BlockContext &blockCtx, TransactionContext &txCtx) { CDataStructureV0 burnPctKey{ AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::FeeBurnPct}; - auto attributes = view.GetAttributes(); - - auto burnFee = MultiplyAmounts(tx.vout[0].nValue, attributes->GetValue(burnPctKey, COIN / 2)); + auto burnFee = MultiplyAmounts(tx.vout[0].nValue, view.GetValue(burnPctKey, COIN / 2)); mnview.GetHistoryWriters().AddFeeBurn(tx.vout[0].scriptPubKey, burnFee); } @@ -611,6 +607,12 @@ Res ApplyCustomTx(BlockContext &blockCtx, TransactionContext &txCtx) { return res; } + // Update Gov var before creating undo to make sure changes are present + if (view.SetAttributes()) { + // Clear attributes in parent so next use loads updated values + mnview.ClearAttributes(); + } + // construct undo auto &flushable = view.GetStorage(); auto undo = CUndo::Construct(mnview.GetStorage(), flushable.GetRaw()); @@ -620,6 +622,7 @@ Res ApplyCustomTx(BlockContext &blockCtx, TransactionContext &txCtx) { if (!undo.before.empty()) { mnview.SetUndo(UndoKey{height, tx.GetHash()}, undo); } + return res; } @@ -963,10 +966,8 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, mnview.Flush(); } - auto attributes = view.GetAttributes(); - CDataStructureV0 dexKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DexTokens}; - auto dexBalances = attributes->GetValue(dexKey, CDexBalances{}); + auto dexBalances = view.GetValue(dexKey, CDexBalances{}); // Set amount to be swapped in pool CTokenAmount swapAmountResult{obj.idTokenFrom, obj.amountFrom}; @@ -1008,8 +1009,8 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, CDataStructureV0 dirAKey{AttributeTypes::Poolpairs, currentID.v, PoolKeys::TokenAFeeDir}; CDataStructureV0 dirBKey{AttributeTypes::Poolpairs, currentID.v, PoolKeys::TokenBFeeDir}; - const auto dirA = attributes->GetValue(dirAKey, CFeeDir{FeeDirValues::Both}); - const auto dirB = attributes->GetValue(dirBKey, CFeeDir{FeeDirValues::Both}); + const auto dirA = view.GetValue(dirAKey, CFeeDir{FeeDirValues::Both}); + const auto dirB = view.GetValue(dirBKey, CFeeDir{FeeDirValues::Both}); const auto asymmetricFee = std::make_pair(dirA, dirB); auto dexfeeInPct = view.GetDexFeeInPct(currentID, swapAmount.nTokenId); @@ -1139,8 +1140,7 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView &view, } if (!testOnly && view.GetDexStatsEnabled().value_or(false)) { - attributes->SetValue(dexKey, std::move(dexBalances)); - view.SetVariable(*attributes); + view.SetValue(dexKey, std::move(dexBalances)); } // Assign to result for loop testing best pool swap result result = swapAmountResult.nValue; @@ -1177,12 +1177,11 @@ Res SwapToDFIorDUSD(CCustomCSView &mnview, return Res::Err("Cannot find token DUSD"); } - const auto attributes = mnview.GetAttributes(); CDataStructureV0 directBurnKey{AttributeTypes::Param, ParamIDs::DFIP2206A, DFIPKeys::DUSDInterestBurn}; // Direct swap from DUSD to DFI as defined in the CPoolSwapMessage. if (tokenId == dUsdToken->first) { - if (to == consensus.burnAddress && !forceLoanSwap && attributes->GetValue(directBurnKey, false)) { + if (to == consensus.burnAddress && !forceLoanSwap && mnview.GetValue(directBurnKey, false)) { // direct burn dUSD CTokenAmount dUSD{dUsdToken->first, amount}; @@ -1207,7 +1206,7 @@ Res SwapToDFIorDUSD(CCustomCSView &mnview, return Res::Err("Cannot find pool pair %s-DUSD!", token->symbol); } - if (to == consensus.burnAddress && !forceLoanSwap && attributes->GetValue(directBurnKey, false)) { + if (to == consensus.burnAddress && !forceLoanSwap && mnview.GetValue(directBurnKey, false)) { obj.idTokenTo = dUsdToken->first; // swap tokenID -> dUSD and burn dUSD @@ -1354,28 +1353,26 @@ struct OpReturnLimitsKeys { CDataStructureV0 evmKey{AttributeTypes::Rules, RulesIDs::TXRules, RulesKeys::EVMOPReturn}; }; -OpReturnLimits OpReturnLimits::From(const uint64_t height, - const Consensus::Params &consensus, - const ATTRIBUTES &attributes) { +OpReturnLimits OpReturnLimits::From(const uint64_t height, const Consensus::Params &consensus, CCustomCSView &mnview) { OpReturnLimitsKeys k{}; auto item = OpReturnLimits::Default(); item.shouldEnforce = height >= static_cast(consensus.DF22MetachainHeight); - item.coreSizeBytes = attributes.GetValue(k.coreKey, item.coreSizeBytes); - item.dvmSizeBytes = attributes.GetValue(k.dvmKey, item.dvmSizeBytes); - item.evmSizeBytes = attributes.GetValue(k.evmKey, item.evmSizeBytes); + item.coreSizeBytes = mnview.GetValue(k.coreKey, item.coreSizeBytes); + item.dvmSizeBytes = mnview.GetValue(k.dvmKey, item.dvmSizeBytes); + item.evmSizeBytes = mnview.GetValue(k.evmKey, item.evmSizeBytes); return item; } -void OpReturnLimits::SetToAttributesIfNotExists(ATTRIBUTES &attrs) const { +void OpReturnLimits::SetToAttributesIfNotExists(CCustomCSView &mnview) const { OpReturnLimitsKeys k{}; - if (!attrs.CheckKey(k.coreKey)) { - attrs.SetValue(k.coreKey, coreSizeBytes); + if (!mnview.CheckKey(k.coreKey)) { + mnview.SetValue(k.coreKey, coreSizeBytes); } - if (!attrs.CheckKey(k.dvmKey)) { - attrs.SetValue(k.dvmKey, dvmSizeBytes); + if (!mnview.CheckKey(k.dvmKey)) { + mnview.SetValue(k.dvmKey, dvmSizeBytes); } - if (!attrs.CheckKey(k.evmKey)) { - attrs.SetValue(k.evmKey, evmSizeBytes); + if (!mnview.CheckKey(k.evmKey)) { + mnview.SetValue(k.evmKey, evmSizeBytes); } } @@ -1447,62 +1444,61 @@ struct TransferDomainConfigKeys { CDataStructureV0 evm_to_dvm_dat_enabled{AttributeTypes::Transfer, TransferIDs::EVMToDVM, TransferKeys::DATEnabled}; }; -TransferDomainConfig TransferDomainConfig::From(const CCustomCSView &mnview) { +TransferDomainConfig TransferDomainConfig::From(CCustomCSView &mnview) { TransferDomainConfigKeys k{}; - const auto attributes = mnview.GetAttributes(); auto r = TransferDomainConfig::Default(); - r.dvmToEvmEnabled = attributes->GetValue(k.dvm_to_evm_enabled, r.dvmToEvmEnabled); - r.dvmToEvmSrcAddresses = attributes->GetValue(k.dvm_to_evm_src_formats, r.dvmToEvmSrcAddresses); - r.dvmToEvmDestAddresses = attributes->GetValue(k.dvm_to_evm_dest_formats, r.dvmToEvmDestAddresses); - r.dvmToEvmNativeTokenEnabled = attributes->GetValue(k.dvm_to_evm_native_enabled, r.dvmToEvmNativeTokenEnabled); - r.dvmToEvmDatEnabled = attributes->GetValue(k.dvm_to_evm_dat_enabled, r.dvmToEvmDatEnabled); + r.dvmToEvmEnabled = mnview.GetValue(k.dvm_to_evm_enabled, r.dvmToEvmEnabled); + r.dvmToEvmSrcAddresses = mnview.GetValue(k.dvm_to_evm_src_formats, r.dvmToEvmSrcAddresses); + r.dvmToEvmDestAddresses = mnview.GetValue(k.dvm_to_evm_dest_formats, r.dvmToEvmDestAddresses); + r.dvmToEvmNativeTokenEnabled = mnview.GetValue(k.dvm_to_evm_native_enabled, r.dvmToEvmNativeTokenEnabled); + r.dvmToEvmDatEnabled = mnview.GetValue(k.dvm_to_evm_dat_enabled, r.dvmToEvmDatEnabled); - r.evmToDvmEnabled = attributes->GetValue(k.evm_to_dvm_enabled, r.evmToDvmEnabled); - r.evmToDvmSrcAddresses = attributes->GetValue(k.evm_to_dvm_src_formats, r.evmToDvmSrcAddresses); - r.evmToDvmDestAddresses = attributes->GetValue(k.evm_to_dvm_dest_formats, r.evmToDvmDestAddresses); - r.evmToDvmAuthFormats = attributes->GetValue(k.evm_to_dvm_auth_formats, r.evmToDvmAuthFormats); - r.evmToDvmNativeTokenEnabled = attributes->GetValue(k.evm_to_dvm_native_enabled, r.evmToDvmNativeTokenEnabled); - r.evmToDvmDatEnabled = attributes->GetValue(k.evm_to_dvm_dat_enabled, r.evmToDvmDatEnabled); + r.evmToDvmEnabled = mnview.GetValue(k.evm_to_dvm_enabled, r.evmToDvmEnabled); + r.evmToDvmSrcAddresses = mnview.GetValue(k.evm_to_dvm_src_formats, r.evmToDvmSrcAddresses); + r.evmToDvmDestAddresses = mnview.GetValue(k.evm_to_dvm_dest_formats, r.evmToDvmDestAddresses); + r.evmToDvmAuthFormats = mnview.GetValue(k.evm_to_dvm_auth_formats, r.evmToDvmAuthFormats); + r.evmToDvmNativeTokenEnabled = mnview.GetValue(k.evm_to_dvm_native_enabled, r.evmToDvmNativeTokenEnabled); + r.evmToDvmDatEnabled = mnview.GetValue(k.evm_to_dvm_dat_enabled, r.evmToDvmDatEnabled); return r; } -void TransferDomainConfig::SetToAttributesIfNotExists(ATTRIBUTES &attrs) const { +void TransferDomainConfig::SetToAttributesIfNotExists(CCustomCSView &mnview) const { TransferDomainConfigKeys k{}; - if (!attrs.CheckKey(k.dvm_to_evm_enabled)) { - attrs.SetValue(k.dvm_to_evm_enabled, dvmToEvmEnabled); + if (!mnview.CheckKey(k.dvm_to_evm_enabled)) { + mnview.SetValue(k.dvm_to_evm_enabled, dvmToEvmEnabled); } - if (!attrs.CheckKey(k.dvm_to_evm_src_formats)) { - attrs.SetValue(k.dvm_to_evm_src_formats, dvmToEvmSrcAddresses); + if (!mnview.CheckKey(k.dvm_to_evm_src_formats)) { + mnview.SetValue(k.dvm_to_evm_src_formats, dvmToEvmSrcAddresses); } - if (!attrs.CheckKey(k.dvm_to_evm_dest_formats)) { - attrs.SetValue(k.dvm_to_evm_dest_formats, dvmToEvmDestAddresses); + if (!mnview.CheckKey(k.dvm_to_evm_dest_formats)) { + mnview.SetValue(k.dvm_to_evm_dest_formats, dvmToEvmDestAddresses); } - if (!attrs.CheckKey(k.dvm_to_evm_native_enabled)) { - attrs.SetValue(k.dvm_to_evm_native_enabled, dvmToEvmNativeTokenEnabled); + if (!mnview.CheckKey(k.dvm_to_evm_native_enabled)) { + mnview.SetValue(k.dvm_to_evm_native_enabled, dvmToEvmNativeTokenEnabled); } - if (!attrs.CheckKey(k.dvm_to_evm_dat_enabled)) { - attrs.SetValue(k.dvm_to_evm_dat_enabled, dvmToEvmDatEnabled); + if (!mnview.CheckKey(k.dvm_to_evm_dat_enabled)) { + mnview.SetValue(k.dvm_to_evm_dat_enabled, dvmToEvmDatEnabled); } - if (!attrs.CheckKey(k.evm_to_dvm_enabled)) { - attrs.SetValue(k.evm_to_dvm_enabled, evmToDvmEnabled); + if (!mnview.CheckKey(k.evm_to_dvm_enabled)) { + mnview.SetValue(k.evm_to_dvm_enabled, evmToDvmEnabled); } - if (!attrs.CheckKey(k.evm_to_dvm_src_formats)) { - attrs.SetValue(k.evm_to_dvm_src_formats, evmToDvmSrcAddresses); + if (!mnview.CheckKey(k.evm_to_dvm_src_formats)) { + mnview.SetValue(k.evm_to_dvm_src_formats, evmToDvmSrcAddresses); } - if (!attrs.CheckKey(k.evm_to_dvm_dest_formats)) { - attrs.SetValue(k.evm_to_dvm_dest_formats, evmToDvmDestAddresses); + if (!mnview.CheckKey(k.evm_to_dvm_dest_formats)) { + mnview.SetValue(k.evm_to_dvm_dest_formats, evmToDvmDestAddresses); } - if (!attrs.CheckKey(k.evm_to_dvm_auth_formats)) { - attrs.SetValue(k.evm_to_dvm_auth_formats, evmToDvmAuthFormats); + if (!mnview.CheckKey(k.evm_to_dvm_auth_formats)) { + mnview.SetValue(k.evm_to_dvm_auth_formats, evmToDvmAuthFormats); } - if (!attrs.CheckKey(k.evm_to_dvm_native_enabled)) { - attrs.SetValue(k.evm_to_dvm_native_enabled, evmToDvmNativeTokenEnabled); + if (!mnview.CheckKey(k.evm_to_dvm_native_enabled)) { + mnview.SetValue(k.evm_to_dvm_native_enabled, evmToDvmNativeTokenEnabled); } - if (!attrs.CheckKey(k.evm_to_dvm_dat_enabled)) { - attrs.SetValue(k.evm_to_dvm_dat_enabled, evmToDvmDatEnabled); + if (!mnview.CheckKey(k.evm_to_dvm_dat_enabled)) { + mnview.SetValue(k.evm_to_dvm_dat_enabled, evmToDvmDatEnabled); } } diff --git a/src/dfi/mn_checks.h b/src/dfi/mn_checks.h index 4104c59ccc..37aed8bf6c 100644 --- a/src/dfi/mn_checks.h +++ b/src/dfi/mn_checks.h @@ -69,9 +69,9 @@ struct OpReturnLimits { uint64_t evmSizeBytes{}; static OpReturnLimits Default(); - static OpReturnLimits From(const uint64_t height, const Consensus::Params &consensus, const ATTRIBUTES &attributes); + static OpReturnLimits From(const uint64_t height, const Consensus::Params &consensus, CCustomCSView &mnview); - void SetToAttributesIfNotExists(ATTRIBUTES &attrs) const; + void SetToAttributesIfNotExists(CCustomCSView &mnviews) const; Res Validate(const CTransaction &tx, const CustomTxType txType) const; uint64_t MaxSize() { return std::max({coreSizeBytes, dvmSizeBytes, evmSizeBytes}); } }; @@ -92,9 +92,9 @@ struct TransferDomainConfig { std::set evmToDvmDisallowedTokens; static TransferDomainConfig Default(); - static TransferDomainConfig From(const CCustomCSView &mnview); + static TransferDomainConfig From(CCustomCSView &mnview); - void SetToAttributesIfNotExists(ATTRIBUTES &attrs) const; + void SetToAttributesIfNotExists(CCustomCSView &mnview) const; }; struct CCustomTxMessageNone {}; diff --git a/src/dfi/mn_rpc.cpp b/src/dfi/mn_rpc.cpp index 932bf0df9d..74519e8264 100644 --- a/src/dfi/mn_rpc.cpp +++ b/src/dfi/mn_rpc.cpp @@ -217,6 +217,7 @@ CTransactionRef send(CTransactionRef tx, CTransactionRef optAuthTx) { if (TransactionError::OK != err) { throw JSONRPCTransactionError(err, err_string); } + return tx; } @@ -293,10 +294,9 @@ static std::vector GetInputs(const UniValue &inputs) { std::optional AmIFounder(CWallet *const pwallet) { auto members = Params().GetConsensus().foundationMembers; - const auto attributes = pcustomcsview->GetAttributes(); - if (attributes->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, - false)) { - if (const auto databaseMembers = attributes->GetValue( + if (pcustomcsview->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, + false)) { + if (const auto databaseMembers = pcustomcsview->GetValue( CDataStructureV0{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}, std::set{}); !databaseMembers.empty()) { members = databaseMembers; @@ -383,10 +383,9 @@ static CTransactionRef CreateAuthTx(CWalletCoinsUnlocker &pwallet, static std::optional GetAnyFoundationAuthInput(CWalletCoinsUnlocker &pwallet) { auto members = Params().GetConsensus().foundationMembers; - const auto attributes = pcustomcsview->GetAttributes(); - if (attributes->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, - false)) { - if (const auto databaseMembers = attributes->GetValue( + if (pcustomcsview->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, + false)) { + if (const auto databaseMembers = pcustomcsview->GetValue( CDataStructureV0{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}, std::set{}); !databaseMembers.empty()) { members = databaseMembers; @@ -513,23 +512,22 @@ CWalletCoinsUnlocker GetWallet(const JSONRPCRequest &request) { std::optional GetFuturesBlock(const uint32_t typeId) { LOCK(cs_main); - const auto attributes = pcustomcsview->GetAttributes(); - CDataStructureV0 activeKey{AttributeTypes::Param, typeId, DFIPKeys::Active}; - const auto active = attributes->GetValue(activeKey, false); + const auto active = pcustomcsview->GetValue(activeKey, false); if (!active) { return {}; } CDataStructureV0 blockKey{AttributeTypes::Param, typeId, DFIPKeys::BlockPeriod}; CDataStructureV0 rewardKey{AttributeTypes::Param, typeId, DFIPKeys::RewardPct}; - if (!attributes->CheckKey(blockKey) || !attributes->CheckKey(rewardKey)) { + if (!pcustomcsview->CheckKey(blockKey) || !pcustomcsview->CheckKey(rewardKey)) { return {}; } CDataStructureV0 startKey{AttributeTypes::Param, typeId, DFIPKeys::StartBlock}; - return FutureSwapHeightInfo{attributes->GetValue(startKey, CAmount{}), attributes->GetValue(blockKey, CAmount{})}; + return FutureSwapHeightInfo{pcustomcsview->GetValue(startKey, CAmount{}), + pcustomcsview->GetValue(blockKey, CAmount{})}; } std::string CTransferDomainToString(const VMDomain domain) { @@ -887,14 +885,14 @@ UniValue getgov(const JSONRPCRequest &request) { throw JSONRPCError(RPC_INVALID_REQUEST, "Variable '" + name + "' not registered"); } -static void AddDefaultVars(uint64_t height, CChainParams params, ATTRIBUTES &attrs) { +static void AddDefaultVars(uint64_t height, CChainParams params, CCustomCSView &mnview) { // OpReturnLimits - const auto opReturnLimits = OpReturnLimits::From(height, params.GetConsensus(), attrs); - opReturnLimits.SetToAttributesIfNotExists(attrs); + const auto opReturnLimits = OpReturnLimits::From(height, params.GetConsensus(), mnview); + opReturnLimits.SetToAttributesIfNotExists(mnview); // TransferDomainConfig - const auto tdConfig = TransferDomainConfig::From(*pcustomcsview); - tdConfig.SetToAttributesIfNotExists(attrs); + const auto tdConfig = TransferDomainConfig::From(mnview); + tdConfig.SetToAttributesIfNotExists(mnview); } UniValue listgovs(const JSONRPCRequest &request) { @@ -974,18 +972,15 @@ UniValue listgovs(const JSONRPCRequest &request) { UniValue ret(UniValue::VOBJ); UniValue val; bool skip = false; - auto name = var->GetName(); - if (name == "ATTRIBUTES") { + if (var->GetName() == "ATTRIBUTES") { if (mode == GovVarsFilter::NoAttributes) { skip = true; } else { + auto view(*pcustomcsview); if (height >= Params().GetConsensus().DF22MetachainHeight) { - if (auto attributes = dynamic_cast(var.get()); attributes) { - AddDefaultVars(height, Params(), *attributes); - } + AddDefaultVars(height, Params(), view); } - auto a = std::dynamic_pointer_cast(var); - val = a->ExportFiltered(mode, prefix); + val = view.ExportFiltered(mode, prefix); } } else { if (mode == GovVarsFilter::LiveAttributes || mode == GovVarsFilter::PrefixedAttributes || diff --git a/src/dfi/oracles.h b/src/dfi/oracles.h index 237ebb1cb5..b6bb78637c 100644 --- a/src/dfi/oracles.h +++ b/src/dfi/oracles.h @@ -156,10 +156,10 @@ class COracleView : public virtual CStorageView { Res EraseIntervalBlock(); uint32_t GetIntervalBlock() const; - [[nodiscard]] virtual bool AreTokensLocked(const std::set &tokenIds) const = 0; + [[nodiscard]] virtual bool AreTokensLocked(const std::set &tokenIds) = 0; [[nodiscard]] virtual std::optional GetTokenGuessId(const std::string &str, DCT_ID &id) const = 0; - [[nodiscard]] virtual std::optional GetLoanTokenByID(DCT_ID const &id) const = 0; + [[nodiscard]] virtual std::optional GetLoanTokenByID(DCT_ID const &id) = 0; struct ByName { static constexpr uint8_t prefix() { return 'O'; } diff --git a/src/dfi/proposals.h b/src/dfi/proposals.h index 9a642e24d6..4191ee88e5 100644 --- a/src/dfi/proposals.h +++ b/src/dfi/proposals.h @@ -157,11 +157,11 @@ class CProposalView : public virtual CStorageView { void ForEachCycleProposal(std::function callback, uint32_t height); - virtual uint32_t GetVotingPeriodFromAttributes() const = 0; - virtual uint32_t GetEmergencyPeriodFromAttributes(const CProposalType &type) const = 0; - virtual CAmount GetApprovalThresholdFromAttributes(const CProposalType &type) const = 0; - virtual CAmount GetQuorumFromAttributes(const CProposalType &type, bool emergency = false) const = 0; - virtual CAmount GetFeeBurnPctFromAttributes() const = 0; + virtual uint32_t GetVotingPeriodFromAttributes() = 0; + virtual uint32_t GetEmergencyPeriodFromAttributes(const CProposalType &type) = 0; + virtual CAmount GetApprovalThresholdFromAttributes(const CProposalType &type) = 0; + virtual CAmount GetQuorumFromAttributes(const CProposalType &type, bool emergency = false) = 0; + virtual CAmount GetFeeBurnPctFromAttributes() = 0; struct ByType { static constexpr uint8_t prefix() { return 0x2B; } diff --git a/src/dfi/rpc_accounts.cpp b/src/dfi/rpc_accounts.cpp index 4550f70814..1dbb4ceff5 100644 --- a/src/dfi/rpc_accounts.cpp +++ b/src/dfi/rpc_accounts.cpp @@ -2477,11 +2477,9 @@ UniValue getburninfo(const JSONRPCRequest &request) { auto hash = ::ChainActive().Tip()->GetBlockHash(); auto fortCanningHeight = Params().GetConsensus().DF11FortCanningHeight; auto burnAddress = Params().GetConsensus().burnAddress; - auto view = *pcustomcsview; - const auto attributes = view.GetAttributes(); CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::PaybackDFITokens}; - auto tokenBalances = attributes->GetValue(liveKey, CBalances{}); + auto tokenBalances = pcustomcsview->GetValue(liveKey, CBalances{}); for (const auto &balance : tokenBalances.balances) { if (balance.first == DCT_ID{0}) { dfiPaybackFee = balance.second; @@ -2490,20 +2488,20 @@ UniValue getburninfo(const JSONRPCRequest &request) { } } liveKey = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::PaybackTokens}; - auto paybacks = attributes->GetValue(liveKey, CTokenPayback{}); + auto paybacks = pcustomcsview->GetValue(liveKey, CTokenPayback{}); paybackfees = std::move(paybacks.tokensFee); paybacktokens = std::move(paybacks.tokensPayback); liveKey = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2203Burned}; - dfi2203Tokens = attributes->GetValue(liveKey, CBalances{}); + dfi2203Tokens = pcustomcsview->GetValue(liveKey, CBalances{}); liveKey = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2206FBurned}; - dfiToDUSDTokens = attributes->GetValue(liveKey, CBalances{}); + dfiToDUSDTokens = pcustomcsview->GetValue(liveKey, CBalances{}); for (const auto &kv : Params().GetConsensus().blockTokenRewards) { if (kv.first == CommunityAccountType::Unallocated || kv.first == CommunityAccountType::IncentiveFunding || (height >= fortCanningHeight && kv.first == CommunityAccountType::Loan)) { - burnt += view.GetCommunityBalance(kv.first); + burnt += pcustomcsview->GetCommunityBalance(kv.first); } } diff --git a/src/dfi/rpc_loan.cpp b/src/dfi/rpc_loan.cpp index 433b58bcf3..1fd5c08717 100644 --- a/src/dfi/rpc_loan.cpp +++ b/src/dfi/rpc_loan.cpp @@ -281,9 +281,7 @@ UniValue listcollateraltokens(const JSONRPCRequest &request) { return ret; } - auto attributes = view.GetAttributes(); - - attributes->ForEach( + view.ForEachAttribute( [&](const CDataStructureV0 &attr, const CAttributeValue &) { if (attr.type != AttributeTypes::Token) { return false; @@ -618,9 +616,7 @@ UniValue listloantokens(const JSONRPCRequest &request) { return ret; } - auto attributes = view.GetAttributes(); - - attributes->ForEach( + view.ForEachAttribute( [&](const CDataStructureV0 &attr, const CAttributeValue &) { if (attr.type != AttributeTypes::Token) { return false; @@ -1541,9 +1537,7 @@ UniValue getloaninfo(const JSONRPCRequest &request) { }); // Now, let's go over attributes. If it's on attributes, the above calls would have done nothing. - auto attributes = view.GetAttributes(); - - attributes->ForEach( + view.ForEachAttribute( [&](const CDataStructureV0 &attr, const CAttributeValue &) { if (attr.type != AttributeTypes::Token) { return false; diff --git a/src/dfi/rpc_poolpair.cpp b/src/dfi/rpc_poolpair.cpp index c1dd0858e4..da15c11d34 100644 --- a/src/dfi/rpc_poolpair.cpp +++ b/src/dfi/rpc_poolpair.cpp @@ -3,11 +3,7 @@ #include #include -UniValue poolToJSON(const CCustomCSView &view, - DCT_ID const &id, - const CPoolPair &pool, - const CToken &token, - bool verbose) { +UniValue poolToJSON(CCustomCSView &view, DCT_ID const &id, const CPoolPair &pool, const CToken &token, bool verbose) { UniValue poolObj(UniValue::VOBJ); poolObj.pushKV("symbol", token.symbol); poolObj.pushKV("name", token.name); @@ -16,12 +12,10 @@ UniValue poolToJSON(const CCustomCSView &view, poolObj.pushKV("idTokenB", pool.idTokenB.ToString()); if (verbose) { - const auto attributes = view.GetAttributes(); - CDataStructureV0 dirAKey{AttributeTypes::Poolpairs, id.v, PoolKeys::TokenAFeeDir}; CDataStructureV0 dirBKey{AttributeTypes::Poolpairs, id.v, PoolKeys::TokenBFeeDir}; - const auto dirA = attributes->GetValue(dirAKey, CFeeDir{FeeDirValues::Both}); - const auto dirB = attributes->GetValue(dirBKey, CFeeDir{FeeDirValues::Both}); + const auto dirA = view.GetValue(dirAKey, CFeeDir{FeeDirValues::Both}); + const auto dirB = view.GetValue(dirBKey, CFeeDir{FeeDirValues::Both}); if (const auto dexFee = view.GetDexFeeInPct(id, pool.idTokenA)) { poolObj.pushKV("dexFeePctTokenA", ValueFromAmount(dexFee)); @@ -1434,10 +1428,8 @@ UniValue listloantokenliquidity(const JSONRPCRequest &request) { UniValue ret(UniValue::VARR); const auto height = ::ChainActive().Height(); - const auto attributes = pcustomcsview->GetAttributes(); - CDataStructureV0 averageKey{AttributeTypes::Param, ParamIDs::DFIP2211F, DFIPKeys::AverageLiquidityPercentage}; - const auto averageLiquidityPercentage = attributes->GetValue(averageKey, DEFAULT_AVERAGE_LIQUIDITY_PERCENTAGE); + const auto averageLiquidityPercentage = pcustomcsview->GetValue(averageKey, DEFAULT_AVERAGE_LIQUIDITY_PERCENTAGE); const auto dusdToken = pcustomcsview->GetToken("DUSD"); if (!dusdToken) { diff --git a/src/dfi/rpc_tokens.cpp b/src/dfi/rpc_tokens.cpp index c51dd27f14..85818b6c30 100644 --- a/src/dfi/rpc_tokens.cpp +++ b/src/dfi/rpc_tokens.cpp @@ -325,11 +325,10 @@ UniValue updatetoken(const JSONRPCRequest &request) { rawTx.vin = GetAuthInputsSmart( pwallet, rawTx.nVersion, auths, true, optAuthTx, txInputs, request.metadata.coinSelectOpts); } else { // post-bayfront auth - const auto attributes = pcustomcsview->GetAttributes(); std::set databaseMembers; - if (attributes->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, - false)) { - databaseMembers = attributes->GetValue( + if (pcustomcsview->GetValue(CDataStructureV0{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovFoundation}, + false)) { + databaseMembers = pcustomcsview->GetValue( CDataStructureV0{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}, std::set{}); } bool isFoundersToken = !databaseMembers.empty() ? databaseMembers.find(owner) != databaseMembers.end() @@ -395,10 +394,9 @@ UniValue tokenToJSON(CCustomCSView &view, DCT_ID const &id, const CTokenImplemen tokenObj.pushKV("finalized", token.IsFinalized()); auto loanToken{token.IsLoanToken()}; if (!loanToken) { - auto attributes = view.GetAttributes(); CDataStructureV0 mintingKey{AttributeTypes::Token, id.v, TokenKeys::LoanMintingEnabled}; CDataStructureV0 interestKey{AttributeTypes::Token, id.v, TokenKeys::LoanMintingInterest}; - loanToken = attributes->GetValue(mintingKey, false) && attributes->CheckKey(interestKey); + loanToken = view.GetValue(mintingKey, false) && view.CheckKey(interestKey); } tokenObj.pushKV("isLoanToken", loanToken); diff --git a/src/dfi/rpc_vault.cpp b/src/dfi/rpc_vault.cpp index 1348059b9f..bbf3e6b943 100644 --- a/src/dfi/rpc_vault.cpp +++ b/src/dfi/rpc_vault.cpp @@ -350,9 +350,8 @@ UniValue createvault(const JSONRPCRequest &request) { { LOCK(cs_main); targetHeight = ::ChainActive().Height() + 1; - const auto attributes = pcustomcsview->GetAttributes(); const CDataStructureV0 creationFeeKey{AttributeTypes::Vaults, VaultIDs::Parameters, VaultKeys::CreationFee}; - vaultCreationFee = attributes->GetValue(creationFeeKey, Params().GetConsensus().vaultCreationFee); + vaultCreationFee = pcustomcsview->GetValue(creationFeeKey, Params().GetConsensus().vaultCreationFee); } CDataStream metadata(DfTxMarker, SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/dfi/validation.cpp b/src/dfi/validation.cpp index 054bdf69f1..9d4c67f74a 100644 --- a/src/dfi/validation.cpp +++ b/src/dfi/validation.cpp @@ -999,21 +999,19 @@ static void LiquidityForFuturesLimit(const CBlockIndex *pindex, return; } - auto attributes = cache.GetAttributes(); - CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2211F, DFIPKeys::Active}; - if (!attributes->GetValue(activeKey, false)) { + if (!cache.GetValue(activeKey, false)) { return; } CDataStructureV0 samplingKey{AttributeTypes::Param, ParamIDs::DFIP2211F, DFIPKeys::LiquidityCalcSamplingPeriod}; - const auto samplingPeriod = attributes->GetValue(samplingKey, DEFAULT_LIQUIDITY_CALC_SAMPLING_PERIOD); + const auto samplingPeriod = cache.GetValue(samplingKey, DEFAULT_LIQUIDITY_CALC_SAMPLING_PERIOD); if ((pindex->nHeight - consensus.DF23Height) % samplingPeriod != 0) { return; } CDataStructureV0 blockKey{AttributeTypes::Param, ParamIDs::DFIP2211F, DFIPKeys::BlockPeriod}; - const auto blockPeriod = attributes->GetValue(blockKey, DEFAULT_FS_LIQUIDITY_BLOCK_PERIOD); + const auto blockPeriod = cache.GetValue(blockKey, DEFAULT_FS_LIQUIDITY_BLOCK_PERIOD); const auto dusdToken = cache.GetToken("DUSD"); if (!dusdToken) { @@ -1105,13 +1103,13 @@ static void LiquidityForFuturesLimit(const CBlockIndex *pindex, } } -static auto GetLoanTokensForFutures(CCustomCSView &cache, ATTRIBUTES attributes) { +static auto GetLoanTokensForFutures(CCustomCSView &cache) { LoanTokenCollection loanTokens; CDataStructureV0 tokenKey{AttributeTypes::Token, 0, TokenKeys::DFIP2203Enabled}; cache.ForEachLoanToken([&](const DCT_ID &id, const CLoanView::CLoanSetLoanTokenImpl &loanToken) { tokenKey.typeId = id.v; - const auto enabled = attributes.GetValue(tokenKey, true); + const auto enabled = cache.GetValue(tokenKey, true); if (!enabled) { return true; } @@ -1122,14 +1120,14 @@ static auto GetLoanTokensForFutures(CCustomCSView &cache, ATTRIBUTES attributes) }); if (loanTokens.empty()) { - attributes.ForEach( + cache.ForEachAttribute( [&](const CDataStructureV0 &attr, const CAttributeValue &) { if (attr.type != AttributeTypes::Token) { return false; } tokenKey.typeId = attr.typeId; - const auto enabled = attributes.GetValue(tokenKey, true); + const auto enabled = cache.GetValue(tokenKey, true); if (!enabled) { return true; } @@ -1154,24 +1152,21 @@ static void ProcessFutures(const CBlockIndex *pindex, CCustomCSView &cache, cons return; } - auto attributes = cache.GetAttributes(); - CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::Active}; CDataStructureV0 blockKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::BlockPeriod}; CDataStructureV0 rewardKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::RewardPct}; - if (!attributes->GetValue(activeKey, false) || !attributes->CheckKey(blockKey) || - !attributes->CheckKey(rewardKey)) { + if (!cache.GetValue(activeKey, false) || !cache.CheckKey(blockKey) || !cache.CheckKey(rewardKey)) { return; } CDataStructureV0 startKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::StartBlock}; - const auto startBlock = attributes->GetValue(startKey, CAmount{}); + const auto startBlock = cache.GetValue(startKey, CAmount{}); if (pindex->nHeight < startBlock) { return; } - const auto loanTokens = GetLoanTokensForFutures(cache, *attributes); - const auto blockPeriod = attributes->GetValue(blockKey, CAmount{}); + const auto loanTokens = GetLoanTokensForFutures(cache); + const auto blockPeriod = cache.GetValue(blockKey, CAmount{}); const auto futureSwapBlock = (pindex->nHeight - startBlock) % blockPeriod == 0; LiquidityForFuturesLimit(pindex, cache, consensus, loanTokens, futureSwapBlock); @@ -1183,7 +1178,7 @@ static void ProcessFutures(const CBlockIndex *pindex, CCustomCSView &cache, cons auto time = GetTimeMillis(); LogPrintf("Future swap settlement in progress.. (height: %d)\n", pindex->nHeight); - const auto rewardPct = attributes->GetValue(rewardKey, CAmount{}); + const auto rewardPct = cache.GetValue(rewardKey, CAmount{}); const auto discount{COIN - rewardPct}; const auto premium{COIN + rewardPct}; @@ -1205,8 +1200,8 @@ static void ProcessFutures(const CBlockIndex *pindex, CCustomCSView &cache, cons CDataStructureV0 burnKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2203Burned}; CDataStructureV0 mintedKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2203Minted}; - auto burned = attributes->GetValue(burnKey, CBalances{}); - auto minted = attributes->GetValue(mintedKey, CBalances{}); + auto burned = cache.GetValue(burnKey, CBalances{}); + auto minted = cache.GetValue(mintedKey, CBalances{}); std::map unpaidContracts; std::set deletionPending; @@ -1285,7 +1280,7 @@ static void ProcessFutures(const CBlockIndex *pindex, CCustomCSView &cache, cons CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2203Current}; - auto balances = attributes->GetValue(liveKey, CBalances{}); + auto balances = cache.GetValue(liveKey, CBalances{}); auto failedContractsCounter = unpaidContracts.size(); @@ -1316,11 +1311,11 @@ static void ProcessFutures(const CBlockIndex *pindex, CCustomCSView &cache, cons cache.EraseFuturesUserValues(key); } - attributes->SetValue(burnKey, std::move(burned)); - attributes->SetValue(mintedKey, std::move(minted)); + cache.SetValue(burnKey, std::move(burned)); + cache.SetValue(mintedKey, std::move(minted)); if (!unpaidContracts.empty()) { - attributes->SetValue(liveKey, std::move(balances)); + cache.SetValue(liveKey, std::move(balances)); } LogPrintf( @@ -1331,8 +1326,6 @@ static void ProcessFutures(const CBlockIndex *pindex, CCustomCSView &cache, cons failedContractsCounter, pindex->nHeight, GetTimeMillis() - time); - - cache.SetVariable(*attributes); } static void ProcessGovEvents(const CBlockIndex *pindex, @@ -1350,9 +1343,7 @@ static void ProcessGovEvents(const CBlockIndex *pindex, CCustomCSView govCache(cache); // Add to existing ATTRIBUTES instead of overwriting. if (var->GetName() == "ATTRIBUTES") { - auto govVar = cache.GetAttributes(); - govVar->time = pindex->GetBlockTime(); - govVar->evmTemplate = evmTemplate; + govCache.SetAttributesMembers(pindex->GetBlockTime(), evmTemplate); auto newVar = std::dynamic_pointer_cast(var); assert(newVar); @@ -1360,7 +1351,7 @@ static void ProcessGovEvents(const CBlockIndex *pindex, auto memberRemoval = newVar->GetValue(key, std::set{}); if (!memberRemoval.empty()) { - auto existingMembers = govVar->GetValue(key, std::set{}); + auto existingMembers = govCache.GetValue(key, std::set{}); for (auto &member : memberRemoval) { if (member.empty()) { @@ -1384,18 +1375,20 @@ static void ProcessGovEvents(const CBlockIndex *pindex, } } - govVar->SetValue(key, existingMembers); + govCache.SetValue(key, existingMembers); // Remove this key and apply any other changes newVar->EraseKey(key); - if (govVar->Import(newVar->Export()) && govVar->Validate(govCache) && - govVar->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*govVar)) { + if (govCache.ImportAttributes(newVar->Export()) && govCache.ValidateAttributes() && + govCache.ApplyAttributes(pindex->nHeight)) { govCache.Flush(); + cache.ClearAttributes(); } } else { - if (govVar->Import(var->Export()) && govVar->Validate(govCache) && - govVar->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*govVar)) { + if (govCache.ImportAttributes(var->Export()) && govCache.ValidateAttributes() && + govCache.ApplyAttributes(pindex->nHeight)) { govCache.Flush(); + cache.ClearAttributes(); } } } else if (var->Validate(govCache) && var->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*var)) { @@ -1409,20 +1402,15 @@ static void ProcessGovEvents(const CBlockIndex *pindex, static bool ApplyGovVars(CCustomCSView &cache, const CBlockIndex &pindex, const std::map &attrs) { - if (auto govVar = cache.GetVariable("ATTRIBUTES")) { - if (auto var = dynamic_cast(govVar.get())) { - var->time = pindex.nTime; + cache.SetAttributesMembers(pindex.nTime, {}); - UniValue obj(UniValue::VOBJ); - for (const auto &[key, value] : attrs) { - obj.pushKV(key, value); - } + UniValue obj(UniValue::VOBJ); + for (const auto &[key, value] : attrs) { + obj.pushKV(key, value); + } - if (var->Import(obj) && var->Validate(cache) && var->Apply(cache, pindex.nHeight) && - cache.SetVariable(*var)) { - return true; - } - } + if (cache.ImportAttributes(obj) && cache.ValidateAttributes() && cache.ApplyAttributes(pindex.nHeight)) { + return true; } return false; @@ -1494,8 +1482,10 @@ static void ProcessTokenToGovVar(const CBlockIndex *pindex, CCustomCSView &cache } CCustomCSView govCache(cache); - if (ApplyGovVars(govCache, *pindex, attrsFirst) && ApplyGovVars(govCache, *pindex, attrsSecond)) { + if ((!attrsFirst.empty() || !attrsSecond.empty()) && ApplyGovVars(govCache, *pindex, attrsFirst) && + ApplyGovVars(govCache, *pindex, attrsSecond)) { govCache.Flush(); + cache.ClearAttributes(); // Erase old tokens afterwards to avoid invalid state during transition for (const auto &item : loanTokens) { @@ -1622,7 +1612,6 @@ static Res UpdateLiquiditySplits(CCustomCSView &view, template static Res PoolSplits(CCustomCSView &view, CAmount &totalBalance, - ATTRIBUTES &attributes, const DCT_ID oldTokenId, const DCT_ID newTokenId, const CBlockIndex *pindex, @@ -1898,17 +1887,29 @@ static Res PoolSplits(CCustomCSView &view, } std::vector eraseKeys; - for (const auto &[key, value] : attributes.GetAttributesMap()) { - if (const auto v0Key = std::get_if(&key); - v0Key->type == AttributeTypes::Poolpairs && v0Key->typeId == oldPoolId.v) { - CDataStructureV0 newKey{AttributeTypes::Poolpairs, newPoolId.v, v0Key->key, v0Key->keyId}; - attributes.SetValue(newKey, value); - eraseKeys.push_back(*v0Key); - } - } + std::map setKeys; + view.ForEachAttribute( + [&, poolId = oldPoolId](const CDataStructureV0 &key, const CAttributeValue &value) { + if (key.type != AttributeTypes::Poolpairs) { + return false; + } + + if (key.typeId == poolId.v) { + CDataStructureV0 newKey{AttributeTypes::Poolpairs, newPoolId.v, key.key, key.keyId}; + setKeys.emplace(newKey, value); + eraseKeys.push_back(key); + } + + return true; + }, + CDataStructureV0{AttributeTypes::Poolpairs}); for (const auto &key : eraseKeys) { - attributes.EraseKey(key); + view.EraseKey(key); + } + + for (const auto &[key, value] : setKeys) { + view.SetValue(key, value); } res = UpdateLiquiditySplits(view, oldPoolId, newPoolId, pindex->nHeight); @@ -1935,11 +1936,11 @@ static Res PoolSplits(CCustomCSView &view, template static Res VaultSplits(CCustomCSView &view, - ATTRIBUTES &attributes, const DCT_ID oldTokenId, const DCT_ID newTokenId, const int height, - const T multiplier) { + const T multiplier, + const std::vector &eraseKeys) { auto time = GetTimeMillis(); LogPrintf("Vaults rebalance in progress.. (token %d -> %d, height: %d)\n", oldTokenId.v, newTokenId.v, height); @@ -1992,13 +1993,18 @@ static Res VaultSplits(CCustomCSView &view, return Res::Err("Failed to get vault data for: %s", failedVault.ToString()); } - attributes.EraseKey(CDataStructureV0{AttributeTypes::Locks, ParamIDs::TokenID, oldTokenId.v}); - attributes.SetValue(CDataStructureV0{AttributeTypes::Locks, ParamIDs::TokenID, newTokenId.v}, true); + view.EraseKey(CDataStructureV0{AttributeTypes::Locks, ParamIDs::TokenID, oldTokenId.v}); + view.SetValue(CDataStructureV0{AttributeTypes::Locks, ParamIDs::TokenID, newTokenId.v}, true); - if (auto res = attributes.Apply(view, height); !res) { + // Erase Token keys just before applying attributes, but + // after SubLoanToken above which requires these entries. + for (const auto &key : eraseKeys) { + view.EraseKey(key); + } + + if (auto res = view.ApplyAttributes(height); !res) { return res; } - view.SetVariable(attributes); for (const auto &[vaultId, amount] : loanTokenAmounts) { auto newAmount = CalculateNewAmount(multiplier, amount); @@ -2164,15 +2170,14 @@ static Res VaultSplits(CCustomCSView &view, } template -static void MigrateV1Remnants(const CCustomCSView &cache, - ATTRIBUTES &attributes, +static void MigrateV1Remnants(CCustomCSView &cache, const uint8_t key, const DCT_ID oldId, const DCT_ID newId, const T multiplier, const uint8_t typeID = ParamIDs::Economy) { CDataStructureV0 attrKey{AttributeTypes::Live, typeID, key}; - auto balances = attributes.GetValue(attrKey, CBalances{}); + auto balances = cache.GetValue(attrKey, CBalances{}); for (auto it = balances.balances.begin(); it != balances.balances.end(); ++it) { const auto &[tokenId, amount] = *it; if (tokenId != oldId) { @@ -2182,14 +2187,14 @@ static void MigrateV1Remnants(const CCustomCSView &cache, balances.Add({newId, CalculateNewAmount(multiplier, amount)}); break; } - attributes.SetValue(attrKey, balances); + cache.SetValue(attrKey, balances); } -Res GetTokenSuffix(const CCustomCSView &view, const ATTRIBUTES &attributes, const uint32_t id, std::string &newSuffix) { +Res GetTokenSuffix(CCustomCSView &view, const uint32_t id, std::string &newSuffix) { CDataStructureV0 ascendantKey{AttributeTypes::Token, id, TokenKeys::Ascendant}; - if (attributes.CheckKey(ascendantKey)) { + if (view.CheckKey(ascendantKey)) { const auto &[previousID, str] = - attributes.GetValue(ascendantKey, AscendantValue{std::numeric_limits::max(), ""}); + view.GetValue(ascendantKey, AscendantValue{std::numeric_limits::max(), ""}); auto previousToken = view.GetToken(DCT_ID{previousID}); if (!previousToken) { return Res::Err("Previous token %d not found\n", id); @@ -2217,9 +2222,9 @@ Res GetTokenSuffix(const CCustomCSView &view, const ATTRIBUTES &attributes, cons } template -static void UpdateOracleSplitKeys(const uint32_t id, ATTRIBUTES &attributes) { +static void UpdateOracleSplitKeys(const uint32_t id, CCustomCSView &view) { std::map updateAttributesKeys; - attributes.ForEach( + view.ForEachAttribute( [&](const CDataStructureV0 &attr, const CAttributeValue &value) { if (attr.type != AttributeTypes::Oracles) { return false; @@ -2250,9 +2255,9 @@ static void UpdateOracleSplitKeys(const uint32_t id, ATTRIBUTES &attributes) { for (const auto &[key, value] : updateAttributesKeys) { if (value.empty()) { - attributes.EraseKey(key); + view.EraseKey(key); } else { - attributes.SetValue(key, value); + view.SetValue(key, value); } } } @@ -2262,7 +2267,6 @@ static void ExecuteTokenSplits(const CBlockIndex *pindex, CCustomCSView &cache, const CreationTxs &creationTxs, const Consensus::Params &consensus, - ATTRIBUTES &attributes, const T &splits, BlockContext &blockCtx) { for (const auto &[id, multiplier] : splits) { @@ -2277,7 +2281,7 @@ static void ExecuteTokenSplits(const CBlockIndex *pindex, auto view{cache}; // Refund affected future swaps - auto res = attributes.RefundFuturesContracts(view, std::numeric_limits::max(), id); + auto res = view.RefundFuturesContracts(std::numeric_limits::max(), id); if (!res) { LogPrintf("Token split failed on refunding futures: %s\n", res.msg); continue; @@ -2292,7 +2296,7 @@ static void ExecuteTokenSplits(const CBlockIndex *pindex, } std::string newTokenSuffix = "/v"; - res = GetTokenSuffix(cache, attributes, oldTokenId.v, newTokenSuffix); + res = GetTokenSuffix(view, oldTokenId.v, newTokenSuffix); if (!res) { LogPrintf("Token split failed on GetTokenSuffix %s\n", res.msg); continue; @@ -2334,50 +2338,47 @@ static void ExecuteTokenSplits(const CBlockIndex *pindex, LogPrintf("Token split info: (symbol: %s, id: %d -> %d)\n", newToken.symbol, oldTokenId.v, newTokenId.v); std::vector eraseKeys; - for (const auto &[key, value] : attributes.GetAttributesMap()) { - if (const auto v0Key = std::get_if(&key); v0Key->type == AttributeTypes::Token) { - if (v0Key->typeId == oldTokenId.v && v0Key->keyId == oldTokenId.v) { - CDataStructureV0 newKey{AttributeTypes::Token, newTokenId.v, v0Key->key, newTokenId.v}; - attributes.SetValue(newKey, value); - eraseKeys.push_back(*v0Key); - } else if (v0Key->typeId == oldTokenId.v) { - CDataStructureV0 newKey{AttributeTypes::Token, newTokenId.v, v0Key->key, v0Key->keyId}; - attributes.SetValue(newKey, value); - eraseKeys.push_back(*v0Key); - } else if (v0Key->keyId == oldTokenId.v) { - CDataStructureV0 newKey{AttributeTypes::Token, v0Key->typeId, v0Key->key, newTokenId.v}; - attributes.SetValue(newKey, value); - eraseKeys.push_back(*v0Key); + cache.ForEachAttribute( + [&](const CDataStructureV0 &attr, const CAttributeValue &value) { + if (attr.type != AttributeTypes::Token) { + return false; } - } - } - for (const auto &key : eraseKeys) { - attributes.EraseKey(key); - } + if (attr.typeId == oldTokenId.v && attr.keyId == oldTokenId.v) { + CDataStructureV0 newKey{AttributeTypes::Token, newTokenId.v, attr.key, newTokenId.v}; + view.SetValue(newKey, value); + eraseKeys.push_back(attr); + } else if (attr.typeId == oldTokenId.v) { + CDataStructureV0 newKey{AttributeTypes::Token, newTokenId.v, attr.key, attr.keyId}; + view.SetValue(newKey, value); + eraseKeys.push_back(attr); + } else if (attr.keyId == oldTokenId.v) { + CDataStructureV0 newKey{AttributeTypes::Token, attr.typeId, attr.key, newTokenId.v}; + view.SetValue(newKey, value); + eraseKeys.push_back(attr); + } + + return true; + }, + CDataStructureV0{AttributeTypes::Token}); CDataStructureV0 newAscendantKey{AttributeTypes::Token, newTokenId.v, TokenKeys::Ascendant}; - attributes.SetValue(newAscendantKey, AscendantValue{oldTokenId.v, "split"}); + view.SetValue(newAscendantKey, AscendantValue{oldTokenId.v, "split"}); CDataStructureV0 descendantKey{AttributeTypes::Token, oldTokenId.v, TokenKeys::Descendant}; - attributes.SetValue(descendantKey, DescendantValue{newTokenId.v, static_cast(pindex->nHeight)}); + view.SetValue(descendantKey, DescendantValue{newTokenId.v, static_cast(pindex->nHeight)}); - MigrateV1Remnants(cache, attributes, EconomyKeys::DFIP2203Current, oldTokenId, newTokenId, multiplier); - MigrateV1Remnants(cache, attributes, EconomyKeys::DFIP2203Burned, oldTokenId, newTokenId, multiplier); - MigrateV1Remnants(cache, attributes, EconomyKeys::DFIP2203Minted, oldTokenId, newTokenId, multiplier); + MigrateV1Remnants(view, EconomyKeys::DFIP2203Current, oldTokenId, newTokenId, multiplier); + MigrateV1Remnants(view, EconomyKeys::DFIP2203Burned, oldTokenId, newTokenId, multiplier); + MigrateV1Remnants(view, EconomyKeys::DFIP2203Minted, oldTokenId, newTokenId, multiplier); + MigrateV1Remnants( + view, EconomyKeys::BatchRoundingExcess, oldTokenId, newTokenId, multiplier, ParamIDs::Auction); MigrateV1Remnants( - cache, attributes, EconomyKeys::BatchRoundingExcess, oldTokenId, newTokenId, multiplier, ParamIDs::Auction); - MigrateV1Remnants(cache, - attributes, - EconomyKeys::ConsolidatedInterest, - oldTokenId, - newTokenId, - multiplier, - ParamIDs::Auction); + view, EconomyKeys::ConsolidatedInterest, oldTokenId, newTokenId, multiplier, ParamIDs::Auction); CAmount totalBalance{0}; - res = PoolSplits(view, totalBalance, attributes, oldTokenId, newTokenId, pindex, creationTxs, multiplier); + res = PoolSplits(view, totalBalance, oldTokenId, newTokenId, pindex, creationTxs, multiplier); if (!res) { LogPrintf("Pool splits failed %s\n", res.msg); continue; @@ -2450,16 +2451,14 @@ static void ExecuteTokenSplits(const CBlockIndex *pindex, continue; } - res = VaultSplits(view, attributes, oldTokenId, newTokenId, pindex->nHeight, multiplier); + res = VaultSplits(view, oldTokenId, newTokenId, pindex->nHeight, multiplier, eraseKeys); if (!res) { LogPrintf("Token splits failed: %s\n", res.msg); continue; } - UpdateOracleSplitKeys(oldTokenId.v, attributes); - UpdateOracleSplitKeys(oldTokenId.v, attributes); - - view.SetVariable(attributes); + UpdateOracleSplitKeys(oldTokenId.v, view); + UpdateOracleSplitKeys(oldTokenId.v, view); // Migrate stored unlock if (pindex->nHeight >= consensus.DF20GrandCentralHeight) { @@ -2472,17 +2471,22 @@ static void ExecuteTokenSplits(const CBlockIndex *pindex, updateStoredVar = false; if (const auto attrVar = std::dynamic_pointer_cast(var); attrVar) { - const auto attrMap = attrVar->GetAttributesMap(); std::vector keysToUpdate; - for (const auto &[key, value] : attrMap) { - if (const auto attrV0 = std::get_if(&key); attrV0) { - if (attrV0->type == AttributeTypes::Locks && attrV0->typeId == ParamIDs::TokenID && - attrV0->key == oldTokenId.v) { - keysToUpdate.push_back(*attrV0); + attrVar->ForEach( + [&](const CDataStructureV0 &attr, const CAttributeValue &value) { + if (attr.type != AttributeTypes::Locks) { + return false; + } + + if (attr.typeId == ParamIDs::TokenID && attr.key == oldTokenId.v) { + keysToUpdate.push_back(attr); updateStoredVar = true; } - } - } + + return true; + }, + CDataStructureV0{AttributeTypes::Locks}); + for (auto &key : keysToUpdate) { const auto value = attrVar->GetValue(key, false); attrVar->EraseKey(key); @@ -2514,18 +2518,15 @@ static void ProcessTokenSplits(const CBlockIndex *pindex, if (pindex->nHeight < consensus.DF16FortCanningCrunchHeight) { return; } - const auto attributes = cache.GetAttributes(); CDataStructureV0 splitKey{AttributeTypes::Oracles, OracleIDs::Splits, static_cast(pindex->nHeight)}; - if (const auto splits32 = attributes->GetValue(splitKey, OracleSplits{}); !splits32.empty()) { - attributes->EraseKey(splitKey); - cache.SetVariable(*attributes); - ExecuteTokenSplits(pindex, cache, creationTxs, consensus, *attributes, splits32, blockCtx); - } else if (const auto splits64 = attributes->GetValue(splitKey, OracleSplits64{}); !splits64.empty()) { - attributes->EraseKey(splitKey); - cache.SetVariable(*attributes); - ExecuteTokenSplits(pindex, cache, creationTxs, consensus, *attributes, splits64, blockCtx); + if (const auto splits32 = cache.GetValue(splitKey, OracleSplits{}); !splits32.empty()) { + cache.EraseKey(splitKey); + ExecuteTokenSplits(pindex, cache, creationTxs, consensus, splits32, blockCtx); + } else if (const auto splits64 = cache.GetValue(splitKey, OracleSplits64{}); !splits64.empty()) { + cache.EraseKey(splitKey); + ExecuteTokenSplits(pindex, cache, creationTxs, consensus, splits64, blockCtx); } } @@ -2534,23 +2535,20 @@ static void ProcessFuturesDUSD(const CBlockIndex *pindex, CCustomCSView &cache, return; } - auto attributes = cache.GetAttributes(); - CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2206F, DFIPKeys::Active}; CDataStructureV0 blockKey{AttributeTypes::Param, ParamIDs::DFIP2206F, DFIPKeys::BlockPeriod}; CDataStructureV0 rewardKey{AttributeTypes::Param, ParamIDs::DFIP2206F, DFIPKeys::RewardPct}; - if (!attributes->GetValue(activeKey, false) || !attributes->CheckKey(blockKey) || - !attributes->CheckKey(rewardKey)) { + if (!cache.GetValue(activeKey, false) || !cache.CheckKey(blockKey) || !cache.CheckKey(rewardKey)) { return; } CDataStructureV0 startKey{AttributeTypes::Param, ParamIDs::DFIP2206F, DFIPKeys::StartBlock}; - const auto startBlock = attributes->GetValue(startKey, CAmount{}); + const auto startBlock = cache.GetValue(startKey, CAmount{}); if (pindex->nHeight < startBlock) { return; } - const auto blockPeriod = attributes->GetValue(blockKey, CAmount{}); + const auto blockPeriod = cache.GetValue(blockKey, CAmount{}); if ((pindex->nHeight - startBlock) % blockPeriod != 0) { return; } @@ -2558,14 +2556,14 @@ static void ProcessFuturesDUSD(const CBlockIndex *pindex, CCustomCSView &cache, auto time = GetTimeMillis(); LogPrintf("Future swap DUSD settlement in progress.. (height: %d)\n", pindex->nHeight); - const auto rewardPct = attributes->GetValue(rewardKey, CAmount{}); + const auto rewardPct = cache.GetValue(rewardKey, CAmount{}); const auto discount{COIN - rewardPct}; const auto useNextPrice{false}, requireLivePrice{true}; const auto discountPrice = cache.GetAmountInCurrency(discount, {"DFI", "USD"}, useNextPrice, requireLivePrice); CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2206FCurrent}; - auto balances = attributes->GetValue(liveKey, CBalances{}); + auto balances = cache.GetValue(liveKey, CBalances{}); const auto contractAddressValue = GetFutureSwapContractAddress(SMART_CONTRACT_DFIP2206F); assert(contractAddressValue); @@ -2609,11 +2607,9 @@ static void ProcessFuturesDUSD(const CBlockIndex *pindex, CCustomCSView &cache, } if (!refunds.empty()) { - attributes->SetValue(liveKey, std::move(balances)); + cache.SetValue(liveKey, std::move(balances)); } - cache.SetVariable(*attributes); - LogPrintf("Future swap DUSD refunded due to no live price: (%d refunds (height: %d, time: %dms)\n", refunds.size(), pindex->nHeight, @@ -2625,8 +2621,8 @@ static void ProcessFuturesDUSD(const CBlockIndex *pindex, CCustomCSView &cache, CDataStructureV0 burnKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2206FBurned}; CDataStructureV0 mintedKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2206FMinted}; - auto burned = attributes->GetValue(burnKey, CBalances{}); - auto minted = attributes->GetValue(mintedKey, CBalances{}); + auto burned = cache.GetValue(burnKey, CBalances{}); + auto minted = cache.GetValue(mintedKey, CBalances{}); std::set deletionPending; @@ -2668,15 +2664,13 @@ static void ProcessFuturesDUSD(const CBlockIndex *pindex, CCustomCSView &cache, cache.EraseFuturesDUSD(key); } - attributes->SetValue(burnKey, std::move(burned)); - attributes->SetValue(mintedKey, std::move(minted)); + cache.SetValue(burnKey, std::move(burned)); + cache.SetValue(mintedKey, std::move(minted)); LogPrintf("Future swap DUSD settlement completed: (%d swaps (height: %d, time: %dms)\n", swapCounter, pindex->nHeight, GetTimeMillis() - time); - - cache.SetVariable(*attributes); } static void ProcessNegativeInterest(const CBlockIndex *pindex, CCustomCSView &cache) { @@ -2684,8 +2678,6 @@ static void ProcessNegativeInterest(const CBlockIndex *pindex, CCustomCSView &ca return; } - auto attributes = cache.GetAttributes(); - DCT_ID dusd{}; const auto token = cache.GetTokenGuessId("DUSD", dusd); if (!token) { @@ -2693,7 +2685,7 @@ static void ProcessNegativeInterest(const CBlockIndex *pindex, CCustomCSView &ca } CDataStructureV0 negativeInterestKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::NegativeInt}; - auto negativeInterestBalances = attributes->GetValue(negativeInterestKey, CBalances{}); + auto negativeInterestBalances = cache.GetValue(negativeInterestKey, CBalances{}); negativeInterestKey.key = EconomyKeys::NegativeIntCurrent; cache.ForEachLoanTokenAmount([&](const CVaultId &vaultId, const CBalances &balances) { @@ -2715,8 +2707,7 @@ static void ProcessNegativeInterest(const CBlockIndex *pindex, CCustomCSView &ca }); if (!negativeInterestBalances.balances.empty()) { - attributes->SetValue(negativeInterestKey, negativeInterestBalances); - cache.SetVariable(*attributes); + cache.SetValue(negativeInterestKey, negativeInterestBalances); } } @@ -2727,10 +2718,8 @@ static void ProcessProposalEvents(const CBlockIndex *pindex, CCustomCSView &cach CDataStructureV0 enabledKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovernanceEnabled}; - auto attributes = cache.GetAttributes(); - auto funds = cache.GetCommunityBalance(CommunityAccountType::CommunityDevFunds); - if (!attributes->GetValue(enabledKey, false)) { + if (!cache.GetValue(enabledKey, false)) { if (funds > 0) { cache.SubCommunityBalance(CommunityAccountType::CommunityDevFunds, funds); cache.AddBalance(consensus.foundationShareScript, {DCT_ID{0}, funds}); @@ -2787,7 +2776,7 @@ static void ProcessProposalEvents(const CBlockIndex *pindex, CCustomCSView &cach CDataStructureV0 feeRedistributionKey{ AttributeTypes::Governance, GovernanceIDs::Proposals, GovernanceKeys::FeeRedistribution}; - if (voters.size() > 0 && attributes->GetValue(feeRedistributionKey, false)) { + if (voters.size() > 0 && cache.GetValue(feeRedistributionKey, false)) { // return half fee among voting masternodes, the rest is burned at creation auto feeBack = prop.fee - prop.feeBurnAmount; auto amountPerVoter = DivideAmounts(feeBack, voters.size() * COIN); @@ -2862,13 +2851,13 @@ static void ProcessProposalEvents(const CBlockIndex *pindex, CCustomCSView &cach CDataStructureV0 payoutKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::CFPPayout}; - if (prop.type == CProposalType::CommunityFundProposal && attributes->GetValue(payoutKey, false)) { + if (prop.type == CProposalType::CommunityFundProposal && cache.GetValue(payoutKey, false)) { auto res = cache.SubCommunityBalance(CommunityAccountType::CommunityDevFunds, prop.nAmount); if (res) { cache.CalculateOwnerRewards(prop.address, pindex->nHeight); cache.AddBalance(prop.address, {DCT_ID{0}, prop.nAmount}); } else { - LogPrintf("Fails to subtract community developement funds: %s\n", res.msg); + LogPrintf("Fails to subtract community development funds: %s\n", res.msg); } } @@ -2920,11 +2909,8 @@ static void ProcessGrandCentralEvents(const CBlockIndex *pindex, return; } - auto attributes = cache.GetAttributes(); - CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}; - attributes->SetValue(key, consensus.foundationMembers); - cache.SetVariable(*attributes); + cache.SetValue(key, consensus.foundationMembers); } static void ProcessNullPoolSwapRefund(const CBlockIndex *pindex, @@ -3044,9 +3030,7 @@ static Res ProcessEVMQueue(const CBlock &block, return res; } - auto attributes = cache.GetAttributes(); - - auto stats = attributes->GetValue(CEvmBlockStatsLive::Key, CEvmBlockStatsLive{}); + auto stats = cache.GetValue(CEvmBlockStatsLive::Key, CEvmBlockStatsLive{}); auto feeBurnt = static_cast(blockResult.total_burnt_fees); auto feePriority = static_cast(blockResult.total_priority_fees); @@ -3069,7 +3053,7 @@ static Res ProcessEVMQueue(const CBlock &block, stats.feePriorityMaxHash = block.GetHash(); } - auto transferDomainStats = attributes->GetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); + auto transferDomainStats = cache.GetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); for (const auto &[id, amount] : transferDomainStats.dvmCurrent.balances) { if (id.v == 0) { @@ -3085,8 +3069,7 @@ static Res ProcessEVMQueue(const CBlock &block, } } - attributes->SetValue(CEvmBlockStatsLive::Key, stats); - cache.SetVariable(*attributes); + cache.SetValue(CEvmBlockStatsLive::Key, stats); return Res::Ok(); } @@ -3095,6 +3078,12 @@ static void FlushCacheCreateUndo(const CBlockIndex *pindex, CCustomCSView &mnview, CCustomCSView &cache, const uint256 hash) { + // Update Gov var before creating undo to make sure changes are present + if (cache.SetAttributes()) { + // Clear attributes in parent so next use loads updated values + mnview.ClearAttributes(); + } + // construct undo auto &flushable = cache.GetStorage(); auto undo = CUndo::Construct(mnview.GetStorage(), flushable.GetRaw()); @@ -3239,8 +3228,7 @@ bool ExecuteTokenMigrationEVM(std::size_t mnview_ptr, const TokenAmount oldAmoun } } - auto attributes = cache->GetAttributes(); - auto stats = attributes->GetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); + auto stats = cache->GetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); // Transfer out old token auto outAmount = CTokenAmount{{oldAmount.id}, static_cast(oldAmount.amount)}; @@ -3258,10 +3246,7 @@ bool ExecuteTokenMigrationEVM(std::size_t mnview_ptr, const TokenAmount oldAmoun stats.evmIn.Add(inAmount); stats.evmCurrent.Add(inAmount); - attributes->SetValue(CTransferDomainStatsLive::Key, stats); - if (const auto res = cache->SetVariable(*attributes); !res) { - return res; - } + cache->SetValue(CTransferDomainStatsLive::Key, stats); return true; } diff --git a/src/dfi/validation.h b/src/dfi/validation.h index f29b5b576b..8edfe2c6ea 100644 --- a/src/dfi/validation.h +++ b/src/dfi/validation.h @@ -35,11 +35,16 @@ Res ProcessDeFiEventFallible(const CBlock &block, const CreationTxs &creationTxs, BlockContext &blockCtx); +void ProcessGovEvents(const CBlockIndex *pindex, + CCustomCSView &cache, + const CChainParams &chainparams, + const std::shared_ptr &evmTemplate); + std::vector CollectAuctionBatches(const CVaultAssets &vaultAssets, const TAmounts &collBalances, const TAmounts &loanBalances); -Res GetTokenSuffix(const CCustomCSView &view, const ATTRIBUTES &attributes, const uint32_t id, std::string &newSuffix); +Res GetTokenSuffix(CCustomCSView &view, const uint32_t id, std::string &newSuffix); bool ExecuteTokenMigrationEVM(std::size_t mnview_ptr, const TokenAmount oldAmount, TokenAmount &newAmount); Res ExecuteTokenMigrationTransferDomain(CCustomCSView &view, CTokenAmount &amount); diff --git a/src/ffi/ffiexports.cpp b/src/ffi/ffiexports.cpp index f71b8998ef..7c43aec38e 100644 --- a/src/ffi/ffiexports.cpp +++ b/src/ffi/ffiexports.cpp @@ -282,24 +282,22 @@ Attributes getAttributeValues(std::size_t mnview_ptr) { view = pcustomcsview.get(); } - const auto attributes = view->GetAttributes(); - CDataStructureV0 blockGasTargetFactorKey{AttributeTypes::EVMType, EVMIDs::Block, EVMKeys::GasTargetFactor}; CDataStructureV0 blockGasLimitKey{AttributeTypes::EVMType, EVMIDs::Block, EVMKeys::GasLimit}; CDataStructureV0 finalityCountKey{AttributeTypes::EVMType, EVMIDs::Block, EVMKeys::Finalized}; CDataStructureV0 rbfIncrementMinPctKey{AttributeTypes::EVMType, EVMIDs::Block, EVMKeys::RbfIncrementMinPct}; - if (attributes->CheckKey(blockGasTargetFactorKey)) { - val.blockGasTargetFactor = attributes->GetValue(blockGasTargetFactorKey, DEFAULT_EVM_BLOCK_GAS_TARGET_FACTOR); + if (view->CheckKey(blockGasTargetFactorKey)) { + val.blockGasTargetFactor = view->GetValue(blockGasTargetFactorKey, DEFAULT_EVM_BLOCK_GAS_TARGET_FACTOR); } - if (attributes->CheckKey(blockGasLimitKey)) { - val.blockGasLimit = attributes->GetValue(blockGasLimitKey, DEFAULT_EVM_BLOCK_GAS_LIMIT); + if (view->CheckKey(blockGasLimitKey)) { + val.blockGasLimit = view->GetValue(blockGasLimitKey, DEFAULT_EVM_BLOCK_GAS_LIMIT); } - if (attributes->CheckKey(finalityCountKey)) { - val.finalityCount = attributes->GetValue(finalityCountKey, DEFAULT_EVM_FINALITY_COUNT); + if (view->CheckKey(finalityCountKey)) { + val.finalityCount = view->GetValue(finalityCountKey, DEFAULT_EVM_FINALITY_COUNT); } - if (attributes->CheckKey(rbfIncrementMinPctKey)) { - val.rbfIncrementMinPct = attributes->GetValue(rbfIncrementMinPctKey, DEFAULT_EVM_RBF_FEE_INCREMENT); + if (view->CheckKey(rbfIncrementMinPctKey)) { + val.rbfIncrementMinPct = view->GetValue(rbfIncrementMinPctKey, DEFAULT_EVM_RBF_FEE_INCREMENT); } return val; @@ -326,7 +324,7 @@ bool getDST20Tokens(std::size_t mnview_ptr, rust::vec &tokens) { LOCK(cs_main); bool res = true; - CCustomCSView *cache = reinterpret_cast(static_cast(mnview_ptr)); + auto cache = reinterpret_cast(static_cast(mnview_ptr)); cache->ForEachToken( [&](DCT_ID const &id, CTokensView::CTokenImpl token) { if (!token.IsDAT() || token.IsPoolShare()) { diff --git a/src/miner.cpp b/src/miner.cpp index 8ba78ed569..c8ad2e0a00 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -118,7 +118,6 @@ static void AddSplitEVMTxs(BlockContext &blockCtx, const SplitMap &splitMap) { } auto &mnview = blockCtx.GetView(); - const auto attributes = mnview.GetAttributes(); for (const auto &[id, splitData] : splitMap) { const auto &[multiplier, creationTx] = splitData; @@ -143,7 +142,7 @@ static void AddSplitEVMTxs(BlockContext &blockCtx, const SplitMap &splitMap) { } std::string newTokenSuffix = "/v"; - auto res = GetTokenSuffix(mnview, *attributes, id, newTokenSuffix); + auto res = GetTokenSuffix(mnview, id, newTokenSuffix); if (!res) { continue; } @@ -378,7 +377,6 @@ ResVal> BlockAssembler::CreateNewBlock(const CSc timeOrdering = false; } - const auto attributes = mnview.GetAttributes(); const auto isEvmEnabledForBlock = blockCtx.GetEVMEnabledForBlock(); const auto &evmTemplate = blockCtx.GetEVMTemplate(); @@ -408,9 +406,9 @@ ResVal> BlockAssembler::CreateNewBlock(const CSc // TXs for the creationTx field in new tokens created via token split if (nHeight >= chainparams.GetConsensus().DF16FortCanningCrunchHeight) { CDataStructureV0 splitKey{AttributeTypes::Oracles, OracleIDs::Splits, static_cast(nHeight)}; - if (const auto splits32 = attributes->GetValue(splitKey, OracleSplits{}); !splits32.empty()) { + if (const auto splits32 = mnview.GetValue(splitKey, OracleSplits{}); !splits32.empty()) { AddSplitDVMTxs(mnview, pblock, pblocktemplate, nHeight, splits32, txVersion, splitMap); - } else if (const auto splits64 = attributes->GetValue(splitKey, OracleSplits64{}); !splits64.empty()) { + } else if (const auto splits64 = mnview.GetValue(splitKey, OracleSplits64{}); !splits64.empty()) { AddSplitDVMTxs(mnview, pblock, pblocktemplate, nHeight, splits64, txVersion, splitMap); } } diff --git a/src/test/loan_tests.cpp b/src/test/loan_tests.cpp index d3ac8d53d9..66c11957e1 100644 --- a/src/test/loan_tests.cpp +++ b/src/test/loan_tests.cpp @@ -5,7 +5,6 @@ #include #include -#include inline uint256 NextTx() { diff --git a/src/validation.cpp b/src/validation.cpp index a57ab9972b..d33ed357d3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2405,13 +2405,11 @@ Res ApplyGeneralCoinbaseTx(CCustomCSView &mnview, } } else { if (height >= consensus.DF20GrandCentralHeight) { - const auto attributes = mnview.GetAttributes(); - if (kv.first == CommunityAccountType::CommunityDevFunds) { CDataStructureV0 enabledKey{ AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovernanceEnabled}; - if (!attributes->GetValue(enabledKey, false)) { + if (!mnview.GetValue(enabledKey, false)) { res = mnview.AddBalance(consensus.foundationShareScript, {DCT_ID{0}, subsidy}); LogPrint(BCLog::ACCOUNTCHANGE, "AccountChange: hash=%s fund=%s change=%s\n", @@ -2427,7 +2425,7 @@ Res ApplyGeneralCoinbaseTx(CCustomCSView &mnview, CDataStructureV0 enabledKey{ AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::EmissionUnusedFund}; - if (attributes->GetValue(enabledKey, false)) { + if (mnview.GetValue(enabledKey, false)) { res = mnview.AddBalance(consensus.unusedEmission, {DCT_ID{0}, subsidy}); if (res) { LogPrint(BCLog::ACCOUNTCHANGE, @@ -2523,13 +2521,11 @@ void ReverseGeneralCoinbaseTx(CCustomCSView &mnview, int height, const Consensus mnview.SubCommunityBalance(CommunityAccountType::Unallocated, subsidy); } else { if (height >= consensus.DF20GrandCentralHeight) { - const auto attributes = mnview.GetAttributes(); - if (kv.first == CommunityAccountType::CommunityDevFunds) { CDataStructureV0 enabledKey{ AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::GovernanceEnabled}; - if (!attributes->GetValue(enabledKey, false)) { + if (!mnview.GetValue(enabledKey, false)) { mnview.SubBalance(consensus.foundationShareScript, {DCT_ID{0}, subsidy}); continue; @@ -2539,7 +2535,7 @@ void ReverseGeneralCoinbaseTx(CCustomCSView &mnview, int height, const Consensus CDataStructureV0 enabledKey{ AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::EmissionUnusedFund}; - if (attributes->GetValue(enabledKey, false)) { + if (mnview.GetValue(enabledKey, false)) { mnview.SubBalance(consensus.unusedEmission, {DCT_ID{0}, subsidy}); } else { mnview.SubCommunityBalance(CommunityAccountType::Unallocated, subsidy); @@ -3007,15 +3003,12 @@ bool CChainState::ConnectBlock(const CBlock &block, blockundo.vtxundo.reserve(block.vtx.size() - 1); std::vector txdata; - const auto attributes = accountsView.GetAttributes(); - txdata.reserve( block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated const auto &consensus = chainparams.GetConsensus(); - auto blockCtx = - BlockContext(pindex->nHeight, pindex->GetBlockTime(), consensus, &accountsView, IsEVMEnabled(attributes)); + auto blockCtx = BlockContext(pindex->nHeight, pindex->GetBlockTime(), consensus, &accountsView); auto isEvmEnabledForBlock = blockCtx.GetEVMEnabledForBlock(); auto &evmTemplate = blockCtx.GetEVMTemplate(); @@ -3333,12 +3326,12 @@ bool CChainState::ConnectBlock(const CBlock &block, bool isSplitsBlock{}; CDataStructureV0 splitKey{AttributeTypes::Oracles, OracleIDs::Splits, static_cast(pindex->nHeight)}; - if (const auto splits32 = attributes->GetValue(splitKey, OracleSplits{}); !splits32.empty()) { + if (const auto splits32 = accountsView.GetValue(splitKey, OracleSplits{}); !splits32.empty()) { if (!GetTokenMigrationCreationTxs(accountsView, block, pindex, splits32, creationTxs, state)) { return false; } isSplitsBlock = true; - } else if (const auto splits64 = attributes->GetValue(splitKey, OracleSplits64{}); !splits64.empty()) { + } else if (const auto splits64 = accountsView.GetValue(splitKey, OracleSplits64{}); !splits64.empty()) { if (!GetTokenMigrationCreationTxs(accountsView, block, pindex, splits64, creationTxs, state)) { return false; } @@ -3599,7 +3592,7 @@ bool CChainState::FlushStateToDisk(const CChainParams &chainparams, return AbortNode(state, "Failed to write to coin or masternode db to disk"); } // Flush the EVM chainstate - if (IsEVMEnabled(pcustomcsview->GetAttributes())) { + if (IsEVMEnabled(*pcustomcsview)) { auto res = XResultStatusLogged(evm_try_flush_db(result)); if (!res) { return AbortNode(state, "Failed to write to EVM db to disk"); diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 811bb19885..755bab7237 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -9,20 +9,9 @@ export LC_ALL=C EXPECTED_CIRCULAR_DEPENDENCIES=( - "chain -> chainparams -> dfi/mn_checks -> index/txindex -> chain" - "chain -> chainparams -> dfi/mn_checks -> index/txindex -> txdb -> chain" - "chain -> chainparams -> dfi/mn_checks -> dfi/vaulthistory -> chain" - "chain -> chainparams -> dfi/mn_checks -> validation -> chain" - "chain -> chainparams -> dfi/mn_checks -> validation -> versionbits -> chain" - "chain -> chainparams -> dfi/mn_checks -> validation -> wallet/wallet -> chain" + "chainparams -> dfi/customtx -> chainparams" + "chainparams -> dfi/customtx -> dfi/accounts -> dfi/errors -> dfi/vault -> chainparams" "chainparams -> key_io -> chainparams" - "chainparams -> dfi/mn_checks -> index/txindex -> index/base -> chainparams" - "chainparams -> dfi/mn_checks -> dfi/customtx -> chainparams" - "chainparams -> dfi/mn_checks -> dfi/vaulthistory -> dfi/vault -> chainparams" - "chainparams -> dfi/mn_checks -> txmempool -> chainparams" - "chainparams -> dfi/mn_checks -> validation -> chainparams" - "chainparams -> dfi/mn_checks -> validation -> spv/spv_wrapper -> chainparams" - "chainparams -> dfi/mn_checks -> validation -> wallet/wallet -> chainparams" "chainparamsbase -> util/system -> chainparamsbase" "consensus/tx_verify -> dfi/mn_checks -> txmempool -> consensus/tx_verify" "consensus/tx_verify -> validation -> consensus/tx_verify" @@ -45,11 +34,11 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "dfi/consensus/smartcontracts -> dfi/mn_checks -> dfi/consensus/smartcontracts" "dfi/consensus/tokens -> dfi/mn_checks -> dfi/consensus/tokens" "dfi/consensus/vaults -> dfi/mn_checks -> dfi/consensus/vaults" + "dfi/consensus/xvm -> dfi/masternodes -> dfi/evm -> dfi/consensus/xvm" "dfi/consensus/xvm -> dfi/mn_checks -> dfi/consensus/xvm" - "dfi/consensus/xvm -> dfi/govvariables/attributes -> dfi/evm -> dfi/consensus/xvm" "dfi/consensus/xvm -> dfi/govvariables/attributes -> dfi/mn_rpc -> dfi/consensus/xvm" + "dfi/govvariables/attributes -> dfi/govvariables/attributetypes -> dfi/loan -> dfi/govvariables/attributes" "dfi/govvariables/attributes -> dfi/gv -> dfi/govvariables/attributes" - "dfi/govvariables/attributes -> dfi/historywriter -> dfi/loan -> dfi/govvariables/attributes" "dfi/govvariables/attributes -> dfi/masternodes -> dfi/govvariables/attributes" "dfi/govvariables/attributes -> dfi/masternodes -> dfi/poolpairs -> dfi/govvariables/attributes" "dfi/govvariables/attributes -> dfi/mn_checks -> dfi/govvariables/attributes"