Skip to content

Commit 3f4b50a

Browse files
Merge #6222: fix: adjust payee predictions after mn_rr activation, add tests
715bc1a test: check `masternode winners` before and after mn_rr (UdjinM6) 9d47cd2 fix: adjust payee predictions after mn_rr activation (UdjinM6) Pull request description: ## Issue being fixed or feature implemented Payment predictions in GUI are wrong when mn_rr is active, `masternode winners` RPC is affected by the same issue too. Actual payments aren't affected. ## What was done? Adjust calculations, add tests for `masternode winners`. ## How Has This Been Tested? Run dash-qt on testnet, check "Next Payment" on "Masternode" tab. Run tests. ## Breaking Changes n/a ## Checklist: - [x] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [ ] I have assigned this pull request to a milestone ACKs for top commit: PastaPastaPasta: utACK 715bc1a Tree-SHA512: 293c77974bcb50c6f9c51449d7bb12f89ad8db5871cad3a6083fe1951fe77e0deba8de7688b2f600fabe977bdc7390a66a984a6a076be19183c23742e00e27bf
2 parents f2940c4 + 715bc1a commit 3f4b50a

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

src/evo/deterministicmns.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,16 @@ std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(gsl
215215
if (nCount < 0 ) {
216216
return {};
217217
}
218-
const auto weighted_count = GetValidWeightedMNsCount();
218+
const bool isMNRewardReallocation = DeploymentActiveAfter(pindexPrev, Params().GetConsensus(),
219+
Consensus::DEPLOYMENT_MN_RR);
220+
const auto weighted_count = isMNRewardReallocation ? GetValidMNsCount() : GetValidWeightedMNsCount();
219221
nCount = std::min(nCount, int(weighted_count));
220222

221223
std::vector<CDeterministicMNCPtr> result;
222224
result.reserve(weighted_count);
223225

224226
int remaining_evo_payments{0};
225227
CDeterministicMNCPtr evo_to_be_skipped{nullptr};
226-
const bool isMNRewardReallocation{DeploymentActiveAfter(pindexPrev, Params().GetConsensus(), Consensus::DEPLOYMENT_MN_RR)};
227228
if (!isMNRewardReallocation) {
228229
ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) {
229230
if (dmn->pdmnState->nLastPaidHeight == nHeight) {
@@ -242,7 +243,7 @@ std::vector<CDeterministicMNCPtr> CDeterministicMNList::GetProjectedMNPayees(gsl
242243

243244
ForEachMNShared(true, [&](const CDeterministicMNCPtr& dmn) {
244245
if (dmn == evo_to_be_skipped) return;
245-
for ([[maybe_unused]] auto _ : irange::range(GetMnType(dmn->nType).voting_weight)) {
246+
for ([[maybe_unused]] auto _ : irange::range(isMNRewardReallocation ? 1 : GetMnType(dmn->nType).voting_weight)) {
246247
result.emplace_back(dmn);
247248
}
248249
});

test/functional/feature_llmq_evo.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
QuorumId, ser_uint256
1818
from test_framework.test_framework import DashTestFramework
1919
from test_framework.util import (
20-
assert_equal, p2p_port
20+
assert_equal, assert_greater_than_or_equal, p2p_port
2121
)
2222

2323

@@ -46,7 +46,7 @@ def getmnlistdiff(self, baseBlockHash, blockHash):
4646

4747
class LLMQEvoNodesTest(DashTestFramework):
4848
def set_test_params(self):
49-
self.set_dash_test_params(5, 4, fast_dip3_enforcement=True, evo_count=7)
49+
self.set_dash_test_params(5, 4, fast_dip3_enforcement=True, evo_count=5)
5050
self.set_dash_llmq_test_params(4, 4)
5151

5252
def run_test(self):
@@ -90,7 +90,7 @@ def run_test(self):
9090
self.mine_cycle_quorum(llmq_type_name='llmq_test_dip0024', llmq_type=103)
9191

9292
evo_protxhash_list = list()
93-
for i in range(5):
93+
for i in range(self.evo_count):
9494
evo_info = self.dynamically_add_masternode(evo=True)
9595
evo_protxhash_list.append(evo_info.proTxHash)
9696
self.nodes[0].generate(8)
@@ -113,6 +113,7 @@ def run_test(self):
113113

114114
self.log.info("Test that EvoNodes are paid 4x blocks in a row")
115115
self.test_evo_payments(window_analysis=48)
116+
self.test_masternode_winners()
116117

117118
self.activate_v20()
118119
self.activate_mn_rr()
@@ -125,6 +126,7 @@ def run_test(self):
125126

126127
self.log.info("Test that EvoNodes are paid 1 block in a row after MN RewardReallocation activation")
127128
self.test_evo_payments(window_analysis=48, v20active=True)
129+
self.test_masternode_winners(mn_rr_active=True)
128130

129131
self.log.info(self.nodes[0].masternodelist())
130132

@@ -246,6 +248,40 @@ def test_masternode_count(self, expected_mns_count, expected_evo_count):
246248
assert_equal(detailed_count['regular']['total'], expected_mns_count)
247249
assert_equal(detailed_count['evo']['total'], expected_evo_count)
248250

251+
def test_masternode_winners(self, mn_rr_active=False):
252+
# ignore recent winners, test future ones only
253+
# we get up to 21 entries here: tip + up to 20 future payees
254+
winners = self.nodes[0].masternode('winners', '0')
255+
weighted_count = self.mn_count + self.evo_count * (1 if mn_rr_active else 4)
256+
assert_equal(len(winners.keys()) - 1, 20 if weighted_count > 20 else weighted_count)
257+
consecutive_payments = 0
258+
full_consecutive_payments_found = 0
259+
payment_cycles = 0
260+
first_payee = None
261+
prev_winner = None
262+
for height in winners.keys():
263+
winner = winners[height]
264+
if mn_rr_active:
265+
assert_equal(prev_winner == winner, False)
266+
else:
267+
if prev_winner == winner:
268+
consecutive_payments += 1
269+
else:
270+
if consecutive_payments == 3:
271+
full_consecutive_payments_found += 1
272+
consecutive_payments = 0
273+
assert_greater_than_or_equal(3, consecutive_payments)
274+
if consecutive_payments == 0 and winner == first_payee:
275+
payment_cycles += 1
276+
if first_payee is None:
277+
first_payee = winner
278+
prev_winner = winner
279+
if mn_rr_active:
280+
assert_equal(full_consecutive_payments_found, 0)
281+
else:
282+
assert_greater_than_or_equal(full_consecutive_payments_found, (len(winners.keys()) - 1 - self.mn_count) // 4 - 1)
283+
assert_equal(payment_cycles, (len(winners.keys()) - 1) // weighted_count)
284+
249285
def test_getmnlistdiff(self, baseBlockHash, blockHash, baseMNList, expectedDeleted, expectedUpdated):
250286
d = self.test_getmnlistdiff_base(baseBlockHash, blockHash)
251287

0 commit comments

Comments
 (0)