Skip to content

Commit dd48ca5

Browse files
Merge branch 'develop' of https://github.com/dashpay/dash into develop
2 parents fbaee1f + 3957e09 commit dd48ca5

16 files changed

Lines changed: 166 additions & 79 deletions

src/active/context.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ void ActiveContext::SetCJServer(gsl::not_null<CCoinJoinServer*> cj_server)
9797
m_cj_server = cj_server;
9898
}
9999

100+
void ActiveContext::InitializeCurrentBlockTip(const CBlockIndex* tip, bool ibd)
101+
{
102+
UpdatedBlockTip(tip, nullptr, ibd);
103+
if (tip) {
104+
qman_handler->InitializeQuorumConnections(tip);
105+
}
106+
}
107+
100108
void ActiveContext::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
101109
{
102110
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones

src/active/context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct ActiveContext final : public CValidationInterface {
7474

7575
void Start(CConnman& connman, PeerManager& peerman, int16_t worker_count);
7676
void Stop();
77+
void InitializeCurrentBlockTip(const CBlockIndex* tip, bool ibd);
7778

7879
CCoinJoinServer& GetCJServer() const;
7980
void SetCJServer(gsl::not_null<CCoinJoinServer*> cj_server);

src/init.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,6 +2417,15 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
24172417
// but don't call it directly to prevent triggering of other listeners like zmq etc.
24182418
// GetMainSignals().UpdatedBlockTip(::ChainActive().Tip());
24192419
g_ds_notification_interface->InitializeCurrentBlockTip();
2420+
{
2421+
const CBlockIndex* tip = WITH_LOCK(::cs_main, return chainman.ActiveTip());
2422+
const bool ibd = chainman.ActiveChainstate().IsInitialBlockDownload();
2423+
if (node.observer_ctx && !node.active_ctx) {
2424+
node.observer_ctx->InitializeCurrentBlockTip(tip, ibd);
2425+
}
2426+
// Note: active_ctx initialization is deferred until after nodeman->Init()
2427+
// so that GetProTxHash() is available for quorum connection setup.
2428+
}
24202429

24212430
{
24222431
// Get all UTXOs for each MN collateral in one go so that we can fill coin cache early
@@ -2481,6 +2490,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
24812490

24822491
if (node.active_ctx) {
24832492
node.active_ctx->nodeman->Init(chainman.ActiveTip());
2493+
// Initialize current block tip after nodeman->Init() so that
2494+
// GetProTxHash() is available for quorum connection setup.
2495+
// Without this ordering, EnsureQuorumConnections returns early
2496+
// because the null proTxHash makes the MN appear as a non-member.
2497+
const CBlockIndex* tip = WITH_LOCK(::cs_main, return chainman.ActiveTip());
2498+
const bool ibd = chainman.ActiveChainstate().IsInitialBlockDownload();
2499+
node.active_ctx->InitializeCurrentBlockTip(tip, ibd);
24842500
}
24852501
});
24862502
#ifdef ENABLE_WALLET

src/llmq/observer/context.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ void ObserverContext::Stop()
4747
qman_handler->Stop();
4848
}
4949

50+
void ObserverContext::InitializeCurrentBlockTip(const CBlockIndex* tip, bool ibd)
51+
{
52+
UpdatedBlockTip(tip, nullptr, ibd);
53+
if (tip) {
54+
qman_handler->InitializeQuorumConnections(tip);
55+
}
56+
}
57+
5058
void ObserverContext::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
5159
{
5260
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones

src/llmq/observer/context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ struct ObserverContext final : public CValidationInterface {
4949

5050
void Start(int16_t worker_count);
5151
void Stop();
52+
void InitializeCurrentBlockTip(const CBlockIndex* tip, bool ibd);
5253

5354
protected:
5455
// CValidationInterface

src/llmq/observer/quorums.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ void QuorumObserver::Stop()
5959
workerPool.stop(true);
6060
}
6161

62+
void QuorumObserver::InitializeQuorumConnections(gsl::not_null<const CBlockIndex*> pindexNew) const
63+
{
64+
for (const auto& params : Params().GetConsensus().llmqs) {
65+
CheckQuorumConnections(params, pindexNew);
66+
}
67+
}
68+
6269
void QuorumObserver::UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload) const
6370
{
6471
if (!pindexNew) return;

src/llmq/observer/quorums.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class QuorumObserver
9696
void Stop();
9797

9898
void UpdatedBlockTip(const CBlockIndex* pindexNew, bool fInitialDownload) const;
99+
void InitializeQuorumConnections(gsl::not_null<const CBlockIndex*> pindexNew) const;
99100

100101
public:
101102
virtual bool SetQuorumSecretKeyShare(CQuorum& quorum, Span<CBLSSecretKey> skContributions) const;

test/functional/feature_asset_locks.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,7 @@ def test_asset_unlocks(self, node_wallet, node, pubkey):
391391

392392
assert_equal(node.getmempoolentry(txid)['fees']['base'], Decimal("0.0007"))
393393
is_id = node_wallet.sendtoaddress(node_wallet.getnewaddress(), 1)
394-
self.bump_mocktime(30)
395-
for node in self.nodes:
396-
self.wait_for_instantlock(is_id, node)
394+
self.wait_for_instantlock(is_id)
397395

398396
rawtx = node.getrawtransaction(txid, 1)
399397
rawtx_is = node.getrawtransaction(is_id, 1)

test/functional/feature_llmq_is_cl_conflicts.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,7 @@ def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting
9999
rawtx4_txid = self.nodes[0].sendrawtransaction(rawtx4)
100100

101101
# wait for transactions to propagate
102-
self.bump_mocktime(30)
103-
self.sync_mempools()
104-
for node in self.nodes:
105-
self.wait_for_instantlock(rawtx1_txid, node)
106-
self.wait_for_instantlock(rawtx4_txid, node)
102+
self.wait_for_instantlock(rawtx1_txid, rawtx4_txid)
107103

108104
block = create_block_with_mnpayments(self.mninfo, self.nodes[0], [rawtx2_obj])
109105
if test_block_conflict:
@@ -160,10 +156,7 @@ def test_chainlock_overrides_islock(self, test_block_conflict, mine_confllicting
160156
rawtx5 = self.nodes[0].signrawtransactionwithwallet(rawtx5)['hex']
161157
rawtx5_txid = self.nodes[0].sendrawtransaction(rawtx5)
162158
# wait for the transaction to propagate
163-
self.bump_mocktime(30)
164-
self.sync_mempools()
165-
for node in self.nodes:
166-
self.wait_for_instantlock(rawtx5_txid, node)
159+
self.wait_for_instantlock(rawtx5_txid)
167160

168161
if mine_confllicting:
169162
# Lets verify that the ISLOCKs got pruned and conflicting txes were mined but never confirmed
@@ -243,17 +236,15 @@ def test_chainlock_overrides_islock_overrides_nonchainlock(self):
243236
# Should drop tx1 and accept tx2 because there is an isdlock waiting for it
244237
self.nodes[0].sendrawtransaction(rawtx2)
245238
# bump mocktime to force tx relay
246-
self.bump_mocktime(60)
247-
for node in self.nodes:
248-
self.wait_for_instantlock(rawtx2_txid, node)
239+
self.wait_for_instantlock(rawtx2_txid)
249240

250241
# Should not allow competing txes now
251242
assert_raises_rpc_error(-26, "tx-txlock-conflict", self.nodes[0].sendrawtransaction, rawtx1)
252243

253244
islock_tip = self.generate(self.nodes[0], 1)[0]
254245

246+
self.wait_for_instantlock(rawtx2_txid, skip_sync=True)
255247
for node in self.nodes:
256-
self.wait_for_instantlock(rawtx2_txid, node)
257248
assert_equal(node.getrawtransaction(rawtx2_txid, True)['confirmations'], 1)
258249
assert_equal(node.getbestblockhash(), islock_tip)
259250

test/functional/feature_llmq_is_retroactive.py

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,6 @@ def sleep_and_assert_no_instantlock(self, txid, node, sleep=5):
3535
time.sleep(sleep)
3636
self.assert_no_instantlock(txid, node)
3737

38-
# random delay before tx is actually send by network could take up to 30 seconds
39-
def wait_for_tx(self, txid, node, expected=True, timeout=60):
40-
def check_tx():
41-
try:
42-
return node.getrawtransaction(txid)
43-
except Exception:
44-
return False
45-
if self.wait_until(check_tx, timeout=timeout, do_assert=expected) and not expected:
46-
raise AssertionError("waiting unexpectedly succeeded")
47-
4838
def create_fund_sign_tx(self):
4939
rawtx = self.nodes[0].createrawtransaction([], {self.nodes[0].getnewaddress(): 1})
5040
rawtx = self.nodes[0].fundrawtransaction(rawtx)['hex']
@@ -67,14 +57,15 @@ def run_test(self):
6757
# 3 nodes should be enough to create an IS lock even if nodes 4 and 5 (which have no tx itself)
6858
# are the only "neighbours" in intra-quorum connections for one of them.
6959
self.bump_mocktime(30)
60+
self.sync_mempools(self.nodes[:3])
7061
self.sleep_and_assert_no_instantlock(txid, self.nodes[0])
7162
# Have to disable ChainLocks to avoid signing a block with a "safe" tx too early
7263
self.nodes[0].sporkupdate("SPORK_19_CHAINLOCKS_ENABLED", 4000000000)
7364
self.wait_for_sporks_same()
7465
# We have to wait in order to include tx in block
7566
self.bump_mocktime(10 * 60 + 1)
7667
block = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[0]
77-
self.wait_for_instantlock(txid, self.nodes[0])
68+
self.wait_for_instantlock(txid, nodes=[self.nodes[0]], skip_sync=True)
7869
self.nodes[0].sporkupdate("SPORK_19_CHAINLOCKS_ENABLED", 0)
7970
self.wait_for_sporks_same()
8071
self.wait_for_chainlocked_block_all_nodes(block)
@@ -87,19 +78,17 @@ def run_test(self):
8778
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
8879
# 3 nodes should be enough to create an IS lock even if nodes 4 and 5 (which have no tx itself)
8980
# are the only "neighbours" in intra-quorum connections for one of them.
90-
self.bump_mocktime(30)
91-
self.wait_for_instantlock(txid, self.nodes[0])
81+
self.wait_for_instantlock(txid, nodes=self.nodes[:3])
9282
block = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[0]
9383
self.wait_for_chainlocked_block_all_nodes(block)
9484

9585
self.log.info("testing normal signing with partially known TX")
9686
self.isolate_node(3)
9787
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
98-
# Make sure nodes 1 and 2 received the TX before we continue,
88+
# Make sure connected nodes received the TX before we continue,
9989
# otherwise it might announce the TX to node 3 when reconnecting
10090
self.bump_mocktime(30)
101-
self.wait_for_tx(txid, self.nodes[1])
102-
self.wait_for_tx(txid, self.nodes[2])
91+
self.sync_mempools(self.nodes[:3])
10392
self.reconnect_isolated_node(3, 0)
10493
# Make sure nodes actually try re-connecting quorum connections
10594
self.bump_mocktime(30)
@@ -110,7 +99,7 @@ def run_test(self):
11099
self.nodes[3].sendrawtransaction(self.nodes[0].getrawtransaction(txid))
111100
# node 3 should vote on a tx now since it became aware of it via sendrawtransaction
112101
# and this should be enough to complete an IS lock
113-
self.wait_for_instantlock(txid, self.nodes[0])
102+
self.wait_for_instantlock(txid, nodes=[self.nodes[0]], skip_sync=True)
114103

115104
self.log.info("testing retroactive signing with unknown TX")
116105
self.isolate_node(3)
@@ -126,11 +115,10 @@ def run_test(self):
126115
self.log.info("testing retroactive signing with partially known TX")
127116
self.isolate_node(3)
128117
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
129-
# Make sure nodes 1 and 2 received the TX before we continue,
118+
# Make sure connected nodes received the TX before we continue,
130119
# otherwise it might announce the TX to node 3 when reconnecting
131120
self.bump_mocktime(30)
132-
self.wait_for_tx(txid, self.nodes[1])
133-
self.wait_for_tx(txid, self.nodes[2])
121+
self.sync_mempools(self.nodes[:3])
134122
self.reconnect_isolated_node(3, 0)
135123
# Make sure nodes actually try re-connecting quorum connections
136124
self.bump_mocktime(30)
@@ -159,10 +147,9 @@ def test_session_timeout(self, do_cycle_llmqs):
159147
rawtx_1 = self.create_fund_sign_tx()
160148
txid_single_node = self.nodes[3].sendrawtransaction(rawtx_1)
161149

162-
# Make sure nodes 1 and 2 received the TX before we continue
150+
# Make sure connected nodes received the TX before we continue
163151
self.bump_mocktime(30)
164-
self.wait_for_tx(txid_all_nodes, self.nodes[1])
165-
self.wait_for_tx(txid_all_nodes, self.nodes[2])
152+
self.sync_mempools(self.nodes[:3])
166153
# Make sure signing is done on nodes 1 and 2 (it's async)
167154
time.sleep(5)
168155
# Make the signing session for the IS lock timeout on nodes 1-3
@@ -174,10 +161,9 @@ def test_session_timeout(self, do_cycle_llmqs):
174161
self.wait_for_mnauth(self.nodes[3], 2)
175162

176163
self.nodes[0].sendrawtransaction(rawtx_1)
177-
# Make sure nodes 1 and 2 received the TX
164+
# Make sure connected nodes received the TX
178165
self.bump_mocktime(30)
179-
self.wait_for_tx(txid_single_node, self.nodes[1])
180-
self.wait_for_tx(txid_single_node, self.nodes[2])
166+
self.sync_mempools(self.nodes[:3])
181167
self.bump_mocktime(30)
182168

183169
# Make sure signing is done on nodes 1 and 2 (it's async)

0 commit comments

Comments
 (0)