diff options
Diffstat (limited to 'src')
38 files changed, 354 insertions, 241 deletions
diff --git a/src/amount.h b/src/amount.h index 449fd1b15f..47968e80b1 100644 --- a/src/amount.h +++ b/src/amount.h @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2009-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/compat.h b/src/compat.h index 049579c365..7b164d5630 100644 --- a/src/compat.h +++ b/src/compat.h @@ -92,8 +92,15 @@ typedef void* sockopt_arg_type; typedef char* sockopt_arg_type; #endif +// Note these both should work with the current usage of poll, but best to be safe +// WIN32 poll is broken https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/ +// __APPLE__ poll is broke https://github.com/bitcoin/bitcoin/pull/14336#issuecomment-437384408 +#if defined(__linux__) +#define USE_POLL +#endif + bool static inline IsSelectableSocket(const SOCKET& s) { -#ifdef WIN32 +#if defined(USE_POLL) || defined(WIN32) return true; #else return (s < FD_SETSIZE); diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index b17a8bb31d..0a7eacfb91 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2017 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -1,4 +1,4 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/init.cpp b/src/init.cpp index a3a7c5a3bb..18c145a023 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -953,8 +953,13 @@ bool AppInitParameterInteraction() // Trim requested connection counts, to fit into system limitations // <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695 - nMaxConnections = std::max(std::min<int>(nMaxConnections, FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0); nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS); +#ifdef USE_POLL + int fd_max = nFD; +#else + int fd_max = FD_SETSIZE; +#endif + nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0); if (nFD < MIN_CORE_FILEDESCRIPTORS) return InitError(_("Not enough file descriptors available.")); nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections); diff --git a/src/key_io.cpp b/src/key_io.cpp index 282385f50d..d998089535 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2017 The Bitcoin Core developers +// Copyright (c) 2014-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/net.cpp b/src/net.cpp index e595fb0b0b..902830f79c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -26,6 +26,10 @@ #include <fcntl.h> #endif +#ifdef USE_POLL +#include <poll.h> +#endif + #ifdef USE_UPNP #include <miniupnpc/miniupnpc.h> #include <miniupnpc/miniwget.h> @@ -33,6 +37,7 @@ #include <miniupnpc/upnperrors.h> #endif +#include <unordered_map> #include <math.h> @@ -71,7 +76,11 @@ enum BindFlags { BF_WHITELIST = (1U << 2), }; -const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; +// The set of sockets cannot be modified while waiting +// The sleep time needs to be small to avoid new sockets stalling +static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50; + +const std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8] static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8] @@ -778,7 +787,6 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete nBytes -= handled; if (msg.complete()) { - //store received bytes per message command //to prevent a memory DOS, only allow valid commands mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.hdr.pchCommand); @@ -1258,28 +1266,10 @@ void CConnman::InactivityCheck(CNode *pnode) } } -void CConnman::SocketHandler() +bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set) { - // - // Find which sockets have data to receive - // - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 50000; // frequency to poll pnode->vSend - - fd_set fdsetRecv; - fd_set fdsetSend; - fd_set fdsetError; - FD_ZERO(&fdsetRecv); - FD_ZERO(&fdsetSend); - FD_ZERO(&fdsetError); - SOCKET hSocketMax = 0; - bool have_fds = false; - for (const ListenSocket& hListenSocket : vhListenSocket) { - FD_SET(hListenSocket.socket, &fdsetRecv); - hSocketMax = std::max(hSocketMax, hListenSocket.socket); - have_fds = true; + recv_set.insert(hListenSocket.socket); } { @@ -1308,46 +1298,151 @@ void CConnman::SocketHandler() if (pnode->hSocket == INVALID_SOCKET) continue; - FD_SET(pnode->hSocket, &fdsetError); - hSocketMax = std::max(hSocketMax, pnode->hSocket); - have_fds = true; - + error_set.insert(pnode->hSocket); if (select_send) { - FD_SET(pnode->hSocket, &fdsetSend); + send_set.insert(pnode->hSocket); continue; } if (select_recv) { - FD_SET(pnode->hSocket, &fdsetRecv); + recv_set.insert(pnode->hSocket); } } } - int nSelect = select(have_fds ? hSocketMax + 1 : 0, - &fdsetRecv, &fdsetSend, &fdsetError, &timeout); + return !recv_set.empty() || !send_set.empty() || !error_set.empty(); +} + +#ifdef USE_POLL +void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set) +{ + std::set<SOCKET> recv_select_set, send_select_set, error_select_set; + if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) { + interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)); + return; + } + + std::unordered_map<SOCKET, struct pollfd> pollfds; + for (SOCKET socket_id : recv_select_set) { + pollfds[socket_id].fd = socket_id; + pollfds[socket_id].events |= POLLIN; + } + + for (SOCKET socket_id : send_select_set) { + pollfds[socket_id].fd = socket_id; + pollfds[socket_id].events |= POLLOUT; + } + + for (SOCKET socket_id : error_select_set) { + pollfds[socket_id].fd = socket_id; + // These flags are ignored, but we set them for clarity + pollfds[socket_id].events |= POLLERR|POLLHUP; + } + + std::vector<struct pollfd> vpollfds; + vpollfds.reserve(pollfds.size()); + for (auto it : pollfds) { + vpollfds.push_back(std::move(it.second)); + } + + if (poll(vpollfds.data(), vpollfds.size(), SELECT_TIMEOUT_MILLISECONDS) < 0) return; + + if (interruptNet) return; + + for (struct pollfd pollfd_entry : vpollfds) { + if (pollfd_entry.revents & POLLIN) recv_set.insert(pollfd_entry.fd); + if (pollfd_entry.revents & POLLOUT) send_set.insert(pollfd_entry.fd); + if (pollfd_entry.revents & (POLLERR|POLLHUP)) error_set.insert(pollfd_entry.fd); + } +} +#else +void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set) +{ + std::set<SOCKET> recv_select_set, send_select_set, error_select_set; + if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) { + interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)); + return; + } + + // + // Find which sockets have data to receive + // + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend + + fd_set fdsetRecv; + fd_set fdsetSend; + fd_set fdsetError; + FD_ZERO(&fdsetRecv); + FD_ZERO(&fdsetSend); + FD_ZERO(&fdsetError); + SOCKET hSocketMax = 0; + + for (SOCKET hSocket : recv_select_set) { + FD_SET(hSocket, &fdsetRecv); + hSocketMax = std::max(hSocketMax, hSocket); + } + + for (SOCKET hSocket : send_select_set) { + FD_SET(hSocket, &fdsetSend); + hSocketMax = std::max(hSocketMax, hSocket); + } + + for (SOCKET hSocket : error_select_set) { + FD_SET(hSocket, &fdsetError); + hSocketMax = std::max(hSocketMax, hSocket); + } + + int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout); + if (interruptNet) return; if (nSelect == SOCKET_ERROR) { - if (have_fds) - { - int nErr = WSAGetLastError(); - LogPrintf("socket select error %s\n", NetworkErrorString(nErr)); - for (unsigned int i = 0; i <= hSocketMax; i++) - FD_SET(i, &fdsetRecv); - } + int nErr = WSAGetLastError(); + LogPrintf("socket select error %s\n", NetworkErrorString(nErr)); + for (unsigned int i = 0; i <= hSocketMax; i++) + FD_SET(i, &fdsetRecv); FD_ZERO(&fdsetSend); FD_ZERO(&fdsetError); - if (!interruptNet.sleep_for(std::chrono::milliseconds(timeout.tv_usec/1000))) + if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS))) return; } + for (SOCKET hSocket : recv_select_set) { + if (FD_ISSET(hSocket, &fdsetRecv)) { + recv_set.insert(hSocket); + } + } + + for (SOCKET hSocket : send_select_set) { + if (FD_ISSET(hSocket, &fdsetSend)) { + send_set.insert(hSocket); + } + } + + for (SOCKET hSocket : error_select_set) { + if (FD_ISSET(hSocket, &fdsetError)) { + error_set.insert(hSocket); + } + } +} +#endif + +void CConnman::SocketHandler() +{ + std::set<SOCKET> recv_set, send_set, error_set; + SocketEvents(recv_set, send_set, error_set); + + if (interruptNet) return; + // // Accept new connections // for (const ListenSocket& hListenSocket : vhListenSocket) { - if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv)) + if (hListenSocket.socket != INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0) { AcceptConnection(hListenSocket); } @@ -1378,9 +1473,9 @@ void CConnman::SocketHandler() LOCK(pnode->cs_hSocket); if (pnode->hSocket == INVALID_SOCKET) continue; - recvSet = FD_ISSET(pnode->hSocket, &fdsetRecv); - sendSet = FD_ISSET(pnode->hSocket, &fdsetSend); - errorSet = FD_ISSET(pnode->hSocket, &fdsetError); + recvSet = recv_set.count(pnode->hSocket) > 0; + sendSet = send_set.count(pnode->hSocket) > 0; + errorSet = error_set.count(pnode->hSocket) > 0; } if (recvSet || errorSet) { @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -346,6 +346,8 @@ private: void DisconnectNodes(); void NotifyNumConnectionsChanged(); void InactivityCheck(CNode *pnode); + bool GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set); + void SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set); void SocketHandler(); void ThreadSocketHandler(); void ThreadDNSAddressSeed(); @@ -548,6 +550,8 @@ struct LocalServiceInfo { extern CCriticalSection cs_mapLocalHost; extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost); + +extern const std::string NET_MESSAGE_COMMAND_OTHER; typedef std::map<std::string, uint64_t> mapMsgCmdSize; //command, total bytes class CNodeStats @@ -694,8 +698,8 @@ public: const uint64_t nKeyedNetGroup; std::atomic_bool fPauseRecv; std::atomic_bool fPauseSend; -protected: +protected: mapMsgCmdSize mapSendBytesPerMsgCmd; mapMsgCmdSize mapRecvBytesPerMsgCmd GUARDED_BY(cs_vRecv); diff --git a/src/netbase.cpp b/src/netbase.cpp index 1c043fc981..355e21d4e6 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -21,6 +21,10 @@ #include <codecvt> #endif +#ifdef USE_POLL +#include <poll.h> +#endif + #if !defined(MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif @@ -264,11 +268,19 @@ static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, c if (!IsSelectableSocket(hSocket)) { return IntrRecvError::NetworkError; } - struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait)); + int timeout_ms = std::min(endTime - curTime, maxWait); +#ifdef USE_POLL + struct pollfd pollfd = {}; + pollfd.fd = hSocket; + pollfd.events = POLLIN | POLLOUT; + int nRet = poll(&pollfd, 1, timeout_ms); +#else + struct timeval tval = MillisToTimeval(timeout_ms); fd_set fdset; FD_ZERO(&fdset); FD_SET(hSocket, &fdset); int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval); +#endif if (nRet == SOCKET_ERROR) { return IntrRecvError::NetworkError; } @@ -499,11 +511,18 @@ bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET& hSocket, i // WSAEINVAL is here because some legacy version of winsock uses it if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { +#ifdef USE_POLL + struct pollfd pollfd = {}; + pollfd.fd = hSocket; + pollfd.events = POLLIN | POLLOUT; + int nRet = poll(&pollfd, 1, nTimeout); +#else struct timeval timeout = MillisToTimeval(nTimeout); fd_set fdset; FD_ZERO(&fdset); FD_SET(hSocket, &fdset); int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout); +#endif if (nRet == 0) { LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString()); diff --git a/src/noui.h b/src/noui.h index 169c2bbd7f..79a79a9af2 100644 --- a/src/noui.h +++ b/src/noui.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2014 The Bitcoin Core developers +// Copyright (c) 2013-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index eaeb93a652..922987b7bc 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -431,7 +431,7 @@ void BitcoinApplication::addWallet(WalletModel* walletModel) window->addWallet(walletModel); if (m_wallet_models.empty()) { - window->setCurrentWallet(walletModel->getWalletName()); + window->setCurrentWallet(walletModel); } #ifdef ENABLE_BIP70 diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 15e1b98fb4..0ca5b5fcdc 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -129,6 +129,7 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty if (QSystemTrayIcon::isSystemTrayAvailable()) { createTrayIcon(networkStyle); } + notificator = new Notificator(QApplication::applicationName(), trayIcon, this); // Create status bar statusBar(); @@ -536,8 +537,7 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel()); OptionsModel* optionsModel = _clientModel->getOptionsModel(); - if(optionsModel) - { + if (optionsModel && trayIcon) { // be aware of the tray icon disable state change reported by the OptionsModel object. connect(optionsModel, &OptionsModel::hideTrayIconChanged, this, &BitcoinGUI::setTrayIconVisible); @@ -569,10 +569,9 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel) { if(!walletFrame) return false; - const QString name = walletModel->getWalletName(); - QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name; + const QString display_name = walletModel->getDisplayName(); setWalletActionsEnabled(true); - m_wallet_selector->addItem(display_name, name); + m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel)); if (m_wallet_selector->count() == 2) { m_wallet_selector_label_action->setVisible(true); m_wallet_selector_action->setVisible(true); @@ -584,8 +583,7 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel) bool BitcoinGUI::removeWallet(WalletModel* walletModel) { if (!walletFrame) return false; - QString name = walletModel->getWalletName(); - int index = m_wallet_selector->findData(name); + int index = m_wallet_selector->findData(QVariant::fromValue(walletModel)); m_wallet_selector->removeItem(index); if (m_wallet_selector->count() == 0) { setWalletActionsEnabled(false); @@ -594,20 +592,20 @@ bool BitcoinGUI::removeWallet(WalletModel* walletModel) m_wallet_selector_action->setVisible(false); } rpcConsole->removeWallet(walletModel); - return walletFrame->removeWallet(name); + return walletFrame->removeWallet(walletModel); } -bool BitcoinGUI::setCurrentWallet(const QString& name) +bool BitcoinGUI::setCurrentWallet(WalletModel* wallet_model) { if(!walletFrame) return false; - return walletFrame->setCurrentWallet(name); + return walletFrame->setCurrentWallet(wallet_model); } bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index) { - QString internal_name = m_wallet_selector->itemData(index).toString(); - return setCurrentWallet(internal_name); + WalletModel* wallet_model = m_wallet_selector->itemData(index).value<WalletModel*>(); + return setCurrentWallet(wallet_model); } void BitcoinGUI::removeAllWallets() @@ -642,14 +640,10 @@ void BitcoinGUI::createTrayIcon(const NetworkStyle *networkStyle) assert(QSystemTrayIcon::isSystemTrayAvailable()); #ifndef Q_OS_MAC - trayIcon = new QSystemTrayIcon(this); + trayIcon = new QSystemTrayIcon(networkStyle->getTrayAndWindowIcon(), this); QString toolTip = tr("%1 client").arg(tr(PACKAGE_NAME)) + " " + networkStyle->getTitleAddText(); trayIcon->setToolTip(toolTip); - trayIcon->setIcon(networkStyle->getTrayAndWindowIcon()); - trayIcon->hide(); #endif - - notificator = new Notificator(QApplication::applicationName(), trayIcon, this); } void BitcoinGUI::createTrayIconMenu() diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index aeff5dae30..1324dd6625 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -206,7 +206,7 @@ public Q_SLOTS: void message(const QString &title, const QString &message, unsigned int style, bool *ret = nullptr); #ifdef ENABLE_WALLET - bool setCurrentWallet(const QString& name); + bool setCurrentWallet(WalletModel* wallet_model); bool setCurrentWalletBySelectorIndex(int index); /** Set the UI status indicators based on the currently selected wallet. */ diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index 8f34e6bc82..507d195b72 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -714,7 +714,7 @@ <item> <widget class="QLabel" name="overriddenByCommandLineInfoLabel"> <property name="text"> - <string>Active command-line options that override above options:</string> + <string>Options set in this dialog are overridden by the command line or in the configuration file:</string> </property> <property name="textFormat"> <enum>Qt::PlainText</enum> diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 04b03a5435..4d6006c582 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -50,5 +50,6 @@ static const int MAX_URI_LENGTH = 255; #define QAPP_ORG_DOMAIN "bitcoin.org" #define QAPP_APP_NAME_DEFAULT "Bitcoin-Qt" #define QAPP_APP_NAME_TESTNET "Bitcoin-Qt-testnet" +#define QAPP_APP_NAME_REGTEST "Bitcoin-Qt-regtest" #endif // BITCOIN_QT_GUICONSTANTS_H diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp index b134a139b0..da048d3211 100644 --- a/src/qt/networkstyle.cpp +++ b/src/qt/networkstyle.cpp @@ -17,7 +17,7 @@ static const struct { } network_styles[] = { {"main", QAPP_APP_NAME_DEFAULT, 0, 0, ""}, {"test", QAPP_APP_NAME_TESTNET, 70, 30, QT_TRANSLATE_NOOP("SplashScreen", "[testnet]")}, - {"regtest", QAPP_APP_NAME_TESTNET, 160, 30, "[regtest]"} + {"regtest", QAPP_APP_NAME_REGTEST, 160, 30, "[regtest]"} }; static const unsigned network_styles_count = sizeof(network_styles)/sizeof(*network_styles); diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp index 94505043dc..4b91c19761 100644 --- a/src/qt/notificator.cpp +++ b/src/qt/notificator.cpp @@ -39,7 +39,7 @@ Notificator::Notificator(const QString &_programName, QSystemTrayIcon *_trayIcon mode(None), trayIcon(_trayIcon) #ifdef USE_DBUS - ,interface(0) + ,interface(nullptr) #endif { if(_trayIcon && _trayIcon->supportsMessages()) @@ -154,14 +154,14 @@ QVariant FreedesktopImage::toVariant(const QImage &img) void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) { - Q_UNUSED(cls); - // Arguments for DBus call: + // https://developer.gnome.org/notification-spec/ + // Arguments for DBus "Notify" call: QList<QVariant> args; // Program Name: args.append(programName); - // Unique ID of this notification type: + // Replaces ID; A value of 0 means that this notification won't replace any existing notifications: args.append(0U); // Application Icon, empty string @@ -209,9 +209,8 @@ void Notificator::notifyDBus(Class cls, const QString &title, const QString &tex } #endif -void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) +void Notificator::notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout) { - Q_UNUSED(icon); QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon; switch(cls) // Set icon based on class { @@ -222,13 +221,12 @@ void Notificator::notifySystray(Class cls, const QString &title, const QString & trayIcon->showMessage(title, text, sicon, millisTimeout); } -// Based on Qt's tray icon implementation #ifdef Q_OS_MAC -void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) { +void Notificator::notifyMacUserNotificationCenter(const QString &title, const QString &text) +{ // icon is not supported by the user notification center yet. OSX will use the app icon. MacNotificationHandler::instance()->showNotification(title, text); } - #endif void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout) @@ -241,11 +239,11 @@ void Notificator::notify(Class cls, const QString &title, const QString &text, c break; #endif case QSystemTray: - notifySystray(cls, title, text, icon, millisTimeout); + notifySystray(cls, title, text, millisTimeout); break; #ifdef Q_OS_MAC case UserNotificationCenter: - notifyMacUserNotificationCenter(cls, title, text, icon); + notifyMacUserNotificationCenter(title, text); break; #endif default: diff --git a/src/qt/notificator.h b/src/qt/notificator.h index 10b7b6c50a..7d80b43e43 100644 --- a/src/qt/notificator.h +++ b/src/qt/notificator.h @@ -57,7 +57,7 @@ private: enum Mode { None, /**< Ignore informational notifications, and show a modal pop-up dialog for Critical notifications. */ Freedesktop, /**< Use DBus org.freedesktop.Notifications */ - QSystemTray, /**< Use QSystemTray::showMessage */ + QSystemTray, /**< Use QSystemTrayIcon::showMessage() */ UserNotificationCenter /**< Use the 10.8+ User Notification Center (Mac only) */ }; QString programName; @@ -68,9 +68,9 @@ private: void notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); #endif - void notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout); + void notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout); #ifdef Q_OS_MAC - void notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon); + void notifyMacUserNotificationCenter(const QString &title, const QString &text); #endif }; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 774a0d78e7..a6187685a9 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -85,7 +85,7 @@ public: explicit RPCExecutor(interfaces::Node& node) : m_node(node) {} public Q_SLOTS: - void request(const QString &command, const QString &walletID); + void request(const QString &command, const WalletModel* wallet_model); Q_SIGNALS: void reply(int category, const QString &command); @@ -148,7 +148,7 @@ public: * @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data */ -bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const std::string *walletID) +bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const WalletModel* wallet_model) { std::vector< std::vector<std::string> > stack; stack.push_back(std::vector<std::string>()); @@ -306,8 +306,8 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes std::string method = stack.back()[0]; std::string uri; #ifdef ENABLE_WALLET - if (walletID) { - QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID)); + if (wallet_model) { + QByteArray encodedName = QUrl::toPercentEncoding(wallet_model->getWalletName()); uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length()); } #endif @@ -387,7 +387,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes } } -void RPCExecutor::request(const QString &command, const QString &walletID) +void RPCExecutor::request(const QString &command, const WalletModel* wallet_model) { try { @@ -418,9 +418,7 @@ void RPCExecutor::request(const QString &command, const QString &walletID) " example: getblock(getblockhash(0),true)[tx][0]\n\n"))); return; } - std::string wallet_id = walletID.toStdString(); - if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, walletID.isNull() ? nullptr : &wallet_id)) - { + if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, wallet_model)) { Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \"")); return; } @@ -698,10 +696,8 @@ void RPCConsole::setClientModel(ClientModel *model) #ifdef ENABLE_WALLET void RPCConsole::addWallet(WalletModel * const walletModel) { - const QString name = walletModel->getWalletName(); - // use name for text and internal data object (to allow to move to a wallet id later) - QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name; - ui->WalletSelector->addItem(display_name, name); + // use name for text and wallet model for internal data object (to allow to move to a wallet id later) + ui->WalletSelector->addItem(walletModel->getDisplayName(), QVariant::fromValue(walletModel)); if (ui->WalletSelector->count() == 2 && !isVisible()) { // First wallet added, set to default so long as the window isn't presently visible (and potentially in use) ui->WalletSelector->setCurrentIndex(1); @@ -714,8 +710,7 @@ void RPCConsole::addWallet(WalletModel * const walletModel) void RPCConsole::removeWallet(WalletModel * const walletModel) { - const QString name = walletModel->getWalletName(); - ui->WalletSelector->removeItem(ui->WalletSelector->findData(name)); + ui->WalletSelector->removeItem(ui->WalletSelector->findData(QVariant::fromValue(walletModel))); if (ui->WalletSelector->count() == 2) { ui->WalletSelector->setVisible(false); ui->WalletSelectorLabel->setVisible(false); @@ -910,25 +905,25 @@ void RPCConsole::on_lineEdit_returnPressed() cmdBeforeBrowsing = QString(); - QString walletID; + WalletModel* wallet_model{nullptr}; #ifdef ENABLE_WALLET const int wallet_index = ui->WalletSelector->currentIndex(); if (wallet_index > 0) { - walletID = (QString)ui->WalletSelector->itemData(wallet_index).value<QString>(); + wallet_model = ui->WalletSelector->itemData(wallet_index).value<WalletModel*>(); } - if (m_last_wallet_id != walletID) { - if (walletID.isNull()) { - message(CMD_REQUEST, tr("Executing command without any wallet")); + if (m_last_wallet_model != wallet_model) { + if (wallet_model) { + message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName())); } else { - message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID)); + message(CMD_REQUEST, tr("Executing command without any wallet")); } - m_last_wallet_id = walletID; + m_last_wallet_model = wallet_model; } #endif message(CMD_REQUEST, QString::fromStdString(strFilteredCmd)); - Q_EMIT cmdRequest(cmd, walletID); + Q_EMIT cmdRequest(cmd, m_last_wallet_model); cmd = QString::fromStdString(strFilteredCmd); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 20dbf5ec95..6c000ba096 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -41,9 +41,9 @@ public: explicit RPCConsole(interfaces::Node& node, const PlatformStyle *platformStyle, QWidget *parent); ~RPCConsole(); - static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr); - static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const std::string *walletID = nullptr) { - return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, walletID); + static bool RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr); + static bool RPCExecuteCommandLine(interfaces::Node& node, std::string &strResult, const std::string &strCommand, std::string * const pstrFilteredOut = nullptr, const WalletModel* wallet_model = nullptr) { + return RPCParseCommandLine(&node, strResult, strCommand, true, pstrFilteredOut, wallet_model); } void setClientModel(ClientModel *model); @@ -133,7 +133,7 @@ public Q_SLOTS: Q_SIGNALS: // For RPC command executor void stopExecutor(); - void cmdRequest(const QString &command, const QString &walletID); + void cmdRequest(const QString &command, const WalletModel* wallet_model); private: void startExecutor(); @@ -165,7 +165,7 @@ private: int consoleFontSize = 0; QCompleter *autoCompleter = nullptr; QThread thread; - QString m_last_wallet_id; + WalletModel* m_last_wallet_model{nullptr}; /** Update UI with latest network info from model. */ void updateNetworkState(); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index d15bd95b8e..4f8b6d363e 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -46,8 +46,7 @@ bool WalletFrame::addWallet(WalletModel *walletModel) return false; } - const QString name = walletModel->getWalletName(); - if (mapWalletViews.count(name) > 0) { + if (mapWalletViews.count(walletModel) > 0) { return false; } @@ -65,7 +64,7 @@ bool WalletFrame::addWallet(WalletModel *walletModel) } walletStack->addWidget(walletView); - mapWalletViews[name] = walletView; + mapWalletViews[walletModel] = walletView; // Ensure a walletView is able to show the main window connect(walletView, &WalletView::showNormalIfMinimized, [this]{ @@ -77,24 +76,24 @@ bool WalletFrame::addWallet(WalletModel *walletModel) return true; } -bool WalletFrame::setCurrentWallet(const QString& name) +bool WalletFrame::setCurrentWallet(WalletModel* wallet_model) { - if (mapWalletViews.count(name) == 0) + if (mapWalletViews.count(wallet_model) == 0) return false; - WalletView *walletView = mapWalletViews.value(name); + WalletView *walletView = mapWalletViews.value(wallet_model); walletStack->setCurrentWidget(walletView); assert(walletView); walletView->updateEncryptionStatus(); return true; } -bool WalletFrame::removeWallet(const QString &name) +bool WalletFrame::removeWallet(WalletModel* wallet_model) { - if (mapWalletViews.count(name) == 0) + if (mapWalletViews.count(wallet_model) == 0) return false; - WalletView *walletView = mapWalletViews.take(name); + WalletView *walletView = mapWalletViews.take(wallet_model); walletStack->removeWidget(walletView); delete walletView; return true; @@ -102,7 +101,7 @@ bool WalletFrame::removeWallet(const QString &name) void WalletFrame::removeAllWallets() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) walletStack->removeWidget(i.value()); mapWalletViews.clear(); @@ -120,35 +119,35 @@ bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient) void WalletFrame::showOutOfSyncWarning(bool fShow) { bOutOfSync = fShow; - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->showOutOfSyncWarning(fShow); } void WalletFrame::gotoOverviewPage() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoOverviewPage(); } void WalletFrame::gotoHistoryPage() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoHistoryPage(); } void WalletFrame::gotoReceiveCoinsPage() { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoReceiveCoinsPage(); } void WalletFrame::gotoSendCoinsPage(QString addr) { - QMap<QString, WalletView*>::const_iterator i; + QMap<WalletModel*, WalletView*>::const_iterator i; for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) i.value()->gotoSendCoinsPage(addr); } diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 05ca569d7a..9fbc8b4d52 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -37,8 +37,8 @@ public: void setClientModel(ClientModel *clientModel); bool addWallet(WalletModel *walletModel); - bool setCurrentWallet(const QString& name); - bool removeWallet(const QString &name); + bool setCurrentWallet(WalletModel* wallet_model); + bool removeWallet(WalletModel* wallet_model); void removeAllWallets(); bool handlePaymentRequest(const SendCoinsRecipient& recipient); @@ -53,7 +53,7 @@ private: QStackedWidget *walletStack; BitcoinGUI *gui; ClientModel *clientModel; - QMap<QString, WalletView*> mapWalletViews; + QMap<WalletModel*, WalletView*> mapWalletViews; bool bOutOfSync; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ba16fdd5e1..b7fa636494 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -578,6 +578,12 @@ QString WalletModel::getWalletName() const return QString::fromStdString(m_wallet->getWalletName()); } +QString WalletModel::getDisplayName() const +{ + const QString name = getWalletName(); + return name.isEmpty() ? "["+tr("default wallet")+"]" : name; +} + bool WalletModel::isMultiwallet() { return m_node.getWallets().size() > 1; diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ec4c5a2a6c..2988682533 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2018 The Bitcoin Core developers +// Copyright (c) 2011-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -219,6 +219,7 @@ public: interfaces::Wallet& wallet() const { return *m_wallet; } QString getWalletName() const; + QString getDisplayName() const; bool isMultiwallet(); diff --git a/src/rest.cpp b/src/rest.cpp index 4988e6ed26..4f26e3afb5 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -136,10 +136,12 @@ static bool rest_headers(HTTPRequest* req, if (!ParseHashStr(hashStr, hash)) return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr); + const CBlockIndex* tip = nullptr; std::vector<const CBlockIndex *> headers; headers.reserve(count); { LOCK(cs_main); + tip = chainActive.Tip(); const CBlockIndex* pindex = LookupBlockIndex(hash); while (pindex != nullptr && chainActive.Contains(pindex)) { headers.push_back(pindex); @@ -175,11 +177,8 @@ static bool rest_headers(HTTPRequest* req, } case RetFormat::JSON: { UniValue jsonHeaders(UniValue::VARR); - { - LOCK(cs_main); - for (const CBlockIndex *pindex : headers) { - jsonHeaders.push_back(blockheaderToJSON(pindex)); - } + for (const CBlockIndex *pindex : headers) { + jsonHeaders.push_back(blockheaderToJSON(tip, pindex)); } std::string strJSON = jsonHeaders.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); @@ -207,8 +206,10 @@ static bool rest_block(HTTPRequest* req, CBlock block; CBlockIndex* pblockindex = nullptr; + CBlockIndex* tip = nullptr; { LOCK(cs_main); + tip = chainActive.Tip(); pblockindex = LookupBlockIndex(hash); if (!pblockindex) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); @@ -241,11 +242,7 @@ static bool rest_block(HTTPRequest* req, } case RetFormat::JSON: { - UniValue objBlock; - { - LOCK(cs_main); - objBlock = blockToJSON(block, pblockindex, showTxDetails); - } + UniValue objBlock = blockToJSON(block, tip, pblockindex, showTxDetails); std::string strJSON = objBlock.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index bd229e5efa..4846d7cc95 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -59,10 +59,7 @@ static CUpdatedBlock latestblock; */ double GetDifficulty(const CBlockIndex* blockindex) { - if (blockindex == nullptr) - { - return 1.0; - } + assert(blockindex); int nShift = (blockindex->nBits >> 24) & 0xff; double dDiff = @@ -82,15 +79,22 @@ double GetDifficulty(const CBlockIndex* blockindex) return dDiff; } -UniValue blockheaderToJSON(const CBlockIndex* blockindex) +static int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next) +{ + next = tip->GetAncestor(blockindex->nHeight + 1); + if (next && next->pprev == blockindex) { + return tip->nHeight - blockindex->nHeight + 1; + } + next = nullptr; + return blockindex == tip ? 1 : -1; +} + +UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex) { - AssertLockHeld(cs_main); UniValue result(UniValue::VOBJ); result.pushKV("hash", blockindex->GetBlockHash().GetHex()); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; + const CBlockIndex* pnext; + int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext); result.pushKV("confirmations", confirmations); result.pushKV("height", blockindex->nHeight); result.pushKV("version", blockindex->nVersion); @@ -106,21 +110,17 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) if (blockindex->pprev) result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()); - CBlockIndex *pnext = chainActive.Next(blockindex); if (pnext) result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex()); return result; } -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) +UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails) { - AssertLockHeld(cs_main); UniValue result(UniValue::VOBJ); result.pushKV("hash", blockindex->GetBlockHash().GetHex()); - int confirmations = -1; - // Only report confirmations if the block is on the main chain - if (chainActive.Contains(blockindex)) - confirmations = chainActive.Height() - blockindex->nHeight + 1; + const CBlockIndex* pnext; + int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext); result.pushKV("confirmations", confirmations); result.pushKV("strippedsize", (int)::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS)); result.pushKV("size", (int)::GetSerializeSize(block, PROTOCOL_VERSION)); @@ -152,7 +152,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx if (blockindex->pprev) result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()); - CBlockIndex *pnext = chainActive.Next(blockindex); if (pnext) result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex()); return result; @@ -769,7 +768,7 @@ static UniValue getblockheader(const JSONRPCRequest& request) return strHex; } - return blockheaderToJSON(pblockindex); + return blockheaderToJSON(chainActive.Tip(), pblockindex); } static CBlock GetBlockChecked(const CBlockIndex* pblockindex) @@ -871,7 +870,7 @@ static UniValue getblock(const JSONRPCRequest& request) return strHex; } - return blockToJSON(block, pblockindex, verbosity >= 2); + return blockToJSON(block, chainActive.Tip(), pblockindex, verbosity >= 2); } struct CCoinsStats @@ -1150,7 +1149,7 @@ static UniValue verifychain(const JSONRPCRequest& request) } /** Implementation of IsSuperMajority with better feedback */ -static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) +static UniValue SoftForkMajorityDesc(int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams) { UniValue rv(UniValue::VOBJ); bool activated = false; @@ -1170,7 +1169,7 @@ static UniValue SoftForkMajorityDesc(int version, CBlockIndex* pindex, const Con return rv; } -static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex* pindex, const Consensus::Params& consensusParams) +static UniValue SoftForkDesc(const std::string &name, int version, const CBlockIndex* pindex, const Consensus::Params& consensusParams) { UniValue rv(UniValue::VOBJ); rv.pushKV("id", name); @@ -1277,20 +1276,21 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) LOCK(cs_main); + const CBlockIndex* tip = chainActive.Tip(); UniValue obj(UniValue::VOBJ); obj.pushKV("chain", Params().NetworkIDString()); obj.pushKV("blocks", (int)chainActive.Height()); obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1); - obj.pushKV("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex()); - obj.pushKV("difficulty", (double)GetDifficulty(chainActive.Tip())); - obj.pushKV("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast()); - obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip())); + obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex()); + obj.pushKV("difficulty", (double)GetDifficulty(tip)); + obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast()); + obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip)); obj.pushKV("initialblockdownload", IsInitialBlockDownload()); - obj.pushKV("chainwork", chainActive.Tip()->nChainWork.GetHex()); + obj.pushKV("chainwork", tip->nChainWork.GetHex()); obj.pushKV("size_on_disk", CalculateCurrentUsage()); obj.pushKV("pruned", fPruneMode); if (fPruneMode) { - CBlockIndex* block = chainActive.Tip(); + const CBlockIndex* block = tip; assert(block); while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) { block = block->pprev; @@ -1307,7 +1307,6 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) } const Consensus::Params& consensusParams = Params().GetConsensus(); - CBlockIndex* tip = chainActive.Tip(); UniValue softforks(UniValue::VARR); UniValue bip9_softforks(UniValue::VOBJ); softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index add335eb8a..529132d033 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -27,7 +27,7 @@ double GetDifficulty(const CBlockIndex* blockindex); void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); /** Block description to JSON */ -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); +UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIndex* blockindex, bool txDetails = false); /** Mempool information to JSON */ UniValue mempoolInfoToJSON(); @@ -36,7 +36,7 @@ UniValue mempoolInfoToJSON(); UniValue mempoolToJSON(bool fVerbose = false); /** Block header to JSON */ -UniValue blockheaderToJSON(const CBlockIndex* blockindex); +UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex); /** Used by getblockstats to get feerates at different percentiles by weight */ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 4d6b260cc7..cc229367ba 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -109,11 +109,15 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) " \"whitelisted\": true|false, (boolean) Whether the peer is whitelisted\n" " \"minfeefilter\": n, (numeric) The minimum fee rate for transactions this peer accepts\n" " \"bytessent_per_msg\": {\n" - " \"addr\": n, (numeric) The total bytes sent aggregated by message type\n" + " \"msg\": n, (numeric) The total bytes sent aggregated by message type\n" + " When a message type is not listed in this json object, the bytes sent are 0.\n" + " Only known message types can appear as keys in the object.\n" " ...\n" " },\n" " \"bytesrecv_per_msg\": {\n" - " \"addr\": n, (numeric) The total bytes received aggregated by message type\n" + " \"msg\": n, (numeric) The total bytes received aggregated by message type\n" + " When a message type is not listed in this json object, the bytes received are 0.\n" + " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n" " ...\n" " }\n" " }\n" @@ -178,14 +182,14 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) obj.pushKV("minfeefilter", ValueFromAmount(stats.minFeeFilter)); UniValue sendPerMsgCmd(UniValue::VOBJ); - for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) { + for (const auto& i : stats.mapSendBytesPerMsgCmd) { if (i.second > 0) sendPerMsgCmd.pushKV(i.first, i.second); } obj.pushKV("bytessent_per_msg", sendPerMsgCmd); UniValue recvPerMsgCmd(UniValue::VOBJ); - for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) { + for (const auto& i : stats.mapRecvBytesPerMsgCmd) { if (i.second > 0) recvPerMsgCmd.pushKV(i.first, i.second); } diff --git a/src/streams.h b/src/streams.h index d5565fe61f..0809c96be1 100644 --- a/src/streams.h +++ b/src/streams.h @@ -64,12 +64,6 @@ public: size_t size() const { return stream->size(); } }; -template<typename S> -OverrideStream<S> WithOrVersion(S* s, int nVersionFlag) -{ - return OverrideStream<S>(s, s->GetType(), s->GetVersion() | nVersionFlag); -} - /* Minimal stream for overwriting and/or appending to an existing byte vector * * The referenced vector will grow as necessary @@ -126,12 +120,6 @@ class CVectorWriter { return nType; } - void seek(size_t nSize) - { - nPos += nSize; - if(nPos > vchData.size()) - vchData.resize(nPos); - } private: const int nType; const int nVersion; @@ -158,9 +146,11 @@ public: * @param[in] pos Starting position. Vector index where reads should start. */ VectorReader(int type, int version, const std::vector<unsigned char>& data, size_t pos) - : m_type(type), m_version(version), m_data(data) + : m_type(type), m_version(version), m_data(data), m_pos(pos) { - seek(pos); + if (m_pos > m_data.size()) { + throw std::ios_base::failure("VectorReader(...): end of data (m_pos > m_data.size())"); + } } /* @@ -203,14 +193,6 @@ public: memcpy(dst, m_data.data() + m_pos, n); m_pos = pos_next; } - - void seek(size_t n) - { - m_pos += n; - if (m_pos > m_data.size()) { - throw std::ios_base::failure("VectorReader::seek(): end of data"); - } - } }; /** Double ended buffer combining vector and stream-like interfaces. diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index 7d8ae46fb8..b61152985f 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -68,11 +68,4 @@ BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target) TestDifficulty(0x12345678, 5913134931067755359633408.0); } -// Verify that difficulty is 1.0 for an empty chain. -BOOST_AUTO_TEST_CASE(get_difficulty_for_null_tip) -{ - double difficulty = GetDifficulty(nullptr); - RejectDifficultyMismatch(difficulty, 1.0); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp index 1abaabd658..bf295042de 100644 --- a/src/test/key_io_tests.cpp +++ b/src/test/key_io_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2017 The Bitcoin Core developers +// Copyright (c) 2011-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index 1556b2f667..3a2a11ef98 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -213,14 +213,22 @@ BOOST_AUTO_TEST_CASE(is) BOOST_CHECK(p2sh.IsPayToScriptHash()); // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes: - static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash()); - static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash()); - static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash()); - static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL }; - BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash()); + std::vector<unsigned char> direct = {OP_HASH160, 20}; + direct.insert(direct.end(), 20, 0); + direct.push_back(OP_EQUAL); + BOOST_CHECK(CScript(direct.begin(), direct.end()).IsPayToScriptHash()); + std::vector<unsigned char> pushdata1 = {OP_HASH160, OP_PUSHDATA1, 20}; + pushdata1.insert(pushdata1.end(), 20, 0); + pushdata1.push_back(OP_EQUAL); + BOOST_CHECK(!CScript(pushdata1.begin(), pushdata1.end()).IsPayToScriptHash()); + std::vector<unsigned char> pushdata2 = {OP_HASH160, 20, 0}; + pushdata2.insert(pushdata2.end(), 20, 0); + pushdata2.push_back(OP_EQUAL); + BOOST_CHECK(!CScript(pushdata2.begin(), pushdata2.end()).IsPayToScriptHash()); + std::vector<unsigned char> pushdata4 = {OP_HASH160, 20, 0, 0, 0}; + pushdata4.insert(pushdata4.end(), 20, 0); + pushdata4.push_back(OP_EQUAL); + BOOST_CHECK(!CScript(pushdata4.begin(), pushdata4.end()).IsPayToScriptHash()); CScript not_p2sh; BOOST_CHECK(!not_p2sh.IsPayToScriptHash()); diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 26cf74830d..a1940eb80e 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -102,15 +102,15 @@ BOOST_AUTO_TEST_CASE(streams_vector_reader) BOOST_CHECK_THROW(reader >> d, std::ios_base::failure); // Read a 4 bytes as a signed int from the beginning of the buffer. - reader.seek(-6); - reader >> d; + VectorReader new_reader(SER_NETWORK, INIT_PROTO_VERSION, vch, 0); + new_reader >> d; BOOST_CHECK_EQUAL(d, 67370753); // 1,255,3,4 in little-endian base-256 - BOOST_CHECK_EQUAL(reader.size(), 2); - BOOST_CHECK(!reader.empty()); + BOOST_CHECK_EQUAL(new_reader.size(), 2); + BOOST_CHECK(!new_reader.empty()); // Reading after end of byte vector throws an error even if the reader is // not totally empty. - BOOST_CHECK_THROW(reader >> d, std::ios_base::failure); + BOOST_CHECK_THROW(new_reader >> d, std::ios_base::failure); } BOOST_AUTO_TEST_CASE(bitstream_reader_writer) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index d952054483..39cff3f463 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -414,7 +414,8 @@ static void ReplaceRedeemScript(CScript& script, const CScript& redeemScript) script = PushAll(stack); } -BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { +BOOST_AUTO_TEST_CASE(test_big_witness_transaction) +{ CMutableTransaction mtx; mtx.nVersion = 1; @@ -456,9 +457,8 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { } CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION); - auto vstream = WithOrVersion(&ssout, 0); - vstream << mtx; - CTransaction tx(deserialize, vstream); + ssout << mtx; + CTransaction tx(deserialize, ssout); // check all inputs concurrently, with the cache PrecomputedTransactionData txdata(tx); diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp index 473ec5addf..c2777cd6d1 100644 --- a/src/test/txvalidation_tests.cpp +++ b/src/test/txvalidation_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017 The Bitcoin Core developers +// Copyright (c) 2017-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/threadinterrupt.h b/src/threadinterrupt.h index 9c6fccfcde..2743571379 100644 --- a/src/threadinterrupt.h +++ b/src/threadinterrupt.h @@ -1,4 +1,4 @@ -// Copyright (c) 2016-2017 The Bitcoin Core developers +// Copyright (c) 2016-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/validation.cpp b/src/validation.cpp index 00d7a60cb7..a18e449af6 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3998,7 +3998,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, LogPrintf("[0%%]..."); /* Continued */ for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); - int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); + const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); if (reportDone < percentageDone/10) { // report every 10% step LogPrintf("[%d%%]...", percentageDone); /* Continued */ @@ -4056,7 +4056,13 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, if (nCheckLevel >= 4) { while (pindex != chainActive.Tip()) { boost::this_thread::interruption_point(); - uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false); + const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))); + if (reportDone < percentageDone/10) { + // report every 10% step + LogPrintf("[%d%%]...", percentageDone); /* Continued */ + reportDone = percentageDone/10; + } + uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false); pindex = chainActive.Next(pindex); CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 1ed1926af2..0db22cf6fe 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2018 The Bitcoin Core developers +// Copyright (c) 2012-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -47,7 +47,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) auto locked_chain = chain->lock(); - // Verify ScanForWalletTransactions accomodates a null start block. + // Verify ScanForWalletTransactions accommodates a null start block. { CWallet wallet(*chain, WalletLocation(), WalletDatabase::CreateDummy()); AddKey(wallet, coinbaseKey); |