Relay double-spends, subject to anti-DOS

cef3711500 (diff-7ec3c68a81efff79b6ca22ac1f1eabbaL929)
This commit is contained in:
lateminer
2018-01-10 21:52:38 +03:00
parent 48feed03ef
commit 72875a2116
12 changed files with 150 additions and 56 deletions

View File

@@ -391,7 +391,7 @@ bool CWallet::SetMaxVersion(int nVersion)
return true;
}
set<uint256> CWallet::GetConflicts(const uint256& txid) const
set<uint256> CWallet::GetConflicts(const uint256& txid, bool includeEquivalent) const
{
set<uint256> result;
AssertLockHeld(cs_wallet);
@@ -409,7 +409,8 @@ set<uint256> CWallet::GetConflicts(const uint256& txid) const
continue; // No conflict if zero or one spends
range = mapTxSpends.equal_range(txin.prevout);
for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
result.insert(it->second);
if (includeEquivalent || !wtx.IsEquivalentTo(mapWallet.at(it->second)))
result.insert(it->second);
}
return result;
}
@@ -1237,7 +1238,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
* pblock is optional, but should be provided if the transaction is known to be in a block.
* If fUpdate is true, existing transactions will be updated.
*/
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fRespend)
{
{
AssertLockHeld(cs_wallet);
@@ -1257,7 +1258,15 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
bool fExisted = mapWallet.count(tx.GetHash()) != 0;
if (fExisted && !fUpdate) return false;
if (fExisted || IsMine(tx) || IsFromMe(tx))
bool fIsConflicting = IsConflicting(tx);
// Don't add respends that pay us, unless they conflict with us. Prevents resource exhaustion.
if (!fIsConflicting && fRespend) return false;
if (fIsConflicting)
nConflictsReceived++;
if (fExisted || IsMine(tx) || IsFromMe(tx) || fIsConflicting)
{
CWalletTx wtx(this,tx);
@@ -1392,24 +1401,21 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
}
}
void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
void void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock, bool fRespend)
{
LOCK2(cs_main, cs_wallet);
if (!pblock) {
// wallets need to refund inputs when disconnecting coinstake
if (tx.IsCoinStake()) {
if (IsFromMe(tx)) {
DisableTransaction(tx);
return;
}
}
}
LOCK2(cs_main, cs_wallet);
if (!pblock) {
// wallets need to refund inputs when disconnecting coinstake
if (tx.IsCoinStake()) {
if (IsFromMe(tx)) {
DisableTransaction(tx);
return;
}
}
}
if (!AddToWalletIfInvolvingMe(tx, pblock, true))
if (!AddToWalletIfInvolvingMe(tx, pblock, true, fRespend))
return; // Not one of ours
// If a transaction changes 'conflicted' state, that changes the balance
@@ -1438,6 +1444,14 @@ isminetype CWallet::IsMine(const CTxIn &txin) const
return ISMINE_NO;
}
bool CWallet::IsConflicting(const CTransaction& tx) const
{
BOOST_FOREACH(const CTxIn& txin, tx.vin)
if (mapTxSpends.count(txin.prevout))
return true;
return false;
}
CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
{
{
@@ -1774,7 +1788,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
ReadBlockFromDisk(block, pindex, Params().GetConsensus());
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
if (AddToWalletIfInvolvingMe(tx, &block, fUpdate, false))
ret++;
}
pindex = chainActive.Next(pindex);
@@ -1805,7 +1819,7 @@ void CWallet::ReacceptWalletTransactions()
int nDepth = wtx.GetDepthInMainChain();
if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && (nDepth == 0 && !wtx.isAbandoned())) {
if (!wtx.IsCoinBase() && !wtx.IsCoinStake() && (nDepth == 0 && !wtx.isAbandoned() && (IsMine(wtx) || IsFromMe(wtx)))) {
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
}
}
@@ -1834,13 +1848,13 @@ bool CWalletTx::RelayWalletTransaction()
return false;
}
set<uint256> CWalletTx::GetConflicts() const
set<uint256> CWalletTx::GetConflicts(bool includeEquivalent) const
{
set<uint256> result;
if (pwallet != NULL)
{
uint256 myHash = GetHash();
result = pwallet->GetConflicts(myHash);
result = pwallet->GetConflicts(myHash, includeEquivalent);
result.erase(myHash);
}
return result;