Skip to content

feat(protocol): 7.15 release additions — hive signing (1614-1617), clearsign identity icons, thorchain denom, ripple memo, zcash#112

Open
BitHighlander wants to merge 11 commits into
masterfrom
up/release-protocol
Open

feat(protocol): 7.15 release additions — hive signing (1614-1617), clearsign identity icons, thorchain denom, ripple memo, zcash#112
BitHighlander wants to merge 11 commits into
masterfrom
up/release-protocol

Conversation

@BitHighlander

@BitHighlander BitHighlander commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Upstream branch → upstream master. keepkey:up/release-protocol is the single protocol PR for the firmware 7.15/RC18 release line. It replaces the mis-structured #111 and remains blocked on human review.

Additions

All changes are additive; existing field numbers and wire behavior remain compatible.

  • Hive signing: HiveSignMessage/HiveSignedMessage (1614/1615) and HiveSignOperations/HiveSignedOperations (1616/1617). 1610-1613 remain reserved for NEAR.
  • Clearsign identity icons on LoadClearsignSigner: bounded RLE icon data, icon_width, icon_height, and the legacy-compatible persist field.
  • Earlier 7.x additions already accumulated on this branch: thorchain any-denom, Ripple memo, and Zcash messages.

RC18 security boundary

  • Clearsign signer identities are session-only in firmware 7.15. The persist field is retained for wire compatibility and future authenticated storage, but RC18 rejects persist=true; the protocol comments no longer promise unauthenticated flash persistence.
  • Orchard/Zcash privacy messages remain defined for wire compatibility and future work. RC18 compiles out the Orchard handlers and refuses the privacy build option until a separately reviewed constant-time Pallas/RedPallas backend exists.
  • Transparent Zcash remains in the regular RC18 image.

Contract hardening already included

  • The icon encoding is RLE, with draw_bitmap_mono_rle() as decoder of record. The field documents the RUN/LITERAL grammar, invalid encodings, golden vector, and exact-consumption rule.
  • icon_width is capped at 40 pixels so it cannot overwrite the alias, fingerprint, or unverified-signer warning.

Validation and dependent gates

Adds the device-protocol messages required by the upcoming firmware release:

- thorchain: ThorchainMsgSend.denom (field 11) — non-RUNE assets (TCY, RUJI, IBC)
- ripple:    RippleSignTx.memo (field 7) — XRP->THORChain swap routing
- hive:      full Hive support — HiveGetPublicKey(s), HiveSignTx,
             HiveSignAccountCreate/Update (MessageType 1600-1609)
- zcash:     clear-signing + Orchard shielded protocol (transparent in/out/ack,
             PCZT, FVK, display-address)

All additions are new optional fields / new message types — additive and
backward-compatible. lib/ bindings are gitignored build artifacts; package.json
build:js/json updated to include messages-hive.proto.
Extends msg 117 for the persistent-identity model ("KeepKey + identity"):
- icon (bytes, <=384): 1bpp mono identity logo, shown on load-confirm, at the
  start of every clearsign it vouches for, and on boot.
- icon_width / icon_height: icon dims (<=64).
- persist (bool): store the identity in flash so it survives reboot; default
  RAM-only (backward compatible with current behavior).

Proto + nanopb options only; the firmware handler + flash storage consume
these in a follow-up. Fork only — never PR to keepkey/device-protocol.
…signBuffer contract

Signature over SHA256(raw message bytes) only: no chain_id prepend, no
message prefix. 1610-1613 skipped: NEAR holds them on master.
…sed generic op signing

Host serializes; firmware parses the Graphene bytes and clear-signs the
phase-1 op table (vote 0, comment 1, custom_json 18). Op types 2/9/10 are
permanently excluded — dedicated messages keep their stronger invariants.
… doc was wrong

LoadClearsignSigner.icon was documented as a "1bpp mono row-major bitmap",
but firmware feeds it to draw_bitmap_mono_rle() (lib/board/draw.c), which
reads signed int8 RLE packets and byte-valued pixels. A client following the
protobuf comment would ship packed bits into an RLE decoder and render a
garbled or missing identity logo on a trust screen.

The RLE is intentional, not the doc: firmware permits icon_width/icon_height
up to 64, but a packed 1bpp 64x64 needs 512 bytes and the cap is 384 — the
documented format is arithmetically impossible at the dimensions the firmware
itself accepts. So specify the grammar rather than change the decoder.

Documents the exact packet grammar (RUN [n][v] for n>0, LITERAL [n][v1..v-n]
for n<0, n==0 invalid, row-major fill, int8 bounds), states that pixels are
byte-valued intensity rendered as value*color/100 (not a 1-bit mask), names
draw_bitmap_mono_rle() as the decoder of record, and adds a golden vector
(03 FF FF 00, w=2 h=2 -> FF FF FF 00) verified against that decoder.

Comment-only: no field, number, or wire behaviour changes.
…h cap allows text overwrite

Two contract errors found in review of the RLE grammar added in f7b4580.

1) The doc claimed a LITERAL may carry up to 128 bytes, i.e. n = -128 (0x80).
   The decoder's counter is `int8_t nonsequence` and it computes
   `nonsequence = -sequence`, so -(-128) = 128 does not fit and wraps back to
   -128 — failing the `nonsequence > 0` invariant. Under NDEBUG (release) the
   assert is compiled out and decoding proceeds with a negative counter
   (signed-overflow UB); on debug/emulator builds it asserts. The load handler
   validates only length and dimensions, so a spec-valid icon could fault the
   device during its own mandatory confirmation. Restrict to [-127,-1] and mark
   0x80 explicitly invalid; encoders split a 128-byte literal in two.

2) icon_width was documented (and enforced) as <= 64, but the confirm screen's
   icon column is LEFT_MARGIN_WITH_ICON = 40 and title/body text starts at
   x=40. stage_runtime_icon() places any icon wider than the column at x=0
   ("would clip the title/body" — its own comment), and confirm_sm draws the
   icon AFTER the text. So a host-supplied 64px icon overwrites 24 columns of
   the alias, fingerprint and the "NOT verified by KeepKey" warning — on the
   screen whose entire purpose is that warning. Cap width at 40.

Firmware must enforce both independently — a hostile host is not bound by this
comment. Companion firmware change rejects 0x80 in the decoder and caps
icon_width at 40 in fsm_msgLoadClearsignSigner.

Comment-only: no field, number, or wire behaviour changes.
…RAM-only claim

Two contract errors found in review.

1) The "a packed 1bpp 64x64 would need 512 bytes and cannot fit the cap"
   rationale is obsolete and misleading. Once icon_width was capped at 40, that
   arithmetic stopped applying: a packed icon at the LEGAL maximum geometry
   (40x64) is 320 bytes and WOULD fit the 384-byte cap. RLE is the format
   because draw_bitmap_mono_rle() is the decoder of record and every bundled
   image already uses it — not because packed wouldn't fit. Say that instead.

2) "Loaded signers live in RAM only and are cleared on reboot" contradicts
   persist=7 in the same message, which writes the identity to flash to survive
   reboot. State the actual behaviour: RAM-only by default, durable with
   persist=true.

Also documents the exactness rule the firmware now enforces (no run straddling
the image, entire input consumed), so encoders learn it from the spec rather
than from a silently-missing logo.

Comment-only: no field, number, or wire behaviour changes.
Add optional signature + signer_key_id so a host can attest a token's
mint->symbol mapping with a clear-sign signer key (LoadClearsignSigner). The
firmware verifies; producing these signatures is a follow-up. Backward
compatible — existing hosts set neither field.
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