@@ -48,6 +48,8 @@ bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS;
48
48
*/
49
49
CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
50
50
51
+ const uint256 CMerkleTx::ABANDON_HASH (uint256S(" 0000000000000000000000000000000000000000000000000000000000000001" ));
52
+
51
53
/* * @defgroup mapWallet
52
54
*
53
55
* @{
@@ -455,8 +457,11 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
455
457
{
456
458
const uint256& wtxid = it->second ;
457
459
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find (wtxid);
458
- if (mit != mapWallet.end () && mit->second .GetDepthInMainChain () >= 0 )
459
- return true ; // Spent
460
+ if (mit != mapWallet.end ()) {
461
+ int depth = mit->second .GetDepthInMainChain ();
462
+ if (depth > 0 || (depth == 0 && !mit->second .isAbandoned ()))
463
+ return true ; // Spent
464
+ }
460
465
}
461
466
return false ;
462
467
}
@@ -610,7 +615,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
610
615
BOOST_FOREACH (const CTxIn& txin, wtx.vin ) {
611
616
if (mapWallet.count (txin.prevout .hash )) {
612
617
CWalletTx& prevtx = mapWallet[txin.prevout .hash ];
613
- if (prevtx.nIndex == -1 && !prevtx.hashBlock . IsNull ()) {
618
+ if (prevtx.nIndex == -1 && !prevtx.hashUnset ()) {
614
619
MarkConflicted (prevtx.hashBlock , wtx.GetHash ());
615
620
}
616
621
}
@@ -631,7 +636,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
631
636
wtxOrdered.insert (make_pair (wtx.nOrderPos , TxPair (&wtx, (CAccountingEntry*)0 )));
632
637
633
638
wtx.nTimeSmart = wtx.nTimeReceived ;
634
- if (!wtxIn.hashBlock . IsNull ())
639
+ if (!wtxIn.hashUnset ())
635
640
{
636
641
if (mapBlockIndex.count (wtxIn.hashBlock ))
637
642
{
@@ -681,7 +686,13 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
681
686
if (!fInsertedNew )
682
687
{
683
688
// Merge
684
- if (!wtxIn.hashBlock .IsNull () && wtxIn.hashBlock != wtx.hashBlock )
689
+ if (!wtxIn.hashUnset () && wtxIn.hashBlock != wtx.hashBlock )
690
+ {
691
+ wtx.hashBlock = wtxIn.hashBlock ;
692
+ fUpdated = true ;
693
+ }
694
+ // If no longer abandoned, update
695
+ if (wtxIn.hashBlock .IsNull () && wtx.isAbandoned ())
685
696
{
686
697
wtx.hashBlock = wtxIn.hashBlock ;
687
698
fUpdated = true ;
@@ -768,6 +779,63 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
768
779
return false ;
769
780
}
770
781
782
+ bool CWallet::AbandonTransaction (const uint256& hashTx)
783
+ {
784
+ LOCK2 (cs_main, cs_wallet);
785
+
786
+ // Do not flush the wallet here for performance reasons
787
+ CWalletDB walletdb (strWalletFile, " r+" , false );
788
+
789
+ std::set<uint256> todo;
790
+ std::set<uint256> done;
791
+
792
+ // Can't mark abandoned if confirmed or in mempool
793
+ assert (mapWallet.count (hashTx));
794
+ CWalletTx& origtx = mapWallet[hashTx];
795
+ if (origtx.GetDepthInMainChain () > 0 || origtx.InMempool ()) {
796
+ return false ;
797
+ }
798
+
799
+ todo.insert (hashTx);
800
+
801
+ while (!todo.empty ()) {
802
+ uint256 now = *todo.begin ();
803
+ todo.erase (now);
804
+ done.insert (now);
805
+ assert (mapWallet.count (now));
806
+ CWalletTx& wtx = mapWallet[now];
807
+ int currentconfirm = wtx.GetDepthInMainChain ();
808
+ // If the orig tx was not in block, none of its spends can be
809
+ assert (currentconfirm <= 0 );
810
+ // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
811
+ if (currentconfirm == 0 && !wtx.isAbandoned ()) {
812
+ // If the orig tx was not in block/mempool, none of its spends can be in mempool
813
+ assert (!wtx.InMempool ());
814
+ wtx.nIndex = -1 ;
815
+ wtx.setAbandoned ();
816
+ wtx.MarkDirty ();
817
+ wtx.WriteToDisk (&walletdb);
818
+ // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
819
+ TxSpends::const_iterator iter = mapTxSpends.lower_bound (COutPoint (hashTx, 0 ));
820
+ while (iter != mapTxSpends.end () && iter->first .hash == now) {
821
+ if (!done.count (iter->second )) {
822
+ todo.insert (iter->second );
823
+ }
824
+ iter++;
825
+ }
826
+ // If a transaction changes 'conflicted' state, that changes the balance
827
+ // available of the outputs it spends. So force those to be recomputed
828
+ BOOST_FOREACH (const CTxIn& txin, wtx.vin )
829
+ {
830
+ if (mapWallet.count (txin.prevout .hash ))
831
+ mapWallet[txin.prevout .hash ].MarkDirty ();
832
+ }
833
+ }
834
+ }
835
+
836
+ return true ;
837
+ }
838
+
771
839
void CWallet::MarkConflicted (const uint256& hashBlock, const uint256& hashTx)
772
840
{
773
841
LOCK2 (cs_main, cs_wallet);
@@ -976,7 +1044,7 @@ int CWalletTx::GetRequestCount() const
976
1044
if (IsCoinBase ())
977
1045
{
978
1046
// Generated block
979
- if (!hashBlock. IsNull ())
1047
+ if (!hashUnset ())
980
1048
{
981
1049
map<uint256, int >::const_iterator mi = pwallet->mapRequestCount .find (hashBlock);
982
1050
if (mi != pwallet->mapRequestCount .end ())
@@ -992,7 +1060,7 @@ int CWalletTx::GetRequestCount() const
992
1060
nRequests = (*mi).second ;
993
1061
994
1062
// How about the block it's in?
995
- if (nRequests == 0 && !hashBlock. IsNull ())
1063
+ if (nRequests == 0 && !hashUnset ())
996
1064
{
997
1065
map<uint256, int >::const_iterator mi = pwallet->mapRequestCount .find (hashBlock);
998
1066
if (mi != pwallet->mapRequestCount .end ())
@@ -1166,7 +1234,7 @@ void CWallet::ReacceptWalletTransactions()
1166
1234
1167
1235
int nDepth = wtx.GetDepthInMainChain ();
1168
1236
1169
- if (!wtx.IsCoinBase () && nDepth == 0 ) {
1237
+ if (!wtx.IsCoinBase () && ( nDepth == 0 && !wtx. isAbandoned ()) ) {
1170
1238
mapSorted.insert (std::make_pair (wtx.nOrderPos , &wtx));
1171
1239
}
1172
1240
}
@@ -1186,7 +1254,7 @@ bool CWalletTx::RelayWalletTransaction()
1186
1254
assert (pwallet->GetBroadcastTransactions ());
1187
1255
if (!IsCoinBase ())
1188
1256
{
1189
- if (GetDepthInMainChain () == 0 ) {
1257
+ if (GetDepthInMainChain () == 0 && ! isAbandoned () ) {
1190
1258
LogPrintf (" Relaying wtx %s\n " , GetHash ().ToString ());
1191
1259
RelayTransaction ((CTransaction)*this );
1192
1260
return true ;
@@ -2927,8 +2995,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
2927
2995
2928
2996
int CMerkleTx::GetDepthInMainChain (const CBlockIndex* &pindexRet) const
2929
2997
{
2930
- if (hashBlock. IsNull ())
2998
+ if (hashUnset ())
2931
2999
return 0 ;
3000
+
2932
3001
AssertLockHeld (cs_main);
2933
3002
2934
3003
// Find the block it claims to be in
@@ -2956,4 +3025,3 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
2956
3025
CValidationState state;
2957
3026
return ::AcceptToMemoryPool (mempool, state, *this , fLimitFree , NULL , false , fRejectAbsurdFee );
2958
3027
}
2959
-
0 commit comments