Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameterised block time #2955

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bench/duplicate_inputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down
5 changes: 4 additions & 1 deletion src/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

#include <chain.h>

#include <dfi/govvariables/attributes.h>
#include <dfi/masternodes.h>

/**
* CChain implementation
*/
Expand Down Expand Up @@ -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<int64_t>::max();
}
Expand Down
15 changes: 0 additions & 15 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/dfi/consensus/masternodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)");
}
Expand Down
6 changes: 6 additions & 0 deletions src/dfi/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"); }
Expand All @@ -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); }
Expand Down
71 changes: 70 additions & 1 deletion src/dfi/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const std::map<std::string, uint8_t> &ATTRIBUTES::allowedParamIDs() {
{"dfip2211f", ParamIDs::DFIP2211F },
{"feature", ParamIDs::Feature },
{"foundation", ParamIDs::Foundation},
{"block_time", ParamIDs::BlockTime },
};
return params;
}
Expand All @@ -119,6 +120,7 @@ const std::map<uint8_t, std::string> &ATTRIBUTES::allowedExportParamsIDs() {
{ParamIDs::DFIP2211F, "dfip2211f" },
{ParamIDs::Feature, "feature" },
{ParamIDs::Foundation, "foundation"},
{ParamIDs::BlockTime, "block_time"},
};
return params;
}
Expand Down Expand Up @@ -283,6 +285,9 @@ const std::map<uint8_t, std::map<std::string, uint8_t>> &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,
{
Expand Down Expand Up @@ -388,6 +393,9 @@ const std::map<uint8_t, std::map<uint8_t, std::string>> &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,
{
Expand Down Expand Up @@ -491,6 +499,18 @@ static ResVal<CAttributeValue> VerifyUInt64(const std::string &str) {
return {x, Res::Ok()};
}

static ResVal<CAttributeValue> VerifyMoreThenZeroUInt32(const std::string &str) {
auto resVal = VerifyUInt32(str);
if (!resVal) {
return resVal;
}
const auto value = std::get<uint32_t>(*resVal.val);
if (value == 0) {
return DeFiErrors::GovVarVerifyFactor();
}
return resVal;
}

static ResVal<CAttributeValue> VerifyMoreThenZeroUInt64(const std::string &str) {
auto resVal = VerifyUInt64(str);
if (!resVal) {
Expand Down Expand Up @@ -817,6 +837,9 @@ const std::map<uint8_t, std::map<uint8_t, std::function<ResVal<CAttributeValue>(
{DFIPKeys::TransferDomain, VerifyBool},
{DFIPKeys::LiquidityCalcSamplingPeriod, VerifyMoreThenZeroInt64},
{DFIPKeys::AverageLiquidityPercentage, VerifyPctInt64},
{DFIPKeys::EmissionReduction, VerifyMoreThenZeroUInt32},
{DFIPKeys::TargetSpacing, VerifyMoreThenZeroInt64},
{DFIPKeys::TargetTimespam, VerifyMoreThenZeroInt64},
}},
{AttributeTypes::Locks,
{
Expand Down Expand Up @@ -994,6 +1017,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();
}
Expand Down Expand Up @@ -2083,6 +2111,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");
}
Expand Down Expand Up @@ -2421,7 +2453,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) {
Expand Down Expand Up @@ -2510,3 +2542,40 @@ Res ATTRIBUTES::Erase(CCustomCSView &mnview, uint32_t, const std::vector<std::st

return Res::Ok();
}

int64_t GetTargetSpacing(const CCustomCSView &view) {
const auto attributes = view.GetAttributes();
CDataStructureV0 key{AttributeTypes::Param, ParamIDs::BlockTime, DFIPKeys::TargetSpacing};
return attributes->GetValue(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;
}
12 changes: 12 additions & 0 deletions src/dfi/govvariables/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum ParamIDs : uint8_t {
Auction = 'i',
Foundation = 'j',
DFIP2211F = 'k',
BlockTime = 'l',
};

enum OracleIDs : uint8_t {
Expand Down Expand Up @@ -124,6 +125,9 @@ enum DFIPKeys : uint8_t {
TransferDomain = 'w',
LiquidityCalcSamplingPeriod = 'x',
AverageLiquidityPercentage = 'y',
EmissionReduction = 'z',
TargetSpacing = 'A',
TargetTimespam = 'B',
};

enum GovernanceKeys : uint8_t {
Expand Down Expand Up @@ -401,6 +405,14 @@ bool IsEVMEnabled(const std::shared_ptr<ATTRIBUTES> 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,
Expand Down
59 changes: 39 additions & 20 deletions src/dfi/loan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,23 +197,32 @@ std::optional<CInterestRateV3> CLoanView::GetInterestRate(const CVaultId &vaultI

// Precision 64bit
template <typename T>
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};
}

Expand Down Expand Up @@ -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<CCustomCSView *>(this), amounts.balances[id], tokenInterest, scheme->rate);

} else if (height >= static_cast<uint32_t>(Params().GetConsensus().DF14FortCanningHillHeight)) {
CBalances amounts;
ReadBy<LoanTokenAmount>(vaultId, amounts);
rate.interestPerBlock = {false,
InterestPerBlockCalculationV2(amounts.balances[id], token->interest, scheme->rate)};
rate.interestPerBlock = {
false,
InterestPerBlockCalculationV2(
*static_cast<CCustomCSView *>(this), amounts.balances[id], token->interest, scheme->rate)};
} else if (height >= static_cast<uint32_t>(Params().GetConsensus().DF12FortCanningMuseumHeight)) {
CAmount interestPerBlock = rate.interestPerBlock.amount.GetLow64();
interestPerBlock +=
std::ceil(InterestPerBlockCalculationV1<float>(loanIncreased, token->interest, scheme->rate));
interestPerBlock += std::ceil(InterestPerBlockCalculationV1<float>(
*static_cast<CCustomCSView *>(this), loanIncreased, token->interest, scheme->rate));
rate.interestPerBlock = {false, interestPerBlock};
} else {
rate.interestPerBlock.amount +=
InterestPerBlockCalculationV1<CAmount>(loanIncreased, token->interest, scheme->rate);
rate.interestPerBlock.amount += InterestPerBlockCalculationV1<CAmount>(
*static_cast<CCustomCSView *>(this), loanIncreased, token->interest, scheme->rate);
}

WriteInterestRate(std::make_pair(vaultId, id), rate, height);
Expand Down Expand Up @@ -387,19 +399,23 @@ Res CLoanView::DecreaseInterest(const uint32_t height,
if (height >= static_cast<uint32_t>(Params().GetConsensus().DF18FortCanningGreatWorldHeight)) {
CBalances amounts;
ReadBy<LoanTokenAmount>(vaultId, amounts);
rate.interestPerBlock = InterestPerBlockCalculationV3(amounts.balances[id], token->interest, scheme->rate);
rate.interestPerBlock = InterestPerBlockCalculationV3(
*static_cast<CCustomCSView *>(this), amounts.balances[id], token->interest, scheme->rate);
} else if (height >= static_cast<uint32_t>(Params().GetConsensus().DF14FortCanningHillHeight)) {
CBalances amounts;
ReadBy<LoanTokenAmount>(vaultId, amounts);
rate.interestPerBlock = {false,
InterestPerBlockCalculationV2(amounts.balances[id], token->interest, scheme->rate)};
rate.interestPerBlock = {
false,
InterestPerBlockCalculationV2(
*static_cast<CCustomCSView *>(this), amounts.balances[id], token->interest, scheme->rate)};
} else if (height >= static_cast<uint32_t>(Params().GetConsensus().DF12FortCanningMuseumHeight)) {
CAmount interestPerBlock = rate.interestPerBlock.amount.GetLow64();
CAmount newInterestPerBlock =
std::ceil(InterestPerBlockCalculationV1<float>(loanDecreased, token->interest, scheme->rate));
CAmount newInterestPerBlock = std::ceil(InterestPerBlockCalculationV1<float>(
*static_cast<CCustomCSView *>(this), loanDecreased, token->interest, scheme->rate));
rate.interestPerBlock = {false, std::max(CAmount{0}, interestPerBlock - newInterestPerBlock)};
} else {
auto interestPerBlock = InterestPerBlockCalculationV1<CAmount>(loanDecreased, token->interest, scheme->rate);
auto interestPerBlock = InterestPerBlockCalculationV1<CAmount>(
*static_cast<CCustomCSView *>(this), loanDecreased, token->interest, scheme->rate);
rate.interestPerBlock = rate.interestPerBlock.amount < interestPerBlock
? CInterestAmount{false, 0}
: CInterestAmount{false, rate.interestPerBlock.amount - interestPerBlock};
Expand All @@ -423,7 +439,10 @@ void CLoanView::ResetInterest(const uint32_t height,
ReadBy<LoanTokenAmount>(vaultId, amounts);

const CInterestRateV3 rate{
height, InterestPerBlockCalculationV3(amounts.balances[id], token->interest, scheme->rate), {false, 0}
height,
InterestPerBlockCalculationV3(
*static_cast<CCustomCSView *>(this), amounts.balances[id], token->interest, scheme->rate),
{false, 0}
};

WriteInterestRate(std::make_pair(vaultId, id), rate, height);
Expand Down
8 changes: 6 additions & 2 deletions src/dfi/loan.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <flushablestorage.h>
#include <script/script.h>

class CCustomCSView;

class CLoanSetCollateralToken {
public:
DCT_ID idToken{UINT_MAX};
Expand Down Expand Up @@ -335,8 +337,10 @@ CAmount CeilInterest(const base_uint<128> &value, uint32_t height);
std::string GetInterestPerBlockHighPrecisionString(const CInterestAmount &value);
std::optional<std::string> TryGetInterestPerBlockHighPrecisionString(const CInterestAmount &value);

base_uint<128> InterestPerBlockCalculationV2(CAmount amount, CAmount tokenInterest, CAmount schemeInterest);
CInterestAmount InterestPerBlockCalculationV3(CAmount amount, CAmount tokenInterest, CAmount schemeInterest);
CInterestAmount InterestPerBlockCalculationV3(const CCustomCSView &view,
CAmount amount,
CAmount tokenInterest,
CAmount schemeInterest);

class CLoanTakeLoanMessage {
public:
Expand Down
Loading
Loading