mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 06:58:57 +01:00
Keep track of explicit wallet conflicts instead of using mempool
This commit is contained in:
@@ -608,6 +608,14 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
|
||||
wtx.BindWallet(this);
|
||||
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
|
||||
AddToSpends(hash);
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin) {
|
||||
if (mapWallet.count(txin.prevout.hash)) {
|
||||
CWalletTx& prevtx = mapWallet[txin.prevout.hash];
|
||||
if (prevtx.nIndex == -1 && !prevtx.hashBlock.IsNull()) {
|
||||
MarkConflicted(prevtx.hashBlock, wtx.GetHash());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -727,6 +735,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
|
||||
{
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
if (pblock) {
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
|
||||
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(txin.prevout);
|
||||
while (range.first != range.second) {
|
||||
if (range.first->second != tx.GetHash()) {
|
||||
LogPrintf("Transaction %s (in block %s) conflicts with wallet transaction %s (both spend %s:%i)\n", tx.GetHash().ToString(), pblock->GetHash().ToString(), range.first->second.ToString(), range.first->first.hash.ToString(), range.first->first.n);
|
||||
MarkConflicted(pblock->GetHash(), range.first->second);
|
||||
}
|
||||
range.first++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool fExisted = mapWallet.count(tx.GetHash()) != 0;
|
||||
if (fExisted && !fUpdate) return false;
|
||||
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
||||
@@ -747,9 +769,57 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
|
||||
CBlockIndex* pindex;
|
||||
assert(mapBlockIndex.count(hashBlock));
|
||||
pindex = mapBlockIndex[hashBlock];
|
||||
int conflictconfirms = 0;
|
||||
if (chainActive.Contains(pindex)) {
|
||||
conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1);
|
||||
}
|
||||
assert(conflictconfirms < 0);
|
||||
|
||||
// Do not flush the wallet here for performance reasons
|
||||
CWalletDB walletdb(strWalletFile, "r+", false);
|
||||
|
||||
std::deque<uint256> todo;
|
||||
std::set<uint256> done;
|
||||
|
||||
todo.push_back(hashTx);
|
||||
|
||||
while (!todo.empty()) {
|
||||
uint256 now = todo.front();
|
||||
todo.pop_front();
|
||||
done.insert(now);
|
||||
assert(mapWallet.count(now));
|
||||
CWalletTx& wtx = mapWallet[now];
|
||||
int currentconfirm = wtx.GetDepthInMainChain();
|
||||
if (conflictconfirms < currentconfirm) {
|
||||
// Block is 'more conflicted' than current confirm; update.
|
||||
// Mark transaction as conflicted with this block.
|
||||
wtx.nIndex = -1;
|
||||
wtx.hashBlock = hashBlock;
|
||||
wtx.MarkDirty();
|
||||
wtx.WriteToDisk(&walletdb);
|
||||
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
|
||||
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
|
||||
while (iter != mapTxSpends.end() && iter->first.hash == now) {
|
||||
if (!done.count(iter->second)) {
|
||||
todo.push_back(iter->second);
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
|
||||
if (!AddToWalletIfInvolvingMe(tx, pblock, true))
|
||||
return; // Not one of ours
|
||||
|
||||
@@ -1089,7 +1159,7 @@ void CWallet::ReacceptWalletTransactions()
|
||||
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
|
||||
if (!wtx.IsCoinBase() && nDepth < 0) {
|
||||
if (!wtx.IsCoinBase() && nDepth == 0) {
|
||||
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
|
||||
}
|
||||
}
|
||||
@@ -1303,6 +1373,14 @@ bool CWalletTx::IsTrusted() const
|
||||
if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
|
||||
return false;
|
||||
|
||||
// Don't trust unconfirmed transactions from us unless they are in the mempool.
|
||||
{
|
||||
LOCK(mempool.cs);
|
||||
if (!mempool.exists(GetHash())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Trusted if all inputs are from us and are in the mempool:
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
{
|
||||
@@ -1879,6 +1957,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
//a chance at a free transaction.
|
||||
//But mempool inputs might still be in the mempool, so their age stays 0
|
||||
int age = pcoin.first->GetDepthInMainChain();
|
||||
assert(age >= 0);
|
||||
if (age != 0)
|
||||
age += 1;
|
||||
dPriority += (double)nCredit * age;
|
||||
@@ -2814,9 +2893,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
|
||||
return chainActive.Height() - pindex->nHeight + 1;
|
||||
}
|
||||
|
||||
int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
|
||||
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
|
||||
{
|
||||
if (hashBlock.IsNull() || nIndex == -1)
|
||||
if (hashBlock.IsNull())
|
||||
return 0;
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
@@ -2829,17 +2908,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
|
||||
return 0;
|
||||
|
||||
pindexRet = pindex;
|
||||
return chainActive.Height() - pindex->nHeight + 1;
|
||||
}
|
||||
|
||||
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
int nResult = GetDepthInMainChainINTERNAL(pindexRet);
|
||||
if (nResult == 0 && !mempool.exists(GetHash()))
|
||||
return -1; // Not in chain, not in mempool
|
||||
|
||||
return nResult;
|
||||
return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1);
|
||||
}
|
||||
|
||||
int CMerkleTx::GetBlocksToMaturity() const
|
||||
|
||||
Reference in New Issue
Block a user