Repository navigation
gui: Rescan a restore from its creation date - #139
BenWestgate wants to merge 5 commits into
Conversation
Restore always imported with timestamp 0, so Bitcoin Core rescanned from 2009. A pruned node, as on Bails, no longer has those blocks: Core imports the keys, then fails the rescan, leaving a filled wallet without its history. A tester hit this on Tails. The restore page now asks for the approximate creation date the wallet record already carries and rescans from a day before it. Before any wallet is touched, the library checks the node's prune height and refuses a rescan it cannot do, naming the date it can. New wallets are created with load_on_startup, so Core loads them at every start and a pruned node never prunes past their last sync, which is the "resync the whole blockchain" error the same tester saw on a wallet made during initial sync. The library is now 5,013 logical lines, so its budget goes from 5,000 to 5,025 in the test, AGENTS.md and the developer docs. Refs BenWestgate/Bails#314
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e40c160c7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Codex review of the first commit found five holes. The prune check ran before wallet selection, so a node pruning during the unlock wait could outrun it; it now runs as the last step before importdescriptors. Unclear pruning metadata no longer reads as an unpruned node: pruned must be a boolean and, when true, pruneheight an integer, or the import is refused. Subtracting the safety day before the future check let tomorrow's date through as today's midnight; the check now runs first, with a UTC+14 margin so the earliest time zone can still enter its own date. Core only warns when it cannot save load_on_startup, so create reads the result and refuses a wallet Core will not load again. Invariant 9 and the wallet creation row now name that argument. Refs BenWestgate/Bails#314
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b93cbe2993
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Second Codex round on the restore date change. pruned=1 compared equal to True and slipped past the boolean check, so it now needs a real bool. Core picks the rescan start by the highest block time seen so far, not the raw time at pruneheight, and block times are not monotonic, so the margin past the pruned blocks grows from four hours to a day; entered dates are only day-accurate anyway. A wallet named "could not be updated" read as a failed load_on_startup, so only Core's warnings are searched. verify now needs the rescan start, so a restore into a new wallet rechecks the pruned history right before createwallet instead of skipping it. Refs BenWestgate/Bails#314
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae90e38e33
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Third Codex round. getblockstats returning time=true counted as the integer 1, so any real date passed the prune check without knowing which blocks the node keeps. A block time is now trusted only as a positive integer that is not a bool; anything else refuses the import. docs/developer/gui.md still listed the old createwallet shape, so it now names load_on_startup=true and the refusal when Core cannot save it. Refs BenWestgate/Bails#314
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 75f5aedf8d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Fourth Codex round. A negative pruneheight passed as an unpruned node, and a createwallet result that was not an object, or whose warnings were not a list, was accepted without knowing whether Core saved load_on_startup. Both now refuse. Refs BenWestgate/Bails#314
Requested by Ben · project thread
Before: restore always imports with timestamp 0, so Bitcoin Core rescans from 2009. On a pruned node, as on Bails, those blocks are gone. Core imports the keys anyway, then fails the rescan, and codex32 reports "did not import every private descriptor" with the wallet already filled but missing its history. Also, wallets created by the GUI were not loaded at Core's next start. If the node kept syncing and pruned past the wallet's last sync, the wallet would no longer open ("You need to -reindex"). A Bails tester (PolymathBT) hit the second case on Tails with a wallet made during initial sync.
After: the restore page asks for the approximate creation date from the wallet record (YYYY-MM-DD, blank searches all history) and rescans from a day before it. Before any wallet is touched, and again right before the import, the library checks the node's prune height. If the rescan needs pruned blocks, it refuses on the same page and names the date the node still covers, so the user can enter a later date. New wallets are created with
load_on_startup=true, so Core keeps them in step with the chain.Stacked on #113 (its GUI budget is needed here). GitHub retargets this to
bails-v1-pinonce #113 merges.How
_bitcoin_core.parse_creation_date: blank → 0. An ISO date that is already in the future at UTC+14 is refused. Otherwise the result is midnight UTC minus one day, which covers any time zone the record was written in.BitcoinCore.check_history(timestamp): on a pruned node, read the time of the block atpruneheight(getblockstats … ["time"]) and refuse a timestamp less than a day after it. Core picks its start by the highest block time so far, and block times are not monotonic. Unclear output (a non-booleanpruned, a missing or negativepruneheight, a block time that is not a positive int) fails closed.initializecalls it as the last step beforeimportdescriptors, so the CLI is covered too. The GUI'swallet_setup.verifycalls it on the fingerprint page and again just before creating a restore wallet._fingerprint_page(restore only) gains the date row and keeps anyBitcoinCoreErrorfrom that check on the page, as it already did for a fingerprint mismatch.wallet_setup.createaddsload_on_startup=trueand refuses the wallet unless Core returns an object whosewarningsis a list without "could not be updated". Invariant 9,docs/security/model.mdanddocs/developer/gui.mdname the new argument.tests/test_cli.py,AGENTS.md,docs/developer/api.mdandgui.md. The GUI stays under its 2,050, at 2,049.The "I have no wallet record" path still restores from 0. On a pruned node it now gets the clear refusal from
initializebefore import, instead of the half-filled wallet.Validation
bip32modules. CI is green on all 12 jobs.tests/test_gui_restore_date.pychecks that the date reaches verify and_wallets, that a pruned-history refusal stays on the page, that a malformed date never reaches Core, and that a new wallet's record check asks for no date. New tests intests/test_bitcoin_core.pycover date parsing (including tomorrow), the one-day margin, the check running right before import, and malformed pruning output. GUI tests cover the createwallet flag, the failed-setting warning, malformed results, and a wallet name that contains the warning text.Written by Claude at Ben's request; needs review by a responsible human per
docs/developer/AI_POLICY.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01T4RnVngvFFCw3U93bJWLTp