Skip to content

test(insight): EVM clear-signing integration tests + metadata signer - #24

Merged
BitHighlander merged 2 commits into
masterfrom
feat/insight-clearsign-tests
Jun 29, 2026
Merged

test(insight): EVM clear-signing integration tests + metadata signer#24
BitHighlander merged 2 commits into
masterfrom
feat/insight-clearsign-tests

Conversation

@BitHighlander

Copy link
Copy Markdown
Owner

Insight (EVM clear-signing) integration tests + signer

Test layer for the firmware EVM clear-signing feature ("Insight"), now merged to firmware alpha (keepkey-firmware PR #257, merge 1f421a8f). Adds the canonical metadata serializer/signer and the device-class + offline tests that exercise it.

keepkeylib/signed_metadata.py

  • Canonical metadata serializer matching the firmware parser byte-for-byte (the SHA-256 signed region — version..key_id — is identical on both sides; signature + recovery are excluded by both).
  • key_id default 0 → 3. The test signer (SignIdentity index 0 of the BIP-39 test mnemonic) derives the pubkey embedded at firmware slot 3 — the #if DEBUG_LINK CI slot. Embedding key_id=0 (the old default = production slot) made every test vector verify-fail as MALFORMED. assert_test_key_matches_slot3() pins the invariant. Production/Pioneer callers must pass key_id=0 explicitly and sign with the offline production key.
  • sign_metadata fails loud if ecdsa is missing (was a silent zero-signature that the device rejects as MALFORMED, disguising the real cause).
  • Pure-python keccak256 + EIP-155 / EIP-1559 RLP sighash helpers, so a metadata blob's tx_hash binds the real signing digest. Cross-checked against the device: recovering an existing erc20-approve signature over eth_sighash_legacy yields the test mnemonic's m/44'/60'/0'/0/0 address.

tests/test_msg_ethereum_clear_signing.py

  • All vectors key_id=3; gated at requires_firmware("7.15.0") (the feature ships in the 7.15.0 tree).
  • New device-class cases: full tx-hash binding happy path (signs, recovered signer matches), replay reject (metadata bound to tx A, signing tx B → "Metadata does not match signed transaction", no signature), AdvancedMode gate (off + unknown contract → hard reject; on → sign; native ERC-20 unaffected), cancel-clears-metadata (no stale reuse).

scripts/generate-test-report.py

  • SECTIONS 'V' (EVM Clear-Signing) min_firmware 7.15.1 → 7.15.0; added V9–V12 mapping the new device-class tests with OLED screenshot expectations so report-driven Phase-1 capture includes them.

Verification

  • Offline (PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python): serializer/keccak/sighash + slot-3 assertion green.
  • Emulator (CI-faithful docker compose up --build python-keepkey against kkemu built from firmware alpha): all 28 clear-signing tests pass; 356 OLED screenshots captured, including the INSIGHT VERIFIED icon screen + decoded method/contract/args, the replay reject, and the AdvancedMode gate.

Note

A separate pre-existing emulator failure in test_msg_ethereum_erc20_uniswap_liquidity.py::test_sign_uni_approve_liquidity_ETH is unrelated (fails at the standard tx-confirm, AdvancedMode-invariant; its two sibling tests already skipTest("Skip until emulator issue resolved")).

After this merges, bump the firmware deps/python-keepkey pin (alpha) to the new master tip so firmware CI runs these tests.

…ests

Integration-test layer for the firmware Insight clear-signing feature
(keepkey-firmware feat/evm-clear-signing-alpha, PR #257).

signed_metadata.py:
- Fix the key_id/slot footgun: serialize_metadata defaults key_id=3, the
  DEBUG_LINK CI slot whose pubkey == firmware METADATA_PUBKEYS[3] (the test
  signer derives to slot 3, NOT slot 0). Production/Pioneer callers must pass
  key_id=0 explicitly. assert_test_key_matches_slot3() pins this invariant.
- sign_metadata fails loud if `ecdsa` is missing (was a silent zero-signature
  that firmware would reject as MALFORMED, disguising the real cause). Signs the
  identical byte range firmware hashes (version..key_id, excl. sig+recovery).
- Add pure-python keccak256 + EIP-155/EIP-1559 RLP sighash helpers so a metadata
  blob's tx_hash binds the REAL signing digest. Cross-checked against the device:
  recovering an existing erc20-approve signature over eth_sighash_legacy yields
  the test mnemonic's m/44'/60'/0'/0/0 address.

test_msg_ethereum_clear_signing.py:
- All vectors use key_id=3.
- New offline (verified green here, 12/12): slot-3 pubkey assertion, key_id=3
  default, keccak256 known vectors.
- New device-class cases (run on the kkemu/DEBUG_LINK emulator): tx_hash binding
  happy path (signs + recovers correct signer), replay reject (metadata bound to
  tx A, sign tx B → "Metadata does not match signed transaction", no signature),
  AdvancedMode gate (OFF+unknown→reject, ON→sign, native ERC-20 unaffected), and
  cancel-clears-metadata (stale blob not reused).

Offline portion verified with PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python.
Device-class cases require the firmware emulator (libkkemu) + DEBUG_LINK.
… SECTIONS

The feature ships in the 7.15.0 firmware tree, so gate the device tests at
7.15.0 (was 7.15.1, which left them dormant on the current build).

- test setUp: requires_firmware 7.15.1 -> 7.15.0.
- generate-test-report.py SECTIONS 'V' (EVM Clear-Signing) min_firmware
  7.15.1 -> 7.15.0; add V9-V12 mapping the new device-class tests
  (full tx-hash binding happy path, replay reject, AdvancedMode gate,
  cancel-clears-metadata) with OLED screenshot expectations so the
  report-driven Phase-1 capture includes them.

Verified on the containerized kkemu emulator (docker compose, CI-faithful):
all 28 clear-signing tests pass; OLED screenshots captured for the verified
flow (INSIGHT VERIFIED icon + decoded method/contract/args), the replay
reject, and the AdvancedMode gate.
@BitHighlander
BitHighlander merged commit ce4bdca into master Jun 29, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant