diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index a1af0b27f..7fbfa9020 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -96,7 +96,6 @@ testScripts = [ 'receivedby.py', 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', - 'txn_doublespendrelay.py', 'txn_clone.py', 'getchaintips.py', 'rawtransactions.py', diff --git a/qa/rpc-tests/txn_doublespendrelay.py b/qa/rpc-tests/txn_doublespendrelay.py deleted file mode 100644 index f349c53c0..000000000 --- a/qa/rpc-tests/txn_doublespendrelay.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python - -# -# Test double-spend-relay and notification code -# - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from decimal import Decimal - -class DoubleSpendRelay(BitcoinTestFramework): - - # - # Create a 4-node network; roles for the nodes are: - # [0] : transaction creator - # [1] : respend sender - # [2] : relay node - # [3] : receiver, should detect/notify of double-spends - # - # Node connectivity is: - # [0,1] <--> [2] <--> [3] - # - def setup_network(self): - self.is_network_split = False - self.nodes = [] - for i in range(0,4): - self.nodes.append(start_node(i, self.options.tmpdir)) - connect_nodes(self.nodes[0], 2) - connect_nodes(self.nodes[1], 2) - connect_nodes(self.nodes[3], 2) - return self.nodes - - def run_test(self): - fee = Decimal("0.01") - - nodes = self.nodes - # Test 1: First spend - # shutdown nodes[1] so it is not aware of the first spend - # and will be willing to broadcast a respend - stop_node(nodes[1], 1) - # First spend: nodes[0] -> nodes[3] - amount = Decimal("144") # We rely on this requiring 3 50-BTC inputs - (total_in, tx1_inputs) = gather_inputs(nodes[0], amount+fee) - change_outputs = make_change(nodes[0], total_in, amount, fee) - outputs = dict(change_outputs) - outputs[nodes[3].getnewaddress()] = amount - signed = nodes[0].signrawtransaction(nodes[0].createrawtransaction(tx1_inputs, outputs)) - txid1 = nodes[0].sendrawtransaction(signed["hex"], True) - sync_mempools([nodes[0], nodes[3]]) - - txid1_info = nodes[3].gettransaction(txid1) - assert_equal(txid1_info["respendsobserved"], []) - - # Test 2: Is double-spend of tx1_inputs[0] relayed? - # Restart nodes[1] - nodes[1] = start_node(1, self.options.tmpdir) - connect_nodes(nodes[1], 2) - # Second spend: nodes[0] -> nodes[0] - amount = Decimal("40") - total_in = Decimal("50") - inputs2 = [tx1_inputs[0]] - change_outputs = make_change(nodes[0], total_in, amount, fee) - outputs = dict(change_outputs) - outputs[nodes[0].getnewaddress()] = amount - signed = nodes[0].signrawtransaction(nodes[0].createrawtransaction(inputs2, outputs)) - txid2 = nodes[1].sendrawtransaction(signed["hex"], True) - # Wait until txid2 is relayed to nodes[3] (but don't wait forever): - # Note we can't use sync_mempools, because the respend isn't added to - # the mempool. - for i in range(1,7): - txid1_info = nodes[3].gettransaction(txid1) - if txid1_info["respendsobserved"] != []: - break - time.sleep(0.1 * i**2) # geometric back-off - assert_equal(txid1_info["respendsobserved"], [txid2]) - - # Test 3: Is triple-spend of tx1_inputs[0] not relayed? - # Clear node1 mempool - stop_node(nodes[1], 1) - nodes[1] = start_node(1, self.options.tmpdir) - connect_nodes(nodes[1], 2) - # Third spend: nodes[0] -> nodes[0] - outputs = dict(change_outputs) - outputs[nodes[0].getnewaddress()] = amount - signed = nodes[0].signrawtransaction(nodes[0].createrawtransaction(inputs2, outputs)) - txid3 = nodes[1].sendrawtransaction(signed["hex"], True) - # Ensure txid3 not relayed to nodes[3]: - time.sleep(9.1) - txid1_info = nodes[3].gettransaction(txid1) - assert_equal(txid1_info["respendsobserved"], [txid2]) - - # Test 4: Is double-spend of tx1_inputs[1] relayed when triple-spend of tx1_inputs[0] precedes it? - # Clear node1 mempool - stop_node(nodes[1], 1) - nodes[1] = start_node(1, self.options.tmpdir) - connect_nodes(nodes[1], 2) - # Inputs are third spend, second spend - amount = Decimal("89") - total_in = Decimal("100") - inputs4 = [tx1_inputs[0],tx1_inputs[1]] - change_outputs = make_change(nodes[0], total_in, amount, fee) - outputs = dict(change_outputs) - outputs[nodes[0].getnewaddress()] = amount - signed = nodes[0].signrawtransaction(nodes[0].createrawtransaction(inputs4, outputs)) - txid4 = nodes[1].sendrawtransaction(signed["hex"], True) - # Wait until txid4 is relayed to nodes[3] (but don't wait forever): - for i in range(1,7): - txid1_info = nodes[3].gettransaction(txid1) - if txid1_info["respendsobserved"] != [txid2]: - break - time.sleep(0.1 * i**2) # geometric back-off - assert_equal(sorted(txid1_info["respendsobserved"]), sorted([txid2,txid4])) - - # Test 5: Is double-spend of tx1_inputs[2] relayed when triple-spend of tx1_inputs[0] follows it? - # Clear node1 mempool - stop_node(nodes[1], 1) - nodes[1] = start_node(1, self.options.tmpdir) - connect_nodes(nodes[1], 2) - # Inputs are second spend, third spend - amount = Decimal("88") - total_in = Decimal("100") - inputs5 = [tx1_inputs[2],tx1_inputs[0]] - change_outputs = make_change(nodes[0], total_in, amount, fee) - outputs = dict(change_outputs) - outputs[nodes[0].getnewaddress()] = amount - signed = nodes[0].signrawtransaction(nodes[0].createrawtransaction(inputs5, outputs)) - txid5 = nodes[1].sendrawtransaction(signed["hex"], True) - # Wait until txid5 is relayed to nodes[3] (but don't wait forever): - for i in range(1,7): - txid1_info = nodes[3].gettransaction(txid1) - if sorted(txid1_info["respendsobserved"]) != sorted([txid2,txid4]): - break - time.sleep(0.1 * i**2) # geometric back-off - assert_equal(sorted(txid1_info["respendsobserved"]), sorted([txid2,txid4,txid5])) - -if __name__ == '__main__': - DoubleSpendRelay().main() - diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e67aeb63b..389147ce6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -92,10 +92,6 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) conflicts.push_back(conflict.GetHex()); entry.push_back(Pair("walletconflicts", conflicts)); - UniValue 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) @@ -1406,12 +1402,6 @@ UniValue listtransactions(const UniValue& params, bool fHelp) " 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 (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" @@ -1604,12 +1594,6 @@ UniValue listsinceblock(const UniValue& params, bool fHelp) " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. 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" @@ -1694,12 +1678,6 @@ UniValue gettransaction(const UniValue& params, bool fHelp) " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\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/wallet/wallet.cpp b/src/wallet/wallet.cpp index dd60cbe97..b09baf89d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1181,28 +1181,6 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD // 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)) - { - // external respend notify - std::string strCmd = GetArg("-respendnotify", ""); - if (!strCmd.empty()) - { - NotifyTransactionChanged(this, conflictHash, CT_GOT_CONFLICT); //Throws dialog - 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", ""); @@ -3751,7 +3729,6 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT)); strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST)); strUsage += HelpMessageOpt("-walletnotify=", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); - strUsage += HelpMessageOpt("-respendnotify=", _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)")); strUsage += HelpMessageOpt("-zapwallettxes=", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));