SyncTransaction->TxAddedToMempool/BlockConnected/Disconnected

This simplifies fixing the wallet-returns-stale-info issue as we
can now hold cs_wallet across an entire block instead of only
per-tx (though we only actually do so in the next commit).

This change also removes the NOT_IN_BLOCK constant in favor of only
passing the CBlockIndex* parameter to SyncTransactions when a new
block is being connected, instead of also when a block is being
disconnected.

This change adds a parameter to BlockConnectedDisconnected which
lists the transactions which were removed from mempool due to
confliction as a result of this operation. While its somewhat of a
shame to make block-validation-logic generate a list of mempool
changes to be included in its generated callbacks, fixing this isnt
too hard.

Further in this change-set, CValidationInterface starts listening
to mempool directly, placing it in the middle and giving it a bit
of logic to know how to route notifications from block-validation,
mempool, etc (though not listening for conflicted-removals yet).
This commit is contained in:
Matt Corallo
2017-03-29 21:12:42 -04:00
parent f404334910
commit 461e49fee2
9 changed files with 109 additions and 63 deletions

View File

@@ -1116,11 +1116,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
}
void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock)
{
LOCK2(cs_main, cs_wallet);
void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindexBlockConnected, int posInBlock) {
const CTransaction& tx = *ptx;
if (!AddToWalletIfInvolvingMe(tx, pindex, posInBlock, true))
if (!AddToWalletIfInvolvingMe(tx, pindexBlockConnected, posInBlock, true))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1133,6 +1132,38 @@ void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex,
}
}
void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) {
LOCK2(cs_main, cs_wallet);
SyncTransaction(ptx, NULL, -1);
}
void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) {
// TODO: Tempoarily ensure that mempool removals are notified before
// connected transactions. This shouldn't matter, but the abandoned
// state of transactions in our wallet is currently cleared when we
// receive another notification and there is a race condition where
// notification of a connected conflict might cause an outside process
// to abandon a transaction and then have it inadvertantly cleared by
// the notification that the conflicted transaction was evicted.
for (const CTransactionRef& ptx : vtxConflicted) {
LOCK2(cs_main, cs_wallet);
SyncTransaction(ptx, NULL, -1);
}
for (size_t i = 0; i < pblock->vtx.size(); i++) {
LOCK2(cs_main, cs_wallet);
SyncTransaction(pblock->vtx[i], pindex, i);
}
}
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
for (const CTransactionRef& ptx : pblock->vtx) {
LOCK2(cs_main, cs_wallet);
SyncTransaction(ptx, NULL, -1);
}
}
isminetype CWallet::IsMine(const CTxIn &txin) const
{