Skip to content

Drop the checksum notice the last-word filter made unreachable - #15

Merged
oroderico merged 1 commit into
mainfrom
drop-unreachable-checksum-notice
Aug 16, 2026
Merged

Drop the checksum notice the last-word filter made unreachable#15
oroderico merged 1 commit into
mainfrom
drop-unreachable-checksum-notice

Conversation

@oroderico

Copy link
Copy Markdown
Owner

Restore announced Invalid checksum after word entry. Nothing can reach that screen any more.

Why it is unreachable

The last word of a whole mnemonic is entered under seedtool_final_word_candidates, and both entry methods narrow to that set rather than merely showing it — enter_word builds its candidates with seedtool_words_with_prefix_in, and enter_word_number gates its digits with seedtool_next_digits_in and seedtool_word_number_in. Neither can return a word outside it.

Stepping back clears the word (words[--index][0] = '\0'), so the last word is always entered last, against a filter rebuilt from the words currently standing. restore_mnemonic has one caller and count is only ever 12 or 24, so last_of_whole is always true for that word and the filter always applies. final_word_filter_is_exact already proves the set is exact in both directions.

So what leaves enter_mnemonic_words with success has a checksum that holds, and the condition guarding the notice is never true.

The notice (ef78374, 8 Aug) predates the filter (f3736bd, 15 Aug) by a week. The filter's own commit said the check was being moved to where it prevents the mistake instead of reporting it. Only the moving happened.

The reader is not left without a gate

review_and_confirm reads the checksum on every redraw and leaves Continue untakeable while it fails. That is the path an edit on the review screen still takes, and it is untouched here. Removing the notice removes an announcement, not a check.

Scope

Four lines of code, and nothing added:

  • main/seedtool_app.c — the condition and the notice. The join_words + seedtool_validate_mnemonic pair that existed only to feed it goes with them, so restore does one fewer join and validation per pass.
  • host/origo_simulator.c — the row for it in the notices table.
  • README.md — no longer cites Invalid checksum as what would happen; the paragraph is reflowed, which is where most of the line count comes from.

The 16-line comment is replaced, not deleted. The old one justified a screen that no longer exists; the new one records why nothing is announced there, so the next reader does not add it back.

Not touched

The other twenty notice() call sites are real error paths. Too long for a QR on the Compact SeedQR looks similar but is not: it guards the bool the renderer returns, not a condition made impossible upstream. Removing that one would mean continuing silently after a failed render.

Verification

Host self-test, the 52 Python tests, and a firmware build the ELF audit passes at 303920 bytes — 32 fewer than main.

Confirmed on a TTGO T-Display: a 24-word restore offers exactly the eight candidates the checksum allows for its last word, and nothing else. That is the property the removal rests on, so it was checked on the device rather than argued from the simulator.

Restore announced "Invalid checksum" after word entry. Nothing can
reach that screen any more.

The last word of a whole mnemonic is entered under
seedtool_final_word_candidates, and both entry methods narrow to that
set rather than merely showing it - enter_word builds its candidates
with seedtool_words_with_prefix_in, and enter_word_number gates its
digits with seedtool_next_digits_in and seedtool_word_number_in.
Stepping back clears the word, so the last one is always entered last,
against a filter rebuilt from the words currently standing.
restore_mnemonic has one caller and count is only ever 12 or 24, so
that filter always applies. What leaves enter_mnemonic_words with
success has a checksum that holds.

The notice predates the filter by a week. The filter's own commit said
the check was being moved to where it prevents the mistake instead of
reporting it; only the moving happened.

The reader keeps a gate either way: review_and_confirm reads the
checksum on every redraw and leaves Continue untakeable while it fails.
That is the path an edit on the review screen still takes, and it is
untouched here.

The comment is replaced rather than deleted, so the next reader learns
why the announcement is absent instead of restoring it.

Verified with the host self-test, the 52 Python tests and a firmware
build the ELF audit passes at 303920 bytes, 32 fewer than main.
Confirmed on a TTGO T-Display: a 24-word restore offers exactly the
eight candidates the checksum allows for its last word, and nothing
else.
@oroderico
oroderico merged commit b3b1d2b into main Aug 16, 2026
3 checks passed
@oroderico
oroderico deleted the drop-unreachable-checksum-notice branch August 16, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant