mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-14 11:26:09 -05:00
![TheCharlatan](/assets/img/avatar_default.png)
-BEGIN VERIFY SCRIPT- regex_string='^(?!//).*(AC_APPLE_UNIVERSAL_BUILD|BOOST_PROCESS_USE_STD_FS|CHAR_EQUALS_INT8|CLIENT_VERSION_BUILD|CLIENT_VERSION_IS_RELEASE|CLIENT_VERSION_MAJOR|CLIENT_VERSION_MINOR|COPYRIGHT_HOLDERS|COPYRIGHT_HOLDERS_FINAL|COPYRIGHT_HOLDERS_SUBSTITUTION|COPYRIGHT_YEAR|ENABLE_ARM_SHANI|ENABLE_AVX2|ENABLE_EXTERNAL_SIGNER|ENABLE_SSE41|ENABLE_TRACING|ENABLE_WALLET|ENABLE_X86_SHANI|ENABLE_ZMQ|HAVE_BOOST|HAVE_BUILTIN_CLZL|HAVE_BUILTIN_CLZLL|HAVE_BYTESWAP_H|HAVE_CLMUL|HAVE_CONSENSUS_LIB|HAVE_CXX20|HAVE_DECL_BE16TOH|HAVE_DECL_BE32TOH|HAVE_DECL_BE64TOH|HAVE_DECL_BSWAP_16|HAVE_DECL_BSWAP_32|HAVE_DECL_BSWAP_64|HAVE_DECL_FORK|HAVE_DECL_FREEIFADDRS|HAVE_DECL_GETIFADDRS|HAVE_DECL_HTOBE16|HAVE_DECL_HTOBE32|HAVE_DECL_HTOBE64|HAVE_DECL_HTOLE16|HAVE_DECL_HTOLE32|HAVE_DECL_HTOLE64|HAVE_DECL_LE16TOH|HAVE_DECL_LE32TOH|HAVE_DECL_LE64TOH|HAVE_DECL_PIPE2|HAVE_DECL_SETSID|HAVE_DECL_STRERROR_R|HAVE_DEFAULT_VISIBILITY_ATTRIBUTE|HAVE_DLFCN_H|HAVE_DLLEXPORT_ATTRIBUTE|HAVE_ENDIAN_H|HAVE_EVHTTP_CONNECTION_GET_PEER_CONST_CHAR|HAVE_FDATASYNC|HAVE_GETENTROPY_RAND|HAVE_GETRANDOM|HAVE_GMTIME_R|HAVE_INTTYPES_H|HAVE_LIBADVAPI32|HAVE_LIBCOMCTL32|HAVE_LIBCOMDLG32|HAVE_LIBGDI32|HAVE_LIBIPHLPAPI|HAVE_LIBKERNEL32|HAVE_LIBOLE32|HAVE_LIBOLEAUT32|HAVE_LIBSHELL32|HAVE_LIBSHLWAPI|HAVE_LIBUSER32|HAVE_LIBUUID|HAVE_LIBWINMM|HAVE_LIBWS2_32|HAVE_MALLOC_INFO|HAVE_MALLOPT_ARENA_MAX|HAVE_MINIUPNPC_MINIUPNPC_H|HAVE_MINIUPNPC_UPNPCOMMANDS_H|HAVE_MINIUPNPC_UPNPERRORS_H|HAVE_NATPMP_H|HAVE_O_CLOEXEC|HAVE_POSIX_FALLOCATE|HAVE_PTHREAD|HAVE_PTHREAD_PRIO_INHERIT|HAVE_STDINT_H|HAVE_STDIO_H|HAVE_STDLIB_H|HAVE_STRERROR_R|HAVE_STRINGS_H|HAVE_STRING_H|HAVE_STRONG_GETAUXVAL|HAVE_SYSCTL|HAVE_SYSCTL_ARND|HAVE_SYSTEM|HAVE_SYS_ENDIAN_H|HAVE_SYS_PRCTL_H|HAVE_SYS_RESOURCES_H|HAVE_SYS_SELECT_H|HAVE_SYS_STAT_H|HAVE_SYS_SYSCTL_H|HAVE_SYS_TYPES_H|HAVE_SYS_VMMETER_H|HAVE_THREAD_LOCAL|HAVE_TIMINGSAFE_BCMP|HAVE_UNISTD_H|HAVE_VM_VM_PARAM_H|LT_OBJDIR|PACKAGE_BUGREPORT|PACKAGE_NAME|PACKAGE_STRING|PACKAGE_TARNAME|PACKAGE_URL|PACKAGE_VERSION|PTHREAD_CREATE_JOINABLE|QT_QPA_PLATFORM_ANDROID|QT_QPA_PLATFORM_COCOA|QT_QPA_PLATFORM_MINIMAL|QT_QPA_PLATFORM_WINDOWS|QT_QPA_PLATFORM_XCB|QT_STATICPLUGIN|STDC_HEADERS|STRERROR_R_CHAR_P|USE_ASM|USE_BDB|USE_DBUS|USE_NATPMP|USE_QRCODE|USE_SQLITE|USE_UPNP|_FILE_OFFSET_BITS|_LARGE_FILES)' exclusion_files=":(exclude)src/minisketch :(exclude)src/crc32c :(exclude)src/secp256k1 :(exclude)src/crypto/sha256_arm_shani.cpp :(exclude)src/crypto/sha256_avx2.cpp :(exclude)src/crypto/sha256_sse41.cpp :(exclude)src/crypto/sha256_x86_shani.cpp" git grep --perl-regexp --files-with-matches "$regex_string" -- '*.cpp' $exclusion_files | xargs git grep -L "bitcoin-config.h" | while read -r file; do line_number=$(awk -v my_file="$file" '/\/\/ file COPYING or https?:\/\/www.opensource.org\/licenses\/mit-license.php\./ {line = NR} /^\/\// && NR == line + 1 {while(getline && /^\/\//) line = NR} END {print line+1}' "$file"); sed -i "${line_number}i\\\\n\#if defined(HAVE_CONFIG_H)\\n#include <config/bitcoin-config.h>\\n\#endif" "$file"; done; git grep --perl-regexp --files-with-matches "$regex_string" -- '*.h' $exclusion_files | xargs git grep -L "bitcoin-config.h" | while read -r file; do sed -i "/#define.*_H/a \\\\n\#if defined(HAVE_CONFIG_H)\\n#include <config/bitcoin-config.h>\\n\#endif" "$file"; done; for file in $(git grep --files-with-matches 'bitcoin-config.h' -- '*.cpp' '*.h' $exclusion_files); do if ! grep -q --perl-regexp "$regex_string" $file; then sed -i '/HAVE_CONFIG_H/{N;N;N;d;}' $file; fi; done; -END VERIFY SCRIPT- The first command creates a regular expression for matching all bitcoin-config.h symbols in the following form: ^(?!//).*(AC_APPLE_UNIVERSAL_BUILD|BOOST_PROCESS_USE_STD_FS|...|_LARGE_FILES). It was generated with: ./autogen.sh && printf '^(?!//).*(%s)' $(awk '/^#undef/ {print $2}' src/config/bitcoin-config.h.in | paste -sd "|" -) The second command holds a list of files and directories that should not be processed. These include subtree directories as well as some crypto files that already get their symbols through the makefile. The third command checks for missing bitcoin-config headers in .cpp files and adds the header if it is missing. The fourth command checks for missing bitcoin-config headers in .h files and adds the header if it is missing. The fifth command checks for unneeded bitcoin-config headers in sources files and removes the header if it is unneeded.
198 lines
7 KiB
C++
198 lines
7 KiB
C++
// Copyright (c) 2016-2022 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include <config/bitcoin-config.h>
|
|
#endif
|
|
|
|
#include <qt/modaloverlay.h>
|
|
#include <qt/forms/ui_modaloverlay.h>
|
|
|
|
#include <chainparams.h>
|
|
#include <qt/guiutil.h>
|
|
|
|
#include <QEasingCurve>
|
|
#include <QPropertyAnimation>
|
|
#include <QResizeEvent>
|
|
|
|
ModalOverlay::ModalOverlay(bool enable_wallet, QWidget* parent)
|
|
: QWidget(parent),
|
|
ui(new Ui::ModalOverlay),
|
|
bestHeaderDate(QDateTime())
|
|
{
|
|
ui->setupUi(this);
|
|
connect(ui->closeButton, &QPushButton::clicked, this, &ModalOverlay::closeClicked);
|
|
if (parent) {
|
|
parent->installEventFilter(this);
|
|
raise();
|
|
}
|
|
|
|
blockProcessTime.clear();
|
|
setVisible(false);
|
|
if (!enable_wallet) {
|
|
ui->infoText->setVisible(false);
|
|
ui->infoTextStrong->setText(tr("%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.").arg(PACKAGE_NAME));
|
|
}
|
|
|
|
m_animation.setTargetObject(this);
|
|
m_animation.setPropertyName("pos");
|
|
m_animation.setDuration(300 /* ms */);
|
|
m_animation.setEasingCurve(QEasingCurve::OutQuad);
|
|
}
|
|
|
|
ModalOverlay::~ModalOverlay()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
bool ModalOverlay::eventFilter(QObject * obj, QEvent * ev) {
|
|
if (obj == parent()) {
|
|
if (ev->type() == QEvent::Resize) {
|
|
QResizeEvent * rev = static_cast<QResizeEvent*>(ev);
|
|
resize(rev->size());
|
|
if (!layerIsVisible)
|
|
setGeometry(0, height(), width(), height());
|
|
|
|
if (m_animation.endValue().toPoint().y() > 0) {
|
|
m_animation.setEndValue(QPoint(0, height()));
|
|
}
|
|
}
|
|
else if (ev->type() == QEvent::ChildAdded) {
|
|
raise();
|
|
}
|
|
}
|
|
return QWidget::eventFilter(obj, ev);
|
|
}
|
|
|
|
//! Tracks parent widget changes
|
|
bool ModalOverlay::event(QEvent* ev) {
|
|
if (ev->type() == QEvent::ParentAboutToChange) {
|
|
if (parent()) parent()->removeEventFilter(this);
|
|
}
|
|
else if (ev->type() == QEvent::ParentChange) {
|
|
if (parent()) {
|
|
parent()->installEventFilter(this);
|
|
raise();
|
|
}
|
|
}
|
|
return QWidget::event(ev);
|
|
}
|
|
|
|
void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate, bool presync)
|
|
{
|
|
if (!presync && count > bestHeaderHeight) {
|
|
bestHeaderHeight = count;
|
|
bestHeaderDate = blockDate;
|
|
UpdateHeaderSyncLabel();
|
|
}
|
|
if (presync) {
|
|
UpdateHeaderPresyncLabel(count, blockDate);
|
|
}
|
|
}
|
|
|
|
void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
|
|
{
|
|
QDateTime currentDate = QDateTime::currentDateTime();
|
|
|
|
// keep a vector of samples of verification progress at height
|
|
blockProcessTime.push_front(qMakePair(currentDate.toMSecsSinceEpoch(), nVerificationProgress));
|
|
|
|
// show progress speed if we have more than one sample
|
|
if (blockProcessTime.size() >= 2) {
|
|
double progressDelta = 0;
|
|
double progressPerHour = 0;
|
|
qint64 timeDelta = 0;
|
|
qint64 remainingMSecs = 0;
|
|
double remainingProgress = 1.0 - nVerificationProgress;
|
|
for (int i = 1; i < blockProcessTime.size(); i++) {
|
|
QPair<qint64, double> sample = blockProcessTime[i];
|
|
|
|
// take first sample after 500 seconds or last available one
|
|
if (sample.first < (currentDate.toMSecsSinceEpoch() - 500 * 1000) || i == blockProcessTime.size() - 1) {
|
|
progressDelta = blockProcessTime[0].second - sample.second;
|
|
timeDelta = blockProcessTime[0].first - sample.first;
|
|
progressPerHour = (progressDelta > 0) ? progressDelta / (double)timeDelta * 1000 * 3600 : 0;
|
|
remainingMSecs = (progressDelta > 0) ? remainingProgress / progressDelta * timeDelta : -1;
|
|
break;
|
|
}
|
|
}
|
|
// show progress increase per hour
|
|
ui->progressIncreasePerH->setText(QString::number(progressPerHour * 100, 'f', 2)+"%");
|
|
|
|
// show expected remaining time
|
|
if(remainingMSecs >= 0) {
|
|
ui->expectedTimeLeft->setText(GUIUtil::formatNiceTimeOffset(remainingMSecs / 1000.0));
|
|
} else {
|
|
ui->expectedTimeLeft->setText(QObject::tr("unknown"));
|
|
}
|
|
|
|
static const int MAX_SAMPLES = 5000;
|
|
if (blockProcessTime.count() > MAX_SAMPLES) {
|
|
blockProcessTime.remove(MAX_SAMPLES, blockProcessTime.count() - MAX_SAMPLES);
|
|
}
|
|
}
|
|
|
|
// show the last block date
|
|
ui->newestBlockDate->setText(blockDate.toString());
|
|
|
|
// show the percentage done according to nVerificationProgress
|
|
ui->percentageProgress->setText(QString::number(nVerificationProgress*100, 'f', 2)+"%");
|
|
|
|
if (!bestHeaderDate.isValid())
|
|
// not syncing
|
|
return;
|
|
|
|
// estimate the number of headers left based on nPowTargetSpacing
|
|
// and check if the gui is not aware of the best header (happens rarely)
|
|
int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing;
|
|
bool hasBestHeader = bestHeaderHeight >= count;
|
|
|
|
// show remaining number of blocks
|
|
if (estimateNumHeadersLeft < HEADER_HEIGHT_DELTA_SYNC && hasBestHeader) {
|
|
ui->numberOfBlocksLeft->setText(QString::number(bestHeaderHeight - count));
|
|
} else {
|
|
UpdateHeaderSyncLabel();
|
|
ui->expectedTimeLeft->setText(tr("Unknown…"));
|
|
}
|
|
}
|
|
|
|
void ModalOverlay::UpdateHeaderSyncLabel() {
|
|
int est_headers_left = bestHeaderDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
|
|
ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1, %2%)…").arg(bestHeaderHeight).arg(QString::number(100.0 / (bestHeaderHeight + est_headers_left) * bestHeaderHeight, 'f', 1)));
|
|
}
|
|
|
|
void ModalOverlay::UpdateHeaderPresyncLabel(int height, const QDateTime& blockDate) {
|
|
int est_headers_left = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
|
|
ui->numberOfBlocksLeft->setText(tr("Unknown. Pre-syncing Headers (%1, %2%)…").arg(height).arg(QString::number(100.0 / (height + est_headers_left) * height, 'f', 1)));
|
|
}
|
|
|
|
void ModalOverlay::toggleVisibility()
|
|
{
|
|
showHide(layerIsVisible, true);
|
|
if (!layerIsVisible)
|
|
userClosed = true;
|
|
}
|
|
|
|
void ModalOverlay::showHide(bool hide, bool userRequested)
|
|
{
|
|
if ( (layerIsVisible && !hide) || (!layerIsVisible && hide) || (!hide && userClosed && !userRequested))
|
|
return;
|
|
|
|
Q_EMIT triggered(hide);
|
|
|
|
if (!isVisible() && !hide)
|
|
setVisible(true);
|
|
|
|
m_animation.setStartValue(QPoint(0, hide ? 0 : height()));
|
|
// The eventFilter() updates the endValue if it is required for QEvent::Resize.
|
|
m_animation.setEndValue(QPoint(0, hide ? height() : 0));
|
|
m_animation.start(QAbstractAnimation::KeepWhenStopped);
|
|
layerIsVisible = !hide;
|
|
}
|
|
|
|
void ModalOverlay::closeClicked()
|
|
{
|
|
showHide(true);
|
|
userClosed = true;
|
|
}
|