@@ -50,57 +50,68 @@ void IncomingFundNotifier::pushTransaction(uint256 const &id)
5050
5151void IncomingFundNotifier::check ()
5252{
53- TRY_LOCK (cs, lock);
54- if (!lock)
55- return ;
53+ // Phase 1: snapshot txs under local lock, enforce update interval
54+ std::vector<uint256> batch;
55+ const int64_t now = GetSystemTimeInSeconds ();
56+ {
57+ TRY_LOCK (cs, lock);
58+ if (!lock)
59+ return ;
5660
57- // update only if there are transaction and last update was done more than 2 minutes ago, and in case it is first time
58- if (txs.empty () || (lastUpdateTime!= 0 && (GetSystemTimeInSeconds () - lastUpdateTime <= 120 ))) {
59- return ;
60- }
61+ if (txs.empty () || (lastUpdateTime != 0 && (now - lastUpdateTime <= 120 ))) {
62+ return ;
63+ }
6164
62- lastUpdateTime = GetSystemTimeInSeconds ();
65+ lastUpdateTime = now;
66+ batch.swap (txs);
67+ }
6368
69+ // Phase 2: process under core locks (no IncomingFundNotifier::cs held)
6470 CAmount credit = 0 ;
6571 std::vector<uint256> immatures;
72+ CCoinControl coinControl;
73+ coinControl.nCoinType = CoinType::ONLY_NOT1000IFMN;
6674
6775 {
68- TRY_LOCK (cs_main,lock_main);
69- if (!lock_main)
76+ TRY_LOCK (cs_main, lock_main);
77+ if (!lock_main) {
78+ // Put back batch if we couldn't proceed
79+ LOCK (cs);
80+ txs.insert (txs.end (), batch.begin (), batch.end ());
7081 return ;
71- TRY_LOCK (wallet->cs_wallet ,lock_wallet);
72- if (!lock_wallet)
82+ }
83+ TRY_LOCK (wallet->cs_wallet , lock_wallet);
84+ if (!lock_wallet) {
85+ LOCK (cs);
86+ txs.insert (txs.end (), batch.begin (), batch.end ());
7387 return ;
74- CCoinControl coinControl;
75- coinControl.nCoinType = CoinType::ONLY_NOT1000IFMN;
76- while (!txs.empty ()) {
77- auto const &tx = txs.back ();
78- txs.pop_back ();
79-
80- auto wtx = wallet->mapWallet .find (tx);
81- if (wtx == wallet->mapWallet .end ()) {
88+ }
89+
90+ for (const auto & txid : batch) {
91+ auto it = wallet->mapWallet .find (txid);
92+ if (it == wallet->mapWallet .end ())
8293 continue ;
83- }
8494
85- for (uint32_t i = 0 ; i != wtx ->second .tx ->vout .size (); i++ ) {
86- coinControl.Select ({wtx ->first , i});
95+ for (uint32_t i = 0 ; i != it ->second .tx ->vout .size (); ++i ) {
96+ coinControl.Select ({it ->first , i});
8797 }
8898
89- if (wtx ->second .GetImmatureCredit () > 0 ) {
90- immatures.push_back (tx );
99+ if (it ->second .GetImmatureCredit () > 0 ) {
100+ immatures.push_back (txid );
91101 }
92102 }
93103
94104 std::vector<std::pair<CAmount, std::vector<COutput>>> valueAndUTXOs;
95105 pwalletMain->AvailableCoinsForLMint (valueAndUTXOs, &coinControl);
96-
97- for (auto const &valueAndUTXO : valueAndUTXOs) {
98- credit += valueAndUTXO.first ;
106+ for (const auto & p : valueAndUTXOs) {
107+ credit += p.first ;
99108 }
100109 }
101110
102- for (auto const &tx : immatures) {
103- txs.push_back (tx);
111+ // Phase 3: push back immatures under local lock
112+ if (!immatures.empty ()) {
113+ LOCK (cs);
114+ txs.insert (txs.end (), immatures.begin (), immatures.end ());
104115 }
105116
106117 if (credit > 0 ) {
@@ -110,16 +121,33 @@ void IncomingFundNotifier::check()
110121
111122void IncomingFundNotifier::importTransactions ()
112123{
113- LOCK2 (cs, cs_main);
114- LOCK (wallet->cs_wallet );
124+ // Gather under core locks only
125+ std::vector<uint256> to_add;
126+ {
127+ TRY_LOCK (cs_main, lock_main);
128+ if (!lock_main) {
129+ QTimer::singleShot (1000 , this , &IncomingFundNotifier::importTransactions);
130+ return ;
131+ }
132+ TRY_LOCK (wallet->cs_wallet , lock_wallet);
133+ if (!lock_wallet) {
134+ QTimer::singleShot (1000 , this , &IncomingFundNotifier::importTransactions);
135+ return ;
136+ }
115137
116- for (auto const &tx : wallet->mapWallet ) {
117- if (tx.second .GetAvailableCredit () > 0 || tx.second .GetImmatureCredit () > 0 ) {
118- txs.push_back (tx.first );
138+ for (const auto & it : wallet->mapWallet ) {
139+ if (it.second .GetAvailableCredit () > 0 || it.second .GetImmatureCredit () > 0 ) {
140+ to_add.push_back (it.first );
141+ }
119142 }
120143 }
121144
122- resetTimer ();
145+ // Append under local lock, no core locks held
146+ {
147+ LOCK (cs);
148+ txs.insert (txs.end (), to_add.begin (), to_add.end ());
149+ resetTimer ();
150+ }
123151}
124152
125153void IncomingFundNotifier::resetTimer ()
0 commit comments