From 75dae28f61cb589040f0936ef94befc13084c290 Mon Sep 17 00:00:00 2001 From: Peter Bushnell Date: Wed, 25 May 2022 10:22:05 +0100 Subject: [PATCH 1/3] Move end of block processes to functions --- src/validation.cpp | 174 +++++++++++++++++++++++++-------------------- src/validation.h | 4 ++ 2 files changed, 99 insertions(+), 79 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index cc7df0c70c..af53933a5a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2203,6 +2203,69 @@ Res AddNonTxToBurnIndex(const CScript& from, const CBalances& amounts) return mapBurnAmounts[from].AddBalances(amounts.balances); } +void CChainState::ProcessEunosEvents(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams) { + if (pindex->nHeight != chainparams.GetConsensus().EunosHeight) { + return; + } + + // Move funds from old burn address to new one + CBalances burnAmounts; + cache.ForEachBalance([&burnAmounts](CScript const & owner, CTokenAmount balance) { + if (owner != Params().GetConsensus().retiredBurnAddress) { + return false; + } + + burnAmounts.Add({balance.nTokenId, balance.nValue}); + + return true; + }, BalanceKey{chainparams.GetConsensus().retiredBurnAddress, DCT_ID{}}); + + AddNonTxToBurnIndex(chainparams.GetConsensus().retiredBurnAddress, burnAmounts); + + // Zero foundation balances + for (const auto& script : chainparams.GetConsensus().accountDestruction) + { + CBalances zeroAmounts; + cache.ForEachBalance([&zeroAmounts, script](CScript const & owner, CTokenAmount balance) { + if (owner != script) { + return false; + } + + zeroAmounts.Add({balance.nTokenId, balance.nValue}); + + return true; + }, BalanceKey{script, DCT_ID{}}); + + cache.SubBalances(script, zeroAmounts); + } + + // Add any non-Tx burns to index as phantom Txs + for (const auto& item : mapBurnAmounts) + { + for (const auto& subItem : item.second.balances) + { + // If amount cannot be deducted then burn skipped. + auto result = cache.SubBalance(item.first, {subItem.first, subItem.second}); + if (result.ok) + { + cache.AddBalance(chainparams.GetConsensus().burnAddress, {subItem.first, subItem.second}); + + // Add transfer as additional TX in block + pburnHistoryDB->WriteAccountHistory({Params().GetConsensus().burnAddress, static_cast(pindex->nHeight), GetNextBurnPosition()}, + {uint256{}, static_cast(CustomTxType::AccountToAccount), {{subItem.first, subItem.second}}}); + } + else // Log burn failure + { + CTxDestination dest; + ExtractDestination(item.first, dest); + LogPrintf("Burn failed: %s Address: %s Token: %d Amount: %d\n", result.msg, EncodeDestination(dest), subItem.first.v, subItem.second); + } + } + } + + mapBurnAmounts.clear(); +} + template static void UpdateDailyGovVariables(const std::map::const_iterator& incentivePair, CCustomCSView& cache, int nHeight) { if (incentivePair != Params().GetConsensus().newNonUTXOSubsidies.end()) @@ -2911,92 +2974,20 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl cache.BayfrontFlagsCleanup(); } - if (pindex->nHeight == chainparams.GetConsensus().EunosHeight) - { - // Move funds from old burn address to new one - CBalances burnAmounts; - cache.ForEachBalance([&burnAmounts](CScript const & owner, CTokenAmount balance) { - if (owner != Params().GetConsensus().retiredBurnAddress) { - return false; - } - - burnAmounts.Add({balance.nTokenId, balance.nValue}); - - return true; - }, BalanceKey{chainparams.GetConsensus().retiredBurnAddress, DCT_ID{}}); - - AddNonTxToBurnIndex(chainparams.GetConsensus().retiredBurnAddress, burnAmounts); - - // Zero foundation balances - for (const auto& script : chainparams.GetConsensus().accountDestruction) - { - CBalances zeroAmounts; - cache.ForEachBalance([&zeroAmounts, script](CScript const & owner, CTokenAmount balance) { - if (owner != script) { - return false; - } - - zeroAmounts.Add({balance.nTokenId, balance.nValue}); - - return true; - }, BalanceKey{script, DCT_ID{}}); - - cache.SubBalances(script, zeroAmounts); - } - } - - // Add any non-Tx burns to index as phantom Txs - for (const auto& item : mapBurnAmounts) - { - for (const auto& subItem : item.second.balances) - { - // If amount cannot be deducted then burn skipped. - auto result = cache.SubBalance(item.first, {subItem.first, subItem.second}); - if (result.ok) - { - cache.AddBalance(chainparams.GetConsensus().burnAddress, {subItem.first, subItem.second}); - - // Add transfer as additional TX in block - pburnHistoryDB->WriteAccountHistory({Params().GetConsensus().burnAddress, static_cast(pindex->nHeight), GetNextBurnPosition()}, - {uint256{}, static_cast(CustomTxType::AccountToAccount), {{subItem.first, subItem.second}}}); - } - else // Log burn failure - { - CTxDestination dest; - ExtractDestination(item.first, dest); - LogPrintf("Burn failed: %s Address: %s Token: %d Amount: %d\n", result.msg, EncodeDestination(dest), subItem.first.v, subItem.second); - } - } - } - - mapBurnAmounts.clear(); + // burn DFI on Eunos height + ProcessEunosEvents(pindex, cache, chainparams); + // set oracle prices ProcessOracleEvents(pindex, cache, chainparams); + + // loan scheme, collateral ratio, liquidations ProcessLoanEvents(pindex, cache, chainparams); // Must be before set gov by height to clear futures in case there's a disabling of loan token in v3+ ProcessFutures(pindex, cache, chainparams); - if (pindex->nHeight >= chainparams.GetConsensus().FortCanningHeight) { - // Apply any pending GovVariable changes. Will come into effect on the next block. - auto storedGovVars = cache.GetStoredVariables(static_cast(pindex->nHeight)); - for (const auto& var : storedGovVars) { - if (var) { - CCustomCSView govCache(cache); - // Add to existing ATTRIBUTES instead of overwriting. - if (var->GetName() == "ATTRIBUTES") { - auto govVar = mnview.GetAttributes(); - govVar->time = pindex->GetBlockTime(); - if (govVar->Import(var->Export()) && govVar->Validate(govCache) && govVar->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*govVar)) { - govCache.Flush(); - } - } else if (var->Validate(govCache) && var->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*var)) { - govCache.Flush(); - } - } - } - cache.EraseStoredVariables(static_cast(pindex->nHeight)); - } + // update governance variables + ProcessGovEvents(pindex, cache, chainparams); // Migrate loan and collateral tokens to Gov vars. ProcessTokenToGovVar(pindex, cache, chainparams); @@ -3681,6 +3672,31 @@ void CChainState::ProcessOracleEvents(const CBlockIndex* pindex, CCustomCSView& }); } +void CChainState::ProcessGovEvents(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams) { + if (pindex->nHeight < chainparams.GetConsensus().FortCanningHeight) { + return; + } + + // Apply any pending GovVariable changes. Will come into effect on the next block. + auto storedGovVars = cache.GetStoredVariables(pindex->nHeight); + for (const auto& var : storedGovVars) { + if (var) { + CCustomCSView govCache(cache); + // Add to existing ATTRIBUTES instead of overwriting. + if (var->GetName() == "ATTRIBUTES") { + auto govVar = cache.GetAttributes(); + govVar->time = pindex->GetBlockTime(); + if (govVar->Import(var->Export()) && govVar->Validate(govCache) && govVar->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*govVar)) { + govCache.Flush(); + } + } else if (var->Validate(govCache) && var->Apply(govCache, pindex->nHeight) && govCache.SetVariable(*var)) { + govCache.Flush(); + } + } + } + cache.EraseStoredVariables(static_cast(pindex->nHeight)); +} + void CChainState::ProcessTokenToGovVar(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams) { // Migrate at +1 height so that GetLastHeight() in Gov var diff --git a/src/validation.h b/src/validation.h index a913de819e..1a62b5a0c0 100644 --- a/src/validation.h +++ b/src/validation.h @@ -765,6 +765,10 @@ class CChainState { static void ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams); + static void ProcessEunosEvents(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams); + + static void ProcessGovEvents(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams); + static void ProcessOracleEvents(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams); static void ProcessFutures(const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams); From e30f4229122653afb668a38765c096d77fb960fb Mon Sep 17 00:00:00 2001 From: Peter Bushnell Date: Wed, 25 May 2022 10:31:32 +0100 Subject: [PATCH 2/3] Migrate last amount to burn address on empty used pool --- src/validation.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/validation.cpp b/src/validation.cpp index af53933a5a..92c8519bf0 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3907,6 +3907,11 @@ static Res PoolSplits(CCustomCSView& view, CAmount& totalBalance, ATTRIBUTES& at return a.second > b.second; }); + // Special case. No liquidity providers in a previously used pool. + if (balancesToMigrate.empty() && oldPoolPair->totalLiquidity == CPoolPair::MINIMUM_LIQUIDITY) { + balancesToMigrate.emplace_back(Params().GetConsensus().burnAddress, CAmount{CPoolPair::MINIMUM_LIQUIDITY}); + } + for (auto& [owner, amount] : balancesToMigrate) { if (oldPoolPair->totalLiquidity < CPoolPair::MINIMUM_LIQUIDITY) { From 5b0a10bc0469f6a5910d03514b5d8b8d811c7489 Mon Sep 17 00:00:00 2001 From: Peter Bushnell Date: Wed, 25 May 2022 11:22:03 +0100 Subject: [PATCH 3/3] Handle case of burnaddress in pool split --- src/validation.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 92c8519bf0..1eb256ab23 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3914,17 +3914,21 @@ static Res PoolSplits(CCustomCSView& view, CAmount& totalBalance, ATTRIBUTES& at for (auto& [owner, amount] : balancesToMigrate) { - if (oldPoolPair->totalLiquidity < CPoolPair::MINIMUM_LIQUIDITY) { - throw std::runtime_error("totalLiquidity less than minimum."); - } + if (owner != Params().GetConsensus().burnAddress) { + view.CalculateOwnerRewards(owner, pindex->nHeight); - view.CalculateOwnerRewards(owner, pindex->nHeight); + res = view.SubBalance(owner, CTokenAmount{oldPoolId, amount}); + if (!res.ok) { + throw std::runtime_error(strprintf("SubBalance failed: %s", res.msg)); + } + } - res = view.SubBalance(owner, CTokenAmount{oldPoolId, amount}); - if (!res.ok) { - throw std::runtime_error(strprintf("SubBalance failed: %s", res.msg)); + if (oldPoolPair->totalLiquidity < CPoolPair::MINIMUM_LIQUIDITY) { + throw std::runtime_error("totalLiquidity less than minimum."); } + // First deposit to the pool has MINIMUM_LIQUIDITY removed and does not + // belong to anyone. Give this to the last person leaving the pool. if (oldPoolPair->totalLiquidity - amount == CPoolPair::MINIMUM_LIQUIDITY) { amount += CPoolPair::MINIMUM_LIQUIDITY; } @@ -3951,7 +3955,7 @@ static Res PoolSplits(CCustomCSView& view, CAmount& totalBalance, ATTRIBUTES& at view.AddBalance(owner, {newPoolPair.idTokenB, amountB}); }; - if (amountA <= 0 || amountB <= 0) { + if (amountA <= 0 || amountB <= 0 || owner == Params().GetConsensus().burnAddress) { refundBalances(); continue; }