From 1b6aa08dc6d0bc6bbe25407cef96c4fcb1a78166 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Sat, 29 Jun 2024 07:53:37 +0100 Subject: [PATCH 01/16] Parameterised block time --- src/bench/duplicate_inputs.cpp | 2 +- src/chain.cpp | 5 +- src/consensus/params.h | 15 ------ src/dfi/consensus/masternodes.cpp | 2 +- src/dfi/errors.h | 6 +++ src/dfi/govvariables/attributes.cpp | 71 ++++++++++++++++++++++++++++- src/dfi/govvariables/attributes.h | 12 +++++ src/dfi/loan.cpp | 59 ++++++++++++++++-------- src/dfi/loan.h | 8 +++- src/dfi/masternodes.cpp | 4 +- src/dfi/masternodes.h | 2 +- src/dfi/oracles.cpp | 3 +- src/dfi/poolpairs.cpp | 17 ++++--- src/dfi/rpc_masternodes.cpp | 8 +--- src/dfi/validation.cpp | 10 ++-- src/miner.cpp | 5 +- src/net_processing.cpp | 11 +++-- src/pos.cpp | 7 +-- src/rest.cpp | 4 +- src/rpc/blockchain.cpp | 47 +++++++++++-------- src/rpc/blockchain.h | 3 +- src/rpc/mining.cpp | 5 +- src/test/dip1fork_tests.cpp | 24 +++++----- src/test/validation_tests.cpp | 5 +- src/validation.cpp | 18 ++++---- src/validation.h | 2 +- 26 files changed, 236 insertions(+), 119 deletions(-) diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 46e0f348e15..656320f4c58 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -39,7 +39,7 @@ static void DuplicateInputs(benchmark::State& state) coinbaseTx.vin[0].prevout.SetNull(); coinbaseTx.vout.resize(1); coinbaseTx.vout[0].scriptPubKey = SCRIPT_PUB; - coinbaseTx.vout[0].nValue = GetBlockSubsidy(nHeight, chainparams.GetConsensus()); + coinbaseTx.vout[0].nValue = GetBlockSubsidy(*pcustomcsview, nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; diff --git a/src/chain.cpp b/src/chain.cpp index bb867ea87ac..e40abf7bd57 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -5,6 +5,9 @@ #include +#include +#include + /** * CChain implementation */ @@ -144,7 +147,7 @@ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& fr r = from.nChainWork - to.nChainWork; sign = -1; } - r = r * arith_uint256(params.pos.nTargetSpacing) / GetBlockProof(tip); + r = r * arith_uint256(GetTargetSpacing(*pcustomcsview)) / GetBlockProof(tip); if (r.bits() > 63) { return sign * std::numeric_limits::max(); } diff --git a/src/consensus/params.h b/src/consensus/params.h index 17bb5f2343c..fa3c58c4005 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -146,21 +146,6 @@ struct Params { }; PoS pos; - uint32_t blocksPerDay() const { - static const uint32_t blocks = 60 * 60 * 24 / pos.nTargetSpacing; - return blocks; - } - - uint32_t blocksCollateralizationRatioCalculation() const { - static const uint32_t blocks = 15 * 60 / pos.nTargetSpacing; - return blocks; - } - - uint32_t blocksCollateralAuction() const { - static const uint32_t blocks = 6 * 60 * 60 / pos.nTargetSpacing; - return blocks; - } - /** * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, * (nTargetTimespan / nTargetSpacing) which is also used for BIP9 deployments. diff --git a/src/dfi/consensus/masternodes.cpp b/src/dfi/consensus/masternodes.cpp index 2c1b16741d8..b5192f56714 100644 --- a/src/dfi/consensus/masternodes.cpp +++ b/src/dfi/consensus/masternodes.cpp @@ -15,7 +15,7 @@ Res CMasternodesConsensus::CheckMasternodeCreationTx() const { const auto height = txCtx.GetHeight(); const auto &tx = txCtx.GetTransaction(); - if (tx.vout.size() < 2 || tx.vout[0].nValue < GetMnCreationFee(height) || tx.vout[0].nTokenId != DCT_ID{0} || + if (tx.vout.size() < 2 || tx.vout[0].nValue < GetMnCreationFee() || tx.vout[0].nTokenId != DCT_ID{0} || tx.vout[1].nValue != GetMnCollateralAmount(height) || tx.vout[1].nTokenId != DCT_ID{0}) { return Res::Err("malformed tx vouts (wrong creation fee or collateral amount)"); } diff --git a/src/dfi/errors.h b/src/dfi/errors.h index 8e2da916b44..f679fbadd04 100644 --- a/src/dfi/errors.h +++ b/src/dfi/errors.h @@ -242,6 +242,10 @@ class DeFiErrors { return Res::Err("Unsupported key for Rules {%d}", type); } + static Res GovVarVariableUnsupportedBlockTimeType(const unsigned char type) { + return Res::Err("Unsupported key for BlockTime {%d}", type); + } + static Res GovVarVariableUnsupportedParamType() { return Res::Err("Unsupported Param ID"); } static Res GovVarVariableUnsupportedGovType() { return Res::Err("Unsupported Governance ID"); } @@ -264,6 +268,8 @@ class DeFiErrors { static Res GovVarValidateDF23Height() { return Res::Err("Cannot be set before DF23Height"); } + static Res GovVarValidateDF24Height() { return Res::Err("Cannot be set before DF24Height"); } + static Res GovVarValidateToken(const uint32_t token) { return Res::Err("No such token (%d)", token); } static Res GovVarValidateTokenExist(const uint32_t token) { return Res::Err("Token (%d) does not exist", token); } diff --git a/src/dfi/govvariables/attributes.cpp b/src/dfi/govvariables/attributes.cpp index a3fc4e7e58b..5e0a3a7a546 100644 --- a/src/dfi/govvariables/attributes.cpp +++ b/src/dfi/govvariables/attributes.cpp @@ -104,6 +104,7 @@ const std::map &ATTRIBUTES::allowedParamIDs() { {"dfip2211f", ParamIDs::DFIP2211F }, {"feature", ParamIDs::Feature }, {"foundation", ParamIDs::Foundation}, + {"block_time", ParamIDs::BlockTime }, }; return params; } @@ -117,6 +118,7 @@ const std::map &ATTRIBUTES::allowedExportParamsIDs() { {ParamIDs::DFIP2211F, "dfip2211f" }, {ParamIDs::Feature, "feature" }, {ParamIDs::Foundation, "foundation"}, + {ParamIDs::BlockTime, "block_time"}, }; return params; } @@ -281,6 +283,9 @@ const std::map> &ATTRIBUTES::allowedKeys {"transferdomain", DFIPKeys::TransferDomain}, {"liquidity_calc_sampling_period", DFIPKeys::LiquidityCalcSamplingPeriod}, {"average_liquidity_percentage", DFIPKeys::AverageLiquidityPercentage}, + {"emission_reduction", DFIPKeys::EmissionReduction}, + {"target_spacing", DFIPKeys::TargetSpacing}, + {"target_timespan", DFIPKeys::TargetTimespam}, }}, {AttributeTypes::EVMType, { @@ -386,6 +391,9 @@ const std::map> &ATTRIBUTES::displayKeys {DFIPKeys::TransferDomain, "transferdomain"}, {DFIPKeys::LiquidityCalcSamplingPeriod, "liquidity_calc_sampling_period"}, {DFIPKeys::AverageLiquidityPercentage, "average_liquidity_percentage"}, + {DFIPKeys::EmissionReduction, "emission_reduction"}, + {DFIPKeys::TargetSpacing, "target_spacing"}, + {DFIPKeys::TargetTimespam, "target_timespan"}, }}, {AttributeTypes::EVMType, { @@ -489,6 +497,18 @@ static ResVal VerifyUInt64(const std::string &str) { return {x, Res::Ok()}; } +static ResVal VerifyMoreThenZeroUInt32(const std::string &str) { + auto resVal = VerifyUInt32(str); + if (!resVal) { + return resVal; + } + const auto value = std::get(*resVal.val); + if (value == 0) { + return DeFiErrors::GovVarVerifyFactor(); + } + return resVal; +} + static ResVal VerifyMoreThenZeroUInt64(const std::string &str) { auto resVal = VerifyUInt64(str); if (!resVal) { @@ -815,6 +835,9 @@ const std::map( {DFIPKeys::TransferDomain, VerifyBool}, {DFIPKeys::LiquidityCalcSamplingPeriod, VerifyMoreThenZeroInt64}, {DFIPKeys::AverageLiquidityPercentage, VerifyPctInt64}, + {DFIPKeys::EmissionReduction, VerifyMoreThenZeroUInt32}, + {DFIPKeys::TargetSpacing, VerifyMoreThenZeroInt64}, + {DFIPKeys::TargetTimespam, VerifyMoreThenZeroInt64}, }}, {AttributeTypes::Locks, { @@ -992,6 +1015,11 @@ static Res CheckValidAttrV0Key(const uint8_t type, const uint32_t typeId, const if (typeKey != DFIPKeys::Members) { return DeFiErrors::GovVarVariableUnsupportedFoundationType(typeKey); } + } else if (typeId == ParamIDs::BlockTime) { + if (typeKey != DFIPKeys::EmissionReduction && typeKey != DFIPKeys::TargetSpacing && + typeKey != DFIPKeys::TargetTimespam) { + return DeFiErrors::GovVarVariableUnsupportedBlockTimeType(typeKey); + } } else { return DeFiErrors::GovVarVariableUnsupportedParamType(); } @@ -2075,6 +2103,10 @@ Res ATTRIBUTES::Validate(const CCustomCSView &view) const { return DeFiErrors::GovVarValidateBlockPeriod(); } } + } else if (attrV0->typeId == ParamIDs::BlockTime) { + if (view.GetLastHeight() < Params().GetConsensus().DF24Height) { + return DeFiErrors::GovVarValidateDF24Height(); + } } else if (attrV0->typeId != ParamIDs::DFIP2201) { return Res::Err("Unrecognised param id"); } @@ -2413,7 +2445,7 @@ Res ATTRIBUTES::Apply(CCustomCSView &mnview, const uint32_t height) { return DeFiErrors::GovVarApplyAutoNoToken(split); } - const auto startHeight = attrV0->key - Params().GetConsensus().blocksPerDay() / 2; + const auto startHeight = attrV0->key - BlocksPerDay(mnview) / 2; if (height < startHeight) { auto var = GovVariable::Create("ATTRIBUTES"); if (!var) { @@ -2502,3 +2534,40 @@ Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t, const std::vectorGetValue(key, Params().GetConsensus().pos.nTargetSpacing); +} + +int64_t GetTargetTimespan(const CCustomCSView &view) { + const auto attributes = view.GetAttributes(); + CDataStructureV0 key{AttributeTypes::Param, ParamIDs::BlockTime, DFIPKeys::TargetTimespam}; + return attributes->GetValue(key, Params().GetConsensus().pos.nTargetTimespanV2); +} + +int64_t DifficultyAdjustment(const CCustomCSView &view) { + return GetTargetTimespan(view) / GetTargetSpacing(view); +} + +int32_t GetEmissionReduction(const CCustomCSView &view) { + const auto attributes = view.GetAttributes(); + CDataStructureV0 key{AttributeTypes::Param, ParamIDs::BlockTime, DFIPKeys::EmissionReduction}; + return attributes->GetValue(key, Params().GetConsensus().emissionReductionPeriod); +} + +uint32_t BlocksPerDay(const CCustomCSView &view) { + uint32_t blocks = 60 * 60 * 24 / GetTargetSpacing(view); + return blocks; +} + +uint32_t BlocksCollateralizationRatioCalculation(const CCustomCSView &view) { + uint32_t blocks = 15 * 60 / GetTargetSpacing(view); + return blocks; +} + +uint32_t BlocksCollateralAuction(const CCustomCSView &view) { + uint32_t blocks = 6 * 60 * 60 / GetTargetSpacing(view); + return blocks; +} diff --git a/src/dfi/govvariables/attributes.h b/src/dfi/govvariables/attributes.h index a1b0d920f5a..358bfb7a211 100644 --- a/src/dfi/govvariables/attributes.h +++ b/src/dfi/govvariables/attributes.h @@ -44,6 +44,7 @@ enum ParamIDs : uint8_t { Auction = 'i', Foundation = 'j', DFIP2211F = 'k', + BlockTime = 'l', }; enum OracleIDs : uint8_t { @@ -124,6 +125,9 @@ enum DFIPKeys : uint8_t { TransferDomain = 'w', LiquidityCalcSamplingPeriod = 'x', AverageLiquidityPercentage = 'y', + EmissionReduction = 'z', + TargetSpacing = 'A', + TargetTimespam = 'B', }; enum GovernanceKeys : uint8_t { @@ -401,6 +405,14 @@ bool IsEVMEnabled(const std::shared_ptr attributes); bool IsEVMEnabled(const CCustomCSView &view); Res StoreGovVars(const CGovernanceHeightMessage &obj, CCustomCSView &view); +int64_t GetTargetSpacing(const CCustomCSView &view); +int64_t GetTargetTimespan(const CCustomCSView &view); +int64_t DifficultyAdjustment(const CCustomCSView &view); +int32_t GetEmissionReduction(const CCustomCSView &view); +uint32_t BlocksPerDay(const CCustomCSView &view); +uint32_t BlocksCollateralizationRatioCalculation(const CCustomCSView &view); +uint32_t BlocksCollateralAuction(const CCustomCSView &view); + enum GovVarsFilter { All, NoAttributes, diff --git a/src/dfi/loan.cpp b/src/dfi/loan.cpp index 48cc952ace8..1e6e9736298 100644 --- a/src/dfi/loan.cpp +++ b/src/dfi/loan.cpp @@ -197,23 +197,32 @@ std::optional CLoanView::GetInterestRate(const CVaultId &vaultI // Precision 64bit template -inline T InterestPerBlockCalculationV1(CAmount amount, CAmount tokenInterest, CAmount schemeInterest) { +inline T InterestPerBlockCalculationV1(const CCustomCSView &view, + CAmount amount, + CAmount tokenInterest, + CAmount schemeInterest) { const auto netInterest = (tokenInterest + schemeInterest) / 100; // in % - static const auto blocksPerYear = T(365) * Params().GetConsensus().blocksPerDay(); + static const auto blocksPerYear = T(365) * BlocksPerDay(view); return MultiplyAmounts(netInterest, amount) / blocksPerYear; } // Precision 128bit -inline base_uint<128> InterestPerBlockCalculationV2(CAmount amount, CAmount tokenInterest, CAmount schemeInterest) { +inline base_uint<128> InterestPerBlockCalculationV2(const CCustomCSView &view, + CAmount amount, + CAmount tokenInterest, + CAmount schemeInterest) { const auto netInterest = (tokenInterest + schemeInterest) / 100; // in % - static const auto blocksPerYear = 365 * Params().GetConsensus().blocksPerDay(); + static const auto blocksPerYear = 365 * BlocksPerDay(view); return arith_uint256(amount) * netInterest * COIN / blocksPerYear; } // Precision 128bit with negative interest -CInterestAmount InterestPerBlockCalculationV3(CAmount amount, CAmount tokenInterest, CAmount schemeInterest) { +CInterestAmount InterestPerBlockCalculationV3(const CCustomCSView &view, + CAmount amount, + CAmount tokenInterest, + CAmount schemeInterest) { const auto netInterest = (tokenInterest + schemeInterest) / 100; // in % - static const auto blocksPerYear = 365 * Params().GetConsensus().blocksPerDay(); + static const auto blocksPerYear = 365 * BlocksPerDay(view); return {netInterest < 0 && amount > 0, arith_uint256(amount) * std::abs(netInterest) * COIN / blocksPerYear}; } @@ -324,21 +333,24 @@ Res CLoanView::IncreaseInterest(const uint32_t height, // Use argument token interest as update from Gov var TX will not be applied to GetLoanTokenByID at this point // in time. - rate.interestPerBlock = InterestPerBlockCalculationV3(amounts.balances[id], tokenInterest, scheme->rate); + rate.interestPerBlock = InterestPerBlockCalculationV3( + *static_cast(this), amounts.balances[id], tokenInterest, scheme->rate); } else if (height >= static_cast(Params().GetConsensus().DF14FortCanningHillHeight)) { CBalances amounts; ReadBy(vaultId, amounts); - rate.interestPerBlock = {false, - InterestPerBlockCalculationV2(amounts.balances[id], token->interest, scheme->rate)}; + rate.interestPerBlock = { + false, + InterestPerBlockCalculationV2( + *static_cast(this), amounts.balances[id], token->interest, scheme->rate)}; } else if (height >= static_cast(Params().GetConsensus().DF12FortCanningMuseumHeight)) { CAmount interestPerBlock = rate.interestPerBlock.amount.GetLow64(); - interestPerBlock += - std::ceil(InterestPerBlockCalculationV1(loanIncreased, token->interest, scheme->rate)); + interestPerBlock += std::ceil(InterestPerBlockCalculationV1( + *static_cast(this), loanIncreased, token->interest, scheme->rate)); rate.interestPerBlock = {false, interestPerBlock}; } else { - rate.interestPerBlock.amount += - InterestPerBlockCalculationV1(loanIncreased, token->interest, scheme->rate); + rate.interestPerBlock.amount += InterestPerBlockCalculationV1( + *static_cast(this), loanIncreased, token->interest, scheme->rate); } WriteInterestRate(std::make_pair(vaultId, id), rate, height); @@ -387,19 +399,23 @@ Res CLoanView::DecreaseInterest(const uint32_t height, if (height >= static_cast(Params().GetConsensus().DF18FortCanningGreatWorldHeight)) { CBalances amounts; ReadBy(vaultId, amounts); - rate.interestPerBlock = InterestPerBlockCalculationV3(amounts.balances[id], token->interest, scheme->rate); + rate.interestPerBlock = InterestPerBlockCalculationV3( + *static_cast(this), amounts.balances[id], token->interest, scheme->rate); } else if (height >= static_cast(Params().GetConsensus().DF14FortCanningHillHeight)) { CBalances amounts; ReadBy(vaultId, amounts); - rate.interestPerBlock = {false, - InterestPerBlockCalculationV2(amounts.balances[id], token->interest, scheme->rate)}; + rate.interestPerBlock = { + false, + InterestPerBlockCalculationV2( + *static_cast(this), amounts.balances[id], token->interest, scheme->rate)}; } else if (height >= static_cast(Params().GetConsensus().DF12FortCanningMuseumHeight)) { CAmount interestPerBlock = rate.interestPerBlock.amount.GetLow64(); - CAmount newInterestPerBlock = - std::ceil(InterestPerBlockCalculationV1(loanDecreased, token->interest, scheme->rate)); + CAmount newInterestPerBlock = std::ceil(InterestPerBlockCalculationV1( + *static_cast(this), loanDecreased, token->interest, scheme->rate)); rate.interestPerBlock = {false, std::max(CAmount{0}, interestPerBlock - newInterestPerBlock)}; } else { - auto interestPerBlock = InterestPerBlockCalculationV1(loanDecreased, token->interest, scheme->rate); + auto interestPerBlock = InterestPerBlockCalculationV1( + *static_cast(this), loanDecreased, token->interest, scheme->rate); rate.interestPerBlock = rate.interestPerBlock.amount < interestPerBlock ? CInterestAmount{false, 0} : CInterestAmount{false, rate.interestPerBlock.amount - interestPerBlock}; @@ -423,7 +439,10 @@ void CLoanView::ResetInterest(const uint32_t height, ReadBy(vaultId, amounts); const CInterestRateV3 rate{ - height, InterestPerBlockCalculationV3(amounts.balances[id], token->interest, scheme->rate), {false, 0} + height, + InterestPerBlockCalculationV3( + *static_cast(this), amounts.balances[id], token->interest, scheme->rate), + {false, 0} }; WriteInterestRate(std::make_pair(vaultId, id), rate, height); diff --git a/src/dfi/loan.h b/src/dfi/loan.h index 1191068db61..ebc6a148a87 100644 --- a/src/dfi/loan.h +++ b/src/dfi/loan.h @@ -11,6 +11,8 @@ #include #include