@@ -766,10 +766,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
766
766
wtx.m_confirm .status = wtxIn.m_confirm .status ;
767
767
wtx.m_confirm .nIndex = wtxIn.m_confirm .nIndex ;
768
768
wtx.m_confirm .hashBlock = wtxIn.m_confirm .hashBlock ;
769
+ wtx.m_confirm .block_height = wtxIn.m_confirm .block_height ;
769
770
fUpdated = true ;
770
771
} else {
771
772
assert (wtx.m_confirm .nIndex == wtxIn.m_confirm .nIndex );
772
773
assert (wtx.m_confirm .hashBlock == wtxIn.m_confirm .hashBlock );
774
+ assert (wtx.m_confirm .block_height == wtxIn.m_confirm .block_height );
773
775
}
774
776
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe )
775
777
{
@@ -820,12 +822,22 @@ void CWallet::LoadToWallet(CWalletTx& wtxIn)
820
822
{
821
823
// If wallet doesn't have a chain (e.g wallet-tool), lock can't be taken.
822
824
auto locked_chain = LockChain ();
823
- // If tx hasn't been reorged out of chain while wallet being shutdown
824
- // change tx status to UNCONFIRMED and reset hashBlock/nIndex.
825
- if (!wtxIn.m_confirm .hashBlock .IsNull ()) {
826
- if (locked_chain && !locked_chain->getBlockHeight (wtxIn.m_confirm .hashBlock )) {
825
+ if (locked_chain) {
826
+ Optional<int > block_height = locked_chain->getBlockHeight (wtxIn.m_confirm .hashBlock );
827
+ if (block_height) {
828
+ // Update cached block height variable since it not stored in the
829
+ // serialized transaction.
830
+ wtxIn.m_confirm .block_height = *block_height;
831
+ } else if (wtxIn.isConflicted () || wtxIn.isConfirmed ()) {
832
+ // If tx block (or conflicting block) was reorged out of chain
833
+ // while the wallet was shutdown, change tx status to UNCONFIRMED
834
+ // and reset block height, hash, and index. ABANDONED tx don't have
835
+ // associated blocks and don't need to be updated. The case where a
836
+ // transaction was reorged out while online and then reconfirmed
837
+ // while offline is covered by the rescan logic.
827
838
wtxIn.setUnconfirmed ();
828
839
wtxIn.m_confirm .hashBlock = uint256 ();
840
+ wtxIn.m_confirm .block_height = 0 ;
829
841
wtxIn.m_confirm .nIndex = 0 ;
830
842
}
831
843
}
@@ -842,7 +854,7 @@ void CWallet::LoadToWallet(CWalletTx& wtxIn)
842
854
if (it != mapWallet.end ()) {
843
855
CWalletTx& prevtx = it->second ;
844
856
if (prevtx.isConflicted ()) {
845
- MarkConflicted (prevtx.m_confirm .hashBlock , wtx.GetHash ());
857
+ MarkConflicted (prevtx.m_confirm .hashBlock , prevtx. m_confirm . block_height , wtx.GetHash ());
846
858
}
847
859
}
848
860
}
@@ -860,7 +872,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
860
872
while (range.first != range.second ) {
861
873
if (range.first ->second != tx.GetHash ()) {
862
874
WalletLogPrintf (" Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n " , tx.GetHash ().ToString (), confirm.hashBlock .ToString (), range.first ->second .ToString (), range.first ->first .hash .ToString (), range.first ->first .n );
863
- MarkConflicted (confirm.hashBlock , range.first ->second );
875
+ MarkConflicted (confirm.hashBlock , confirm. block_height , range.first ->second );
864
876
}
865
877
range.first ++;
866
878
}
@@ -948,7 +960,6 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
948
960
if (currentconfirm == 0 && !wtx.isAbandoned ()) {
949
961
// If the orig tx was not in block/mempool, none of its spends can be in mempool
950
962
assert (!wtx.InMempool ());
951
- wtx.m_confirm .nIndex = 0 ;
952
963
wtx.setAbandoned ();
953
964
wtx.MarkDirty ();
954
965
batch.WriteTx (wtx);
@@ -970,7 +981,7 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
970
981
return true ;
971
982
}
972
983
973
- void CWallet::MarkConflicted (const uint256& hashBlock, const uint256& hashTx)
984
+ void CWallet::MarkConflicted (const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
974
985
{
975
986
auto locked_chain = chain ().lock ();
976
987
LOCK (cs_wallet);
@@ -1004,6 +1015,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
1004
1015
// Mark transaction as conflicted with this block.
1005
1016
wtx.m_confirm .nIndex = 0 ;
1006
1017
wtx.m_confirm .hashBlock = hashBlock;
1018
+ wtx.m_confirm .block_height = conflicting_height;
1007
1019
wtx.setConflicted ();
1008
1020
wtx.MarkDirty ();
1009
1021
batch.WriteTx (wtx);
@@ -1036,7 +1048,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmatio
1036
1048
void CWallet::TransactionAddedToMempool (const CTransactionRef& ptx) {
1037
1049
auto locked_chain = chain ().lock ();
1038
1050
LOCK (cs_wallet);
1039
- CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, {}, 0 );
1051
+ CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, /* block_height */ 0 , {}, /* nIndex */ 0 );
1040
1052
SyncTransaction (ptx, confirm);
1041
1053
1042
1054
auto it = mapWallet.find (ptx->GetHash ());
@@ -1061,10 +1073,10 @@ void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransaction
1061
1073
1062
1074
m_last_block_processed_height = height;
1063
1075
m_last_block_processed = block_hash;
1064
- for (size_t i = 0 ; i < block.vtx .size (); i ++) {
1065
- CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, m_last_block_processed, i );
1066
- SyncTransaction (block.vtx [i ], confirm);
1067
- TransactionRemovedFromMempool (block.vtx [i ]);
1076
+ for (size_t index = 0 ; index < block.vtx .size (); index ++) {
1077
+ CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, height, block_hash, index );
1078
+ SyncTransaction (block.vtx [index ], confirm);
1079
+ TransactionRemovedFromMempool (block.vtx [index ]);
1068
1080
}
1069
1081
for (const CTransactionRef& ptx : vtxConflicted) {
1070
1082
TransactionRemovedFromMempool (ptx);
@@ -1083,7 +1095,7 @@ void CWallet::BlockDisconnected(const CBlock& block, int height)
1083
1095
m_last_block_processed_height = height - 1 ;
1084
1096
m_last_block_processed = block.hashPrevBlock ;
1085
1097
for (const CTransactionRef& ptx : block.vtx ) {
1086
- CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, {}, 0 );
1098
+ CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, /* block_height */ 0 , {}, /* nIndex */ 0 );
1087
1099
SyncTransaction (ptx, confirm);
1088
1100
}
1089
1101
}
@@ -1630,7 +1642,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
1630
1642
break ;
1631
1643
}
1632
1644
for (size_t posInBlock = 0 ; posInBlock < block.vtx .size (); ++posInBlock) {
1633
- CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, block_hash, posInBlock);
1645
+ CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, *block_height, block_hash, posInBlock);
1634
1646
SyncTransaction (block.vtx [posInBlock], confirm, fUpdate );
1635
1647
}
1636
1648
// scan succeeded, record block as most recent successfully scanned
0 commit comments