@@ -608,6 +608,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
608
608
wtx.BindWallet (this );
609
609
wtxOrdered.insert (make_pair (wtx.nOrderPos , TxPair (&wtx, (CAccountingEntry*)0 )));
610
610
AddToSpends (hash);
611
+ BOOST_FOREACH (const CTxIn& txin, wtx.vin ) {
612
+ if (mapWallet.count (txin.prevout .hash )) {
613
+ CWalletTx& prevtx = mapWallet[txin.prevout .hash ];
614
+ if (prevtx.nIndex == -1 && !prevtx.hashBlock .IsNull ()) {
615
+ MarkConflicted (prevtx.hashBlock , wtx.GetHash ());
616
+ }
617
+ }
618
+ }
611
619
}
612
620
else
613
621
{
@@ -727,6 +735,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
727
735
{
728
736
{
729
737
AssertLockHeld (cs_wallet);
738
+
739
+ if (pblock) {
740
+ BOOST_FOREACH (const CTxIn& txin, tx.vin ) {
741
+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range (txin.prevout );
742
+ while (range.first != range.second ) {
743
+ if (range.first ->second != tx.GetHash ()) {
744
+ 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 );
745
+ MarkConflicted (pblock->GetHash (), range.first ->second );
746
+ }
747
+ range.first ++;
748
+ }
749
+ }
750
+ }
751
+
730
752
bool fExisted = mapWallet.count (tx.GetHash ()) != 0 ;
731
753
if (fExisted && !fUpdate ) return false ;
732
754
if (fExisted || IsMine (tx) || IsFromMe (tx))
@@ -747,9 +769,57 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
747
769
return false ;
748
770
}
749
771
772
+ void CWallet::MarkConflicted (const uint256& hashBlock, const uint256& hashTx)
773
+ {
774
+ LOCK2 (cs_main, cs_wallet);
775
+
776
+ CBlockIndex* pindex;
777
+ assert (mapBlockIndex.count (hashBlock));
778
+ pindex = mapBlockIndex[hashBlock];
779
+ int conflictconfirms = 0 ;
780
+ if (chainActive.Contains (pindex)) {
781
+ conflictconfirms = -(chainActive.Height () - pindex->nHeight + 1 );
782
+ }
783
+ assert (conflictconfirms < 0 );
784
+
785
+ // Do not flush the wallet here for performance reasons
786
+ CWalletDB walletdb (strWalletFile, " r+" , false );
787
+
788
+ std::deque<uint256> todo;
789
+ std::set<uint256> done;
790
+
791
+ todo.push_back (hashTx);
792
+
793
+ while (!todo.empty ()) {
794
+ uint256 now = todo.front ();
795
+ todo.pop_front ();
796
+ done.insert (now);
797
+ assert (mapWallet.count (now));
798
+ CWalletTx& wtx = mapWallet[now];
799
+ int currentconfirm = wtx.GetDepthInMainChain ();
800
+ if (conflictconfirms < currentconfirm) {
801
+ // Block is 'more conflicted' than current confirm; update.
802
+ // Mark transaction as conflicted with this block.
803
+ wtx.nIndex = -1 ;
804
+ wtx.hashBlock = hashBlock;
805
+ wtx.MarkDirty ();
806
+ wtx.WriteToDisk (&walletdb);
807
+ // Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
808
+ TxSpends::const_iterator iter = mapTxSpends.lower_bound (COutPoint (now, 0 ));
809
+ while (iter != mapTxSpends.end () && iter->first .hash == now) {
810
+ if (!done.count (iter->second )) {
811
+ todo.push_back (iter->second );
812
+ }
813
+ iter++;
814
+ }
815
+ }
816
+ }
817
+ }
818
+
750
819
void CWallet::SyncTransaction (const CTransaction& tx, const CBlock* pblock)
751
820
{
752
821
LOCK2 (cs_main, cs_wallet);
822
+
753
823
if (!AddToWalletIfInvolvingMe (tx, pblock, true ))
754
824
return ; // Not one of ours
755
825
@@ -1089,7 +1159,7 @@ void CWallet::ReacceptWalletTransactions()
1089
1159
1090
1160
int nDepth = wtx.GetDepthInMainChain ();
1091
1161
1092
- if (!wtx.IsCoinBase () && nDepth < 0 ) {
1162
+ if (!wtx.IsCoinBase () && nDepth == 0 ) {
1093
1163
mapSorted.insert (std::make_pair (wtx.nOrderPos , &wtx));
1094
1164
}
1095
1165
}
@@ -1303,6 +1373,14 @@ bool CWalletTx::IsTrusted() const
1303
1373
if (!bSpendZeroConfChange || !IsFromMe (ISMINE_ALL)) // using wtx's cached debit
1304
1374
return false ;
1305
1375
1376
+ // Don't trust unconfirmed transactions from us unless they are in the mempool.
1377
+ {
1378
+ LOCK (mempool.cs );
1379
+ if (!mempool.exists (GetHash ())) {
1380
+ return false ;
1381
+ }
1382
+ }
1383
+
1306
1384
// Trusted if all inputs are from us and are in the mempool:
1307
1385
BOOST_FOREACH (const CTxIn& txin, vin)
1308
1386
{
@@ -1879,6 +1957,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
1879
1957
// a chance at a free transaction.
1880
1958
// But mempool inputs might still be in the mempool, so their age stays 0
1881
1959
int age = pcoin.first ->GetDepthInMainChain ();
1960
+ assert (age >= 0 );
1882
1961
if (age != 0 )
1883
1962
age += 1 ;
1884
1963
dPriority += (double )nCredit * age;
@@ -2814,9 +2893,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
2814
2893
return chainActive.Height () - pindex->nHeight + 1 ;
2815
2894
}
2816
2895
2817
- int CMerkleTx::GetDepthInMainChainINTERNAL (const CBlockIndex* &pindexRet) const
2896
+ int CMerkleTx::GetDepthInMainChain (const CBlockIndex* &pindexRet) const
2818
2897
{
2819
- if (hashBlock.IsNull () || nIndex == - 1 )
2898
+ if (hashBlock.IsNull ())
2820
2899
return 0 ;
2821
2900
AssertLockHeld (cs_main);
2822
2901
@@ -2829,17 +2908,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
2829
2908
return 0 ;
2830
2909
2831
2910
pindexRet = pindex;
2832
- return chainActive.Height () - pindex->nHeight + 1 ;
2833
- }
2834
-
2835
- int CMerkleTx::GetDepthInMainChain (const CBlockIndex* &pindexRet) const
2836
- {
2837
- AssertLockHeld (cs_main);
2838
- int nResult = GetDepthInMainChainINTERNAL (pindexRet);
2839
- if (nResult == 0 && !mempool.exists (GetHash ()))
2840
- return -1 ; // Not in chain, not in mempool
2841
-
2842
- return nResult;
2911
+ return ((nIndex == -1 ) ? (-1 ) : 1 ) * (chainActive.Height () - pindex->nHeight + 1 );
2843
2912
}
2844
2913
2845
2914
int CMerkleTx::GetBlocksToMaturity () const
0 commit comments