aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2014-07-21 08:52:45 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2014-07-21 08:52:54 +0200
commit3bc4fd955e8845c2aea1d04c7e3cf3e85ee53906 (patch)
tree848534bd7e65b1c81e2893e9957c1254090582c1 /src
parent0de61e7585e14cb552e985934fc5ddfeb6e8bd67 (diff)
parent8f3f94a470cdc7195efdbafd45ea03e6c707d9c8 (diff)
downloadbitcoin-3bc4fd955e8845c2aea1d04c7e3cf3e85ee53906.tar.xz
Merge pull request #4558
8f3f94a Revert "CBloomFilter::clear() method" (Wladimir J. van der Laan) 98e84aa Revert "Relay double-spends, subject to anti-DOS" (Wladimir J. van der Laan) 3015e0b Revert "UI to alert of respend attempt affecting wallet." (Wladimir J. van der Laan) 39d3f2c Revert "Add -respendnotify option and new RPC data" (Wladimir J. van der Laan) 680f725 Revert "Add release notes entry" (Wladimir J. van der Laan) ad26dc9 Revert "Formatting, spelling, comment fixes." (Wladimir J. van der Laan) cd057bf Revert "Check signatures before respend relay" (Wladimir J. van der Laan) 67cc8f2 Revert "Remove signal DoubleSpendDetected, use function" (Wladimir J. van der Laan)
Diffstat (limited to 'src')
-rw-r--r--src/bloom.cpp7
-rw-r--r--src/bloom.h2
-rw-r--r--src/core.cpp16
-rw-r--r--src/core.h3
-rw-r--r--src/init.cpp1
-rw-r--r--src/main.cpp104
-rw-r--r--src/main.h3
-rw-r--r--src/qt/guiconstants.h4
-rw-r--r--src/qt/transactionfilterproxy.cpp4
-rw-r--r--src/qt/transactionrecord.cpp10
-rw-r--r--src/qt/transactionrecord.h24
-rw-r--r--src/qt/transactiontablemodel.cpp18
-rw-r--r--src/qt/walletmodel.cpp8
-rw-r--r--src/rpcwallet.cpp22
-rw-r--r--src/test/bloom_tests.cpp4
-rw-r--r--src/txmempool.cpp1
-rw-r--r--src/ui_interface.h3
-rw-r--r--src/wallet.cpp41
-rw-r--r--src/wallet.h15
19 files changed, 42 insertions, 248 deletions
diff --git a/src/bloom.cpp b/src/bloom.cpp
index 85a2ddc189..26e366179c 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -94,13 +94,6 @@ bool CBloomFilter::contains(const uint256& hash) const
return contains(data);
}
-void CBloomFilter::clear()
-{
- vData.assign(vData.size(),0);
- isFull = false;
- isEmpty = true;
-}
-
bool CBloomFilter::IsWithinSizeConstraints() const
{
return vData.size() <= MAX_BLOOM_FILTER_SIZE && nHashFuncs <= MAX_HASH_FUNCS;
diff --git a/src/bloom.h b/src/bloom.h
index d0caf9e9fa..956bead87f 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -78,8 +78,6 @@ public:
bool contains(const COutPoint& outpoint) const;
bool contains(const uint256& hash) const;
- void clear();
-
// True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS
// (catch a filter which was just deserialized which was too big)
bool IsWithinSizeConstraints() const;
diff --git a/src/core.cpp b/src/core.cpp
index b56994ecf3..149b3532a1 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -124,22 +124,6 @@ CTransaction& CTransaction::operator=(const CTransaction &tx) {
return *this;
}
-bool CTransaction::IsEquivalentTo(const CTransaction& tx) const
-{
- if (nVersion != tx.nVersion ||
- nLockTime != tx.nLockTime ||
- vin.size() != tx.vin.size() ||
- vout != tx.vout)
- return false;
- for (unsigned int i = 0; i < vin.size(); i++)
- {
- if (vin[i].nSequence != tx.vin[i].nSequence ||
- vin[i].prevout != tx.vin[i].prevout)
- return false;
- }
- return true;
-}
-
int64_t CTransaction::GetValueOut() const
{
int64_t nValueOut = 0;
diff --git a/src/core.h b/src/core.h
index 0387336c98..fb64e6c08e 100644
--- a/src/core.h
+++ b/src/core.h
@@ -255,9 +255,6 @@ public:
return hash;
}
- // True if only scriptSigs are different
- bool IsEquivalentTo(const CTransaction& tx) const;
-
// Return sum of txouts.
int64_t GetValueOut() const;
// GetValueIn() is a method on CCoinsViewCache, because
diff --git a/src/init.cpp b/src/init.cpp
index 031b9db480..3488a8bedf 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1229,7 +1229,6 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
#endif
- InitRespendFilter();
StartNode(threadGroup);
if (fServer)
StartRPCThreads();
diff --git a/src/main.cpp b/src/main.cpp
index dd9e76378e..84178b16e2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -7,7 +7,6 @@
#include "addrman.h"
#include "alert.h"
-#include "bloom.h"
#include "chainparams.h"
#include "checkpoints.h"
#include "checkqueue.h"
@@ -126,15 +125,6 @@ namespace {
} // anon namespace
-// Bloom filter to limit respend relays to one
-static const unsigned int MAX_DOUBLESPEND_BLOOM = 1000;
-static CBloomFilter doubleSpendFilter;
-void InitRespendFilter() {
- seed_insecure_rand();
- doubleSpendFilter = CBloomFilter(MAX_DOUBLESPEND_BLOOM, 0.01, insecure_rand(), BLOOM_UPDATE_NONE);
-}
-
-
//////////////////////////////////////////////////////////////////////////////
//
// dispatching functions
@@ -161,7 +151,6 @@ struct CMainSignals {
} // anon namespace
-
void RegisterWallet(CWalletInterface* pwalletIn) {
g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2));
g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
@@ -881,60 +870,6 @@ int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
return nMinFee;
}
-// Exponentially limit the rate of nSize flow to nLimit. nLimit unit is thousands-per-minute.
-bool RateLimitExceeded(double& dCount, int64_t& nLastTime, int64_t nLimit, unsigned int nSize)
-{
- static CCriticalSection csLimiter;
- int64_t nNow = GetTime();
-
- LOCK(csLimiter);
-
- dCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
- nLastTime = nNow;
- if (dCount >= nLimit*10*1000)
- return true;
- dCount += nSize;
- return false;
-}
-
-static bool RelayableRespend(const COutPoint& outPoint, const CTransaction& doubleSpend, bool fInBlock, CBloomFilter& filter)
-{
- // Relaying double-spend attempts to our peers lets them detect when
- // somebody might be trying to cheat them. However, blindly relaying
- // every double-spend across the entire network gives attackers
- // a denial-of-service attack: just generate a stream of double-spends
- // re-spending the same (limited) set of outpoints owned by the attacker.
- // So, we use a bloom filter and only relay (at most) the first double
- // spend for each outpoint. False-positives ("we have already relayed")
- // are OK, because if the peer doesn't hear about the double-spend
- // from us they are very likely to hear about it from another peer, since
- // each peer uses a different, randomized bloom filter.
-
- if (fInBlock || filter.contains(outPoint)) return false;
-
- // Apply an independent rate limit to double-spend relays
- static double dRespendCount;
- static int64_t nLastRespendTime;
- static int64_t nRespendLimit = GetArg("-limitrespendrelay", 100);
- unsigned int nSize = ::GetSerializeSize(doubleSpend, SER_NETWORK, PROTOCOL_VERSION);
-
- if (RateLimitExceeded(dRespendCount, nLastRespendTime, nRespendLimit, nSize))
- {
- LogPrint("mempool", "Double-spend relay rejected by rate limiter\n");
- return false;
- }
-
- LogPrint("mempool", "Rate limit dRespendCount: %g => %g\n", dRespendCount, dRespendCount+nSize);
-
- // Clear the filter on average every MAX_DOUBLE_SPEND_BLOOM
- // insertions
- if (insecure_rand()%MAX_DOUBLESPEND_BLOOM == 0)
- filter.clear();
-
- filter.insert(outPoint);
-
- return true;
-}
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
bool* pfMissingInputs, bool fRejectInsaneFee)
@@ -964,18 +899,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return false;
// Check for conflicts with in-memory transactions
- bool relayableRespend = false;
{
LOCK(pool.cs); // protect pool.mapNextTx
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
COutPoint outpoint = tx.vin[i].prevout;
- // Does tx conflict with a member of the pool, and is it not equivalent to that member?
- if (pool.mapNextTx.count(outpoint) && !tx.IsEquivalentTo(*pool.mapNextTx[outpoint].ptx))
+ if (pool.mapNextTx.count(outpoint))
{
- relayableRespend = RelayableRespend(outpoint, tx, false, doubleSpendFilter);
- if (!relayableRespend)
- return false;
+ // Disable replacement feature for now
+ return false;
}
}
}
@@ -1046,15 +978,23 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// be annoying or make others' transactions take longer to confirm.
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
{
+ static CCriticalSection csFreeLimiter;
static double dFreeCount;
- static int64_t nLastFreeTime;
- static int64_t nFreeLimit = GetArg("-limitfreerelay", 15);
+ static int64_t nLastTime;
+ int64_t nNow = GetTime();
- if (RateLimitExceeded(dFreeCount, nLastFreeTime, nFreeLimit, nSize))
+ LOCK(csFreeLimiter);
+
+ // Use an exponentially decaying ~10-minute window:
+ dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
+ nLastTime = nNow;
+ // -limitfreerelay unit is thousand-bytes-per-minute
+ // At default rate it would take over a month to fill 1GB
+ if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000)
return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"),
REJECT_INSUFFICIENTFEE, "insufficient priority");
-
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
+ dFreeCount += nSize;
}
if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
@@ -1068,21 +1008,13 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
{
return error("AcceptToMemoryPool: : ConnectInputs failed %s", hash.ToString());
}
-
- if (relayableRespend)
- {
- RelayTransaction(tx);
- }
- else
- {
- // Store transaction in memory
- pool.addUnchecked(hash, entry);
- }
+ // Store transaction in memory
+ pool.addUnchecked(hash, entry);
}
g_signals.SyncTransaction(tx, NULL);
- return !relayableRespend;
+ return true;
}
diff --git a/src/main.h b/src/main.h
index 20a83db605..5f231fa45b 100644
--- a/src/main.h
+++ b/src/main.h
@@ -112,9 +112,6 @@ struct CNodeStateStats;
struct CBlockTemplate;
-/** Initialize respend bloom filter **/
-void InitRespendFilter();
-
/** Register a wallet to receive updates from core */
void RegisterWallet(CWalletInterface* pwalletIn);
/** Unregister a wallet from core */
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index 696761e234..5ae4bc833d 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -23,10 +23,6 @@ static const int STATUSBAR_ICONSIZE = 16;
#define COLOR_NEGATIVE QColor(255, 0, 0)
/* Transaction list -- bare address (without label) */
#define COLOR_BAREADDRESS QColor(140, 140, 140)
-/* Transaction list -- has conflicting transactions */
-#define COLOR_HASCONFLICTING QColor(255, 255, 255)
-/* Transaction list -- has conflicting transactions - background */
-#define COLOR_HASCONFLICTING_BG QColor(192, 0, 0)
/* Tooltips longer than this (in characters) are converted into rich text,
so that they can be word-wrapped.
diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp
index 7293029787..f9546fddb5 100644
--- a/src/qt/transactionfilterproxy.cpp
+++ b/src/qt/transactionfilterproxy.cpp
@@ -24,7 +24,7 @@ TransactionFilterProxy::TransactionFilterProxy(QObject *parent) :
typeFilter(ALL_TYPES),
minAmount(0),
limitRows(-1),
- showInactive(false)
+ showInactive(true)
{
}
@@ -39,7 +39,7 @@ bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &
qint64 amount = llabs(index.data(TransactionTableModel::AmountRole).toLongLong());
int status = index.data(TransactionTableModel::StatusRole).toInt();
- if(!showInactive && status == TransactionStatus::Conflicted && type == TransactionRecord::Other)
+ if(!showInactive && status == TransactionStatus::Conflicted)
return false;
if(!(TYPE(type) & typeFilter))
return false;
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 7d29c212b3..d7bd25e08b 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -184,8 +184,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.depth = wtx.GetDepthInMainChain();
status.cur_num_blocks = chainActive.Height();
- status.hasConflicting = false;
-
if (!IsFinalTx(wtx, chainActive.Height() + 1))
{
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
@@ -229,7 +227,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
if (status.depth < 0)
{
status.status = TransactionStatus::Conflicted;
- status.hasConflicting = !(wtx.GetConflicts(false).empty());
}
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
{
@@ -238,7 +235,6 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
else if (status.depth == 0)
{
status.status = TransactionStatus::Unconfirmed;
- status.hasConflicting = !(wtx.GetConflicts(false).empty());
}
else if (status.depth < RecommendedNumConfirmations)
{
@@ -249,13 +245,13 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
status.status = TransactionStatus::Confirmed;
}
}
+
}
-bool TransactionRecord::statusUpdateNeeded(int64_t nConflictsReceived)
+bool TransactionRecord::statusUpdateNeeded()
{
AssertLockHeld(cs_main);
- return (status.cur_num_blocks != chainActive.Height() ||
- status.cur_num_conflicts != nConflictsReceived);
+ return status.cur_num_blocks != chainActive.Height();
}
QString TransactionRecord::getTxID() const
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index d3cfa77d97..626b7654c6 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -19,17 +19,9 @@ class TransactionStatus
{
public:
TransactionStatus():
- countsForBalance(false),
- sortKey(""),
- matures_in(0),
- status(Offline),
- hasConflicting(false),
- depth(0),
- open_for(0),
- cur_num_blocks(-1),
- cur_num_conflicts(-1)
- {
- }
+ countsForBalance(false), sortKey(""),
+ matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1)
+ { }
enum Status {
Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/
@@ -59,10 +51,6 @@ public:
/** @name Reported status
@{*/
Status status;
-
- // Has conflicting transactions spending same prevout
- bool hasConflicting;
-
qint64 depth;
qint64 open_for; /**< Timestamp if status==OpenUntilDate, otherwise number
of additional blocks that need to be mined before
@@ -71,10 +59,6 @@ public:
/** Current number of blocks (to know whether cached status is still valid) */
int cur_num_blocks;
-
- /** Number of conflicts received into wallet as of last status update */
- int64_t cur_num_conflicts;
-
};
/** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has
@@ -152,7 +136,7 @@ public:
/** Return whether a status update is needed.
*/
- bool statusUpdateNeeded(int64_t nConflictsReceived);
+ bool statusUpdateNeeded();
};
#endif // TRANSACTIONRECORD_H
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index cf4c90c7ff..4825713b69 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -167,7 +167,8 @@ public:
parent->endRemoveRows();
break;
case CT_UPDATED:
- emit parent->dataChanged(parent->index(lowerIndex, parent->Status), parent->index(upperIndex-1, parent->Amount));
+ // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
+ // visible transactions.
break;
}
}
@@ -188,21 +189,20 @@ public:
// stuck if the core is holding the locks for a longer time - for
// example, during a wallet rescan.
//
- // If a status update is needed (blocks or conflicts came in since last check),
- // update the status of this transaction from the wallet. Otherwise,
+ // If a status update is needed (blocks came in since last check),
+ // update the status of this transaction from the wallet. Otherwise,
// simply re-use the cached status.
TRY_LOCK(cs_main, lockMain);
if(lockMain)
{
TRY_LOCK(wallet->cs_wallet, lockWallet);
- if(lockWallet && rec->statusUpdateNeeded(wallet->nConflictsReceived))
+ if(lockWallet && rec->statusUpdateNeeded())
{
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
if(mi != wallet->mapWallet.end())
{
rec->updateStatus(mi->second);
- rec->status.cur_num_conflicts = wallet->nConflictsReceived;
}
}
}
@@ -368,8 +368,6 @@ QString TransactionTableModel::formatTxType(const TransactionRecord *wtx) const
return tr("Payment to yourself");
case TransactionRecord::Generated:
return tr("Mined");
- case TransactionRecord::Other:
- return tr("Other");
default:
return QString();
}
@@ -545,13 +543,7 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
return formatTooltip(rec);
case Qt::TextAlignmentRole:
return column_alignments[index.column()];
- case Qt::BackgroundColorRole:
- if (rec->status.hasConflicting)
- return COLOR_HASCONFLICTING_BG;
- break;
case Qt::ForegroundRole:
- if (rec->status.hasConflicting)
- return COLOR_HASCONFLICTING;
// Non-confirmed (but not immature) as transactions are grey
if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)
{
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 7df8812ccd..0ad123f39d 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -164,14 +164,6 @@ void WalletModel::checkBalanceChanged()
void WalletModel::updateTransaction(const QString &hash, int status)
{
- if (status == CT_GOT_CONFLICT)
- {
- emit message(tr("Conflict Received"),
- tr("WARNING: Transaction may never be confirmed. Its input was seen being spent by another transaction on the network. Wait for confirmation!"),
- CClientUIInterface::MSG_WARNING);
- return;
- }
-
if(transactionTableModel)
transactionTableModel->updateTransaction(hash, status);
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 631f72d1a1..5b83fe900e 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -58,10 +58,6 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
conflicts.push_back(conflict.GetHex());
entry.push_back(Pair("walletconflicts", conflicts));
- Array respends;
- BOOST_FOREACH(const uint256& respend, wtx.GetConflicts(false))
- respends.push_back(respend.GetHex());
- entry.push_back(Pair("respendsobserved", respends));
entry.push_back(Pair("time", wtx.GetTxTime()));
entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
@@ -1252,12 +1248,6 @@ Value listtransactions(const Array& params, bool fHelp)
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
" category of transactions.\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
- " \"walletconflicts\" : [\n"
- " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n"
- " ],\n"
- " \"respendsobserved\" : [\n"
- " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n"
- " ],\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
" for 'send' and 'receive' category of transactions.\n"
@@ -1434,12 +1424,6 @@ Value listsinceblock(const Array& params, bool fHelp)
" \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
- " \"walletconflicts\" : [\n"
- " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n"
- " ],\n"
- " \"respendsobserved\" : [\n"
- " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n"
- " ],\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
" \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
@@ -1518,12 +1502,6 @@ Value gettransaction(const Array& params, bool fHelp)
" \"blockindex\" : xx, (numeric) The block index\n"
" \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
" \"txid\" : \"transactionid\", (string) The transaction id.\n"
- " \"walletconflicts\" : [\n"
- " \"conflictid\", (string) Ids of transactions, including equivalent clones, that re-spend a txid input.\n"
- " ],\n"
- " \"respendsobserved\" : [\n"
- " \"respendid\", (string) Ids of transactions, NOT equivalent clones, that re-spend a txid input. \"Double-spends.\"\n"
- " ],\n"
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
" \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
" \"details\" : [\n"
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 2cdafa4bdd..69de3b5bb1 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -45,10 +45,6 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
expected[i] = (char)vch[i];
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
-
- BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
- filter.clear();
- BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter should be empty!");
}
BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index a852de5da8..ebb1369e31 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -420,6 +420,7 @@ void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed
void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
{
// Remove transactions which depend on inputs of tx, recursively
+ list<CTransaction> result;
LOCK(cs);
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
diff --git a/src/ui_interface.h b/src/ui_interface.h
index a48ba237d2..b3df2b5a85 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -21,8 +21,7 @@ enum ChangeType
{
CT_NEW,
CT_UPDATED,
- CT_DELETED,
- CT_GOT_CONFLICT
+ CT_DELETED
};
/** Signals for UI communication. */
diff --git a/src/wallet.cpp b/src/wallet.cpp
index efefb71b6d..7c04743c0f 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -274,7 +274,7 @@ bool CWallet::SetMaxVersion(int nVersion)
return true;
}
-set<uint256> CWallet::GetConflicts(const uint256& txid, bool includeEquivalent) const
+set<uint256> CWallet::GetConflicts(const uint256& txid) const
{
set<uint256> result;
AssertLockHeld(cs_wallet);
@@ -292,8 +292,7 @@ set<uint256> CWallet::GetConflicts(const uint256& txid, bool includeEquivalent)
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)
- if (includeEquivalent || !wtx.IsEquivalentTo(mapWallet.at(it->second)))
- result.insert(it->second);
+ result.insert(it->second);
}
return result;
}
@@ -322,7 +321,6 @@ void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
const uint256& hash = it->second;
CWalletTx* copyTo = &mapWallet[hash];
if (copyFrom == copyTo) continue;
- if (!copyFrom->IsEquivalentTo(*copyTo)) continue;
copyTo->mapValue = copyFrom->mapValue;
copyTo->vOrderForm = copyFrom->vOrderForm;
// fTimeReceivedIsTxTime not copied on purpose
@@ -610,28 +608,6 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet)
// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
- // Notifications for existing transactions that now have conflicts with this one
- if (fInsertedNew)
- {
- BOOST_FOREACH(const uint256& conflictHash, wtxIn.GetConflicts(false))
- {
- CWalletTx& txConflict = mapWallet[conflictHash];
- NotifyTransactionChanged(this, conflictHash, CT_UPDATED); //Updates UI table
- if (IsFromMe(txConflict) || IsMine(txConflict))
- {
- NotifyTransactionChanged(this, conflictHash, CT_GOT_CONFLICT); //Throws dialog
- // external respend notify
- std::string strCmd = GetArg("-respendnotify", "");
- if (!strCmd.empty())
- {
- boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
- boost::replace_all(strCmd, "%t", conflictHash.GetHex());
- boost::thread t(runCommand, strCmd); // thread runs free
- }
- }
- }
- }
-
// notify an external script when a wallet transaction comes in or is updated
std::string strCmd = GetArg("-walletnotify", "");
@@ -654,12 +630,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
AssertLockHeld(cs_wallet);
bool fExisted = mapWallet.count(tx.GetHash());
if (fExisted && !fUpdate) return false;
-
- bool fIsConflicting = IsConflicting(tx);
- if (fIsConflicting)
- nConflictsReceived++;
-
- if (fExisted || IsMine(tx) || IsFromMe(tx) || fIsConflicting)
+ if (fExisted || IsMine(tx) || IsFromMe(tx))
{
CWalletTx wtx(this,tx);
// Get merkle branch if transaction was found in a block
@@ -948,7 +919,7 @@ void CWallet::ReacceptWalletTransactions()
int nDepth = wtx.GetDepthInMainChain();
- if (!wtx.IsCoinBase() && nDepth < 0 && (IsMine(wtx) || IsFromMe(wtx)))
+ if (!wtx.IsCoinBase() && nDepth < 0)
{
// Try to add to memory pool
LOCK(mempool.cs);
@@ -968,13 +939,13 @@ void CWalletTx::RelayWalletTransaction()
}
}
-set<uint256> CWalletTx::GetConflicts(bool includeEquivalent) const
+set<uint256> CWalletTx::GetConflicts() const
{
set<uint256> result;
if (pwallet != NULL)
{
uint256 myHash = GetHash();
- result = pwallet->GetConflicts(myHash, includeEquivalent);
+ result = pwallet->GetConflicts(myHash);
result.erase(myHash);
}
return result;
diff --git a/src/wallet.h b/src/wallet.h
index eaf9e96309..73fcfa24e0 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -144,9 +144,6 @@ public:
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID;
- // Increment to cause UI refresh, similar to new block
- int64_t nConflictsReceived;
-
CWallet()
{
SetNull();
@@ -169,7 +166,6 @@ public:
nNextResend = 0;
nLastResend = 0;
nTimeFirstKey = 0;
- nConflictsReceived = 0;
}
std::map<uint256, CWalletTx> mapWallet;
@@ -322,13 +318,6 @@ public:
{
return (GetDebit(tx, ISMINE_ALL) > 0);
}
- bool IsConflicting(const CTransaction& tx) const
- {
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- if (mapTxSpends.count(txin.prevout))
- return true;
- return false;
- }
int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const
{
int64_t nDebit = 0;
@@ -401,7 +390,7 @@ public:
int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
// Get wallet transactions that conflict with given transaction (spend same outputs)
- std::set<uint256> GetConflicts(const uint256& txid, bool includeEquivalent) const;
+ std::set<uint256> GetConflicts(const uint256& txid) const;
/** Address book entry changed.
* @note called with lock cs_wallet held.
@@ -812,7 +801,7 @@ public:
void RelayWalletTransaction();
- std::set<uint256> GetConflicts(bool includeEquivalent=true) const;
+ std::set<uint256> GetConflicts() const;
};