wallet: Ask for the record fingerprint before the cards - #104
Draft
BenWestgate wants to merge 13 commits into
Draft
BenWestgate wants to merge 13 commits into
BenWestgate wants to merge 13 commits into
Conversation
Apply the established majority-case interpretation to standalone correction while preserving immutable context, entered edit semantics, and disclosure accounting. Account the normalized retry frontier even when the first optional search reaches its deadline after finding a candidate, so cumulative capture mass remains fail-closed. Fixes #37.
Give standalone correction a stable status contract: 0 for already-valid input, 1 when a suggestion is emitted, 2 for command or input syntax errors, and 3 when no usable suggestion is emitted. Keep incomplete best-effort suggestions at status 1 and document status 3 only for incomplete searches without a usable suggestion. Fixes #39.
Remove unreachable creation guards and the permanently false correction ambiguity field, align the CLI test Core stub with production, and move reference-only correction helpers out of the installed package.\n\nSecurity: fail-closed correction and wallet behavior are unchanged.\n\nRefs #38.
Gate restore and existing-seed wallet initialization on the independently recorded BIP32 master fingerprint before any Bitcoin Core wallet mutation. Keep the correction path from disclosing or reusing a fingerprint derived from the candidate being authenticated. Fixes #30.
When RIPEMD-160 is unavailable, a valid standard Bails identifier cannot be checked. Preserve the Bails-alpha SHA-256 result and distinguish that inconclusive state from a completed identifier mismatch, so the no-record restore prompt does not claim the cards are wrong. Keep the independent fingerprint and explicit operator-confirmation boundary unchanged. Refs #79
The no-record restore flow can no longer claim a standard Bails identifier mismatch when RIPEMD-160 is unavailable. Record that platform-dependent inconclusive outcome in both the security model and invariant so reviewers can distinguish it from a completed comparison. Refs #79
An existing hex seed or codex32 master secret previously reached the wallet-record fingerprint check only after new recovery cards had been generated and confirmed. Check the typed record immediately after parsing the source, before any card output or ceremony. Preserve the explicit recordless path at the same early decision point, and pass the checked result through to wallet initialization so it is not prompted twice. Cover matching, mismatching, and recordless flows for both source encodings. Refs #30.
Translate Ctrl-C or EOF at the early wallet-record gate for ms32 create --existing into the existing wallet-setup interruption path. This keeps an operator from being told to invalidate a pre-existing recovery card before any new share ceremony has started. Add a focused regression proving the interruption occurs before share creation or output and preserves the valid-backup message.
Reassign the expected_fingerprint argument instead of copying it into a local, and give existing_secret its None default before the source checks instead of in an else branch. Behavior is unchanged. The installed package drops from 5161 to 5159 logical review lines, which keeps the integrated #7/#42/#57/#46/#80/#81 tip under the <5200 budget. Security: the record gate still runs before any card is generated or shown, and interrupts at that gate still raise _WalletSetupInterrupted. Validation: ruff check, ruff format --check, mypy src/codex32, and pytest (918 passed, with and without -O). Refs #81, #38. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018az69UX4773mYohXAtE8kD
A raw seed imported with create --existing was assigned a temporary random identifier for the no-record safety screen, then assigned a different random identifier when the new share set was created. Reuse the first identifier as the share-set identifier so the safety screen describes the backup that will actually be produced.\n\nExtend the recordless-creation regression to require the displayed, emitted, and imported identifiers to agree.\n\nRefs #30
Ben authorized raising the budget so #91 fits. The stack tip with the open fix PRs was at 5,197 of 5,200, and #91 adds 26 lines. Update the enforcing test and both places that document the number. Claude-Session: https://claude.ai/code/session_015CuLXqAvAovfoVcUmmogwa
`ms32 wallet` and `ms32 create --existing` hid the recovered master fingerprint while confirming a correction (#57), so a wrong correction was caught only after the operator accepted it and typed the record. Ask for the record first: before the shares in `ms32 wallet` and before the seed in `ms32 create --existing`. A correction that completes the secret then says whether it matches the record, without showing the fingerprint, and the record picks between equally likely corrections. The final identity check, the retry on mismatch and the Enter path for no record work as before; without a record nothing is shown until the recordless gate. Ctrl-C at the moved prompt still says the existing cards are valid. Closes #91 Claude-Session: https://claude.ai/code/session_015CuLXqAvAovfoVcUmmogwa
BenWestgate
force-pushed
the
codex/30-existing-fingerprint-before-shares
branch
4 times, most recently
from
October 2, 2026 08:59
9f88b21 to
1d5b6f5
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Ben · project thread
Before:
ms32 walletandms32 create --existinghid the recovered master fingerprint while a correction was being confirmed (#57). The wallet record was typed only after the cards, so a wrong correction was caught after the operator had accepted it.After: both commands ask for the record fingerprint first, before the cards in
walletand before the secret increate --existing. A suggested correction that completes the secret says "Master fingerprint matches your wallet record" or "does not match", without showing the value, and the record picks between equally likely corrections. The final identity check, the re-ask on mismatch and Enter for no record behave as before. With no record, nothing is shown until the recordless gate. Ctrl-C at the moved prompt still says the existing cards are valid.How:
cli._recordasks for the record and is called before input._recorded_fingerprintreplaces the post-input prompt with the verify-and-re-ask loop._cli_input._completedprovisionally recovers the secret when the candidate is the last neededmsshare, and_fingerprint_matcherand_confirm_correctioncompare it with the record. The user guide's restore step andcreate --existingparagraph follow the new order.Needs a security review before ready (recovery). What to check: the record preview prints only matches or does not match, never the fingerprint (
test_record_preview_and_ranking_never_show_the_fingerprint,test_wallet_checks_a_corrected_final_share_against_the_typed_record). The provisional secret is used only for that comparison, and a candidate the operator accepts still goes throughverify_identitybefore Bitcoin Core is changed. The record is the last tie-breaker in_best, after rank, Hamming weight and CRC padding, so it can only choose among equally likely corrections and never promotes a less likely one.Budget: the first commit raises it from < 5200 to < 5250 at Ben's request (
tests/test_cli.py,docs/developer/api.md,AGENTS.md). This branch is at 5224. On #98's tip it merges cleanly at 5210, and 5217 with #99 and #100. 936 tests pass; ruff, mypy and the touched files under-Oare clean.Conflicts with #101 in two
_confirm_correctioncalls, where each PR adds one argument. Keep both:_confirm_correction(candidates[0], accepted, basis, str(error), fingerprint, record), and the same in_creation_source.Closes #91
🤖 Generated with Claude Code
https://claude.ai/code/session_015CuLXqAvAovfoVcUmmogwa
Generated by Claude Code