Skip to content

fix(core): raise NotInitialized on BTC-only seed derivation #7035

Merged
romanz merged 3 commits into
mainfrom
romanz/2606/not-initialized
Jun 1, 2026
Merged

fix(core): raise NotInitialized on BTC-only seed derivation #7035
romanz merged 3 commits into
mainfrom
romanz/2606/not-initialized

Conversation

@romanz
Copy link
Copy Markdown
Contributor

@romanz romanz commented Jun 1, 2026

Also add device test for NotInitialized exception

Fixes #6941.

Notes to QA:

trezorctl -v btc get-public-node -n 'm/0h' should return NotInitialized (instead of FirmwareError)

@romanz romanz self-assigned this Jun 1, 2026
@romanz romanz added core Trezor Core firmware. Runs on Trezor Model T and Safe models. bitcoin Bitcoin related translations Put this label on a PR to run tests in all languages labels Jun 1, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f9d27fb5-21cc-453d-9c47-ac400cb38712

📥 Commits

Reviewing files that changed from the base of the PR and between 2904a62 and 64317ac.

📒 Files selected for processing (4)
  • core/.changelog.d/6941.fixed
  • core/src/apps/common/seed.py
  • tests/device_tests/test_basic.py
  • tests/ui_tests/fixtures.json
✅ Files skipped from review due to trivial changes (1)
  • core/.changelog.d/6941.fixed
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/device_tests/test_basic.py
  • core/src/apps/common/seed.py

Walkthrough

This PR extracts a shared raise_if_not_initialized() helper in apps.common.seed and replaces many ad-hoc storage_device.is_initialized() checks across the codebase with calls to this helper. Changes touch seed derivation paths (THP and v1), management handlers, base/Cardano/Evolu/WebAuthn handlers, add a test enforcing failure on uninitialized devices, updates UI test fixtures, and adds a changelog entry.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • obrusvit
  • andrewkozlik
  • mmilata
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(core): raise NotInitialized on BTC-only seed derivation' directly describes the main objective of the PR—handling the NotInitialized exception for Bitcoin-only firmware seed derivation.
Description check ✅ Passed The PR description is brief but sufficient, referencing the linked issue and mentioning the addition of a device test. While it doesn't follow the provided template, it conveys the essential information about the changes.
Linked Issues check ✅ Passed The PR successfully addresses issue #6941 by adding a shared raise_if_not_initialized() helper and applying it across multiple modules to properly handle the NotInitialized exception when device is not initialized.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the shared initialization check mechanism and applying it consistently across relevant modules, with a test added to verify the behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch romanz/2606/not-initialized

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@trezor-bot trezor-bot Bot added this to Firmware Jun 1, 2026
@github-project-automation github-project-automation Bot moved this to 🔎 Needs review in Firmware Jun 1, 2026
@romanz romanz moved this from 🔎 Needs review to 🏃‍♀️ In progress in Firmware Jun 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

en main(all)

model device_test click_test persistence_test
T2T1 test(all) main(all) test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all) test(all) main(all)
Translations

cs main(all)

model device_test click_test
T2T1 test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all)

de main(all)

model device_test click_test
T2T1 test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all)

es main(all)

model device_test click_test
T2T1 test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all)

fr main(all)

model device_test click_test
T2T1 test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all)

pt main(all)

model device_test click_test
T2T1 test(all) main(all) test(all) main(all)
T3B1 test(all) main(all) test(all) main(all)
T3T1 test(all) main(all) test(all) main(all)
T3W1 test(all) main(all) test(all) main(all)

Latest CI run: 26755369536

@romanz romanz force-pushed the romanz/2606/not-initialized branch from 8b9afc2 to 0d681ed Compare June 1, 2026 10:53
@romanz romanz force-pushed the romanz/2606/not-initialized branch from 0d681ed to 2904a62 Compare June 1, 2026 11:20
@romanz romanz moved this from 🏃‍♀️ In progress to 🔎 Needs review in Firmware Jun 1, 2026
@romanz romanz marked this pull request as ready for review June 1, 2026 11:23
@romanz romanz requested a review from M1nd3r June 1, 2026 11:23
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
core/src/apps/common/seed.py (1)

174-175: ⚡ Quick win

Consider aligning exception type with the new helper for consistency.

The function _get_seed_without_passphrase() still raises a generic Exception when the device is not initialized, while the new helper raises trezor.wire.NotInitialized. This creates inconsistency in exception types across the module.

Updating this location would complete the centralization and ensure uniform error handling contracts for callers.

♻️ Proposed alignment
 `@cache.stored`(APP_COMMON_SEED_WITHOUT_PASSPHRASE)
 def _get_seed_without_passphrase() -> bytes:
-    if not storage_device.is_initialized():
-        raise Exception("Device is not initialized")
+    raise_if_not_initialized()
     return mnemonic.get_seed(progress_bar=False)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/apps/common/seed.py` around lines 174 - 175, Replace the generic
Exception raised in _get_seed_without_passphrase when
storage_device.is_initialized() returns False with the same NotInitialized
exception used by the new helper: import or reference trezor.wire.NotInitialized
and raise NotInitialized() (or re-raise the helper's NotInitialized) instead of
Exception("Device is not initialized") so the function and callers use the
consistent exception type.
tests/device_tests/test_basic.py (1)

66-74: 💤 Low value

Consider more explicit conditional for readability.

The tuple indexing with boolean (expected[session.test_ctx.is_thp()]) is correct but relies on implicit False=0, True=1 conversion. A conditional expression or if-statement would be more immediately readable:

expected = (
    messages.FailureType.InvalidSession
    if session.test_ctx.is_thp()
    else messages.FailureType.NotInitialized
)
assert resp.code == expected
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/device_tests/test_basic.py` around lines 66 - 74, Replace the
boolean-indexed tuple in test_not_initialized with an explicit conditional to
improve readability: instead of using expected[session.test_ctx.is_thp()],
compute expected by checking session.test_ctx.is_thp() and selecting
messages.FailureType.InvalidSession or messages.FailureType.NotInitialized
accordingly, then assert resp.code == expected; update references to
messages.FailureType and session.test_ctx.is_thp() in that test to reflect this
clearer conditional.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/.changelog.d/6941.fixed`:
- Line 1: Update the changelog entry text "[T2B1,T2T1,T3B1,T3T1] Return an
explicit error when try to derive seed on Bicoin-only firmware." by correcting
the typo "Bicoin-only" → "Bitcoin-only" and fixing the grammar "when try" →
"when trying" so the line reads e.g. "[T2B1,T2T1,T3B1,T3T1] Return an explicit
error when trying to derive seed on Bitcoin-only firmware."

In `@core/src/apps/common/seed.py`:
- Around line 89-92: Move the initialization precondition check before the
business logic: call raise_if_not_initialized() prior to checking
ctx.cache.is_set(APP_COMMON_SEED). Specifically, in the seed logic where
ctx.cache.is_set(APP_COMMON_SEED) is currently checked, reorder the statements
so raise_if_not_initialized() runs first and then perform the cache check to
preserve the fail-fast behavior like the Cardano variant.

---

Nitpick comments:
In `@core/src/apps/common/seed.py`:
- Around line 174-175: Replace the generic Exception raised in
_get_seed_without_passphrase when storage_device.is_initialized() returns False
with the same NotInitialized exception used by the new helper: import or
reference trezor.wire.NotInitialized and raise NotInitialized() (or re-raise the
helper's NotInitialized) instead of Exception("Device is not initialized") so
the function and callers use the consistent exception type.

In `@tests/device_tests/test_basic.py`:
- Around line 66-74: Replace the boolean-indexed tuple in test_not_initialized
with an explicit conditional to improve readability: instead of using
expected[session.test_ctx.is_thp()], compute expected by checking
session.test_ctx.is_thp() and selecting messages.FailureType.InvalidSession or
messages.FailureType.NotInitialized accordingly, then assert resp.code ==
expected; update references to messages.FailureType and
session.test_ctx.is_thp() in that test to reflect this clearer conditional.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 748d9590-341b-45b2-a5f9-d8ea73bb3eed

📥 Commits

Reviewing files that changed from the base of the PR and between 501a0f8 and 2904a62.

📒 Files selected for processing (18)
  • core/.changelog.d/6941.fixed
  • core/src/apps/base.py
  • core/src/apps/cardano/seed.py
  • core/src/apps/common/seed.py
  • core/src/apps/evolu/get_node.py
  • core/src/apps/management/apply_flags.py
  • core/src/apps/management/apply_settings.py
  • core/src/apps/management/backup_device.py
  • core/src/apps/management/change_wipe_code.py
  • core/src/apps/management/get_next_u2f_counter.py
  • core/src/apps/management/recovery_device/__init__.py
  • core/src/apps/management/sd_protect.py
  • core/src/apps/management/set_brightness.py
  • core/src/apps/management/set_u2f_counter.py
  • core/src/apps/webauthn/add_resident_credential.py
  • core/src/apps/webauthn/remove_resident_credential.py
  • tests/device_tests/test_basic.py
  • tests/ui_tests/fixtures.json

Comment thread core/.changelog.d/6941.fixed Outdated
Comment thread core/src/apps/common/seed.py Outdated
Copy link
Copy Markdown
Contributor

@M1nd3r M1nd3r left a comment

Choose a reason for hiding this comment

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

utACK

Please, fix the issues mentioned by CodeRabbit.

@romanz romanz force-pushed the romanz/2606/not-initialized branch from 2904a62 to 64317ac Compare June 1, 2026 12:38
@romanz romanz merged commit 560a071 into main Jun 1, 2026
170 checks passed
@romanz romanz deleted the romanz/2606/not-initialized branch June 1, 2026 13:16
@trezor-bot trezor-bot Bot moved this from 🔎 Needs review to 🤝 Needs QA in Firmware Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bitcoin Bitcoin related core Trezor Core firmware. Runs on Trezor Model T and Safe models. translations Put this label on a PR to run tests in all languages

Projects

Status: 🤝 Needs QA

Development

Successfully merging this pull request may close these issues.

Return NotInitialized error also at BITCOIN_ONLY=1

2 participants