diff --git a/src/main.cpp b/src/main.cpp index 32859ebc2..4dc9d71ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6431,7 +6431,7 @@ bool SendMessages(CNode* pto, CConnman& connman) // transactions become unconfirmed and spams other nodes. if (!fReindex && !fImporting && !IsInitialBlockDownload()) { - GetMainSignals().Broadcast(nTimeBestReceived); + GetMainSignals().Broadcast(nTimeBestReceived, &connman); } // diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ae7efc7a0..73851e97f 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -328,7 +328,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran } CReserveKey *keyChange = transaction.getPossibleKeyChange(); - if(!wallet->CommitTransaction(*newTx, *keyChange)) + if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get())) return TransactionCommitFailed; CTransaction* t = (CTransaction*)newTx; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index cf1d6ca08..6ddf37658 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -18,7 +18,7 @@ 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, _1)); + g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); @@ -28,7 +28,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1)); + g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); 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 094b1cfe2..0c91ec830 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -13,6 +13,7 @@ class CBlock; class CBlockIndex; struct CBlockLocator; class CBlockIndex; +class CConnman; class CReserveScript; class CTransaction; class CValidationInterface; @@ -37,7 +38,7 @@ protected: virtual void SetBestChain(const CBlockLocator &locator) {} virtual void UpdatedTransaction(const uint256 &hash) {} virtual void Inventory(const uint256 &hash) {} - virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} + virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} virtual void GetScriptForMining(boost::shared_ptr&) {}; virtual void ResetRequestCount(const uint256 &hash) {}; @@ -58,7 +59,7 @@ struct CMainSignals { /** Notifies listeners about an inventory item being seen on the network. */ boost::signals2::signal Inventory; /** Tells listeners to broadcast their data. */ - boost::signals2::signal Broadcast; + boost::signals2::signal Broadcast; /** Notifies listeners of a block validation result */ boost::signals2::signal BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0ba6706ba..a399f8ad9 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -346,6 +346,9 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr if (nValue > curBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); + if (pwalletMain->GetBroadcastTransactions() && !g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + // Parse Bitcoin address CScript scriptPubKey = GetScriptForDestination(address); @@ -362,7 +365,7 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } - if (!pwalletMain->CommitTransaction(wtxNew, reservekey)) + if (!pwalletMain->CommitTransaction(wtxNew, reservekey, g_connman.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here."); } @@ -891,6 +894,9 @@ UniValue sendmany(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); + if (pwalletMain->GetBroadcastTransactions() && !g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + string strAccount = AccountFromValue(params[0]); UniValue sendTo = params[1].get_obj(); int nMinDepth = 1; @@ -953,7 +959,7 @@ UniValue sendmany(const UniValue& params, bool fHelp) bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); - if (!pwalletMain->CommitTransaction(wtx, keyChange)) + if (!pwalletMain->CommitTransaction(wtx, keyChange, g_connman.get())) throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed"); return wtx.GetHash().GetHex(); @@ -2308,9 +2314,12 @@ UniValue resendwallettransactions(const UniValue& params, bool fHelp) "Returns array of transaction ids that were re-broadcast.\n" ); + if (!g_connman) + throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); + LOCK2(cs_main, pwalletMain->cs_wallet); - std::vector txids = pwalletMain->ResendWalletTransactionsBefore(GetTime()); + std::vector txids = pwalletMain->ResendWalletTransactionsBefore(GetTime(), g_connman.get()); UniValue result(UniValue::VARR); BOOST_FOREACH(const uint256& txid, txids) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 10aca2e49..4396c2a2b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1453,7 +1453,7 @@ void CWallet::ReacceptWalletTransactions() } } -bool CWalletTx::RelayWalletTransaction() +bool CWalletTx::RelayWalletTransaction(CConnman* connman) { assert(pwallet->GetBroadcastTransactions()); if (!IsCoinBase()) @@ -1688,7 +1688,7 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& tx) const return CTransaction(tx1) == CTransaction(tx2); } -std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) +std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman) { std::vector result; @@ -1706,13 +1706,13 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime) BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) { CWalletTx& wtx = *item.second; - if (wtx.RelayWalletTransaction()) + if (wtx.RelayWalletTransaction(connman)) result.push_back(wtx.GetHash()); } return result; } -void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) +void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) { // Do this infrequently and randomly to avoid giving away // that these are our transactions. @@ -1730,7 +1730,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime) // Rebroadcast unconfirmed txes older than 5 minutes before the last // block was found: - std::vector relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60); + std::vector relayed = ResendWalletTransactionsBefore(nBestBlockTime-5*60, connman); if (!relayed.empty()) LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, relayed.size()); } @@ -2447,7 +2447,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt /** * Call after CreateTransaction unless you want to abort */ -bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) +bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman) { { LOCK2(cs_main, cs_wallet); @@ -2481,7 +2481,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); return false; } - wtxNew.RelayWalletTransaction(); + wtxNew.RelayWalletTransaction(connman); } } return true; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c06513650..7a771350c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -401,7 +401,7 @@ public: int64_t GetTxTime() const; int GetRequestCount() const; - bool RelayWalletTransaction(); + bool RelayWalletTransaction(CConnman* connman); std::set GetConflicts() const; }; @@ -748,8 +748,8 @@ public: bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); - void ResendWalletTransactions(int64_t nBestBlockTime); - std::vector ResendWalletTransactionsBefore(int64_t nTime); + void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman); + std::vector ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman); CAmount GetBalance() const; CAmount GetUnconfirmedBalance() const; CAmount GetImmatureBalance() const; @@ -770,7 +770,7 @@ public: */ bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); - bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman); bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb);