Skip to content

Disable software expiry by default #124

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 1 commit into
base: 28.x-knots
Choose a base branch
from

Conversation

1440000bytes
Copy link

Rationale: This config option should only be used by power users as it could reject blocks. Some information about its usage could be added in docs or release notes.

Alternative solution: Warning or error after expiry.


I couldn't find a way to exploit this feature however it could lead to bugs, bad user experience etc. Related discussion: https://njump.me/nevent1qvzqqqqqqypzqt4s8g0nzmpul8yspel4xmhz3e2gvdysv7lqrz5ktf78efd57leuqqs9ll49daxc2w2qsn8xckr54acr2xcj076x2hfufyswtmgyx4kuqqqcgf23c

@luke-jr
Copy link
Collaborator

luke-jr commented May 14, 2025

It should only be disabled by power users, would be accurate. The current default behaviour is best for ordinary users.

@arejula27
Copy link

arejula27 commented May 14, 2025

utAck b408201

Updated the default value to 0, ensuring the checker always returns false, effectively bypassing the comparative check, preventing shutting down

bool IsThisSoftwareExpired(int64_t nTime)
{
    if (g_software_expiry <= 0) {
        return false;
    }
    return (nTime > g_software_expiry);
}

The current approach carries potential issues, particularly for non-admin users. Without proper handling, it increases the risk of unexpected behaviour. This can be especially problematic if a Lightning Network (LN) node relies on this behaviour.
Additionally, the expiration date limits the ability to run a preferred version, removing the freedom to reject updates. This can be a significant concern for some users, as highlighted by the recent discussions around the OP_RETURN limit, where many preferred to maintain older behaviour. It’s crucial to preserve this flexibility, allowing the plebs to make their own choices rather than enforcing a single path forward.

@pithosian
Copy link

pithosian commented May 14, 2025

I think having a way of yelling at users running very old software (who haven't explicitly indicated that they want to, eg with the config option) is a fair idea, given upstream's disclosure policies, but agree shutting down isn't the best solution. Maybe a warning prompt which requires typing out a confirmation (eg: "I accept that this software may be insecure"), so users can't just ignore it by hitting space/enter.

bitcoind running detached or under a service manager needs consideration with such an approach, however.

@MrRGnome
Copy link

MrRGnome commented May 14, 2025

NACK.

I'm for your node forcing you to acknowledge changing security contexts and actively manage it by default. I don't think the default behavior should be to ignore a lack of node management and pretend everything is fine without being explicitly told to.

That said, I think the proposed idea of setting the override setting via GUI with explicit error message and consent is a good idea.

I appreciate that this may cause passively managed daemon only nodes some troubleshooting as they are forced to actively manage their node. Good. That's the point.

For RPC users such as lightning use cases, I presume that these users will be alerted by the fact they aren't in sync anymore. If more than that is necessary it could be reasonable to throw RPC errors regarding the invalid node state so users are forced to investigate the error and make some intentional management choices.

What this 2 year default really highlights for me however is that the existing security disclosure policies are entirely inappropriate. How can a user make an informed choice about the code they run and the safety of an older client if they don't have the disclosures?

@pithosian
Copy link

pithosian commented May 15, 2025

For an alternative, here's what I'm thinking(, have partially implemented), and am seeking opinions on:

Startup

  • Add a warning (log under bitcoind, message box under bitcoin-qt) if we're <T from expiry, but haven't expired yet, so the user (hopefully) gets prompted to make a decision before we have to actually interrupt their node's operation.
  • In bitcoin-qt, change current message box to input box, requiring user to type I accept this software may be unsafe. (or something else, if you have suggestions) to continue, and write a change to config if they do so. Whether to set the flag to 0, now+2y, or something else, I'm all ears. If they fail to confirm (cancel, close, type something else, 'Ok' with an empty string), shut down.
  • In bitcoind, just add information to the existing error message. In a terminal, the user can add the flag to their args there and then, or go edit config. Under a service manager, they wouldn't be able to interact with any text prompt anyway.
    This should at minimum prevent any confusion, eg users wasting time creating issues, as they'll be made explicitly aware of the config option.

At runtime

The validation.cpp check currently starts rejecting blocks a day after expiry.

  • In bitcoin-qt, when we first enter this state we can give them the same prompt as at startup. If they fail to confirm, shut down. Reject blocks in the meantime.
  • In bitcoind, we should log the same error as at startup, and shut down.
    Having your node running, quietly rejecting valid blocks is a pretty bad state to be in. Shutting down bitcoind makes this state far more obvious, and in the terminal window or log clearly tells the user what they need to do (and even if they don't check it, they'll be told when they try to restart!), and QT can 'seamlessly' recover.

Rough Impls

Two branches for implementing (roughly) the above:
https://github.com/pithosian/bitcoin/pull/2/files achieves almost the above, but expiration at runtime has QT just shut down with a (message box) error message; attempting to restart it yields the prompt.

https://github.com/pithosian/bitcoin/pull/1/files achieves the above at the cost of a much larger change. A middleground could be to use a Question at runtime for QT, which would enable overriding at runtime without most of the additional code, but only with a simple yes/no, ok/abort, whatever two-button modal.

@1440000bytes
Copy link
Author

It should only be disabled by power users, would be accurate. The current default behaviour is best for ordinary users.

Most ordinary users are unaware of this option and expiration followed by rejection of blocks.

@frenzyball
Copy link

Just a general comment here. I would also avoid too much "calculations" in the constants, such as DEFAULT_SOFTWARE_EXPIRY. Set it to zero as suggested and do the calculation/check in function/method instead. This will make it more readable and easier to understand, in addition to make tests on it. Or even better IMO implement all time and date handling into it's own library.

@portlandhodl
Copy link

Concept ACK, the current knots creates a fork like behavior between other client implementations on the Bitcoin networks. This could also lead to a miner losing revenue or wasting energy if their node stops running after the expiry.

@michaelfolkson
Copy link

michaelfolkson commented May 18, 2025

the current knots creates a fork like behavior between other client implementations on the Bitcoin networks

No fork like behavior. The node drops off the network. It doesn't follow a fork of the chain or get tricked into joining a fork of the network. If you mean a Git fork (Knots is a Git fork of Core) Luke has been able to maintain this code diff from Bitcoin Core without a problem for years. One can certainly argue for and against this default but it isn't "fork like behavior".

edit: Interesting. Some people are claiming that the node doesn't drop off the network (the Bitcoin daemon is killed) and it just stops accepting blocks on the most proof-of-work consensus valid chain.

edit edit: From a quick perusal I think the claims are rubbish. The daemon would need to stay running, disconnect from all peers or be restarted with different consensus rules to when it shutdown to "accept backdated blocks on a lower PoW chain". I would like to test this though to check this is definitely FUD.

@portlandhodl
Copy link

portlandhodl commented May 18, 2025

edit: Interesting. Some people are claiming that the node doesn't drop off the network (the Bitcoin daemon is killed) and it just stops accepting blocks on the most proof-of-work consensus valid chain.

This is exactly what is happening 24 hours after the MTP passses expiration, so at that point could someone not start building blocks (n) blocks back. Then end up with a timestamp just higher than the last valid MTP and get a reorg off that?

edit: sauce

if (IsThisSoftwareExpired(block.nTime)) {

@michaelfolkson
Copy link

@portlandhodl: If that's the case and it isn't a complete shutdown in all cases then yeah the code isn't doing how the feature has been described ("software expiry"). It is one thing to completely shutdown after x years, it is a whole other thing entirely to stay up in some kind of zombie state without the user realizing.

@luke-jr luke-jr added the default/opinion Changes to default settings and/or matters of opinion label May 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
default/opinion Changes to default settings and/or matters of opinion
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants