Skip to content
Merged
2 changes: 1 addition & 1 deletion test/functional/feature_asset_locks.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ def test_withdrawal_limits(self, node_wallet, node, pubkey):
def test_mn_rr(self, node_wallet, node, pubkey):
self.log.info("Activate mn_rr...")
locked = self.get_credit_pool_balance()
self.activate_mn_rr(expected_activation_height=560)
self.activate_mn_rr()
self.log.info(f'mn-rr height: {node.getblockcount()} credit: {self.get_credit_pool_balance()}')
assert_equal(locked, self.get_credit_pool_balance())

Expand Down
12 changes: 11 additions & 1 deletion test/functional/feature_llmq_chainlocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@
from test_framework.test_framework import DashTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, force_finish_mnsync

import time

class LLMQChainLocksTest(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(5, 4)
self.delay_v20_and_mn_rr(height=200)

def sleep_and_assert_no_cl(self, block_hash, sleep_time=5):
time.sleep(sleep_time)

for node in self.nodes:
self.log.info(f"Expecting no ChainLock for {block_hash}")
block = node.getblock(block_hash)
#assert_equal(block["confirmations"], 0)
assert not block["chainlock"]

Comment on lines +26 to +34
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Flake8 E265 and remove stale commented assertion.

The commented line lacks a space after '#', tripping E265. It’s also misleading (confirmations can be >0). Remove it.

Apply this diff:

-            #assert_equal(block["confirmations"], 0)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def sleep_and_assert_no_cl(self, block_hash, sleep_time=5):
time.sleep(sleep_time)
for node in self.nodes:
self.log.info(f"Expecting no ChainLock for {block_hash}")
block = node.getblock(block_hash)
#assert_equal(block["confirmations"], 0)
assert not block["chainlock"]
def sleep_and_assert_no_cl(self, block_hash, sleep_time=5):
time.sleep(sleep_time)
for node in self.nodes:
self.log.info(f"Expecting no ChainLock for {block_hash}")
block = node.getblock(block_hash)
assert not block["chainlock"]
🧰 Tools
🪛 Flake8 (7.2.0)

[error] 32-32: block comment should start with '# '

(E265)

🤖 Prompt for AI Agents
In test/functional/feature_llmq_chainlocks.py around lines 26 to 34, remove the
stale commented assertion line "#assert_equal(block["confirmations"], 0)" to fix
Flake8 E265 (missing space after '#') and to avoid misleading code; leave the
time.sleep, logging, getblock call, and the assert not block["chainlock"] check
intact.

def run_test(self):
# Connect all nodes to node1 so that we always have the whole network connected
# Otherwise only masternode connections will be established between nodes, which won't propagate TXs/blocks
Expand Down Expand Up @@ -84,7 +94,7 @@ def run_test(self):
previous_block_hash = self.nodes[0].getbestblockhash()
for _ in range(2):
block_hash = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[0]
self.wait_for_chainlocked_block_all_nodes(block_hash, timeout=5, expected=False)
self.sleep_and_assert_no_cl(block_hash)
assert self.nodes[0].getblock(previous_block_hash)["chainlock"]

self.nodes[0].sporkupdate("SPORK_19_CHAINLOCKS_ENABLED", 0)
Expand Down
42 changes: 20 additions & 22 deletions test/functional/feature_llmq_evo.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ def getmnlistdiff(self, baseBlockHash, blockHash):

class LLMQEvoNodesTest(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(5, 4, evo_count=5)
self.set_dash_llmq_test_params(4, 4)
self.mn_rr_height = 400
# we just need a couple of regular nodes to be ensured that they are not included in platform quorum, 2 is enough
self.set_dash_test_params(3, 2, evo_count=4)
self.mn_rr_height = 320

def run_test(self):
# Connect all nodes to node1 so that we always have the whole network connected
Expand All @@ -62,18 +62,12 @@ def run_test(self):
null_hash = format(0, "064x")

self.nodes[0].sporkupdate("SPORK_17_QUORUM_DKG_ENABLED", 0)
self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 1)
self.wait_for_sporks_same()

expectedUpdated = [mn.proTxHash for mn in self.mninfo]
b_0 = self.nodes[0].getbestblockhash()
self.test_getmnlistdiff(null_hash, b_0, {}, [], expectedUpdated)

self.test_masternode_count(expected_mns_count=4, expected_evo_count=0)

self.nodes[0].sporkupdate("SPORK_2_INSTANTSEND_ENABLED", 0)
self.wait_for_sporks_same()

self.test_masternode_count(expected_mns_count=2, expected_evo_count=0)
evo_protxhash_list = list()
for i in range(self.evo_count):
evo_info: MasternodeInfo = self.dynamically_add_masternode(evo=True)
Expand All @@ -84,7 +78,7 @@ def run_test(self):
b_i = self.nodes[0].getbestblockhash()
self.test_getmnlistdiff(null_hash, b_i, {}, [], expectedUpdated)

self.test_masternode_count(expected_mns_count=4, expected_evo_count=i+1)
self.test_masternode_count(expected_mns_count=2, expected_evo_count=i+1)
self.dynamically_evo_update_service(evo_info)

self.log.info("Test llmq_platform are formed only with EvoNodes")
Expand All @@ -100,7 +94,7 @@ def run_test(self):
self.test_masternode_winners()

self.activate_mn_rr()
self.log.info("Activated MN RewardReallocation, current height:" + str(self.nodes[0].getblockcount()))
self.log.info(f"Activated MN RewardReallocation, current height: {self.nodes[0].getblockcount()}")

# Generate a few blocks to make EvoNode/MN analysis on a pure MN RewardReallocation window
self.bump_mocktime(1)
Expand All @@ -110,10 +104,6 @@ def run_test(self):
self.test_evo_payments(window_analysis=48, mnrr_active=True)
self.test_masternode_winners(mn_rr_active=True)

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

return

def test_evo_payments(self, window_analysis, mnrr_active):
current_evo: MasternodeInfo = None
consecutive_payments = 0
Expand Down Expand Up @@ -183,13 +173,21 @@ def test_quorum_members_are_evo_nodes(self, quorum_hash, llmq_type):

def test_evo_protx_are_in_mnlist(self, evo_protx_list):
mn_list = self.nodes[0].masternodelist()
mn_list_evo = self.nodes[0].masternodelist(mode="evo")
for evo_protx in evo_protx_list:
found = False
for mn in mn_list:
if mn_list.get(mn)['proTxHash'] == evo_protx:
found = True
assert_equal(mn_list.get(mn)['type'], "Evo")
assert_equal(found, True)
found_in_mns = False
for _, mn in mn_list.items():
if mn['proTxHash'] == evo_protx:
found_in_mns = True
assert_equal(mn['type'], "Evo")
assert_equal(found_in_mns, True)

found_in_evos = False
for _, mn in mn_list_evo.items():
assert_equal(mn['type'], "Evo")
if mn['proTxHash'] == evo_protx:
found_in_evos = True
assert_equal(found_in_evos, True)

def test_masternode_count(self, expected_mns_count, expected_evo_count):
mn_count = self.nodes[0].masternode('count')
Expand Down
21 changes: 6 additions & 15 deletions test/functional/feature_llmq_rotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ def getmnlistdiff(self, baseBlockHash, blockHash):

class LLMQQuorumRotationTest(DashTestFramework):
def set_test_params(self):
self.set_dash_test_params(9, 8)
self.set_dash_test_params(9, 8, extra_args=[["-vbparams=testdummy:999999999999:999999999999"]] * 9)
self.set_dash_llmq_test_params(4, 4)
self.delay_v20_and_mn_rr(height=900)
self.delay_v20_and_mn_rr(height=300)

def run_test(self):
llmq_type=103
Expand Down Expand Up @@ -106,14 +106,8 @@ def run_test(self):
expectedNew = [h_100_0, h_100_1]
quorumList = self.test_getmnlistdiff_quorums(b_h_0, b_h_1, {}, expectedDeleted, expectedNew, testQuorumsCLSigs=False)

projected_activation_height = 900

self.activate_v20(expected_activation_height=900)
self.log.info("Activated v20 at height:" + str(self.nodes[0].getblockcount()))

softfork_info = self.nodes[0].getblockchaininfo()['softforks']['v20']
assert_equal(softfork_info['active'], True)
assert_equal(projected_activation_height, softfork_info['height'])
self.activate_v20(expected_activation_height=self.mn_rr_height)
self.log.info(f"Activated v20 at height: {self.nodes[0].getblockcount()}")

# v20 is active for the next block, not for the tip
self.generate(self.nodes[0], 1)
Expand Down Expand Up @@ -161,13 +155,12 @@ def run_test(self):
self.log.info("Quorum #0_1 members: " + str(quorum_members_0_1))

q_100_0 = QuorumId(100, int(quorum_info_0_0["quorumHash"], 16))
q_102_0 = QuorumId(102, int(quorum_info_0_0["quorumHash"], 16))
q_103_0_0 = QuorumId(103, int(quorum_info_0_0["quorumHash"], 16))
q_103_0_1 = QuorumId(103, int(quorum_info_0_1["quorumHash"], 16))

b_1 = self.nodes[0].getbestblockhash()
expectedDeleted = [h_100_0]
expectedNew = [q_100_0, q_102_0, q_103_0_0, q_103_0_1]
expectedNew = [q_100_0, q_103_0_0, q_103_0_1]
quorumList = self.test_getmnlistdiff_quorums(b_0, b_1, quorumList, expectedDeleted, expectedNew)

self.log.info("Wait for chainlock")
Expand All @@ -183,13 +176,12 @@ def run_test(self):
self.log.info("Quorum #1_1 members: " + str(quorum_members_1_1))

q_100_1 = QuorumId(100, int(quorum_info_1_0["quorumHash"], 16))
q_102_1 = QuorumId(102, int(quorum_info_1_0["quorumHash"], 16))
q_103_1_0 = QuorumId(103, int(quorum_info_1_0["quorumHash"], 16))
q_103_1_1 = QuorumId(103, int(quorum_info_1_1["quorumHash"], 16))

b_2 = self.nodes[0].getbestblockhash()
expectedDeleted = [h_100_1, q_103_0_0, q_103_0_1]
expectedNew = [q_100_1, q_102_1, q_103_1_0, q_103_1_1]
expectedNew = [q_100_1, q_103_1_0, q_103_1_1]
quorumList = self.test_getmnlistdiff_quorums(b_1, b_2, quorumList, expectedDeleted, expectedNew)

mninfos_online = self.mninfo.copy()
Expand Down Expand Up @@ -374,7 +366,6 @@ def compute_mn_score(self, mn, modifier):
def get_llmq_size(self, llmq_type):
return {
100: 4, # In this test size for llmqType 100 is overwritten to 4
102: 3,
103: 4,
106: 3
}.get(llmq_type, -1)
Expand Down
23 changes: 13 additions & 10 deletions test/functional/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -1578,8 +1578,8 @@ def activate_by_name(self, name, expected_activation_height=None, slow_mode=True
def activate_v20(self, expected_activation_height=None):
self.activate_by_name('v20', expected_activation_height)

def activate_mn_rr(self, expected_activation_height=None):
self.activate_by_name('mn_rr', expected_activation_height)
def activate_mn_rr(self):
self.activate_by_name('mn_rr', self.mn_rr_height)

def set_dash_llmq_test_params(self, llmq_size, llmq_threshold):
self.llmq_size = llmq_size
Expand Down Expand Up @@ -1953,9 +1953,9 @@ def check_chainlocked_block():
if self.wait_until(check_chainlocked_block, timeout=timeout, do_assert=expected) and not expected:
raise AssertionError("waiting unexpectedly succeeded")

def wait_for_chainlocked_block_all_nodes(self, block_hash, timeout=15, expected=True):
def wait_for_chainlocked_block_all_nodes(self, block_hash, timeout=15):
for node in self.nodes:
self.wait_for_chainlocked_block(node, block_hash, expected=expected, timeout=timeout)
self.wait_for_chainlocked_block(node, block_hash, timeout=timeout)

def wait_for_best_chainlock(self, node, block_hash, timeout=15):
self.wait_until(lambda: node.getbestchainlock()["blockhash"] == block_hash, timeout=timeout)
Expand Down Expand Up @@ -2309,13 +2309,16 @@ def mine_cycle_quorum(self, is_first=True):
self.log.info("New quorum: height=%d, quorumHash=%s, quorumIndex=%d, minedBlock=%s" % (quorum_info_0["height"], q_0, quorum_info_0["quorumIndex"], quorum_info_0["minedBlock"]))
self.log.info("New quorum: height=%d, quorumHash=%s, quorumIndex=%d, minedBlock=%s" % (quorum_info_1["height"], q_1, quorum_info_1["quorumIndex"], quorum_info_1["minedBlock"]))

self.log.info("quorum_info_0:"+str(quorum_info_0))
self.log.info("quorum_info_1:"+str(quorum_info_1))
extra_debug_rotation_info = False
if extra_debug_rotation_info:
# these logs are useful to debug quorum rotation but it is not usefull for all other cases
self.log.info("quorum_info_0:"+str(quorum_info_0))
self.log.info("quorum_info_1:"+str(quorum_info_1))

best_block_hash = self.nodes[0].getbestblockhash()
block_height = self.nodes[0].getblockcount()
quorum_rotation_info = self.nodes[0].quorum("rotationinfo", best_block_hash)
self.log.info("h("+str(block_height)+"):"+str(quorum_rotation_info))
best_block_hash = self.nodes[0].getbestblockhash()
block_height = self.nodes[0].getblockcount()
quorum_rotation_info = self.nodes[0].quorum("rotationinfo", best_block_hash)
self.log.info("h("+str(block_height)+"):"+str(quorum_rotation_info))

return (quorum_info_0, quorum_info_1)

Expand Down
Loading