@@ -930,11 +930,13 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
930930 wtx.m_confirm .status = wtxIn.m_confirm .status ;
931931 wtx.m_confirm .nIndex = wtxIn.m_confirm .nIndex ;
932932 wtx.m_confirm .hashBlock = wtxIn.m_confirm .hashBlock ;
933+ wtx.m_confirm .block_height = wtxIn.m_confirm .block_height ;
933934 wtx.UpdateTimeSmart ();
934935 fUpdated = true ;
935936 } else {
936937 assert (wtx.m_confirm .nIndex == wtxIn.m_confirm .nIndex );
937938 assert (wtx.m_confirm .hashBlock == wtxIn.m_confirm .hashBlock );
939+ assert (wtx.m_confirm .block_height == wtxIn.m_confirm .block_height );
938940 }
939941 if (HasSaplingSPKM () && m_sspk_man->UpdatedNoteData (wtxIn, wtx)) {
940942 fUpdated = true ;
@@ -971,17 +973,38 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
971973 return true ;
972974}
973975
976+ // Internal function for now, this will be part of a chain interface class in the future.
977+ Optional<int > getTipBlockHeight (const uint256& hash)
978+ {
979+ auto it = mapBlockIndex.find (hash);
980+ CBlockIndex* pindex = it == mapBlockIndex.end () ? nullptr : it->second ;
981+ if (pindex && chainActive.Contains (pindex)) {
982+ return Optional<int >(pindex->nHeight );
983+ }
984+ return nullopt ;
985+ }
986+
974987bool CWallet::LoadToWallet (CWalletTx& wtxIn)
975988{
976989 LOCK2 (cs_main, cs_wallet);
977990 // If tx hasn't been reorged out of chain while wallet being shutdown
978991 // change tx status to UNCONFIRMED and reset hashBlock/nIndex.
979992 if (!wtxIn.m_confirm .hashBlock .IsNull ()) {
980- auto it = mapBlockIndex.find (wtxIn.m_confirm .hashBlock );
981- CBlockIndex* pindex = it == mapBlockIndex.end () ? nullptr : it->second ;
982- if (!pindex || !chainActive.Contains (pindex)) {
993+ Optional<int > block_height = getTipBlockHeight (wtxIn.m_confirm .hashBlock );
994+ if (block_height) {
995+ // Update cached block height variable since it not stored in the
996+ // serialized transaction.
997+ wtxIn.m_confirm .block_height = *block_height;
998+ } else if (wtxIn.isConflicted () || wtxIn.isConfirmed ()) {
999+ // If tx block (or conflicting block) was reorged out of chain
1000+ // while the wallet was shutdown, change tx status to UNCONFIRMED
1001+ // and reset block height, hash, and index. ABANDONED tx don't have
1002+ // associated blocks and don't need to be updated. The case where a
1003+ // transaction was reorged out while online and then reconfirmed
1004+ // while offline is covered by the rescan logic.
9831005 wtxIn.setUnconfirmed ();
9841006 wtxIn.m_confirm .hashBlock = UINT256_ZERO;
1007+ wtxIn.m_confirm .block_height = 0 ;
9851008 wtxIn.m_confirm .nIndex = 0 ;
9861009 }
9871010 }
@@ -997,7 +1020,7 @@ bool CWallet::LoadToWallet(CWalletTx& wtxIn)
9971020 if (it != mapWallet.end ()) {
9981021 CWalletTx& prevtx = it->second ;
9991022 if (prevtx.isConflicted ()) {
1000- MarkConflicted (prevtx.m_confirm .hashBlock , wtx.GetHash ());
1023+ MarkConflicted (prevtx.m_confirm .hashBlock , prevtx. m_confirm . block_height , wtx.GetHash ());
10011024 }
10021025 }
10031026 }
@@ -1067,7 +1090,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CWallet
10671090 while (range.first != range.second ) {
10681091 if (range.first ->second != tx.GetHash ()) {
10691092 LogPrintf (" 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 );
1070- MarkConflicted (confirm.hashBlock , range.first ->second );
1093+ MarkConflicted (confirm.hashBlock , confirm. block_height , range.first ->second );
10711094 }
10721095 range.first ++;
10731096 }
@@ -1152,7 +1175,6 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
11521175 if (currentconfirm == 0 && !wtx.isAbandoned ()) {
11531176 // If the orig tx was not in block/mempool, none of its spends can be in mempool
11541177 assert (!wtx.InMempool ());
1155- wtx.m_confirm .nIndex = 0 ;
11561178 wtx.setAbandoned ();
11571179 wtx.MarkDirty ();
11581180 walletdb.WriteTx (wtx);
@@ -1179,7 +1201,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
11791201 return true ;
11801202}
11811203
1182- void CWallet::MarkConflicted (const uint256& hashBlock, const uint256& hashTx)
1204+ void CWallet::MarkConflicted (const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
11831205{
11841206 LOCK2 (cs_main, cs_wallet);
11851207
@@ -1219,6 +1241,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
12191241 // Mark transaction as conflicted with this block.
12201242 wtx.m_confirm .nIndex = 0 ;
12211243 wtx.m_confirm .hashBlock = hashBlock;
1244+ wtx.m_confirm .block_height = conflicting_height;
12221245 wtx.setConflicted ();
12231246 wtx.MarkDirty ();
12241247 walletdb.WriteTx (wtx);
@@ -1254,7 +1277,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CWalletTx::Confi
12541277void CWallet::TransactionAddedToMempool (const CTransactionRef& ptx)
12551278{
12561279 LOCK2 (cs_main, cs_wallet);
1257- CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, {}, 0 );
1280+ CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, /* block_height */ 0 , {}, /* nIndex */ 0 );
12581281 SyncTransaction (ptx, confirm);
12591282
12601283 auto it = mapWallet.find (ptx->GetHash ());
@@ -1278,10 +1301,10 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
12781301 m_last_block_processed = pindex->GetBlockHash ();
12791302 m_last_block_processed_time = pindex->GetBlockTime ();
12801303 m_last_block_processed_height = pindex->nHeight ;
1281- for (size_t i = 0 ; i < pblock->vtx .size (); i ++) {
1282- CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, m_last_block_processed->GetBlockHash (), i );
1283- SyncTransaction (pblock->vtx [i ], confirm);
1284- TransactionRemovedFromMempool (pblock->vtx [i ]);
1304+ for (size_t index = 0 ; index < pblock->vtx .size (); index ++) {
1305+ CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, m_last_block_processed_height, m_last_block_processed->GetBlockHash (), index );
1306+ SyncTransaction (pblock->vtx [index ], confirm);
1307+ TransactionRemovedFromMempool (pblock->vtx [index ]);
12851308 }
12861309 for (const CTransactionRef& ptx : vtxConflicted) {
12871310 TransactionRemovedFromMempool (ptx);
@@ -1316,7 +1339,7 @@ void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, con
13161339 m_last_block_processed_time = blockTime;
13171340 m_last_block_processed = blockHash;
13181341 for (const CTransactionRef& ptx : pblock->vtx ) {
1319- CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, {}, 0 );
1342+ CWalletTx::Confirmation confirm (CWalletTx::Status::UNCONFIRMED, /* block_height */ 0 , {}, /* nIndex */ 0 );
13201343 SyncTransaction (ptx, confirm);
13211344 }
13221345
@@ -1848,7 +1871,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, b
18481871 }
18491872 for (int posInBlock = 0 ; posInBlock < (int ) block.vtx .size (); posInBlock++) {
18501873 const auto & tx = block.vtx [posInBlock];
1851- CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, pindex->GetBlockHash (), posInBlock);
1874+ CWalletTx::Confirmation confirm (CWalletTx::Status::CONFIRMED, pindex->nHeight , pindex-> GetBlockHash (), posInBlock);
18521875 if (AddToWalletIfInvolvingMe (tx, confirm, fUpdate )) {
18531876 myTxHashes.push_back (tx->GetHash ());
18541877 ret++;
0 commit comments