diff --git a/src/masternodes/masternodes.h b/src/masternodes/masternodes.h index 50623bc3f0b..2202cdb34a6 100644 --- a/src/masternodes/masternodes.h +++ b/src/masternodes/masternodes.h @@ -371,7 +371,7 @@ class CCustomCSView ByPoolLoanReward, CGovView :: ByName, ByHeightVars, CAnchorConfirmsView :: BtcTx, - COracleView :: ByName, FixedIntervalBlockKey, FixedIntervalPriceKey, PriceDeviation, + COracleView :: ByName, FixedIntervalBlockKey, FixedIntervalPriceKey, PriceDeviation, FixedIntervalHeightkKey, CICXOrderView :: ICXOrderCreationTx, ICXMakeOfferCreationTx, ICXSubmitDFCHTLCCreationTx, ICXSubmitEXTHTLCCreationTx, ICXClaimDFCHTLCCreationTx, ICXCloseOrderCreationTx, ICXCloseOfferCreationTx, ICXOrderOpenKey, ICXOrderCloseKey, ICXMakeOfferOpenKey, diff --git a/src/masternodes/oracles.cpp b/src/masternodes/oracles.cpp index 44ea551b9d5..44636d86fa6 100644 --- a/src/masternodes/oracles.cpp +++ b/src/masternodes/oracles.cpp @@ -200,4 +200,21 @@ uint32_t COracleView::GetIntervalBlock() const // Default return 60 * 60 / Params().GetConsensus().pos.nTargetSpacing; -} \ No newline at end of file +} + +Res COracleView::SetLastFixedPriceBlock(const uint32_t height) +{ + Write(FixedIntervalHeightkKey::prefix(), height); + return Res::Ok(); +} + +uint32_t COracleView::GetLastFixedPriceBlock() const +{ + uint32_t height; + if (Read(FixedIntervalHeightkKey::prefix(), height)) { + return height; + } + + // Default + return 0; +} diff --git a/src/masternodes/oracles.h b/src/masternodes/oracles.h index 5920e626f0b..12ddc6dd242 100644 --- a/src/masternodes/oracles.h +++ b/src/masternodes/oracles.h @@ -150,10 +150,14 @@ class COracleView : public virtual CStorageView Res SetIntervalBlock(const uint32_t blockInterval); uint32_t GetIntervalBlock() const; + Res SetLastFixedPriceBlock(const uint32_t height); + uint32_t GetLastFixedPriceBlock() const; + struct ByName { static constexpr uint8_t prefix() { return 'O'; } }; struct PriceDeviation { static constexpr uint8_t prefix() { return 'Y'; } }; struct FixedIntervalBlockKey { static constexpr uint8_t prefix() { return 'z'; } }; struct FixedIntervalPriceKey { static constexpr uint8_t prefix() { return 'y'; } }; + struct FixedIntervalHeightkKey { static constexpr uint8_t prefix() { return 'm'; } }; }; #endif // DEFI_MASTERNODES_ORACLES_H diff --git a/src/validation.cpp b/src/validation.cpp index c55a54d7e6e..15159f54f45 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3073,7 +3073,11 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca viewCache.Flush(); } - if (pindex->nHeight % chainparams.GetConsensus().blocksCollateralizationRatioCalculation() == 0) { + auto lastFixedPriceBlock = cache.GetLastFixedPriceBlock(); + auto blockCollateralRatioCalculation = chainparams.GetConsensus().blocksCollateralizationRatioCalculation(); + + if (pindex->nHeight % blockCollateralRatioCalculation == 0 + && (lastFixedPriceBlock == 0 || lastFixedPriceBlock > pindex->nHeight - blockCollateralRatioCalculation)) { bool useNextPrice = false, requireLivePrice = true; LogPrint(BCLog::LOAN,"ProcessLoanEvents()->ForEachVaultCollateral():\n"); /* Continued */ @@ -3259,6 +3263,7 @@ void CChainState::ProcessOracleEvents(const CBlockIndex* pindex, CCustomCSView& if (pindex->nHeight % blockInterval != 0) { return; } + bool actualPriceUpdate = false; cache.ForEachFixedIntervalPrice([&](const CTokenCurrencyPair&, CFixedIntervalPrice fixedIntervalPrice){ // Ensure that we update active and next regardless of state of things // And SetFixedIntervalPrice on each evaluation of this block. @@ -3273,20 +3278,22 @@ void CChainState::ProcessOracleEvents(const CBlockIndex* pindex, CCustomCSView& // Furthermore, the time stamp is always indicative of the // last price time. - auto nextPrice = fixedIntervalPrice.priceRecord[1]; + auto& nextPrice = fixedIntervalPrice.priceRecord[1]; if (nextPrice > 0) { - fixedIntervalPrice.priceRecord[0] = fixedIntervalPrice.priceRecord[1]; + auto& currentPrice = fixedIntervalPrice.priceRecord[0]; + actualPriceUpdate = actualPriceUpdate || nextPrice != currentPrice; + currentPrice = nextPrice; } // keep timestamp updated fixedIntervalPrice.timestamp = pindex->nTime; // Use -1 to indicate empty price - fixedIntervalPrice.priceRecord[1] = -1; + nextPrice = -1; auto aggregatePrice = GetAggregatePrice(cache, fixedIntervalPrice.priceFeedId.first, fixedIntervalPrice.priceFeedId.second, pindex->nTime); if (aggregatePrice) { - fixedIntervalPrice.priceRecord[1] = aggregatePrice; + nextPrice = aggregatePrice; } else { LogPrint(BCLog::ORACLE,"ProcessOracleEvents(): No aggregate price available: %s\n", aggregatePrice.msg); } @@ -3296,6 +3303,10 @@ void CChainState::ProcessOracleEvents(const CBlockIndex* pindex, CCustomCSView& } return true; }); + + if (actualPriceUpdate && pindex->nHeight >= chainparams.GetConsensus().FortCanningHillHeight) { + cache.SetLastFixedPriceBlock(pindex->nHeight); + } } bool CChainState::FlushStateToDisk(