Skip to content

feat(debuglink): report the last confirmation text; reconcile the Solana LUT capability - #123

Open
BitHighlander wants to merge 10 commits into
up/release-protocolfrom
feat/debuglink-confirm-text
Open

BitHighlander wants to merge 10 commits into
up/release-protocolfrom
feat/debuglink-confirm-text

Conversation

@BitHighlander

Copy link
Copy Markdown
Collaborator

Into the canonical 7.15 release protocol branch (PR #112).

1. Solana LUT capability reconciled. python-keepkey's canonical branch (keepkey/python-keepkey#197) and the 7.15 firmware stack already pin dd9c85d (Features.supports_solana_lut_attestation = 29). That commit existed only on keepkey:reconcile/7.15-release and was not on this branch. This merge makes one protocol head serve every pin.

2. DebugLinkState.confirm_title (16) and confirm_body (17). These carry the title and body of the most recent confirmation, as the firmware formatted them and before pagination. They are filled only in DEBUG_LINK builds. Until now tests could read only OLED pixels, so they asserted screen counts, and a count-based test passed on unfixed firmware when raw glyphs paged the same as text. ERC-7730 formatter work (keepkey-firmware block 7, BitHighlander/keepkey-firmware#837, issue #861) needs exact-text assertions.

Diff against up/release-protocol: messages.proto, +9 lines. Field numbers 16 and 17 are unused on every branch.

BitHighlander and others added 10 commits September 10, 2026 21:06
dice_entropy alone is now the MIXED mode: the device commits its own 32-byte
draw as 24 BIP-39 words before the rolls are entered, then derives
seed = SHA256d("KK\x01SM" || draw || SHA256("KK\x01D" || rolls)). With
dice_only the derivation is seed = SHA256(rolls) and the draw is discarded,
matching Coldcard's Dice-Rolls-Only byte for byte.

The mode is a host-side selection so a wallet can explain what is coming --
99 rolls, and for MIXED 24 words to copy down -- before the ceremony starts.
The device still shows a consent screen naming the mode the host chose, so a
host cannot select dice-only silently. In both modes the host's EntropyAck is
consumed and its bytes dropped; the wire flow is otherwise unchanged.

dice_only without dice_entropy is rejected with a SyntaxError.

(cherry picked from commit 451e9a7)
Reports that ResetDevice.dice_only, the on-device consent screen and the
tagged MIXED derivation are implemented. Needed because nanopb skips unknown
fields: a host that sends dice_only to older firmware gets the older ceremony
and a different wallet, with no error. Hosts and the test suite gate on this
bit rather than on a version.

(cherry picked from commit fbaf8ec)
…tocol

python-keepkey's canonical branch already pins dd9c85d, which existed only on
keepkey:reconcile/7.15-release. Merging it here makes one head serve the
firmware and python-keepkey pins.
Tests could only read OLED pixels, so they asserted screen counts, which
passed on unfixed firmware when raw glyphs paged like text. Reporting the
formatted title and body lets them assert the exact text shown.
BitHighlander added a commit to BitHighlander/keepkey-firmware that referenced this pull request Sep 25, 2026
…ot run

Phase 0 of docs/security/HANDOFF-ERC7730-715-FORMATTERS.md (issue #861).
The preload verifier accepted formatter kinds, display opcodes, path shapes
and conditions that the signing runtime cannot execute, so a signed program
could load and then fail after the user had approved the signer, the intent
and earlier fields. Copilot found three narrower cases of this drift.

- erc7730_capabilities.{h,c}: one table of what the runtime executes
  (intent at pc 0, raw fields without conditions, end; formatter kind 1 with
  one role-1 value; path source 1 with index steps; no conditions). The
  verifier and the runtime call the same predicates.
- The verifier walks every value path against the ABI at preload: tuple
  index in range, fixed-array index in [-length, length), dynamic-array
  index in [-64, 64), and a leaf target. The walk table lives in the
  delegate-record buffer, unused until the bindings, so SRAM is unchanged
  (full reserve 18,336 B).
- DebugLinkState.confirm_title/confirm_body (DEBUG_LINK only) record the
  last confirmation, so wire tests assert exact text instead of counts.
- Pins device-protocol 5fec9e6 (keepkey/device-protocol#123 into
  up/release-protocol) and python-keepkey 67f561c (keepkey/python-keepkey#227
  into reconcile/upstream-sync): both canonical heads plus these changes, and
  dp now also carries dd9c85d, which canonical pyk already pinned.

Registry: 92 of 1,450 formats are signable (the plan said 94; two raw fields
read the @.from container, which the runtime never captured). The device
and the compiler's mirror agree on all 1,440 compiled formats.
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