diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index b8e67dccbc69f..6462e0e1deeaa 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -130,8 +130,10 @@ static bool ParseArgs(ArgsManager& args, int argc, char* argv[]) } g_software_expiry = args.GetIntArg("-softwareexpiry", DEFAULT_SOFTWARE_EXPIRY); - if (IsThisSoftwareExpired(GetTime())) { - tfm::format(std::cerr, "This software is expired, and may be out of consensus. You must choose to upgrade or override this expiration.\n"); + if (IsThisSoftwareExpiringSoon(GetTime())) { + tfm::format(std::cerr, "Warning: This software expires soon, and may fall out of consensus. You must choose to upgrade, or override this expiration with the 'softwareexpiry' option (Unix datetime, or 0 for no expiry).\n"); + } else if (IsThisSoftwareExpired(GetTime())) { + tfm::format(std::cerr, "This software is expired, and may be out of consensus. You must choose to upgrade, or override this expiration with the 'softwareexpiry' option (Unix datetime, or 0 for no expiry).\n"); exit(EXIT_FAILURE); } diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 6bf7ef640661d..e6f87faad391c 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -113,3 +113,12 @@ bool IsThisSoftwareExpired(int64_t nTime) } return (nTime > g_software_expiry); } + +bool IsThisSoftwareExpiringSoon(int64_t ntime) +{ + if (g_software_expiry <= 0) { + return false; + } + + return (ntime <= g_software_expiry && ntime > g_software_expiry - SOFTWARE_EXPIRY_WARN_PERIOD); +} diff --git a/src/clientversion.h b/src/clientversion.h index 0d3fd033a37f9..c154ff29a6ae1 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -49,9 +49,14 @@ static constexpr int64_t SECONDS_PER_YEAR = 31558060; static constexpr int POSIX_EPOCH_YEAR = 1970; static constexpr int64_t DEFAULT_SOFTWARE_EXPIRY_OFFSET = 26784000; // Around Nov 7 static constexpr int64_t DEFAULT_SOFTWARE_EXPIRY = ((COPYRIGHT_YEAR - POSIX_EPOCH_YEAR) * SECONDS_PER_YEAR) + (SECONDS_PER_YEAR * 2) + DEFAULT_SOFTWARE_EXPIRY_OFFSET; + +static constexpr int64_t SECONDS_PER_WEEK = 604800; +static constexpr int64_t SOFTWARE_EXPIRY_WARN_PERIOD = SECONDS_PER_WEEK * 4; + extern int64_t g_software_expiry; bool IsThisSoftwareExpired(int64_t nTime); +bool IsThisSoftwareExpiringSoon(int64_t nTime); #endif // WINDRES_PREPROC diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index f835ef62b3a94..ab772bd481152 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -654,9 +655,23 @@ int GuiMain(int argc, char* argv[]) initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator); g_software_expiry = gArgs.GetIntArg("-softwareexpiry", DEFAULT_SOFTWARE_EXPIRY); - if (IsThisSoftwareExpired(GetTime())) { - QMessageBox::critical(nullptr, QObject::tr("Software expired"), QObject::tr("This software is expired, and may be out of consensus. You must choose to upgrade or override this expiration.")); - return EXIT_FAILURE; + if (IsThisSoftwareExpiringSoon(GetTime())) { + QMessageBox::warning(nullptr, QObject::tr("Software expires soon"), QObject::tr("This software expires soon, and may fall out of consensus. You must choose to upgrade, or override this expiration with the 'softwareexpiry' option (Unix datetime, or 0 for no expiry).")); + } else if (IsThisSoftwareExpired(GetTime())) { + bool override_expiry_ok; + QString override_expiry = QInputDialog::getText( + nullptr, + QObject::tr("Software Expired"), + QObject::tr("This software is expired, and may be out of consensus.\nYou must choose to upgrade, or override this expiration by typing:\nI accept this software may be unsafe."), + QLineEdit::Normal, + "", + &override_expiry_ok); + if (!override_expiry_ok || override_expiry != QObject::tr("I accept this software may be unsafe.")) { + return EXIT_FAILURE; + } + + gArgs.ModifyRWConfigFile("softwareexpiry", "0"); + g_software_expiry = 0; } #ifdef ENABLE_WALLET diff --git a/src/validation.cpp b/src/validation.cpp index 388ba9de56af9..b90f66339b52a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4458,12 +4458,13 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio if (IsThisSoftwareExpired(block.nTime)) { // Wait an extra day before we start rejecting blocks CBlockIndex const *blockindex_old = pindexPrev; - for (int i = 0; i < 144; ++i) { + for (int i = 0; i < std::min(144, pindexPrev->nHeight); ++i) { assert(blockindex_old); blockindex_old = blockindex_old->pprev; } assert(blockindex_old); if (IsThisSoftwareExpired(blockindex_old->GetMedianTimePast())) { + chainman.GetNotifications().fatalError(_("This software is expired, and may be out of consensus. You must choose to upgrade, or override this expiration with the 'softwareexpiry' option (Unix datetime, or 0 for no expiry).")); return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "node-expired", "node software has expired"); } }