Skip to content

Commit 4ba40fb

Browse files
ogabrielidesknst
authored andcommitted
feat: v20 evonodes payment adjustment - cummulative changes from dashpay#5493
1 parent c5b42c9 commit 4ba40fb

File tree

6 files changed

+43
-20
lines changed

6 files changed

+43
-20
lines changed

src/evo/deterministicmns.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNPayee(const CBlockIndex* pIndex)
182182
}
183183

184184
bool isv19Active = llmq::utils::IsV19Active(pIndex);
185-
// Starting from v19 and until v20 (Platform release), HPMN will be rewarded 4 blocks in a row
186-
// TODO: Skip this code once v20 is active
185+
bool isMNRewardReallocation = llmq::utils::IsMNRewardReallocationActive(pIndex);
186+
// Starting from v19 and until MNRewardReallocation (Platform release), HPMN will be rewarded 4 blocks in a row
187187
CDeterministicMNCPtr best = nullptr;
188-
if (isv19Active) {
188+
if (isv19Active && !isMNRewardReallocation) {
189189
ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) {
190190
if (dmn->pdmnState->nLastPaidHeight == nHeight) {
191191
// We found the last MN Payee.
@@ -211,7 +211,12 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNPayee(const CBlockIndex* pIndex)
211211
return best;
212212
}
213213

214-
std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(int nCount) const
214+
std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayeesAtChainTip(int nCount) const
215+
{
216+
return GetProjectedMNPayees(::ChainActive()[nHeight], nCount);
217+
}
218+
219+
std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(const CBlockIndex* const pindex, int nCount) const
215220
{
216221
if (nCount < 0 ) {
217222
return {};
@@ -223,11 +228,12 @@ std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(int
223228

224229
auto remaining_hpmn_payments = 0;
225230
CDeterministicMNCPtr hpmn_to_be_skipped = nullptr;
231+
bool isMNRewardReallocation = llmq::utils::IsMNRewardReallocationActive(pindex);
226232
ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) {
227233
if (dmn->pdmnState->nLastPaidHeight == nHeight) {
228234
// We found the last MN Payee.
229235
// If the last payee is a HPMN, we need to check its consecutive payments and pay him again if needed
230-
if (dmn->nType == MnType::HighPerformance && dmn->pdmnState->nConsecutivePayments < dmn_types::HighPerformance.voting_weight) {
236+
if (!isMNRewardReallocation && dmn->nType == MnType::HighPerformance && dmn->pdmnState->nConsecutivePayments < dmn_types::HighPerformance.voting_weight) {
231237
remaining_hpmn_payments = dmn_types::HighPerformance.voting_weight - dmn->pdmnState->nConsecutivePayments;
232238
for ([[maybe_unused]] auto _ : irange::range(remaining_hpmn_payments)) {
233239
result.emplace_back(dmn);
@@ -720,6 +726,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
720726

721727
DecreasePoSePenalties(newList);
722728

729+
bool isMNRewardReallocation = llmq::utils::IsMNRewardReallocationActive(pindexPrev);
730+
723731
// we skip the coinbase
724732
for (int i = 1; i < (int)block.vtx.size(); i++) {
725733
const CTransaction& tx = *block.vtx[i];
@@ -937,11 +945,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
937945
auto dmn = newList.GetMN(payee->proTxHash);
938946
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
939947
newState->nLastPaidHeight = nHeight;
940-
// Starting from v19 and until v20, HPMN will be paid 4 blocks in a row
948+
// Starting from v19 and until MNRewardReallocation, HPMN will be paid 4 blocks in a row
941949
// No need to check if v19 is active, since HPMN ProRegTx are allowed only after v19 activation
942-
// TODO: Skip this code once v20 is active
943950
// Note: If the payee wasn't found in the current block that's fine
944-
if (dmn->nType == MnType::HighPerformance) {
951+
if (dmn->nType == MnType::HighPerformance && !isMNRewardReallocation) {
945952
++newState->nConsecutivePayments;
946953
if (debugLogs) {
947954
LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s is a HPMN, bumping nConsecutivePayments to %d\n",
@@ -959,8 +966,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
959966
// reset nConsecutivePayments on non-paid HPMNs
960967
auto newList2 = newList;
961968
newList2.ForEachMN(false, [&](auto& dmn) {
962-
if (payee != nullptr && dmn.proTxHash == payee->proTxHash) return;
963969
if (dmn.nType != MnType::HighPerformance) return;
970+
if (payee != nullptr && dmn.proTxHash == payee->proTxHash && !isMNRewardReallocation) return;
964971
if (dmn.pdmnState->nConsecutivePayments == 0) return;
965972
if (debugLogs) {
966973
LogPrint(BCLog::MNPAYMENTS, "CDeterministicMNManager::%s -- MN %s, reset nConsecutivePayments %d->0\n",

src/evo/deterministicmns.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@ class CDeterministicMNList
342342
* @param nCount the number of payees to return. "nCount = max()"" means "all", use it to avoid calling GetValidWeightedMNsCount twice.
343343
* @return
344344
*/
345-
[[nodiscard]] std::vector<CDeterministicMNCPtr> GetProjectedMNPayees(int nCount = std::numeric_limits<int>::max()) const;
345+
[[nodiscard]] std::vector<CDeterministicMNCPtr> GetProjectedMNPayees(const CBlockIndex* const pindex, int nCount = std::numeric_limits<int>::max()) const;
346+
[[nodiscard]] std::vector<CDeterministicMNCPtr> GetProjectedMNPayeesAtChainTip(int nCount = std::numeric_limits<int>::max()) const;
346347

347348
/**
348349
* Calculate a quorum based on the modifier. The resulting list is deterministically sorted by score

src/llmq/utils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ bool IsV20Active(const CBlockIndex* pindex)
726726

727727
bool IsMNRewardReallocationActive(const CBlockIndex* pindex)
728728
{
729+
assert(pindex);
729730
if (!IsV20Active(pindex)) return false;
730731

731732
LOCK(cs_llmq_vbc);

src/qt/masternodelist.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ void MasternodeList::updateDIP3List()
191191

192192
nTimeUpdatedDIP3 = GetTime();
193193

194-
auto projectedPayees = mnList.GetProjectedMNPayees();
194+
auto projectedPayees = mnList.GetProjectedMNPayeesAtChainTip();
195195
std::map<uint256, int> nextPayments;
196196
for (size_t i = 0; i < projectedPayees.size(); i++) {
197197
const auto& dmn = projectedPayees[i];

src/rpc/masternode.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ static UniValue masternode_count(const JSONRPCRequest& request)
136136
static UniValue GetNextMasternodeForPayment(int heightShift)
137137
{
138138
auto mnList = deterministicMNManager->GetListAtChainTip();
139-
auto payees = mnList.GetProjectedMNPayees(heightShift);
139+
auto payees = mnList.GetProjectedMNPayeesAtChainTip(heightShift);
140140
if (payees.empty())
141141
return "unknown";
142142
auto payee = payees.back();
@@ -362,7 +362,7 @@ static UniValue masternode_winners(const JSONRPCRequest& request, const Chainsta
362362
obj.pushKV(strprintf("%d", h), strPayments);
363363
}
364364

365-
auto projection = deterministicMNManager->GetListForBlock(pindexTip).GetProjectedMNPayees(20);
365+
auto projection = deterministicMNManager->GetListForBlock(pindexTip).GetProjectedMNPayees(pindexTip, 20);
366366
for (size_t i = 0; i < projection.size(); i++) {
367367
int h = nChainTipHeight + 1 + i;
368368
std::string strPayments = GetRequiredPaymentsString(h, projection[i]);

test/functional/feature_llmq_hpmn.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,41 +114,55 @@ def run_test(self):
114114
self.log.info("Test that HPMNs are paid 4x blocks in a row")
115115
self.test_hpmn_payments(window_analysis=256)
116116

117+
self.activate_mn_rr()
118+
self.log.info("Activated MN RewardReallocation at height:" + str(self.nodes[0].getblockcount()))
119+
120+
# Generate a few blocks to make HPMN/MN analysis on a pure MN RewardReallocation window
121+
self.bump_mocktime(1)
122+
self.nodes[0].generate(4)
123+
self.sync_blocks()
124+
125+
self.log.info("Test that HPMNs are paid 1 block in a row after MN RewardReallocation activation")
126+
self.test_hpmn_payments(window_analysis=256, v20active=True)
127+
117128
self.log.info(self.nodes[0].masternodelist())
118129

119130
return
120131

121-
def test_hpmn_payments(self, window_analysis):
132+
def test_hpmn_payments(self, window_analysis, v20active=False):
122133
current_hpmn = None
123134
consecutive_payments = 0
135+
n_payments = 0 if v20active else 4
124136
for i in range(0, window_analysis):
125137
payee = self.get_mn_payee_for_block(self.nodes[0].getbestblockhash())
126138
if payee is not None and payee.hpmn:
127139
if current_hpmn is not None and payee.proTxHash == current_hpmn.proTxHash:
128140
# same HPMN
129141
assert consecutive_payments > 0
130-
consecutive_payments += 1
142+
if not v20active:
143+
consecutive_payments += 1
131144
consecutive_payments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments']
132145
assert_equal(consecutive_payments, consecutive_payments_rpc)
133146
else:
134147
# new HPMN
135148
if current_hpmn is not None:
136-
# make sure the old one was paid 4 times in a row
137-
assert_equal(consecutive_payments, 4)
149+
# make sure the old one was paid N times in a row
150+
assert_equal(consecutive_payments, n_payments)
138151
consecutive_payments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments']
139152
# old HPMN should have its nConsecutivePayments reset to 0
140153
assert_equal(consecutive_payments_rpc, 0)
141154
consecutive_payments_rpc = self.nodes[0].protx('info', payee.proTxHash)['state']['consecutivePayments']
142155
# if hpmn is the one we start "for" loop with,
143156
# we have no idea how many times it was paid before - rely on rpc results here
144-
consecutive_payments = consecutive_payments_rpc if i == 0 and current_hpmn is None else 1
157+
new_payment_value = 0 if v20active else 1
158+
consecutive_payments = consecutive_payments_rpc if i == 0 and current_hpmn is None else new_payment_value
145159
current_hpmn = payee
146160
assert_equal(consecutive_payments, consecutive_payments_rpc)
147161
else:
148162
# not a HPMN
149163
if current_hpmn is not None:
150-
# make sure the old one was paid 4 times in a row
151-
assert_equal(consecutive_payments, 4)
164+
# make sure the old one was paid N times in a row
165+
assert_equal(consecutive_payments, n_payments)
152166
consecutive_payments_rpc = self.nodes[0].protx('info', current_hpmn.proTxHash)['state']['consecutivePayments']
153167
# old HPMN should have its nConsecutivePayments reset to 0
154168
assert_equal(consecutive_payments_rpc, 0)

0 commit comments

Comments
 (0)