mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Merge pull request #4414 from PastaPastaPasta/backport-trivial-pr17
Backport trivial pr17
This commit is contained in:
commit
9005b1a307
@ -242,8 +242,11 @@ class BlockDataCopier:
|
||||
|
||||
inMagic = inhdr[:4]
|
||||
if (inMagic != self.settings['netmagic']):
|
||||
print("Invalid magic: " + inMagic.hex())
|
||||
return
|
||||
# Seek backwards 7 bytes (skipping the first byte in the previous search)
|
||||
# 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:]
|
||||
su = struct.unpack("<I", inLenLE)
|
||||
inLen = su[0] - 80 # length without header
|
||||
|
@ -638,6 +638,28 @@ Strings and formatting
|
||||
|
||||
- *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
|
||||
--------------
|
||||
|
||||
|
5
doc/release-notes-17410.md
Normal file
5
doc/release-notes-17410.md
Normal 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.
|
@ -78,7 +78,15 @@ void BCLog::Logger::EnableCategory(BCLog::LogFlags flag)
|
||||
bool BCLog::Logger::EnableCategory(const std::string& str)
|
||||
{
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
@ -122,7 +130,7 @@ const CLogCategoryDesc LogCategories[] =
|
||||
{BCLog::HTTP, "http"},
|
||||
{BCLog::BENCHMARK, "bench"},
|
||||
{BCLog::ZMQ, "zmq"},
|
||||
{BCLog::DB, "db"},
|
||||
{BCLog::WALLETDB, "walletdb"},
|
||||
{BCLog::RPC, "rpc"},
|
||||
{BCLog::ESTIMATEFEE, "estimatefee"},
|
||||
{BCLog::ADDRMAN, "addrman"},
|
||||
|
@ -41,7 +41,7 @@ namespace BCLog {
|
||||
HTTP = (1 << 3),
|
||||
BENCHMARK = (1 << 4),
|
||||
ZMQ = (1 << 5),
|
||||
DB = (1 << 6),
|
||||
WALLETDB = (1 << 6),
|
||||
RPC = (1 << 7),
|
||||
ESTIMATEFEE = (1 << 8),
|
||||
ADDRMAN = (1 << 9),
|
||||
@ -194,12 +194,13 @@ static inline void LogPrintf(const char* fmt, const Args&... args)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args)
|
||||
{
|
||||
if (LogAcceptCategory((category))) {
|
||||
LogPrintf(args...);
|
||||
}
|
||||
}
|
||||
// Use a macro instead of a function for conditional logging to prevent
|
||||
// evaluating arguments when logging for the category is not enabled.
|
||||
#define LogPrint(category, ...) \
|
||||
do { \
|
||||
if (LogAcceptCategory((category))) { \
|
||||
LogPrintf(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // BITCOIN_LOGGING_H
|
||||
|
@ -540,24 +540,16 @@ void BitcoinGUI::createMenuBar()
|
||||
connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) {
|
||||
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
|
||||
|
||||
if (walletFrame) {
|
||||
#ifdef Q_OS_MAC
|
||||
window_menu->addSeparator();
|
||||
QAction* main_window_action = window_menu->addAction(tr("Main Window"));
|
||||
connect(main_window_action, &QAction::triggered, [this] {
|
||||
GUIUtil::bringToFront(this);
|
||||
});
|
||||
|
||||
#endif
|
||||
window_menu->addSeparator();
|
||||
window_menu->addAction(usedSendingAddressesAction);
|
||||
window_menu->addAction(usedReceivingAddressesAction);
|
||||
|
@ -42,8 +42,8 @@
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslError>
|
||||
#include <QSslSocket>
|
||||
#include <QStringList>
|
||||
#include <QTextDocument>
|
||||
#include <QUrlQuery>
|
||||
@ -453,9 +453,9 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
|
||||
|
||||
certList = QSslCertificate::fromPath(certFile);
|
||||
// Use those certificates when fetching payment requests, too:
|
||||
QSslSocket::setDefaultCaCertificates(certList);
|
||||
QSslConfiguration::defaultConfiguration().setCaCertificates(certList);
|
||||
} else
|
||||
certList = QSslSocket::systemCaCertificates();
|
||||
certList = QSslConfiguration::systemCaCertificates();
|
||||
|
||||
int nRootCerts = 0;
|
||||
const QDateTime currentTime = QDateTime::currentDateTime();
|
||||
|
@ -71,11 +71,6 @@ void WalletFrame::addWallet(WalletModel *walletModel)
|
||||
walletStack->addWidget(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);
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,6 @@ public Q_SLOTS:
|
||||
/** Update selected DASH amount from transactionview */
|
||||
void trxAmount(QString amount);
|
||||
Q_SIGNALS:
|
||||
/** Signal that we want to show the main window */
|
||||
void showNormalIfMinimized();
|
||||
/** Fired when a message should be reported to the user */
|
||||
void message(const QString &title, const QString &message, unsigned int style);
|
||||
/** Encryption status of wallet changed */
|
||||
|
@ -6,14 +6,11 @@
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <shutdown.h>
|
||||
#include <util/system.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
// 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.
|
||||
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);
|
||||
|
||||
// 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)
|
||||
{
|
||||
case WM_QUERYENDSESSION:
|
||||
|
@ -146,6 +146,34 @@ static bool GetHardwareRand(unsigned char* ent32) noexcept {
|
||||
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)
|
||||
{
|
||||
#ifdef WIN32
|
||||
@ -432,7 +460,23 @@ static void SeedSlow(CSHA512& hasher) noexcept
|
||||
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
|
||||
SeedFast(hasher);
|
||||
@ -448,9 +492,12 @@ static void SeedSleep(CSHA512& hasher)
|
||||
|
||||
// Windows performance monitor data (once every 10 minutes)
|
||||
RandAddSeedPerfmon(hasher);
|
||||
|
||||
// Strengthen every minute
|
||||
SeedStrengthen(hasher, rng);
|
||||
}
|
||||
|
||||
static void SeedStartup(CSHA512& hasher) noexcept
|
||||
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
|
||||
{
|
||||
#ifdef WIN32
|
||||
RAND_screen();
|
||||
@ -461,6 +508,9 @@ static void SeedStartup(CSHA512& hasher) noexcept
|
||||
|
||||
// Windows performance monitor data.
|
||||
RandAddSeedPerfmon(hasher);
|
||||
|
||||
// Strengthen
|
||||
SeedStrengthen(hasher, rng);
|
||||
}
|
||||
|
||||
enum class RNGLevel {
|
||||
@ -485,7 +535,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
|
||||
SeedSlow(hasher);
|
||||
break;
|
||||
case RNGLevel::SLEEP:
|
||||
SeedSleep(hasher);
|
||||
SeedSleep(hasher, rng);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -493,7 +543,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
|
||||
if (!rng.MixExtract(out, num, std::move(hasher), false)) {
|
||||
// On the first invocation, also seed with SeedStartup().
|
||||
CSHA512 startup_hasher;
|
||||
SeedStartup(startup_hasher);
|
||||
SeedStartup(startup_hasher, rng);
|
||||
rng.MixExtract(out, num, std::move(startup_hasher), true);
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
* - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
|
||||
* - A high-precision timestamp before and after sleeping 1ms.
|
||||
* - (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
|
||||
* slightly.
|
||||
*
|
||||
@ -51,6 +52,7 @@
|
||||
* sources used in the 'slow' seeder are included, but also:
|
||||
* - (On Windows) Performance monitoring data from the OS.
|
||||
* - (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
|
||||
* (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
|
||||
|
@ -198,6 +198,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
|
||||
return sigdata.complete;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class SignatureExtractorChecker final : public BaseSignatureChecker
|
||||
{
|
||||
private:
|
||||
@ -206,10 +207,7 @@ private:
|
||||
|
||||
public:
|
||||
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 SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
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);
|
||||
@ -218,9 +216,8 @@ bool SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scrip
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Stacks
|
||||
{
|
||||
std::vector<valtype> script;
|
||||
|
@ -746,6 +746,43 @@ BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
|
||||
pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants);
|
||||
BOOST_CHECK_EQUAL(ancestors, 9ULL);
|
||||
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()
|
||||
|
@ -3,8 +3,11 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <util/fees.h>
|
||||
|
||||
#include <policy/fees.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
std::string StringForFeeReason(FeeReason reason) {
|
||||
|
@ -243,7 +243,7 @@ BerkeleyEnvironment::BerkeleyEnvironment()
|
||||
{
|
||||
Reset();
|
||||
|
||||
LogPrint(BCLog::DB, "BerkeleyEnvironment::MakeMock\n");
|
||||
LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::MakeMock\n");
|
||||
|
||||
dbenv->set_cachesize(1, 0, 1);
|
||||
dbenv->set_lg_bsize(10485760 * 4);
|
||||
@ -725,7 +725,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
// 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)
|
||||
return;
|
||||
{
|
||||
@ -734,21 +734,21 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
|
||||
while (mi != mapFileUseCount.end()) {
|
||||
std::string strFile = (*mi).first;
|
||||
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) {
|
||||
// Move log data to the dat file
|
||||
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);
|
||||
LogPrint(BCLog::DB, "BerkeleyEnvironment::Flush: %s detach\n", strFile);
|
||||
LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: %s detach\n", strFile);
|
||||
if (!fMockDb)
|
||||
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++);
|
||||
} else
|
||||
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) {
|
||||
char** listp;
|
||||
if (mapFileUseCount.empty()) {
|
||||
@ -787,7 +787,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
|
||||
std::map<std::string, int>::iterator mi = env->mapFileUseCount.find(strFile);
|
||||
if (mi != env->mapFileUseCount.end())
|
||||
{
|
||||
LogPrint(BCLog::DB, "Flushing %s\n", strFile);
|
||||
LogPrint(BCLog::WALLETDB, "Flushing %s\n", strFile);
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
// Flush wallet file so it's self contained
|
||||
@ -795,7 +795,7 @@ bool BerkeleyBatch::PeriodicFlush(BerkeleyDatabase& database)
|
||||
env->CheckpointLSN(strFile);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -100,13 +100,14 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
|
||||
|
||||
static Mutex g_wallet_release_mutex;
|
||||
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>.
|
||||
static void ReleaseWallet(CWallet* wallet)
|
||||
{
|
||||
// Unregister and delete the wallet right after BlockUntilSyncedToCurrentChain
|
||||
// so that it's in sync with the current chainstate.
|
||||
const std::string name = wallet->GetName();
|
||||
wallet->WalletLogPrintf("Releasing wallet\n");
|
||||
wallet->BlockUntilSyncedToCurrentChain();
|
||||
wallet->Flush();
|
||||
@ -115,7 +116,7 @@ static void ReleaseWallet(CWallet* wallet)
|
||||
// Wallet is now released, notify UnloadWallet, if any.
|
||||
{
|
||||
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.
|
||||
return;
|
||||
}
|
||||
@ -126,21 +127,21 @@ static void ReleaseWallet(CWallet* wallet)
|
||||
void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
|
||||
{
|
||||
// Mark wallet for unloading.
|
||||
CWallet* pwallet = wallet.get();
|
||||
const std::string name = wallet->GetName();
|
||||
{
|
||||
LOCK(g_wallet_release_mutex);
|
||||
auto it = g_unloading_wallet_set.insert(pwallet);
|
||||
auto it = g_unloading_wallet_set.insert(name);
|
||||
assert(it.second);
|
||||
}
|
||||
// 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
|
||||
// released.
|
||||
pwallet->NotifyUnload();
|
||||
wallet->NotifyUnload();
|
||||
// Time to ditch our shared_ptr and wait for ReleaseWallet call.
|
||||
wallet.reset();
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -791,7 +791,7 @@ DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<u
|
||||
}
|
||||
else if ((*it) == 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;
|
||||
}
|
||||
vTxHashOut.push_back(hash);
|
||||
|
@ -235,7 +235,13 @@ Use the `-v` option for verbose output.
|
||||
|
||||
#### 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
|
||||
|
||||
|
@ -334,6 +334,7 @@ def initialize_datadir(dirname, n, chain):
|
||||
f.write("listenonion=0\n")
|
||||
f.write("printtoconsole=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, 'stdout'), exist_ok=True)
|
||||
return datadir
|
||||
|
@ -83,10 +83,10 @@ enabled=(
|
||||
)
|
||||
|
||||
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
|
||||
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
|
||||
fi
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user