Skip to content

Rework Software Expiry #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: 28.x-knots
Choose a base branch
from

Conversation

pithosian
Copy link

@pithosian pithosian commented May 24, 2025

As an alternative to #124.

  • Add a warning on startup within 4 weeks of expiry to bitcoind and bitcoin-qt.
  • Add a note on how to override in the existing bitcoind startup failure message for expired software.
  • Replace the existing bitcoin-qt startup error message for expired software with an input box requiring the user to type I accept this software may be unsafe. to continue (overriding expiry this way updates configuration).
  • Shut down when bitcoind or bitcoin-qt expire at runtime, rather than silently rejecting blocks.

The rationale for these changes is largely explained by my comments on the above-linked PR. I considered using the same prompt at runtime as at startup for bitcoin-qt, but the churn required was much higher with minimal benefit (as it stands, the software pops up a dialog telling the user the software is expired, on closing, bitcoin-qt exits, and if the user tries to start it again, they get the override prompt).

As a brief summary:

  • It's good to make a user who hasn't explicitly indicated that they want to run EOLed software (see Core's end of life policy and disclosure policy) think about what they're running.
  • In bitcoind, shutting down with an error message telling the user how to override is effectively identical to pushing a prompt for continued operation when running attached to a terminal and, when not running attached to a terminal (eg disowned, or under a service manager), a prompt cannot be displayed anyway.
  • bitcoin-qt now gives the user the opportunity to override without going and manually editing the configuration files, without simply showing them a dialog they can hit yes on to continue without thinking about anything.
  • Shutting down outright is far more detectable and safe than leaving the node running, but silently rejecting blocks.

@1440000bytes
Copy link

Approach ACK

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)."));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't pause startup waiting for a response

return EXIT_FAILURE;
}

gArgs.ModifyRWConfigFile("softwareexpiry", "0");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rwconf is kind of deprecated at this point (superceded by settings.json)

return EXIT_FAILURE;
}

gArgs.ModifyRWConfigFile("softwareexpiry", "0");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't persist forever, and should reset to default if the user upgrades?

@@ -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) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it should be

Suggested change
for (int i = 0; i < std::min(144, pindexPrev->nHeight); ++i) {
for (int i = 0; i < std::min(144, pindexPrev->nHeight - 1); ++i) {

?

But to avoid re-calculating it every iteration, better to offset the starting index.

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)."));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use warningSet so it shows up in RPC, -alertnotify, etc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants