@@ -2433,11 +2433,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
24332433 continue ;
24342434
24352435 // Search block for matching tx, turn into wtx, set merkle branch, add to wallet
2436- for (const CTransaction& tx : block.vtx ) {
2436+ int posInBlock = 0 ;
2437+ for (posInBlock = 0 ; posInBlock < (int )block.vtx .size (); posInBlock++) {
2438+ auto & tx = block.vtx [posInBlock];
24372439 if (tx.GetHash () == pSpend.second ) {
24382440 CWalletTx wtx (pwalletMain, tx);
24392441 wtx.nTimeReceived = pindex->GetBlockTime ();
2440- wtx.SetMerkleBranch (block );
2442+ wtx.SetMerkleBranch (pindex, posInBlock );
24412443 pwalletMain->AddToWallet (wtx);
24422444 setAddedTx.insert (pSpend.second );
24432445 }
@@ -2708,7 +2710,7 @@ bool static DisconnectTip(CValidationState& state)
27082710 // Let wallets know transactions went from 1-confirmed to
27092711 // 0-confirmed or conflicted:
27102712 for (const CTransaction& tx : block.vtx ) {
2711- SyncWithWallets (tx, NULL );
2713+ SyncWithWallets (tx, pindexDelete-> pprev );
27122714 }
27132715 return true ;
27142716}
@@ -2723,7 +2725,7 @@ static int64_t nTimePostConnect = 0;
27232725 * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
27242726 * corresponding to pindexNew, to bypass loading it again from disk.
27252727 */
2726- bool static ConnectTip (CValidationState& state, CBlockIndex* pindexNew, const CBlock* pblock, bool fAlreadyChecked )
2728+ bool static ConnectTip (CValidationState& state, CBlockIndex* pindexNew, const CBlock* pblock, bool fAlreadyChecked , std::list<CTransaction> &txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*, int >> &txChanged )
27272729{
27282730 assert (pindexNew->pprev == chainActive.Tip ());
27292731
@@ -2773,18 +2775,12 @@ bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, const CB
27732775 LogPrint (BCLog::BENCH, " - Writing chainstate: %.2fms [%.2fs]\n " , (nTime5 - nTime4) * 0.001 , nTimeChainState * 0.000001 );
27742776
27752777 // Remove conflicting transactions from the mempool.
2776- std::list<CTransaction> txConflicted;
27772778 mempool.removeForBlock (pblock->vtx , pindexNew->nHeight , txConflicted, !IsInitialBlockDownload ());
27782779 // Update chainActive & related variables.
27792780 UpdateTip (pindexNew);
2780- // Tell wallet about transactions that went from mempool
2781- // to conflicted:
2782- for (const CTransaction& tx : txConflicted) {
2783- SyncWithWallets (tx, NULL );
2784- }
2785- // ... and about transactions that got confirmed:
2786- for (const CTransaction& tx : pblock->vtx ) {
2787- SyncWithWallets (tx, pblock);
2781+
2782+ for (unsigned int i=0 ; i < pblock->vtx .size (); i++) {
2783+ txChanged.push_back (std::make_tuple (pblock->vtx [i], pindexNew, i));
27882784 }
27892785
27902786 int64_t nTime6 = GetTimeMicros ();
@@ -2915,7 +2911,7 @@ static void PruneBlockIndexCandidates()
29152911 * Try to make some progress towards making pindexMostWork the active block.
29162912 * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
29172913 */
2918- static bool ActivateBestChainStep (CValidationState& state, CBlockIndex* pindexMostWork, const CBlock* pblock, bool fAlreadyChecked )
2914+ static bool ActivateBestChainStep (CValidationState& state, CBlockIndex* pindexMostWork, const CBlock* pblock, bool fAlreadyChecked , std::list<CTransaction>& txConflicted, std::vector<std::tuple<CTransaction,CBlockIndex*, int >>& txChanged )
29192915{
29202916 AssertLockHeld (cs_main);
29212917 if (pblock == NULL )
@@ -2951,7 +2947,7 @@ static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMo
29512947
29522948 // Connect new blocks.
29532949 BOOST_REVERSE_FOREACH (CBlockIndex* pindexConnect, vpindexToConnect) {
2954- if (!ConnectTip (state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL , fAlreadyChecked )) {
2950+ if (!ConnectTip (state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL , fAlreadyChecked , txConflicted, txChanged )) {
29552951 if (state.IsInvalid ()) {
29562952 // The block violates a consensus rule.
29572953 if (!state.CorruptionPossible ())
@@ -3009,6 +3005,8 @@ bool ActivateBestChain(CValidationState& state, const CBlock* pblock, bool fAlre
30093005 boost::this_thread::interruption_point ();
30103006
30113007 const CBlockIndex *pindexFork;
3008+ std::list<CTransaction> txConflicted;
3009+ std::vector<std::tuple<CTransaction,CBlockIndex*,int >> txChanged;
30123010 bool fInitialDownload ;
30133011 while (true ) {
30143012 TRY_LOCK (cs_main, lockMain);
@@ -3024,7 +3022,7 @@ bool ActivateBestChain(CValidationState& state, const CBlock* pblock, bool fAlre
30243022 if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip ())
30253023 return true ;
30263024
3027- if (!ActivateBestChainStep (state, pindexMostWork, pblock && pblock->GetHash () == pindexMostWork->GetBlockHash () ? pblock : NULL , fAlreadyChecked ))
3025+ if (!ActivateBestChainStep (state, pindexMostWork, pblock && pblock->GetHash () == pindexMostWork->GetBlockHash () ? pblock : NULL , fAlreadyChecked , txConflicted, txChanged ))
30283026 return false ;
30293027
30303028 pindexNewTip = chainActive.Tip ();
@@ -3035,6 +3033,17 @@ bool ActivateBestChain(CValidationState& state, const CBlock* pblock, bool fAlre
30353033
30363034 // When we reach this point, we switched to a new tip (stored in pindexNewTip).
30373035 // Notifications/callbacks that can run without cs_main
3036+
3037+ // throw all transactions though the signal-interface
3038+ // while _not_ holding the cs_main lock
3039+ for (const CTransaction &tx : txConflicted) {
3040+ SyncWithWallets (tx, pindexNewTip);
3041+ }
3042+ // ... and about transactions that got confirmed:
3043+ for (unsigned int i = 0 ; i < txChanged.size (); i++) {
3044+ SyncWithWallets (std::get<0 >(txChanged[i]), std::get<1 >(txChanged[i]), std::get<2 >(txChanged[i]));
3045+ }
3046+
30383047 // Always notify the UI if a new block tip was connected
30393048 if (pindexFork != pindexNewTip) {
30403049
0 commit comments