@@ -691,6 +691,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
691691 wtxOrdered.insert (std::make_pair (wtx.nOrderPos , TxPair (&wtx, (CAccountingEntry*)0 )));
692692 wtx.nTimeSmart = ComputeTimeSmart (wtx);
693693 AddToSpends (hash);
694+ for (const CTxIn& txin : wtx.vin ) {
695+ if (mapWallet.count (txin.prevout .hash )) {
696+ CWalletTx& prevtx = mapWallet[txin.prevout .hash ];
697+ if (prevtx.nIndex == -1 && !prevtx.hashBlock .IsNull ()) {
698+ MarkConflicted (prevtx.hashBlock , wtx.GetHash ());
699+ }
700+ }
701+ }
694702 }
695703
696704 bool fUpdated = false ;
@@ -744,6 +752,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
744752{
745753 {
746754 AssertLockHeld (cs_wallet);
755+
756+ if (pblock) {
757+ for (const CTxIn& txin : tx.vin ) {
758+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range (txin.prevout );
759+ while (range.first != range.second ) {
760+ if (range.first ->second != tx.GetHash ()) {
761+ LogPrintf (" Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n " , tx.GetHash ().ToString (), pblock->GetHash ().ToString (), range.first ->second .ToString (), range.first ->first .hash .ToString (), range.first ->first .n );
762+ MarkConflicted (pblock->GetHash (), range.first ->second );
763+ }
764+ range.first ++;
765+ }
766+ }
767+ }
768+
747769 bool fExisted = mapWallet.count (tx.GetHash ()) != 0 ;
748770 if (fExisted && !fUpdate ) return false ;
749771 if (fExisted || IsMine (tx) || IsFromMe (tx)) {
@@ -761,6 +783,53 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
761783 return false ;
762784}
763785
786+ void CWallet::MarkConflicted (const uint256& hashBlock, const uint256& hashTx)
787+ {
788+ LOCK2 (cs_main, cs_wallet);
789+
790+ CBlockIndex* pindex;
791+ assert (mapBlockIndex.count (hashBlock));
792+ pindex = mapBlockIndex[hashBlock];
793+ int conflictconfirms = 0 ;
794+ if (chainActive.Contains (pindex)) {
795+ conflictconfirms = -(chainActive.Height () - pindex->nHeight + 1 );
796+ }
797+ assert (conflictconfirms < 0 );
798+
799+ // Do not flush the wallet here for performance reasons
800+ CWalletDB walletdb (strWalletFile, " r+" , false );
801+
802+ std::deque<uint256> todo;
803+ std::set<uint256> done;
804+
805+ todo.push_back (hashTx);
806+
807+ while (!todo.empty ()) {
808+ uint256 now = todo.front ();
809+ todo.pop_front ();
810+ done.insert (now);
811+ assert (mapWallet.count (now));
812+ CWalletTx& wtx = mapWallet[now];
813+ int currentconfirm = wtx.GetDepthInMainChain ();
814+ if (conflictconfirms < currentconfirm) {
815+ // Block is 'more conflicted' than current confirm; update.
816+ // Mark transaction as conflicted with this block.
817+ wtx.nIndex = -1 ;
818+ wtx.hashBlock = hashBlock;
819+ wtx.MarkDirty ();
820+ wtx.WriteToDisk (&walletdb);
821+ // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
822+ TxSpends::const_iterator iter = mapTxSpends.lower_bound (COutPoint (now, 0 ));
823+ while (iter != mapTxSpends.end () && iter->first .hash == now) {
824+ if (!done.count (iter->second )) {
825+ todo.push_back (iter->second );
826+ }
827+ iter++;
828+ }
829+ }
830+ }
831+ }
832+
764833void CWallet::SyncTransaction (const CTransaction& tx, const CBlock* pblock)
765834{
766835 LOCK2 (cs_main, cs_wallet);
@@ -1375,7 +1444,7 @@ void CWallet::ReacceptWalletTransactions()
13751444
13761445 int nDepth = wtx.GetDepthInMainChain ();
13771446
1378- if (!wtx.IsCoinBase () && !wtx.IsCoinStake () && nDepth < 0 ) {
1447+ if (!wtx.IsCoinBase () && !wtx.IsCoinStake () && nDepth == 0 ) {
13791448 // Try to add to memory pool
13801449 LOCK (mempool.cs );
13811450 wtx.AcceptToMemoryPool (false );
@@ -2216,6 +2285,7 @@ bool CWallet::CreateTransaction(const std::vector<std::pair<CScript, CAmount> >&
22162285 // a chance at a free transaction.
22172286 // But mempool inputs might still be in the mempool, so their age stays 0
22182287 int age = pcoin.first ->GetDepthInMainChain ();
2288+ assert (age >= 0 );
22192289 if (age != 0 )
22202290 age += 1 ;
22212291 dPriority += (double )nCredit * age;
@@ -3671,7 +3741,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
36713741
36723742int CMerkleTx::GetDepthInMainChainINTERNAL (const CBlockIndex*& pindexRet) const
36733743{
3674- if (hashBlock == 0 || nIndex == - 1 )
3744+ if (hashBlock == 0 )
36753745 return 0 ;
36763746 AssertLockHeld (cs_main);
36773747
@@ -3684,7 +3754,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex*& pindexRet) const
36843754 return 0 ;
36853755
36863756 pindexRet = pindex;
3687- return chainActive.Height () - pindex->nHeight + 1 ;
3757+ return ((nIndex == - 1 ) ? (- 1 ) : 1 ) * ( chainActive.Height () - pindex->nHeight + 1 ) ;
36883758}
36893759
36903760int CMerkleTx::GetDepthInMainChain (const CBlockIndex*& pindexRet, bool enableIX) const
@@ -5386,6 +5456,14 @@ bool CWalletTx::IsTrusted() const
53865456 return false ;
53875457 if (!bSpendZeroConfChange || !IsFromMe (ISMINE_ALL)) // using wtx's cached debit
53885458 return false ;
5459+
5460+ // Don't trust unconfirmed transactions from us unless they are in the mempool.
5461+ {
5462+ LOCK (mempool.cs );
5463+ if (!mempool.exists (GetHash ())) {
5464+ return false ;
5465+ }
5466+ }
53895467
53905468 // Trusted if all inputs are from us and are in the mempool:
53915469 for (const CTxIn& txin : vin) {
0 commit comments