mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +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]
|
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
|
||||||
|
@ -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
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
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)
|
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"},
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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,10 +207,7 @@ 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
|
||||||
};
|
|
||||||
|
|
||||||
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)) {
|
if (checker.CheckSig(scriptSig, vchPubKey, scriptCode, sigversion)) {
|
||||||
CPubKey pubkey(vchPubKey);
|
CPubKey pubkey(vchPubKey);
|
||||||
@ -218,9 +216,8 @@ bool SignatureExtractorChecker::CheckSig(const std::vector<unsigned char>& scrip
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct Stacks
|
struct Stacks
|
||||||
{
|
{
|
||||||
std::vector<valtype> script;
|
std::vector<valtype> script;
|
||||||
|
@ -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()
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user