aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/debian/examples/bitcoin.conf18
-rwxr-xr-xqa/rpc-tests/wallet.py21
-rw-r--r--src/main.cpp2
-rw-r--r--src/main.h1
-rw-r--r--src/qt/bitcoingui.cpp18
-rw-r--r--src/qt/bitcoingui.h2
-rw-r--r--src/qt/peertablemodel.cpp2
-rw-r--r--src/qt/rpcconsole.cpp1
-rw-r--r--src/qt/transactiontablemodel.cpp4
-rw-r--r--src/qt/walletview.cpp8
-rw-r--r--src/qt/walletview.h2
-rw-r--r--src/rpcserver.cpp3
-rw-r--r--src/rpcserver.h1
-rw-r--r--src/txdb.h2
-rw-r--r--src/validationinterface.cpp4
-rw-r--r--src/validationinterface.h6
-rw-r--r--src/wallet/rpcwallet.cpp22
-rw-r--r--src/wallet/wallet.cpp57
-rw-r--r--src/wallet/wallet.h5
19 files changed, 127 insertions, 52 deletions
diff --git a/contrib/debian/examples/bitcoin.conf b/contrib/debian/examples/bitcoin.conf
index 31cca981e0..ade80d60ea 100644
--- a/contrib/debian/examples/bitcoin.conf
+++ b/contrib/debian/examples/bitcoin.conf
@@ -13,6 +13,12 @@
# Connect via a SOCKS5 proxy
#proxy=127.0.0.1:9050
+# Bind to given address and always listen on it. Use [host]:port notation for IPv6
+#bind=<addr>
+
+# Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6
+#whitebind=<addr>
+
##############################################################
## Quick Primer on addnode vs connect ##
## Let's say for instance you use addnode=4.2.2.4 ##
@@ -57,6 +63,10 @@
# server=1 tells Bitcoin-QT and bitcoind to accept JSON-RPC commands
#server=0
+# Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6.
+# This option can be specified multiple times (default: bind to all interfaces)
+#rpcbind=<addr>
+
# You must set rpcuser and rpcpassword to secure the JSON-RPC api
#rpcuser=Ulysseys
#rpcpassword=YourSuperGreatPasswordNumber_DO_NOT_USE_THIS_OR_YOU_WILL_GET_ROBBED_385593
@@ -94,6 +104,14 @@
#rpcsslcertificatechainfile=server.cert
#rpcsslprivatekeyfile=server.pem
+# Transaction Fee Changes in 0.10.0
+
+# Send transactions as zero-fee transactions if possible (default: 0)
+#sendfreetransactions=0
+
+# Create transactions that have enough fees (or priority) so they are likely to begin confirmation within n blocks (default: 1).
+# This setting is over-ridden by the -paytxfee option.
+#txconfirmtarget=n
# Miscellaneous options
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index dc4e0f77bd..01e9fa57b2 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -16,6 +16,7 @@
# h) node0 should now have 2 unspent outputs; send these to node2 via raw tx broadcast by node1
# i) have node1 mine a block
# j) check balances - node0 should have 0, node2 should have 100
+# k) test ResendWalletTransactions - create transactions, startup fourth node, make sure it syncs
#
from test_framework import BitcoinTestFramework
@@ -26,7 +27,7 @@ class WalletTest (BitcoinTestFramework):
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
- initialize_chain_clean(self.options.tmpdir, 3)
+ initialize_chain_clean(self.options.tmpdir, 4)
def setup_network(self, split=False):
self.nodes = start_nodes(3, self.options.tmpdir)
@@ -132,5 +133,23 @@ class WalletTest (BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), Decimal('59.99800000'))
assert_equal(self.nodes[0].getbalance(), Decimal('39.99800000'))
+ # Test ResendWalletTransactions:
+ # Create a couple of transactions, then start up a fourth
+ # node (nodes[3]) and ask nodes[0] to rebroadcast.
+ # EXPECT: nodes[3] should have those transactions in its mempool.
+ txid1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
+ txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1)
+ sync_mempools(self.nodes)
+
+ self.nodes.append(start_node(3, self.options.tmpdir))
+ connect_nodes_bi(self.nodes, 0, 3)
+ sync_blocks(self.nodes)
+
+ relayed = self.nodes[0].resendwallettransactions()
+ assert_equal(set(relayed), set([txid1, txid2]))
+ sync_mempools(self.nodes)
+
+ assert(txid1 in self.nodes[3].getrawmempool())
+
if __name__ == '__main__':
WalletTest ().main ()
diff --git a/src/main.cpp b/src/main.cpp
index 1d78eedc1a..3ceacf32e7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4475,7 +4475,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// transactions become unconfirmed and spams other nodes.
if (!fReindex && !fImporting && !IsInitialBlockDownload())
{
- GetMainSignals().Broadcast();
+ GetMainSignals().Broadcast(nTimeBestReceived);
}
//
diff --git a/src/main.h b/src/main.h
index ac73b242f1..3ef042895d 100644
--- a/src/main.h
+++ b/src/main.h
@@ -115,7 +115,6 @@ extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
extern const std::string strMessageMagic;
-extern int64_t nTimeBestReceived;
extern CWaitableCriticalSection csBestBlock;
extern CConditionVariable cvBlockChange;
extern bool fImporting;
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 58c005ae75..198dd1fdf9 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -859,18 +859,18 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
}
#ifdef ENABLE_WALLET
-void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address)
+void BitcoinGUI::incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label)
{
// On new transaction, make an info balloon
+ QString msg = tr("Date: %1\n").arg(date) +
+ tr("Amount: %1\n").arg(BitcoinUnits::formatWithUnit(unit, amount, true)) +
+ tr("Type: %1\n").arg(type);
+ if (!label.isEmpty())
+ msg += tr("Label: %1\n").arg(label);
+ else if (!address.isEmpty())
+ msg += tr("Address: %1\n").arg(address);
message((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"),
- tr("Date: %1\n"
- "Amount: %2\n"
- "Type: %3\n"
- "Address: %4\n")
- .arg(date)
- .arg(BitcoinUnits::formatWithUnit(unit, amount, true))
- .arg(type)
- .arg(address), CClientUIInterface::MSG_INFORMATION);
+ msg, CClientUIInterface::MSG_INFORMATION);
}
#endif // ENABLE_WALLET
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 5a289a9046..494541f002 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -165,7 +165,7 @@ public slots:
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
/** Show incoming transaction notification for new transactions. */
- void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address);
+ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label);
#endif // ENABLE_WALLET
private slots:
diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp
index dfb7a623af..220f273d02 100644
--- a/src/qt/peertablemodel.cpp
+++ b/src/qt/peertablemodel.cpp
@@ -115,7 +115,7 @@ PeerTableModel::PeerTableModel(ClientModel *parent) :
clientModel(parent),
timer(0)
{
- columns << tr("Address/Hostname") << tr("User Agent") << tr("Ping Time");
+ columns << tr("Node/Service") << tr("User Agent") << tr("Ping Time");
priv = new PeerTablePriv();
// default to unsorted
priv->sortColumn = -1;
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index ccde44fb29..29c971ec79 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -357,7 +357,6 @@ void RPCConsole::clear()
ui->messagesWidget->document()->setDefaultStyleSheet(
"table { }"
"td.time { color: #808080; padding-top: 3px; } "
- "td.message { font-family: monospace; font-size: 12px; } " // Todo: Remove fixed font-size
"td.cmd-request { color: #006060; } "
"td.cmd-error { color: red; } "
"b { color: #006060; } "
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index dff2676b10..34464b4075 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -227,7 +227,7 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren
priv(new TransactionTablePriv(wallet, this)),
fProcessingQueuedTransactions(false)
{
- columns << QString() << QString() << tr("Date") << tr("Type") << tr("Address") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
+ columns << QString() << QString() << tr("Date") << tr("Type") << tr("Label") << BitcoinUnits::getAmountColumnTitle(walletModel->getOptionsModel()->getDisplayUnit());
priv->refreshWallet();
connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
@@ -626,7 +626,7 @@ QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientat
case Watchonly:
return tr("Whether or not a watch-only address is involved in this transaction.");
case ToAddress:
- return tr("Destination address of transaction.");
+ return tr("User-defined intent/purpose of the transaction.");
case Amount:
return tr("Amount removed from or added to balance.");
}
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 9d6a060194..956c8b8913 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -93,7 +93,7 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));
// Pass through transaction notifications
- connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString)));
+ connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString)));
}
}
@@ -149,9 +149,11 @@ void WalletView::processNewTransaction(const QModelIndex& parent, int start, int
QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
- QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString();
+ QModelIndex index = ttm->index(start, 0, parent);
+ QString address = ttm->data(index, TransactionTableModel::AddressRole).toString();
+ QString label = ttm->data(index, TransactionTableModel::LabelRole).toString();
- emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
+ emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address, label);
}
void WalletView::gotoOverviewPage()
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index f3d14c065c..1840e21e9c 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -113,7 +113,7 @@ signals:
/** Encryption status of wallet changed */
void encryptionStatusChanged(int status);
/** Notify that a new transaction appeared */
- void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address);
+ void incomingTransaction(const QString& date, int unit, const CAmount& amount, const QString& type, const QString& address, const QString& label);
};
#endif // BITCOIN_QT_WALLETVIEW_H
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index ba71725222..d30fa32eb4 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -333,6 +333,9 @@ static const CRPCCommand vRPCCommands[] =
{ "hidden", "invalidateblock", &invalidateblock, true, false },
{ "hidden", "reconsiderblock", &reconsiderblock, true, false },
{ "hidden", "setmocktime", &setmocktime, true, false },
+#ifdef ENABLE_WALLET
+ { "hidden", "resendwallettransactions", &resendwallettransactions, true, true },
+#endif
#ifdef ENABLE_WALLET
/* Wallet */
diff --git a/src/rpcserver.h b/src/rpcserver.h
index f63438ecb8..7011d41fc1 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -207,6 +207,7 @@ extern json_spirit::Value getwalletinfo(const json_spirit::Array& params, bool f
extern json_spirit::Value getblockchaininfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value setmocktime(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value resendwallettransactions(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
diff --git a/src/txdb.h b/src/txdb.h
index 1ce93969d8..86e1c5d831 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -16,7 +16,7 @@
class CBlockFileInfo;
class CBlockIndex;
-class CDiskTxPos;
+struct CDiskTxPos;
class uint256;
//! -dbcache default (MiB)
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index ae4cd3c592..aa9aefb0de 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -18,13 +18,13 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
- g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
+ g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
- g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
+ g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
diff --git a/src/validationinterface.h b/src/validationinterface.h
index b21b6e5782..b4c93d72ca 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -9,7 +9,7 @@
#include <boost/signals2/signal.hpp>
class CBlock;
-class CBlockLocator;
+struct CBlockLocator;
class CTransaction;
class CValidationInterface;
class CValidationState;
@@ -33,7 +33,7 @@ protected:
virtual void SetBestChain(const CBlockLocator &locator) {};
virtual void UpdatedTransaction(const uint256 &hash) {};
virtual void Inventory(const uint256 &hash) {};
- virtual void ResendWalletTransactions() {};
+ virtual void ResendWalletTransactions(int64_t nBestBlockTime) {};
virtual void BlockChecked(const CBlock&, const CValidationState&) {};
friend void ::RegisterValidationInterface(CValidationInterface*);
friend void ::UnregisterValidationInterface(CValidationInterface*);
@@ -52,7 +52,7 @@ struct CMainSignals {
/** Notifies listeners about an inventory item being seen on the network. */
boost::signals2::signal<void (const uint256 &)> Inventory;
/** Tells listeners to broadcast their data. */
- boost::signals2::signal<void ()> Broadcast;
+ boost::signals2::signal<void (int64_t nBestBlockTime)> Broadcast;
/** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
};
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 9318c1b2b1..29f3eda15d 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2096,3 +2096,25 @@ Value getwalletinfo(const Array& params, bool fHelp)
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
return obj;
}
+
+Value resendwallettransactions(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "resendwallettransactions\n"
+ "Immediately re-broadcast unconfirmed wallet transactions to all peers.\n"
+ "Intended only for testing; the wallet code periodically re-broadcasts\n"
+ "automatically.\n"
+ "Returns array of transaction ids that were re-broadcast.\n"
+ );
+
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
+ std::vector<uint256> txids = pwalletMain->ResendWalletTransactionsBefore(GetTime());
+ Array result;
+ BOOST_FOREACH(const uint256& txid, txids)
+ {
+ result.push_back(txid.ToString());
+ }
+ return result;
+}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 09bcda577e..a10123002e 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1114,15 +1114,17 @@ void CWallet::ReacceptWalletTransactions()
}
}
-void CWalletTx::RelayWalletTransaction()
+bool CWalletTx::RelayWalletTransaction()
{
if (!IsCoinBase())
{
if (GetDepthInMainChain() == 0) {
LogPrintf("Relaying wtx %s\n", GetHash().ToString());
RelayTransaction((CTransaction)*this);
+ return true;
}
}
+ return false;
}
set<uint256> CWalletTx::GetConflicts() const
@@ -1324,7 +1326,31 @@ bool CWalletTx::IsTrusted() const
return true;
}
-void CWallet::ResendWalletTransactions()
+std::vector<uint256> CWallet::ResendWalletTransactionsBefore(int64_t nTime)
+{
+ std::vector<uint256> result;
+
+ LOCK(cs_wallet);
+ // Sort them in chronological order
+ multimap<unsigned int, CWalletTx*> mapSorted;
+ BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+ {
+ CWalletTx& wtx = item.second;
+ // Don't rebroadcast if newer than nTime:
+ if (wtx.nTimeReceived > nTime)
+ continue;
+ mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
+ }
+ BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
+ {
+ CWalletTx& wtx = *item.second;
+ if (wtx.RelayWalletTransaction())
+ result.push_back(wtx.GetHash());
+ }
+ return result;
+}
+
+void CWallet::ResendWalletTransactions(int64_t nBestBlockTime)
{
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
@@ -1336,30 +1362,15 @@ void CWallet::ResendWalletTransactions()
return;
// Only do it if there's been a new block since last time
- if (nTimeBestReceived < nLastResend)
+ if (nBestBlockTime < nLastResend)
return;
nLastResend = GetTime();
- // Rebroadcast any of our txes that aren't in a block yet
- LogPrintf("ResendWalletTransactions()\n");
- {
- LOCK(cs_wallet);
- // Sort them in chronological order
- multimap<unsigned int, CWalletTx*> mapSorted;
- BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
- {
- CWalletTx& wtx = item.second;
- // Don't rebroadcast until it's had plenty of time that
- // it should have gotten in already by now.
- if (nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60)
- mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
- }
- BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
- {
- CWalletTx& wtx = *item.second;
- wtx.RelayWalletTransaction();
- }
- }
+ // Rebroadcast unconfirmed txes older than 5 minutes before the last
+ // block was found:
+ std::vector<uint256> relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60);
+ if (!relayed.empty())
+ LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size());
}
/** @} */ // end of mapWallet
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 4a13f02195..6ae1c87b1d 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -381,7 +381,7 @@ public:
int64_t GetTxTime() const;
int GetRequestCount() const;
- void RelayWalletTransaction();
+ bool RelayWalletTransaction();
std::set<uint256> GetConflicts() const;
};
@@ -614,7 +614,8 @@ public:
void EraseFromWallet(const uint256 &hash);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
- void ResendWalletTransactions();
+ void ResendWalletTransactions(int64_t nBestBlockTime);
+ std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime);
CAmount GetBalance() const;
CAmount GetUnconfirmedBalance() const;
CAmount GetImmatureBalance() const;