◐ Shell
clean mode source ↗

feat(zcash): seed_fingerprint client + tests by BitHighlander · Pull Request #15 · BitHighlander/python-keepkey

added 2 commits

April 28, 2026 21:35
Wires the ZIP-32 §6.1 seed fingerprint binding into the python-keepkey
client to mirror the firmware-side validation.

  device-protocol submodule
    - URL: keepkey/device-protocol -> BitHighlander/device-protocol
      (zcash work pins to fork master while seed_fingerprint sits in
      long-term review for upstream; revert when upstream merges.)
    - pin: d0b8d80 -> 4337c452 (BitHighlander/master with PR keepkey#27 merged).
    - messages_zcash_pb2.py regenerated via docker_build_pb.sh
      (kktech/firmware:v8 → libprotoc 3.5.1, the canonical toolchain).
      Selective regen — other pb2 files are intentionally NOT
      regenerated because they currently include content from
      BitHighlander/device-protocol open PRs (#18 SolanaTokenInfo,
      #19 TRON clear-signing, #20 TON clear-signing, keepkey#21
      EthereumTxMetadata). Until those merge, regenerating them
      against current master would back out work that the existing
      python-keepkey client relies on.

  keepkeylib/zcash.py (new)
    calculate_seed_fingerprint(seed) -> 32 bytes
      Pure-Python helper. BLAKE2b-256("Zcash_HD_Seed_FP",
      I2LEBSP_8(len) || seed). Matches the firmware C
      implementation byte-for-byte and the keystone3-firmware
      reference vector
        seed = 000102...1f
        fp   = deff604c246710f7176dead02aa746f2fd8d5389f7072556dcb555fdbe5e3ae3

  keepkeylib/client.py
    zcash_display_address  — add expected_seed_fingerprint kwarg
    zcash_sign_pczt         — add expected_seed_fingerprint kwarg
    Both pass through unchanged when the kwarg is None
    (backward compatible).

  tests/test_msg_zcash_seed_fingerprint.py (new)
    Pure-Python helper:
      - reference vector (Keystone3 cross-check)
      - rejects all-zero, all-0xFF, short, long
    Device-backed:
      - GetOrchardFVK returns non-empty seed_fingerprint
      - fingerprint stable across accounts (bound to seed, not account)
      - DisplayAddress: matching expected_seed_fingerprint succeeds,
        response carries seed_fingerprint
      - DisplayAddress: wrong expected_seed_fingerprint rejected
      - DisplayAddress: omitting expected_seed_fingerprint still works
      - SignPCZT: wrong expected_seed_fingerprint rejected before
        any signing crypto runs
Addresses review of PR #15.

Test structure
  Helper tests (no device) move to a dedicated module:
    tests/test_zcash_seed_fingerprint_helper.py
  This module deliberately does NOT import common, transport, or any
  protobuf bindings, so it runs on a stock dev box:
    pytest tests/test_zcash_seed_fingerprint_helper.py
  The previous file inherited common.KeepKeyTest, whose setUp wipes
  the device — pytest -k 'helper' was never actually offline.

Client wrapper coverage
  Device-backed tests now go through the public client helpers
  (self.client.zcash_display_address(... expected_seed_fingerprint=...)
  and self.client.zcash_sign_pczt(... expected_seed_fingerprint=...))
  rather than building raw protobuf messages with self.client.call().
  Confirms the kwarg pass-through end-to-end.

New test
  test_device_fingerprint_matches_python_helper: cross-checks the
  device-computed fingerprint against the python-keepkey helper for
  the same seed (all-allallall mnemonic, empty passphrase). Ties the
  firmware C, python-keepkey helper, and ZIP-32 §6.1 reference vector
  to the same byte-for-byte output.