diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bench/bench_bitcoin.cpp | 4 | ||||
-rw-r--r-- | src/bitcoin-cli.cpp | 16 | ||||
-rw-r--r-- | src/bitcoin-tx.cpp | 16 | ||||
-rw-r--r-- | src/bitcoin-wallet.cpp | 12 | ||||
-rw-r--r-- | src/bitcoind.cpp | 18 | ||||
-rw-r--r-- | src/init.cpp | 7 | ||||
-rw-r--r-- | src/net_processing.cpp | 125 | ||||
-rw-r--r-- | src/netaddress.cpp | 4 | ||||
-rw-r--r-- | src/noui.cpp | 2 | ||||
-rw-r--r-- | src/policy/fees.cpp | 2 | ||||
-rw-r--r-- | src/qt/bitcoingui.cpp | 5 | ||||
-rw-r--r-- | src/qt/utilitydialog.cpp | 2 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 7 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 2 | ||||
-rw-r--r-- | src/sync.cpp | 8 | ||||
-rw-r--r-- | src/test/crypto_tests.cpp | 2 | ||||
-rw-r--r-- | src/tinyformat.h | 1 | ||||
-rw-r--r-- | src/torcontrol.cpp | 2 | ||||
-rw-r--r-- | src/util/system.cpp | 4 | ||||
-rw-r--r-- | src/wallet/wallettool.cpp | 38 |
20 files changed, 175 insertions, 102 deletions
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index a788b23823..8eea96d930 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -36,7 +36,7 @@ int main(int argc, char** argv) SetupBenchArgs(); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str()); + tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str()); return EXIT_FAILURE; } @@ -53,7 +53,7 @@ int main(int argc, char** argv) double scaling_factor; if (!ParseDouble(scaling_str, &scaling_factor)) { - fprintf(stderr, "Error parsing scaling factor as double: %s\n", scaling_str.c_str()); + tfm::format(std::cerr, "Error parsing scaling factor as double: %s\n", scaling_str.c_str()); return EXIT_FAILURE; } diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 1009a771f8..38010c461e 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -101,7 +101,7 @@ static int AppInitRPC(int argc, char* argv[]) SetupCliArgs(); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str()); + tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str()); return EXIT_FAILURE; } if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) { @@ -115,26 +115,26 @@ static int AppInitRPC(int argc, char* argv[]) strUsage += "\n" + gArgs.GetHelpMessage(); } - fprintf(stdout, "%s", strUsage.c_str()); + tfm::format(std::cout, "%s", strUsage.c_str()); if (argc < 2) { - fprintf(stderr, "Error: too few parameters\n"); + tfm::format(std::cerr, "Error: too few parameters\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } if (!fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); + tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return EXIT_FAILURE; } if (!gArgs.ReadConfigFiles(error, true)) { - fprintf(stderr, "Error reading configuration file: %s\n", error.c_str()); + tfm::format(std::cerr, "Error reading configuration file: %s\n", error.c_str()); return EXIT_FAILURE; } // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause) try { SelectBaseParams(gArgs.GetChainName()); } catch (const std::exception& e) { - fprintf(stderr, "Error: %s\n", e.what()); + tfm::format(std::cerr, "Error: %s\n", e.what()); return EXIT_FAILURE; } return CONTINUE_EXECUTION; @@ -495,7 +495,7 @@ static int CommandLineRPC(int argc, char *argv[]) } if (strPrint != "") { - fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); + tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint.c_str()); } return nRet; } @@ -508,7 +508,7 @@ int main(int argc, char* argv[]) #endif SetupEnvironment(); if (!SetupNetworking()) { - fprintf(stderr, "Error: Initializing networking failed\n"); + tfm::format(std::cerr, "Error: Initializing networking failed\n"); return EXIT_FAILURE; } event_set_log_callback(&libevent_log_cb); diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index ac1d62a8f4..933b34744d 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -82,7 +82,7 @@ static int AppInitRawTx(int argc, char* argv[]) SetupBitcoinTxArgs(); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str()); + tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str()); return EXIT_FAILURE; } @@ -90,7 +90,7 @@ static int AppInitRawTx(int argc, char* argv[]) try { SelectParams(gArgs.GetChainName()); } catch (const std::exception& e) { - fprintf(stderr, "Error: %s\n", e.what()); + tfm::format(std::cerr, "Error: %s\n", e.what()); return EXIT_FAILURE; } @@ -104,10 +104,10 @@ static int AppInitRawTx(int argc, char* argv[]) "\n"; strUsage += gArgs.GetHelpMessage(); - fprintf(stdout, "%s", strUsage.c_str()); + tfm::format(std::cout, "%s", strUsage.c_str()); if (argc < 2) { - fprintf(stderr, "Error: too few parameters\n"); + tfm::format(std::cerr, "Error: too few parameters\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; @@ -723,21 +723,21 @@ static void OutputTxJSON(const CTransaction& tx) TxToUniv(tx, uint256(), entry); std::string jsonOutput = entry.write(4); - fprintf(stdout, "%s\n", jsonOutput.c_str()); + tfm::format(std::cout, "%s\n", jsonOutput.c_str()); } static void OutputTxHash(const CTransaction& tx) { std::string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id) - fprintf(stdout, "%s\n", strHexHash.c_str()); + tfm::format(std::cout, "%s\n", strHexHash.c_str()); } static void OutputTxHex(const CTransaction& tx) { std::string strHex = EncodeHexTx(tx); - fprintf(stdout, "%s\n", strHex.c_str()); + tfm::format(std::cout, "%s\n", strHex.c_str()); } static void OutputTx(const CTransaction& tx) @@ -828,7 +828,7 @@ static int CommandLineRawTx(int argc, char* argv[]) } if (strPrint != "") { - fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); + tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint.c_str()); } return nRet; } diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index ad31f0be4a..cbb4ea750c 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -36,7 +36,7 @@ static bool WalletAppInit(int argc, char* argv[]) SetupWalletToolArgs(); std::string error_message; if (!gArgs.ParseParameters(argc, argv, error_message)) { - fprintf(stderr, "Error parsing command line arguments: %s\n", error_message.c_str()); + tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message.c_str()); return false; } if (argc < 2 || HelpRequested(gArgs)) { @@ -48,7 +48,7 @@ static bool WalletAppInit(int argc, char* argv[]) " bitcoin-wallet [options] <command>\n\n" + gArgs.GetHelpMessage(); - fprintf(stdout, "%s", usage.c_str()); + tfm::format(std::cout, "%s", usage.c_str()); return false; } @@ -56,7 +56,7 @@ static bool WalletAppInit(int argc, char* argv[]) LogInstance().m_print_to_console = gArgs.GetBoolArg("-printtoconsole", gArgs.GetBoolArg("-debug", false)); if (!fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); + tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return false; } // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) @@ -87,7 +87,7 @@ int main(int argc, char* argv[]) for(int i = 1; i < argc; ++i) { if (!IsSwitchChar(argv[i][0])) { if (!method.empty()) { - fprintf(stderr, "Error: two methods provided (%s and %s). Only one method should be provided.\n", method.c_str(), argv[i]); + tfm::format(std::cerr, "Error: two methods provided (%s and %s). Only one method should be provided.\n", method.c_str(), argv[i]); return EXIT_FAILURE; } method = argv[i]; @@ -95,13 +95,13 @@ int main(int argc, char* argv[]) } if (method.empty()) { - fprintf(stderr, "No method provided. Run `bitcoin-wallet -help` for valid methods.\n"); + tfm::format(std::cerr, "No method provided. Run `bitcoin-wallet -help` for valid methods.\n"); return EXIT_FAILURE; } // A name must be provided when creating a file if (method == "create" && !gArgs.IsArgSet("-wallet")) { - fprintf(stderr, "Wallet name must be provided when creating a new wallet.\n"); + tfm::format(std::cerr, "Wallet name must be provided when creating a new wallet.\n"); return EXIT_FAILURE; } diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 094820293e..ba6de702e0 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -70,7 +70,7 @@ static bool AppInit(int argc, char* argv[]) SetupServerArgs(); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str()); + tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str()); return false; } @@ -88,7 +88,7 @@ static bool AppInit(int argc, char* argv[]) strUsage += "\n" + gArgs.GetHelpMessage(); } - fprintf(stdout, "%s", strUsage.c_str()); + tfm::format(std::cout, "%s", strUsage.c_str()); return true; } @@ -96,25 +96,25 @@ static bool AppInit(int argc, char* argv[]) { if (!fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); + tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return false; } if (!gArgs.ReadConfigFiles(error, true)) { - fprintf(stderr, "Error reading configuration file: %s\n", error.c_str()); + tfm::format(std::cerr, "Error reading configuration file: %s\n", error.c_str()); return false; } // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) try { SelectParams(gArgs.GetChainName()); } catch (const std::exception& e) { - fprintf(stderr, "Error: %s\n", e.what()); + tfm::format(std::cerr, "Error: %s\n", e.what()); return false; } // Error out when loose non-argument tokens are encountered on command line for (int i = 1; i < argc; i++) { if (!IsSwitchChar(argv[i][0])) { - fprintf(stderr, "Error: Command line contains unexpected token '%s', see bitcoind -h for a list of options.\n", argv[i]); + tfm::format(std::cerr, "Error: Command line contains unexpected token '%s', see bitcoind -h for a list of options.\n", argv[i]); return false; } } @@ -146,18 +146,18 @@ static bool AppInit(int argc, char* argv[]) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif - fprintf(stdout, "Bitcoin server starting\n"); + tfm::format(std::cout, "Bitcoin server starting\n"); // Daemonize if (daemon(1, 0)) { // don't chdir (1), do close FDs (0) - fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno)); + tfm::format(std::cerr, "Error: daemon() failed: %s\n", strerror(errno)); return false; } #if defined(MAC_OSX) #pragma GCC diagnostic pop #endif #else - fprintf(stderr, "Error: -daemon is not supported on this operating system\n"); + tfm::format(std::cerr, "Error: -daemon is not supported on this operating system\n"); return false; #endif // HAVE_DECL_DAEMON } diff --git a/src/init.cpp b/src/init.cpp index 6912b49717..93aa6f21b5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -108,14 +108,13 @@ static fs::path GetPidFile() NODISCARD static bool CreatePidFile() { - FILE* file = fsbridge::fopen(GetPidFile(), "w"); + fsbridge::ofstream file{GetPidFile()}; if (file) { #ifdef WIN32 - fprintf(file, "%d\n", GetCurrentProcessId()); + tfm::format(file, "%d\n", GetCurrentProcessId()); #else - fprintf(file, "%d\n", getpid()); + tfm::format(file, "%d\n", getpid()); #endif - fclose(file); return true; } else { return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno))); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 0d9e314afd..e57706980a 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -68,11 +68,13 @@ static constexpr int32_t MAX_PEER_TX_IN_FLIGHT = 100; /** Maximum number of announced transactions from a peer */ static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS = 2 * MAX_INV_SZ; /** How many microseconds to delay requesting transactions from inbound peers */ -static constexpr int64_t INBOUND_PEER_TX_DELAY = 2 * 1000000; +static constexpr int64_t INBOUND_PEER_TX_DELAY = 2 * 1000000; // 2 seconds /** How long to wait (in microseconds) before downloading a transaction from an additional peer */ -static constexpr int64_t GETDATA_TX_INTERVAL = 60 * 1000000; +static constexpr int64_t GETDATA_TX_INTERVAL = 60 * 1000000; // 1 minute /** Maximum delay (in microseconds) for transaction requests to avoid biasing some peers over others. */ -static constexpr int64_t MAX_GETDATA_RANDOM_DELAY = 2 * 1000000; +static constexpr int64_t MAX_GETDATA_RANDOM_DELAY = 2 * 1000000; // 2 seconds +/** How long to wait (in microseconds) before expiring an in-flight getdata request to a peer */ +static constexpr int64_t TX_EXPIRY_INTERVAL = 10 * GETDATA_TX_INTERVAL; static_assert(INBOUND_PEER_TX_DELAY >= MAX_GETDATA_RANDOM_DELAY, "To preserve security, MAX_GETDATA_RANDOM_DELAY should not exceed INBOUND_PEER_DELAY"); /** Limit to avoid sending big packets. Not used in processing incoming GETDATA for compatibility */ @@ -343,8 +345,11 @@ struct CNodeState { //! Store all the transactions a peer has recently announced std::set<uint256> m_tx_announced; - //! Store transactions which were requested by us - std::set<uint256> m_tx_in_flight; + //! Store transactions which were requested by us, with timestamp + std::map<uint256, int64_t> m_tx_in_flight; + + //! Periodically check for stuck getdata requests + int64_t m_check_expiry_timer{0}; }; TxDownloadState m_tx_download; @@ -702,30 +707,40 @@ void UpdateTxRequestTime(const uint256& txid, int64_t request_time) EXCLUSIVE_LO } } - -void RequestTx(CNodeState* state, const uint256& txid, int64_t nNow) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +int64_t CalculateTxGetDataTime(const uint256& txid, int64_t current_time, bool use_inbound_delay) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - CNodeState::TxDownloadState& peer_download_state = state->m_tx_download; - if (peer_download_state.m_tx_announced.size() >= MAX_PEER_TX_ANNOUNCEMENTS || peer_download_state.m_tx_announced.count(txid)) { - // Too many queued announcements from this peer, or we already have - // this announcement - return; - } - peer_download_state.m_tx_announced.insert(txid); - int64_t process_time; int64_t last_request_time = GetTxRequestTime(txid); // First time requesting this tx if (last_request_time == 0) { - process_time = nNow; + process_time = current_time; } else { // Randomize the delay to avoid biasing some peers over others (such as due to // fixed ordering of peer processing in ThreadMessageHandler) process_time = last_request_time + GETDATA_TX_INTERVAL + GetRand(MAX_GETDATA_RANDOM_DELAY); } - // We delay processing announcements from non-preferred (eg inbound) peers - if (!state->fPreferredDownload) process_time += INBOUND_PEER_TX_DELAY; + // We delay processing announcements from inbound peers + if (use_inbound_delay) process_time += INBOUND_PEER_TX_DELAY; + + return process_time; +} + +void RequestTx(CNodeState* state, const uint256& txid, int64_t nNow) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +{ + CNodeState::TxDownloadState& peer_download_state = state->m_tx_download; + if (peer_download_state.m_tx_announced.size() >= MAX_PEER_TX_ANNOUNCEMENTS || + peer_download_state.m_tx_process_time.size() >= MAX_PEER_TX_ANNOUNCEMENTS || + peer_download_state.m_tx_announced.count(txid)) { + // Too many queued announcements from this peer, or we already have + // this announcement + return; + } + peer_download_state.m_tx_announced.insert(txid); + + // Calculate the time to try requesting this transaction. Use + // fPreferredDownload as a proxy for outbound peers. + int64_t process_time = CalculateTxGetDataTime(txid, nNow, !state->fPreferredDownload); peer_download_state.m_tx_process_time.emplace(process_time, txid); } @@ -1544,12 +1559,19 @@ void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnm if (!vNotFound.empty()) { // Let the peer know that we didn't find what it asked for, so it doesn't - // have to wait around forever. Currently only SPV clients actually care - // about this message: it's needed when they are recursively walking the - // dependencies of relevant unconfirmed transactions. SPV clients want to - // do that because they want to know about (and store and rebroadcast and - // risk analyze) the dependencies of transactions relevant to them, without - // having to download the entire memory pool. + // have to wait around forever. + // SPV clients care about this message: it's needed when they are + // recursively walking the dependencies of relevant unconfirmed + // transactions. SPV clients want to do that because they want to know + // about (and store and rebroadcast and risk analyze) the dependencies + // of transactions relevant to them, without having to download the + // entire memory pool. + // Also, other nodes can use these messages to automatically request a + // transaction from some other peer that annnounced it, and stop + // waiting for us to respond. + // In normal operation, we often send NOTFOUND messages for parents of + // transactions that we relay; if a peer is missing a parent, they may + // assume we have them and request the parents from us. connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::NOTFOUND, vNotFound)); } } @@ -3146,8 +3168,27 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } if (strCommand == NetMsgType::NOTFOUND) { - // We do not care about the NOTFOUND message, but logging an Unknown Command - // message would be undesirable as we transmit it ourselves. + // Remove the NOTFOUND transactions from the peer + LOCK(cs_main); + CNodeState *state = State(pfrom->GetId()); + std::vector<CInv> vInv; + vRecv >> vInv; + if (vInv.size() <= MAX_PEER_TX_IN_FLIGHT + MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + for (CInv &inv : vInv) { + if (inv.type == MSG_TX || inv.type == MSG_WITNESS_TX) { + // If we receive a NOTFOUND message for a txid we requested, erase + // it from our data structures for this peer. + auto in_flight_it = state->m_tx_download.m_tx_in_flight.find(inv.hash); + if (in_flight_it == state->m_tx_download.m_tx_in_flight.end()) { + // Skip any further work if this is a spurious NOTFOUND + // message. + continue; + } + state->m_tx_download.m_tx_in_flight.erase(in_flight_it); + state->m_tx_download.m_tx_announced.erase(inv.hash); + } + } + } return true; } @@ -3945,9 +3986,33 @@ bool PeerLogicValidation::SendMessages(CNode* pto) // // Message: getdata (non-blocks) // + + // For robustness, expire old requests after a long timeout, so that + // we can resume downloading transactions from a peer even if they + // were unresponsive in the past. + // Eventually we should consider disconnecting peers, but this is + // conservative. + if (state.m_tx_download.m_check_expiry_timer <= nNow) { + for (auto it=state.m_tx_download.m_tx_in_flight.begin(); it != state.m_tx_download.m_tx_in_flight.end();) { + if (it->second <= nNow - TX_EXPIRY_INTERVAL) { + LogPrint(BCLog::NET, "timeout of inflight tx %s from peer=%d\n", it->first.ToString(), pto->GetId()); + state.m_tx_download.m_tx_announced.erase(it->first); + state.m_tx_download.m_tx_in_flight.erase(it++); + } else { + ++it; + } + } + // On average, we do this check every TX_EXPIRY_INTERVAL. Randomize + // so that we're not doing this for all peers at the same time. + state.m_tx_download.m_check_expiry_timer = nNow + TX_EXPIRY_INTERVAL/2 + GetRand(TX_EXPIRY_INTERVAL); + } + auto& tx_process_time = state.m_tx_download.m_tx_process_time; while (!tx_process_time.empty() && tx_process_time.begin()->first <= nNow && state.m_tx_download.m_tx_in_flight.size() < MAX_PEER_TX_IN_FLIGHT) { - const uint256& txid = tx_process_time.begin()->second; + const uint256 txid = tx_process_time.begin()->second; + // Erase this entry from tx_process_time (it may be added back for + // processing at a later time, see below) + tx_process_time.erase(tx_process_time.begin()); CInv inv(MSG_TX | GetFetchFlags(pto), txid); if (!AlreadyHave(inv)) { // If this transaction was last requested more than 1 minute ago, @@ -3961,20 +4026,20 @@ bool PeerLogicValidation::SendMessages(CNode* pto) vGetData.clear(); } UpdateTxRequestTime(inv.hash, nNow); - state.m_tx_download.m_tx_in_flight.insert(inv.hash); + state.m_tx_download.m_tx_in_flight.emplace(inv.hash, nNow); } else { // This transaction is in flight from someone else; queue // up processing to happen after the download times out // (with a slight delay for inbound peers, to prefer // requests to outbound peers). - RequestTx(&state, txid, nNow); + int64_t next_process_time = CalculateTxGetDataTime(txid, nNow, !state.fPreferredDownload); + tx_process_time.emplace(next_process_time, txid); } } else { // We have already seen this transaction, no need to download. state.m_tx_download.m_tx_announced.erase(inv.hash); state.m_tx_download.m_tx_in_flight.erase(inv.hash); } - tx_process_time.erase(tx_process_time.begin()); } diff --git a/src/netaddress.cpp b/src/netaddress.cpp index db6c46d12a..4fbfa2b5c8 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -239,7 +239,7 @@ bool CNetAddr::IsLocal() const * be used to refer to an actual host. * * @note A valid address may or may not be publicly routable on the global - * internet. As in, the set of valid addreses is a superset of the set of + * internet. As in, the set of valid addresses is a superset of the set of * publicly routable addresses. * * @see CNetAddr::IsRoutable() @@ -287,7 +287,7 @@ bool CNetAddr::IsValid() const * @returns Whether or not this network address is publicly routable on the * global internet. * - * @note A routable address is always valid. As in, the set of routable addreses + * @note A routable address is always valid. As in, the set of routable addresses * is a subset of the set of valid addresses. * * @see CNetAddr::IsValid() diff --git a/src/noui.cpp b/src/noui.cpp index c7d8fee0ba..0c18b0e231 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -37,7 +37,7 @@ bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& ca if (!fSecure) LogPrintf("%s: %s\n", strCaption, message); - fprintf(stderr, "%s: %s\n", strCaption.c_str(), message.c_str()); + tfm::format(std::cerr, "%s: %s\n", strCaption.c_str(), message.c_str()); return false; } diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 7e93a746ca..5d538606c2 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -47,7 +47,7 @@ private: std::vector<double> txCtAvg; // Count the total # of txs confirmed within Y blocks in each bucket - // Track the historical moving average of theses totals over blocks + // Track the historical moving average of these totals over blocks std::vector<std::vector<double>> confAvg; // confAvg[Y][X] // Track moving avg of txs which have been evicted from the mempool diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b5c92e10a2..1444dddeb1 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -335,7 +335,7 @@ void BitcoinGUI::createActions() openAction->setStatusTip(tr("Open a bitcoin: URI or payment request")); m_open_wallet_action = new QAction(tr("Open Wallet"), this); - m_open_wallet_action->setMenu(new QMenu(this)); + m_open_wallet_action->setEnabled(false); m_open_wallet_action->setStatusTip(tr("Open a wallet")); m_close_wallet_action = new QAction(tr("Close Wallet..."), this); @@ -633,6 +633,9 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller) m_wallet_controller = wallet_controller; + m_open_wallet_action->setEnabled(true); + m_open_wallet_action->setMenu(new QMenu(this)); + connect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet); connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 3a4eebd94a..aa810690c9 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -124,7 +124,7 @@ HelpMessageDialog::~HelpMessageDialog() void HelpMessageDialog::printToConsole() { // On other operating systems, the expected action is to print the message to the console. - fprintf(stdout, "%s\n", qPrintable(text)); + tfm::format(std::cout, "%s\n", qPrintable(text)); } void HelpMessageDialog::showOrPrint() diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 49d7ae2016..50c4589d9f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1061,7 +1061,12 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) } PruneBlockFilesManual(height); - return uint64_t(height); + const CBlockIndex* block = ::ChainActive().Tip(); + assert(block); + while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) { + block = block->pprev; + } + return uint64_t(block->nHeight); } static UniValue gettxoutsetinfo(const JSONRPCRequest& request) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index df6e9f029d..196ca0f17b 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -39,7 +39,7 @@ /** High fee for sendrawtransaction and testmempoolaccept. * By default, transaction with a fee higher than this will be rejected by the - * RPCs. This can be overriden with the maxfeerate argument. + * RPCs. This can be overridden with the maxfeerate argument. */ constexpr static CAmount DEFAULT_MAX_RAW_TX_FEE{COIN / 10}; diff --git a/src/sync.cpp b/src/sync.cpp index c2767b200a..20258d8e9a 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -57,7 +57,7 @@ struct CLockLocation { std::string ToString() const { - return tfm::format( + return strprintf( "%s %s:%s%s (in thread %s)", mutexName, sourceFile, itostr(sourceLine), (fTry ? " (TRY)" : ""), m_thread_name); } @@ -118,7 +118,7 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, LogPrintf(" %s\n", i.second.ToString()); } if (g_debug_lockorder_abort) { - fprintf(stderr, "Assertion failed: detected inconsistent lock order at %s:%i, details in debug log.\n", __FILE__, __LINE__); + tfm::format(std::cerr, "Assertion failed: detected inconsistent lock order at %s:%i, details in debug log.\n", __FILE__, __LINE__); abort(); } throw std::logic_error("potential deadlock detected"); @@ -175,7 +175,7 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, for (const std::pair<void*, CLockLocation>& i : g_lockstack) if (i.first == cs) return; - fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); + tfm::format(std::cerr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); abort(); } @@ -183,7 +183,7 @@ void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLi { for (const std::pair<void*, CLockLocation>& i : g_lockstack) { if (i.first == cs) { - fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); + tfm::format(std::cerr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); abort(); } } diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 35911e507f..4e2acca4c3 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -567,7 +567,7 @@ BOOST_AUTO_TEST_CASE(poly1305_testvector) BOOST_AUTO_TEST_CASE(hkdf_hmac_sha256_l32_tests) { - // Use rfc5869 test vectors but trucated to 32 bytes (our implementation only support length 32) + // Use rfc5869 test vectors but truncated to 32 bytes (our implementation only support length 32) TestHKDF_SHA256_32( /* IKM */ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", /* salt */ "000102030405060708090a0b0c", diff --git a/src/tinyformat.h b/src/tinyformat.h index 14b7cd3026..182f518a0b 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -1063,6 +1063,7 @@ std::string format(const std::string &fmt, const Args&... args) } // namespace tinyformat +/** Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for details) */ #define strprintf tfm::format #endif // TINYFORMAT_H_INCLUDED diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 550e23b222..84f54da515 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -412,7 +412,7 @@ public: TorController(struct event_base* base, const std::string& target); ~TorController(); - /** Get name fo file to store private key in */ + /** Get name of file to store private key in */ fs::path GetPrivateKeyFile(); /** Reconnect, after getting disconnected */ diff --git a/src/util/system.cpp b/src/util/system.cpp index 6a6b82c967..fca29a9f31 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -673,7 +673,7 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); LogPrintf("\n\n************************\n%s\n", message); - fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); + tfm::format(std::cerr, "\n\n************************\n%s\n", message.c_str()); } fs::path GetDefaultDataDir() @@ -933,7 +933,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) } } for (const std::string& to_include : includeconf) { - fprintf(stderr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include.c_str()); + tfm::format(std::cerr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include.c_str()); } } } diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index 440c32c367..0843194511 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -22,7 +22,7 @@ static void WalletToolReleaseWallet(CWallet* wallet) static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs::path& path) { if (fs::exists(path)) { - fprintf(stderr, "Error: File exists already\n"); + tfm::format(std::cerr, "Error: File exists already\n"); return nullptr; } // dummy chain interface @@ -30,7 +30,7 @@ static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs:: bool first_run = true; DBErrors load_wallet_ret = wallet_instance->LoadWallet(first_run); if (load_wallet_ret != DBErrors::LOAD_OK) { - fprintf(stderr, "Error creating %s", name.c_str()); + tfm::format(std::cerr, "Error creating %s", name.c_str()); return nullptr; } @@ -40,7 +40,7 @@ static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs:: CPubKey seed = wallet_instance->GenerateNewSeed(); wallet_instance->SetHDSeed(seed); - fprintf(stdout, "Topping up keypool...\n"); + tfm::format(std::cout, "Topping up keypool...\n"); wallet_instance->TopUpKeyPool(); return wallet_instance; } @@ -48,7 +48,7 @@ static std::shared_ptr<CWallet> CreateWallet(const std::string& name, const fs:: static std::shared_ptr<CWallet> LoadWallet(const std::string& name, const fs::path& path) { if (!fs::exists(path)) { - fprintf(stderr, "Error: Wallet files does not exist\n"); + tfm::format(std::cerr, "Error: Wallet files does not exist\n"); return nullptr; } @@ -59,28 +59,28 @@ static std::shared_ptr<CWallet> LoadWallet(const std::string& name, const fs::pa bool first_run; load_wallet_ret = wallet_instance->LoadWallet(first_run); } catch (const std::runtime_error&) { - fprintf(stderr, "Error loading %s. Is wallet being used by another process?\n", name.c_str()); + tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name.c_str()); return nullptr; } if (load_wallet_ret != DBErrors::LOAD_OK) { wallet_instance = nullptr; if (load_wallet_ret == DBErrors::CORRUPT) { - fprintf(stderr, "Error loading %s: Wallet corrupted", name.c_str()); + tfm::format(std::cerr, "Error loading %s: Wallet corrupted", name.c_str()); return nullptr; } else if (load_wallet_ret == DBErrors::NONCRITICAL_ERROR) { - fprintf(stderr, "Error reading %s! All keys read correctly, but transaction data" + tfm::format(std::cerr, "Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect.", name.c_str()); } else if (load_wallet_ret == DBErrors::TOO_NEW) { - fprintf(stderr, "Error loading %s: Wallet requires newer version of %s", + tfm::format(std::cerr, "Error loading %s: Wallet requires newer version of %s", name.c_str(), PACKAGE_NAME); return nullptr; } else if (load_wallet_ret == DBErrors::NEED_REWRITE) { - fprintf(stderr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME); + tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME); return nullptr; } else { - fprintf(stderr, "Error loading %s", name.c_str()); + tfm::format(std::cerr, "Error loading %s", name.c_str()); return nullptr; } } @@ -92,12 +92,12 @@ static void WalletShowInfo(CWallet* wallet_instance) { LOCK(wallet_instance->cs_wallet); - fprintf(stdout, "Wallet info\n===========\n"); - fprintf(stdout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no"); - fprintf(stdout, "HD (hd seed available): %s\n", wallet_instance->GetHDChain().seed_id.IsNull() ? "no" : "yes"); - fprintf(stdout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize()); - fprintf(stdout, "Transactions: %zu\n", wallet_instance->mapWallet.size()); - fprintf(stdout, "Address Book: %zu\n", wallet_instance->mapAddressBook.size()); + tfm::format(std::cout, "Wallet info\n===========\n"); + tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no"); + tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->GetHDChain().seed_id.IsNull() ? "no" : "yes"); + tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize()); + tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size()); + tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->mapAddressBook.size()); } bool ExecuteWalletToolFunc(const std::string& command, const std::string& name) @@ -112,12 +112,12 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name) } } else if (command == "info") { if (!fs::exists(path)) { - fprintf(stderr, "Error: no wallet file at %s\n", name.c_str()); + tfm::format(std::cerr, "Error: no wallet file at %s\n", name.c_str()); return false; } std::string error; if (!WalletBatch::VerifyEnvironment(path, error)) { - fprintf(stderr, "Error loading %s. Is wallet being used by other process?\n", name.c_str()); + tfm::format(std::cerr, "Error loading %s. Is wallet being used by other process?\n", name.c_str()); return false; } std::shared_ptr<CWallet> wallet_instance = LoadWallet(name, path); @@ -125,7 +125,7 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name) WalletShowInfo(wallet_instance.get()); wallet_instance->Flush(true); } else { - fprintf(stderr, "Invalid command: %s\n", command.c_str()); + tfm::format(std::cerr, "Invalid command: %s\n", command.c_str()); return false; } |