Merge pull request #4414 from PastaPastaPasta/backport-trivial-pr17

Backport trivial pr17
This commit is contained in:
UdjinM6 2021-09-15 23:50:59 +03:00 committed by GitHub
commit 9005b1a307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 189 additions and 81 deletions

View File

@ -242,8 +242,11 @@ class BlockDataCopier:
inMagic = inhdr[:4] inMagic = inhdr[:4]
if (inMagic != self.settings['netmagic']): if (inMagic != self.settings['netmagic']):
print("Invalid magic: " + inMagic.hex()) # Seek backwards 7 bytes (skipping the first byte in the previous search)
return # and continue searching from the new position if the magic bytes are not
# found.
self.inF.seek(-7, os.SEEK_CUR)
continue
inLenLE = inhdr[4:] inLenLE = inhdr[4:]
su = struct.unpack("<I", inLenLE) su = struct.unpack("<I", inLenLE)
inLen = su[0] - 80 # length without header inLen = su[0] - 80 # length without header

View File

@ -638,6 +638,28 @@ Strings and formatting
- *Rationale*: Dash Core uses tinyformat, which is type safe. Leave them out to avoid confusion - *Rationale*: Dash Core uses tinyformat, which is type safe. Leave them out to avoid confusion
- Use `.c_str()` sparingly. Its only valid use is to pass C++ strings to C functions that take NULL-terminated
strings.
- Do not use it when passing a sized array (so along with `.size()`). Use `.data()` instead to get a pointer
to the raw data.
- *Rationale*: Although this is guaranteed to be safe starting with C++11, `.data()` communicates the intent better.
- Do not use it when passing strings to `tfm::format`, `strprintf`, `LogPrint[f]`.
- *Rationale*: This is redundant. Tinyformat handles strings.
- Do not use it to convert to `QString`. Use `QString::fromStdString()`.
- *Rationale*: Qt has build-in functionality for converting their string
type from/to C++. No need to roll your own.
- In cases where do you call `.c_str()`, you might want to additionally check that the string does not contain embedded '\0' characters, because
it will (necessarily) truncate the string. This might be used to hide parts of the string from logging or to circumvent
checks. If a use of strings is sensitive to this, take care to check the string for embedded NULL characters first
and reject it if there are any (see `ParsePrechecks` in `strencodings.cpp` for an example).
Shadowing Shadowing
-------------- --------------

View File

@ -0,0 +1,5 @@
Command-line options
--------------------
- The `-debug=db` logging category has been renamed to `-debug=walletdb`, to distinguish it from `coindb`.
`-debug=db` has been deprecated and will be removed in the next major release.

View File

@ -78,7 +78,15 @@ void BCLog::Logger::EnableCategory(BCLog::LogFlags flag)
bool BCLog::Logger::EnableCategory(const std::string& str) bool BCLog::Logger::EnableCategory(const std::string& str)
{ {
BCLog::LogFlags flag; BCLog::LogFlags flag;
if (!GetLogCategory(flag, str)) return false; if (!GetLogCategory(flag, str)) {
if (str == "db") {
// DEPRECATION: Added in 0.20, should start returning an error in 0.21
LogPrintf("Warning: logging category 'db' is deprecated, use 'walletdb' instead\n");
EnableCategory(BCLog::WALLETDB);
return true;
}
return false;
}
EnableCategory(flag); EnableCategory(flag);
return true; return true;
} }
@ -122,7 +130,7 @@ const CLogCategoryDesc LogCategories[] =
{BCLog::HTTP, "http"}, {BCLog::HTTP, "http"},
{BCLog::BENCHMARK, "bench"}, {BCLog::BENCHMARK, "bench"},
{BCLog::ZMQ, "zmq"}, {BCLog::ZMQ, "zmq"},
{BCLog::DB, "db"}, {BCLog::WALLETDB, "walletdb"},
{BCLog::RPC, "rpc"}, {BCLog::RPC, "rpc"},
{BCLog::ESTIMATEFEE, "estimatefee"}, {BCLog::ESTIMATEFEE, "estimatefee"},
{BCLog::ADDRMAN, "addrman"}, {BCLog::ADDRMAN, "addrman"},

View File

@ -41,7 +41,7 @@ namespace BCLog {
HTTP = (1 << 3), HTTP = (1 << 3),
BENCHMARK = (1 << 4), BENCHMARK = (1 << 4),
ZMQ = (1 << 5), ZMQ = (1 << 5),
DB = (1 << 6), WALLETDB = (1 << 6),
RPC = (1 << 7), RPC = (1 << 7),
ESTIMATEFEE = (1 << 8), ESTIMATEFEE = (1 << 8),
ADDRMAN = (1 << 9), ADDRMAN = (1 << 9),
@ -194,12 +194,13 @@ static inline void LogPrintf(const char* fmt, const Args&... args)
} }
} }
template <typename... Args> // Use a macro instead of a function for conditional logging to prevent
static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args) // evaluating arguments when logging for the category is not enabled.
{ #define LogPrint(category, ...) \
if (LogAcceptCategory((category))) { do { \
LogPrintf(args...); if (LogAcceptCategory((category))) { \
} LogPrintf(__VA_ARGS__); \
} } \
} while (0)
#endif // BITCOIN_LOGGING_H #endif // BITCOIN_LOGGING_H

View File

@ -540,24 +540,16 @@ void BitcoinGUI::createMenuBar()
connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) { connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) {
zoom_action->setEnabled(window != nullptr); zoom_action->setEnabled(window != nullptr);
}); });
#else
QAction* restore_action = window_menu->addAction(tr("Restore"));
connect(restore_action, &QAction::triggered, [] {
qApp->focusWindow()->showNormal();
});
connect(qApp, &QApplication::focusWindowChanged, [restore_action] (QWindow* window) {
restore_action->setEnabled(window != nullptr);
});
#endif #endif
if (walletFrame) { if (walletFrame) {
#ifdef Q_OS_MAC
window_menu->addSeparator(); window_menu->addSeparator();
QAction* main_window_action = window_menu->addAction(tr("Main Window")); QAction* main_window_action = window_menu->addAction(tr("Main Window"));
connect(main_window_action, &QAction::triggered, [this] { connect(main_window_action, &QAction::triggered, [this] {
GUIUtil::bringToFront(this); GUIUtil::bringToFront(this);
}); });
#endif
window_menu->addSeparator(); window_menu->addSeparator();
window_menu->addAction(usedSendingAddressesAction); window_menu->addAction(usedSendingAddressesAction);
window_menu->addAction(usedReceivingAddressesAction); window_menu->addAction(usedReceivingAddressesAction);

View File

@ -42,8 +42,8 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QSslCertificate> #include <QSslCertificate>
#include <QSslConfiguration>
#include <QSslError> #include <QSslError>
#include <QSslSocket>
#include <QStringList> #include <QStringList>
#include <QTextDocument> #include <QTextDocument>
#include <QUrlQuery> #include <QUrlQuery>
@ -453,9 +453,9 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
certList = QSslCertificate::fromPath(certFile); certList = QSslCertificate::fromPath(certFile);
// Use those certificates when fetching payment requests, too: // Use those certificates when fetching payment requests, too:
QSslSocket::setDefaultCaCertificates(certList); QSslConfiguration::defaultConfiguration().setCaCertificates(certList);
} else } else
certList = QSslSocket::systemCaCertificates(); certList = QSslConfiguration::systemCaCertificates();
int nRootCerts = 0; int nRootCerts = 0;
const QDateTime currentTime = QDateTime::currentDateTime(); const QDateTime currentTime = QDateTime::currentDateTime();

View File

@ -71,11 +71,6 @@ void WalletFrame::addWallet(WalletModel *walletModel)
walletStack->addWidget(walletView); walletStack->addWidget(walletView);
mapWalletViews[walletModel] = walletView; mapWalletViews[walletModel] = walletView;
// Ensure a walletView is able to show the main window
connect(walletView, &WalletView::showNormalIfMinimized, [this]{
gui->showNormalIfMinimized();
});
connect(walletView, &WalletView::outOfSyncWarningClicked, this, &WalletFrame::outOfSyncWarningClicked); connect(walletView, &WalletView::outOfSyncWarningClicked, this, &WalletFrame::outOfSyncWarningClicked);
} }

View File

@ -127,8 +127,6 @@ public Q_SLOTS:
/** Update selected DASH amount from transactionview */ /** Update selected DASH amount from transactionview */
void trxAmount(QString amount); void trxAmount(QString amount);
Q_SIGNALS: Q_SIGNALS:
/** Signal that we want to show the main window */
void showNormalIfMinimized();
/** Fired when a message should be reported to the user */ /** Fired when a message should be reported to the user */
void message(const QString &title, const QString &message, unsigned int style); void message(const QString &title, const QString &message, unsigned int style);
/** Encryption status of wallet changed */ /** Encryption status of wallet changed */

View File

@ -6,14 +6,11 @@
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
#include <shutdown.h> #include <shutdown.h>
#include <util/system.h>
#include <windows.h> #include <windows.h>
#include <QDebug> #include <QDebug>
#include <openssl/rand.h>
// If we don't want a message to be processed by Qt, return true and set result to // If we don't want a message to be processed by Qt, return true and set result to
// the value that the window procedure should return. Otherwise return false. // the value that the window procedure should return. Otherwise return false.
bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
@ -22,16 +19,6 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM
MSG *pMsg = static_cast<MSG *>(pMessage); MSG *pMsg = static_cast<MSG *>(pMessage);
// Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions)
if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
// Warn only once as this is performance-critical
static bool warned = false;
if (!warned) {
LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
warned = true;
}
}
switch(pMsg->message) switch(pMsg->message)
{ {
case WM_QUERYENDSESSION: case WM_QUERYENDSESSION:

View File

@ -146,6 +146,34 @@ static bool GetHardwareRand(unsigned char* ent32) noexcept {
return false; return false;
} }
/** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */
static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
{
CSHA512 inner_hasher;
inner_hasher.Write(seed, sizeof(seed));
// Hash loop
unsigned char buffer[64];
int64_t stop = GetTimeMicros() + microseconds;
do {
for (int i = 0; i < 1000; ++i) {
inner_hasher.Finalize(buffer);
inner_hasher.Reset();
inner_hasher.Write(buffer, sizeof(buffer));
}
// Benchmark operation and feed it into outer hasher.
int64_t perf = GetPerformanceCounter();
hasher.Write((const unsigned char*)&perf, sizeof(perf));
} while (GetTimeMicros() < stop);
// Produce output from inner state and feed it to outer hasher.
inner_hasher.Finalize(buffer);
hasher.Write(buffer, sizeof(buffer));
// Try to clean up.
inner_hasher.Reset();
memory_cleanse(buffer, sizeof(buffer));
}
static void RandAddSeedPerfmon(CSHA512& hasher) static void RandAddSeedPerfmon(CSHA512& hasher)
{ {
#ifdef WIN32 #ifdef WIN32
@ -432,7 +460,23 @@ static void SeedSlow(CSHA512& hasher) noexcept
SeedTimestamp(hasher); SeedTimestamp(hasher);
} }
static void SeedSleep(CSHA512& hasher) /** Extract entropy from rng, strengthen it, and feed it into hasher. */
static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept
{
static std::atomic<int64_t> last_strengthen{0};
int64_t last_time = last_strengthen.load();
int64_t current_time = GetTimeMicros();
if (current_time > last_time + 60000000) { // Only run once a minute
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
unsigned char strengthen_seed[32];
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
// Strengthen it for 10ms (100ms on first run), and feed it into hasher.
Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher);
last_strengthen = current_time;
}
}
static void SeedSleep(CSHA512& hasher, RNGState& rng)
{ {
// Everything that the 'fast' seeder includes // Everything that the 'fast' seeder includes
SeedFast(hasher); SeedFast(hasher);
@ -448,9 +492,12 @@ static void SeedSleep(CSHA512& hasher)
// Windows performance monitor data (once every 10 minutes) // Windows performance monitor data (once every 10 minutes)
RandAddSeedPerfmon(hasher); RandAddSeedPerfmon(hasher);
// Strengthen every minute
SeedStrengthen(hasher, rng);
} }
static void SeedStartup(CSHA512& hasher) noexcept static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
{ {
#ifdef WIN32 #ifdef WIN32
RAND_screen(); RAND_screen();
@ -461,6 +508,9 @@ static void SeedStartup(CSHA512& hasher) noexcept
// Windows performance monitor data. // Windows performance monitor data.
RandAddSeedPerfmon(hasher); RandAddSeedPerfmon(hasher);
// Strengthen
SeedStrengthen(hasher, rng);
} }
enum class RNGLevel { enum class RNGLevel {
@ -485,7 +535,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
SeedSlow(hasher); SeedSlow(hasher);
break; break;
case RNGLevel::SLEEP: case RNGLevel::SLEEP:
SeedSleep(hasher); SeedSleep(hasher, rng);
break; break;
} }
@ -493,7 +543,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
if (!rng.MixExtract(out, num, std::move(hasher), false)) { if (!rng.MixExtract(out, num, std::move(hasher), false)) {
// On the first invocation, also seed with SeedStartup(). // On the first invocation, also seed with SeedStartup().
CSHA512 startup_hasher; CSHA512 startup_hasher;
SeedStartup(startup_hasher); SeedStartup(startup_hasher, rng);
rng.MixExtract(out, num, std::move(startup_hasher), true); rng.MixExtract(out, num, std::move(startup_hasher), true);
} }

View File

@ -44,6 +44,7 @@
* - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally: * - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
* - A high-precision timestamp before and after sleeping 1ms. * - A high-precision timestamp before and after sleeping 1ms.
* - (On Windows) Once every 10 minutes, performance monitoring data from the OS. * - (On Windows) Once every 10 minutes, performance monitoring data from the OS.
- - Once every minute, strengthen the entropy for 10 ms using repeated SHA512.
* These just exploit the fact the system is idle to improve the quality of the RNG * These just exploit the fact the system is idle to improve the quality of the RNG
* slightly. * slightly.
* *
@ -51,6 +52,7 @@
* sources used in the 'slow' seeder are included, but also: * sources used in the 'slow' seeder are included, but also:
* - (On Windows) Performance monitoring data from the OS. * - (On Windows) Performance monitoring data from the OS.
* - (On Windows) Through OpenSSL, the screen contents. * - (On Windows) Through OpenSSL, the screen contents.
* - Strengthen the entropy for 100 ms using repeated SHA512.
* *
* When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
* (up to) the first 32 bytes of H are produced as output, while the last 32 bytes * (up to) the first 32 bytes of H are produced as output, while the last 32 bytes

View File

@ -198,6 +198,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
return sigdata.complete; return sigdata.complete;
} }
namespace {
class SignatureExtractorChecker final : public BaseSignatureChecker class SignatureExtractorChecker final : public BaseSignatureChecker
{ {
private: private:
@ -206,21 +207,17 @@ private:
public: public:
SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : sigdata(sigdata), checker(checker) {} SignatureExtractorChecker(SignatureData& sigdata, BaseSignatureChecker& checker) : sigdata(sigdata), checker(checker) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override; bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
{
if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) {
CPubKey pubkey(vchPubKey);
sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));
return true;
}
return false;
}
}; };
bool SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) {
CPubKey pubkey(vchPubKey);
sigdata.signatures.emplace(pubkey.GetID(), SigPair(pubkey, scriptSig));
return true;
}
return false;
}
namespace
{
struct Stacks struct Stacks
{ {
std::vector<valtype> script; std::vector<valtype> script;

View File

@ -746,6 +746,43 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants); pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, 9ULL); BOOST_CHECK_EQUAL(ancestors, 9ULL);
BOOST_CHECK_EQUAL(descendants, 6ULL); BOOST_CHECK_EQUAL(descendants, 6ULL);
/* Ancestors represented more than once ("diamond") */
//
// [ta].0 <- [tb].0 -----<------- [td].0
// | |
// \---1 <- [tc].0 --<--/
//
CTransactionRef ta, tb, tc, td;
ta = make_tx(/* output_values */ {10 * COIN});
tb = make_tx(/* output_values */ {5 * COIN, 3 * COIN}, /* inputs */ {ta});
tc = make_tx(/* output_values */ {2 * COIN}, /* inputs */ {tb}, /* input_indices */ {1});
td = make_tx(/* output_values */ {6 * COIN}, /* inputs */ {tb, tc}, /* input_indices */ {0, 0});
pool.clear();
pool.addUnchecked(entry.Fee(10000LL).FromTx(ta));
pool.addUnchecked(entry.Fee(10000LL).FromTx(tb));
pool.addUnchecked(entry.Fee(10000LL).FromTx(tc));
pool.addUnchecked(entry.Fee(10000LL).FromTx(td));
// Ancestors / descendants should be:
// transaction ancestors descendants
// ============ =================== ===========
// ta 1 (ta 4 (ta,tb,tc,td)
// tb 2 (ta,tb) 4 (ta,tb,tc,td)
// tc 3 (ta,tb,tc) 4 (ta,tb,tc,td)
// td 4 (ta,tb,tc,td) 4 (ta,tb,tc,td)
pool.GetTransactionAncestry(ta->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, 1ULL);
BOOST_CHECK_EQUAL(descendants, 4ULL);
pool.GetTransactionAncestry(tb->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, 2ULL);
BOOST_CHECK_EQUAL(descendants, 4ULL);
pool.GetTransactionAncestry(tc->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, 3ULL);
BOOST_CHECK_EQUAL(descendants, 4ULL);
pool.GetTransactionAncestry(td->GetHash(), ancestors, descendants);
BOOST_CHECK_EQUAL(ancestors, 4ULL);
BOOST_CHECK_EQUAL(descendants, 4ULL);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -3,8 +3,11 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <util/fees.h>
#include <policy/fees.h> #include <policy/fees.h>
#include <map>
#include <string> #include <string>
std::string StringForFeeReason(FeeReason reason) { std::string StringForFeeReason(FeeReason reason) {

View File

@ -243,7 +243,7 @@ BerkeleyEnvironment::BerkeleyEnvironment()
{ {
Reset(); Reset();
LogPrint(BCLog::DB, "BerkeleyEnvironment::MakeMock\n"); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::MakeMock\n");
dbenv->set_cachesize(1, 0, 1); dbenv->set_cachesize(1, 0, 1);
dbenv->set_lg_bsize(10485760 * 4); dbenv->set_lg_bsize(10485760 * 4);
@ -725,7 +725,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
{ {
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
// Flush log data to the actual data file on all files that are not in use // Flush log data to the actual data file on all files that are not in use
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: [%s] Flush(%s)%s\n", strPath, fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started"); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: [%s] Flush(%s)%s\n", strPath, fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
if (!fDbEnvInit) if (!fDbEnvInit)
return; return;
{ {
@ -734,21 +734,21 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
while (mi != mapFileUseCount.end()) { while (mi != mapFileUseCount.end()) {
std::string strFile = (*mi).first; std::string strFile = (*mi).first;
int nRefCount = (*mi).second; int nRefCount = (*mi).second;
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: Flushing %s (refcount = %d)...\n", strFile, nRefCount); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: Flushing %s (refcount = %d)...\n", strFile, nRefCount);
if (nRefCount == 0) { if (nRefCount == 0) {
// Move log data to the dat file // Move log data to the dat file
CloseDb(strFile); CloseDb(strFile);
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: %s checkpoint\n", strFile); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: %s checkpoint\n", strFile);
dbenv->txn_checkpoint(0, 0, 0); dbenv->txn_checkpoint(0, 0, 0);
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: %s detach\n", strFile); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: %s detach\n", strFile);
if (!fMockDb) if (!fMockDb)
dbenv->lsn_reset(strFile.c_str(), 0); dbenv->lsn_reset(strFile.c_str(), 0);
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: %s closed\n", strFile); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: %s closed\n", strFile);
mapFileUseCount.erase(mi++); mapFileUseCount.erase(mi++);
} else } else
mi++; mi++;
} }
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart); LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
if (fShutdown) { if (fShutdown) {
char** listp; char** listp;
if (mapFileUseCount.empty()) { if (mapFileUseCount.empty()) {
@ -787,7 +787,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
std::map<std::string, int>::iterator mi = env->mapFileUseCount.find(strFile); std::map<std::string, int>::iterator mi = env->mapFileUseCount.find(strFile);
if (mi != env->mapFileUseCount.end()) if (mi != env->mapFileUseCount.end())
{ {
LogPrint(BCLog::DB, "Flushing %s\n", strFile); LogPrint(BCLog::WALLETDB, "Flushing %s\n", strFile);
int64_t nStart = GetTimeMillis(); int64_t nStart = GetTimeMillis();
// Flush wallet file so it's self contained // Flush wallet file so it's self contained
@ -795,7 +795,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
env->CheckpointLSN(strFile); env->CheckpointLSN(strFile);
env->mapFileUseCount.erase(mi++); env->mapFileUseCount.erase(mi++);
LogPrint(BCLog::DB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart); LogPrint(BCLog::WALLETDB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
ret = true; ret = true;
} }
} }

View File

@ -100,13 +100,14 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
static Mutex g_wallet_release_mutex; static Mutex g_wallet_release_mutex;
static std::condition_variable g_wallet_release_cv; static std::condition_variable g_wallet_release_cv;
static std::set<CWallet*> g_unloading_wallet_set; static std::set<std::string> g_unloading_wallet_set;
// Custom deleter for shared_ptr<CWallet>. // Custom deleter for shared_ptr<CWallet>.
static void ReleaseWallet(CWallet* wallet) static void ReleaseWallet(CWallet* wallet)
{ {
// Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain // Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
// so that it's in sync with the current chainstate. // so that it's in sync with the current chainstate.
const std::string name = wallet->GetName();
wallet->WalletLogPrintf("Releasing wallet\n"); wallet->WalletLogPrintf("Releasing wallet\n");
wallet->BlockUntilSyncedToCurrentChain(); wallet->BlockUntilSyncedToCurrentChain();
wallet->Flush(); wallet->Flush();
@ -115,7 +116,7 @@ static void ReleaseWallet(CWallet* wallet)
// Wallet is now released, notify UnloadWallet, if any. // Wallet is now released, notify UnloadWallet, if any.
{ {
LOCK(g_wallet_release_mutex); LOCK(g_wallet_release_mutex);
if (g_unloading_wallet_set.erase(wallet) == 0) { if (g_unloading_wallet_set.erase(name) == 0) {
// UnloadWallet was not called for this wallet, all done. // UnloadWallet was not called for this wallet, all done.
return; return;
} }
@ -126,21 +127,21 @@ static void ReleaseWallet(CWallet* wallet)
void UnloadWallet(std::shared_ptr<CWallet>&& wallet) void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
{ {
// Mark wallet for unloading. // Mark wallet for unloading.
CWallet* pwallet = wallet.get(); const std::string name = wallet->GetName();
{ {
LOCK(g_wallet_release_mutex); LOCK(g_wallet_release_mutex);
auto it = g_unloading_wallet_set.insert(pwallet); auto it = g_unloading_wallet_set.insert(name);
assert(it.second); assert(it.second);
} }
// The wallet can be in use so it's not possible to explicitly unload here. // The wallet can be in use so it's not possible to explicitly unload here.
// Notify the unload intent so that all remaining shared pointers are // Notify the unload intent so that all remaining shared pointers are
// released. // released.
pwallet->NotifyUnload(); wallet->NotifyUnload();
// Time to ditch our shared_ptr and wait for ReleaseWallet call. // Time to ditch our shared_ptr and wait for ReleaseWallet call.
wallet.reset(); wallet.reset();
{ {
WAIT_LOCK(g_wallet_release_mutex, lock); WAIT_LOCK(g_wallet_release_mutex, lock);
while (g_unloading_wallet_set.count(pwallet) == 1) { while (g_unloading_wallet_set.count(name) == 1) {
g_wallet_release_cv.wait(lock); g_wallet_release_cv.wait(lock);
} }
} }

View File

@ -791,7 +791,7 @@ DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<u
} }
else if ((*it) == hash) { else if ((*it) == hash) {
if(!EraseTx(hash)) { if(!EraseTx(hash)) {
LogPrint(BCLog::DB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex()); LogPrint(BCLog::WALLETDB, "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
delerror = true; delerror = true;
} }
vTxHashOut.push_back(hash); vTxHashOut.push_back(hash);

View File

@ -235,7 +235,13 @@ Use the `-v` option for verbose output.
#### Dependencies #### Dependencies
The lint tests require codespell and flake8. To install: `pip3 install codespell flake8`. | Lint test | Dependency | Version [used by CI](../ci/lint/04_install.sh) | Installation
|-----------|:----------:|:-------------------------------------------:|--------------
| [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8) | [3.7.8](https://github.com/bitcoin/bitcoin/pull/15257) | `pip3 install flake8==3.7.8`
| [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck) | [0.6.0](https://github.com/bitcoin/bitcoin/pull/15166) | [details...](https://github.com/koalaman/shellcheck#installing)
| [`lint-spelling.sh`](lint/lint-spelling.sh) | [codespell](https://github.com/codespell-project/codespell) | [1.15.0](https://github.com/bitcoin/bitcoin/pull/16186) | `pip3 install codespell==1.15.0`
Please be aware that on Linux distributions all dependencies are usually available as packages, but could be outdated.
#### Running the tests #### Running the tests

View File

@ -334,6 +334,7 @@ def initialize_datadir(dirname, n, chain):
f.write("listenonion=0\n") f.write("listenonion=0\n")
f.write("printtoconsole=0\n") f.write("printtoconsole=0\n")
f.write("upnp=0\n") f.write("upnp=0\n")
f.write("shrinkdebugfile=0\n")
os.makedirs(os.path.join(datadir, 'stderr'), exist_ok=True) os.makedirs(os.path.join(datadir, 'stderr'), exist_ok=True)
os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True) os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
return datadir return datadir

View File

@ -83,10 +83,10 @@ enabled=(
) )
if ! command -v flake8 > /dev/null; then if ! command -v flake8 > /dev/null; then
echo "Skipping Python linting since flake8 is not installed. Install by running \"pip3 install flake8\"" echo "Skipping Python linting since flake8 is not installed."
exit 0 exit 0
elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then
echo "Skipping Python linting since flake8 is running under Python 2. Install the Python 3 version of flake8 by running \"pip3 install flake8\"" echo "Skipping Python linting since flake8 is running under Python 2. Install the Python 3 version of flake8."
exit 0 exit 0
fi fi