Skip to content

test(7.15): ERC-7730 formatter mirror and runtime evidence (block 7b) - #228

Open
BitHighlander wants to merge 15 commits into
release/715-stack07-phase0from
release/715-stack07b-formatters
Open

BitHighlander wants to merge 15 commits into
release/715-stack07-phase0from
release/715-stack07b-formatters

Conversation

@BitHighlander

Copy link
Copy Markdown
Contributor

Stacked on #227. Mirrors firmware block 7b (BitHighlander/keepkey-firmware, Phase A of the ERC-7730 formatter plan).

  • DEVICE_CAPABILITIES now includes tokenAmount, addressName, the @.from/@.to containers (calldata only) and literal paths.
  • It also carries the value-class rules the device checks at preload.
  • The registry test asserts that the device and the compiler agree on every compiled format, and that exactly 812 formats are signable.
  • Compiler test expectations move to the next unexecuted feature for each fixture.

BitHighlander and others added 12 commits September 25, 2026 04:00
…ants

Phase A of the ERC-7730 formatter plan. The device now executes
tokenAmount (value, token, threshold, message, native aliases),
addressName, @.from/@.to (calldata only) and signed constants, and
type-checks every argument at preload. Mirror that table, including the
value classes: amount and threshold are integers, token and addressName
values are addresses, raw literals are integers, addresses or strings, and
an alias set names at most four addresses.

The registry test now asserts 812 signable formats (from 92). The device
still refuses addressName and tokenAmount over bytes32/uint256 words that
pack an address or an encrypted amount.
Phase B. The device executes display opcodes 2 and 3 as one run directly
after the plain intent, showing each fragment and value as a numbered part.
Mirror the opcodes and the run rule, and trim fragment edges: each part is
its own screen, and the device escapes edge spaces. The registry test now
asserts 954 signable formats.
Phase C. Mirror the device's new formatters and their argument classes:
a date encoding must be the string "timestamp" or "blockheight", unit
decimals a one-byte literal and the prefix a flag, an enum map at most 16
entries, an NFT collection an address, and @.value an unsigned value. The
registry test now asserts 1,138 signable formats.
…elds

Phase D. Mirror the device: display opcodes 5-8, the "every element"
path step reached through tuples only, iteration over one array at a time
in calldata definitions, every field inside it reading that array, and only
the "optional" condition (always shown). A path ending in its every-element
step is also a value when its element is a leaf (address[] recipients). The
registry test now asserts 1,294 signable formats.
Phase E1. Emit amountPath and spenderPath as formatter roles 17 and 18
beside the callee (15), and mirror the device: embedded calldata executes
for calldata definitions, shown under a blind-sign warning in 7.15. The
registry test now asserts 1,326 signable formats.
Phase E2. When the device asks for an embedded call's definition
(recursion_depth >= 1) and the catalog holds none, reply with the empty
chunk (offset 0, total_length 0, no data) instead of failing: firmware 7.15
then shows the inner call under a blind-sign warning, and 7.16 rejects it.
A top-level lookup that fails is still an error.
The compiler's device-capability mirror now refuses what the firmware
verifier refuses after the 7b audit:
- signer text (labels, threshold messages, unit bases, enum labels) over
  64 bytes, and unit decimals over 77;
- an embedded call's callee given as a literal, and an embedded call used
  as an intent value part;
- tables beyond the device's limits (alias sets, enum maps).
Numeric constants are values of every width, as on the device. The string
table is parsed before the literals that reference it.

The registry lockstep test still asserts 1,326 signable formats; its
comment now says what the count means: preload-accepted, not "runs end to
end".
The Phase 0-E ERC-7730 runtime wire tests move here from
keepkey-firmware's scripts/emulator/test_stack07_regressions.py. Only
python-keepkey tests get OLED captures in the release PDF. Firmware
keeps its 7a contracts and imports Erc7730Harness from this module.

tests/test_msg_ethereum_erc7730_runtime.py (34 tests, full product,
7.15.0+):
- every test that signs first signs the same transaction on the
  ordinary path and requires an identical signature;
- the showcased walk runs last, because only its frames are kept;
- the ordinary review that follows is not captured: it is unchanged,
  and the report's frame picker would otherwise prefer its
  per-transaction data hash over the certified screens;
- new: a call at depth two is shown blind, and the device requests no
  definition deeper than depth one;
- test_inner_containers_and_depth_two is renamed
  test_inner_calls_read_their_own_containers: it has no depth-2 call.

generate-test-report.py:
- new section EX (7.15.0): what the device executes, where each fact
  comes from, the 7.15 blind-sign rule for embedded calls (7.16
  rejects), and the known fail-closed limits;
- rows EX1-EX34 with the OLED screens each test must capture;
- four full-sequence flows;
- the module is must-run from 7.15.0 on the full product.
The existing ER section (7.19.0) is unchanged.
… tests

Mirror (device_refusal), in step with the firmware verifier:
- an enum's value must come from the signed data, never a constant;
- an interpolated-intent value part may not show a signer constant;
- the bindings table (section 8) is bounded at 64 like the others.
The registry still has 1,326 signable formats.

Runtime tests:
- _certified now also requires that the device asked for the
  definition, so a walk that silently took the ordinary path cannot
  pass;
- a Wanchain transaction (tx_type) is refused on the certified path
  before any screen (EX35);
- the containers test distinguishes the outer spenderPath from the
  default authority.
Report: EX26 no longer claims an address stays on one OLED page.
The device now shows a mapped enum value as "label (value)" followed by "label set by signer", like a unit's base. The runtime test and report row EX13 expect it.
Re-audit round 3:
- No calldata test declined an ERC-7730 screen. The new test declines
  each of these and requires ActionCancelled and no final sign screen:
  a blind-sign warning (a value too long to capture, no inner
  definition, a refused inner definition), the second part of a split
  value, and an inner field. It is report row EX36. It fails when the
  long-value warning ignores a decline.
- The parallel-arrays test now checks each element's amount as well as
  its token.
_walk can decline by confirmation title (cancel_title).
…tests

Re-audit round 4 and its completeness critic:
- Only a raw field may show a signer constant. A constant formatted
  as an amount, date, unit, enum, NFT or address looks decoded, so the
  mirror refuses it, as it refuses a constant embedded value or
  authority (callee already). The value classes return to what they
  were before D1. The official registry uses no such constant: 1,326
  formats remain signable.
- Lockstep gaps that predate this block, found by the re-audit:
  - fixed ABI arrays over 64 elements are refused;
  - program strings must be printable text;
  - signed enum keys use minimal two's complement (-128 is 0x80), so
    the device no longer refuses them.
  Each is tested through the mirror and the firmware validator
  together, and fails when reverted.

Runtime tests:
- test_only_a_raw_field_shows_a_signer_constant replaces
  test_numeric_constants_are_values;
- a long typed-data value points to the walk, with no blind warning
  (EX37);
- a refused inner definition streamed over several chunks;
- two embedded calls where the first is refused and the second is
  still clear-signed (EX38);
- unit and enum marks now come before the value.
@BitHighlander BitHighlander changed the title test(7.15): ERC-7730 Phase A capability mirror (tokenAmount, addressName) test(7.15): ERC-7730 formatter mirror and runtime evidence (block 7b) Sep 25, 2026
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