aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
authorAntoine Riard <[email protected]>2019-04-20 11:22:59 -0400
committerAntoine Riard <[email protected]>2019-11-06 13:29:53 -0500
commit5971d3848e09abf571e5308185275296127efca4 (patch)
treed72dc502a73f4e3b955c772225fedfa18be59cc9 /src/wallet/wallet.cpp
parentReplace CWalletTx::SetConf by Confirmation initialization list (diff)
downloaddiscoin-5971d3848e09abf571e5308185275296127efca4.tar.xz
discoin-5971d3848e09abf571e5308185275296127efca4.zip
Add block_height field in struct Confirmation
At wallet loading, we rely on chain state querying to retrieve height of txn, to do so we ensure that lock order is respected between cs_main and cs_wallet. If wallet loaded is the wallet-tool one, all wallet txn will show up with a height of zero. It doesn't matter as confirmation height is not used by wallet-tool. Reorder arguments and document Confirmation calls to avoid ambiguity. Fixes nits left from #16624
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp42
1 files changed, 27 insertions, 15 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 2ee1d001b..512273aa8 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -766,10 +766,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
wtx.m_confirm.status = wtxIn.m_confirm.status;
wtx.m_confirm.nIndex = wtxIn.m_confirm.nIndex;
wtx.m_confirm.hashBlock = wtxIn.m_confirm.hashBlock;
+ wtx.m_confirm.block_height = wtxIn.m_confirm.block_height;
fUpdated = true;
} else {
assert(wtx.m_confirm.nIndex == wtxIn.m_confirm.nIndex);
assert(wtx.m_confirm.hashBlock == wtxIn.m_confirm.hashBlock);
+ assert(wtx.m_confirm.block_height == wtxIn.m_confirm.block_height);
}
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
{
@@ -820,12 +822,22 @@ void CWallet::LoadToWallet(CWalletTx& wtxIn)
{
// If wallet doesn't have a chain (e.g wallet-tool), lock can't be taken.
auto locked_chain = LockChain();
- // If tx hasn't been reorged out of chain while wallet being shutdown
- // change tx status to UNCONFIRMED and reset hashBlock/nIndex.
- if (!wtxIn.m_confirm.hashBlock.IsNull()) {
- if (locked_chain && !locked_chain->getBlockHeight(wtxIn.m_confirm.hashBlock)) {
+ if (locked_chain) {
+ Optional<int> block_height = locked_chain->getBlockHeight(wtxIn.m_confirm.hashBlock);
+ if (block_height) {
+ // Update cached block height variable since it not stored in the
+ // serialized transaction.
+ wtxIn.m_confirm.block_height = *block_height;
+ } else if (wtxIn.isConflicted() || wtxIn.isConfirmed()) {
+ // If tx block (or conflicting block) was reorged out of chain
+ // while the wallet was shutdown, change tx status to UNCONFIRMED
+ // and reset block height, hash, and index. ABANDONED tx don't have
+ // associated blocks and don't need to be updated. The case where a
+ // transaction was reorged out while online and then reconfirmed
+ // while offline is covered by the rescan logic.
wtxIn.setUnconfirmed();
wtxIn.m_confirm.hashBlock = uint256();
+ wtxIn.m_confirm.block_height = 0;
wtxIn.m_confirm.nIndex = 0;
}
}
@@ -842,7 +854,7 @@ void CWallet::LoadToWallet(CWalletTx& wtxIn)
if (it != mapWallet.end()) {
CWalletTx& prevtx = it->second;
if (prevtx.isConflicted()) {
- MarkConflicted(prevtx.m_confirm.hashBlock, wtx.GetHash());
+ MarkConflicted(prevtx.m_confirm.hashBlock, prevtx.m_confirm.block_height, wtx.GetHash());
}
}
}
@@ -860,7 +872,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
while (range.first != range.second) {
if (range.first->second != tx.GetHash()) {
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);
- MarkConflicted(confirm.hashBlock, range.first->second);
+ MarkConflicted(confirm.hashBlock, confirm.block_height, range.first->second);
}
range.first++;
}
@@ -948,7 +960,6 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
if (currentconfirm == 0 && !wtx.isAbandoned()) {
// If the orig tx was not in block/mempool, none of its spends can be in mempool
assert(!wtx.InMempool());
- wtx.m_confirm.nIndex = 0;
wtx.setAbandoned();
wtx.MarkDirty();
batch.WriteTx(wtx);
@@ -970,7 +981,7 @@ bool CWallet::AbandonTransaction(interfaces::Chain::Lock& locked_chain, const ui
return true;
}
-void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
+void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx)
{
auto locked_chain = chain().lock();
LOCK(cs_wallet);
@@ -1004,6 +1015,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
// Mark transaction as conflicted with this block.
wtx.m_confirm.nIndex = 0;
wtx.m_confirm.hashBlock = hashBlock;
+ wtx.m_confirm.block_height = conflicting_height;
wtx.setConflicted();
wtx.MarkDirty();
batch.WriteTx(wtx);
@@ -1036,7 +1048,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, CWalletTx::Confirmatio
void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
auto locked_chain = chain().lock();
LOCK(cs_wallet);
- CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, {}, 0);
+ CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, /* block_height */ 0, {}, /* nIndex */ 0);
SyncTransaction(ptx, confirm);
auto it = mapWallet.find(ptx->GetHash());
@@ -1061,10 +1073,10 @@ void CWallet::BlockConnected(const CBlock& block, const std::vector<CTransaction
m_last_block_processed_height = height;
m_last_block_processed = block_hash;
- for (size_t i = 0; i < block.vtx.size(); i++) {
- CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, m_last_block_processed, i);
- SyncTransaction(block.vtx[i], confirm);
- TransactionRemovedFromMempool(block.vtx[i]);
+ for (size_t index = 0; index < block.vtx.size(); index++) {
+ CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, height, block_hash, index);
+ SyncTransaction(block.vtx[index], confirm);
+ TransactionRemovedFromMempool(block.vtx[index]);
}
for (const CTransactionRef& ptx : vtxConflicted) {
TransactionRemovedFromMempool(ptx);
@@ -1083,7 +1095,7 @@ void CWallet::BlockDisconnected(const CBlock& block, int height)
m_last_block_processed_height = height - 1;
m_last_block_processed = block.hashPrevBlock;
for (const CTransactionRef& ptx : block.vtx) {
- CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, {}, 0);
+ CWalletTx::Confirmation confirm(CWalletTx::Status::UNCONFIRMED, /* block_height */ 0, {}, /* nIndex */ 0);
SyncTransaction(ptx, confirm);
}
}
@@ -1630,7 +1642,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
break;
}
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
- CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, block_hash, posInBlock);
+ CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, *block_height, block_hash, posInBlock);
SyncTransaction(block.vtx[posInBlock], confirm, fUpdate);
}
// scan succeeded, record block as most recent successfully scanned