From 049908491b47f9211559384937125b204cdeaa2a Mon Sep 17 00:00:00 2001 From: highlander Date: Sat, 12 Sep 2026 04:08:55 -0600 Subject: [PATCH 1/4] test(hive): assert the wire asset symbol the chain uses, not the display name Two assertions read the asset symbol out of the transaction the DEVICE serialized and expected "HIVE". This file already knows better: _WIRE_SYMBOL at the top records that the 2020 rebrand renamed the tokens but not their on-chain serialization, and every operation this file builds itself is assembled with "STEEM"/"SBD" (confirmed against condenser_api.get_transaction_hex). So these two assertions were pinning the firmware's own mistake: it wrote "HIVE" where hived writes "STEEM", and the test agreed with it. The firmware side is fixed on the 7.15 line; this makes the expectation match the chain. --- tests/test_msg_hive.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_msg_hive.py b/tests/test_msg_hive.py index bee79251..b5b5cb07 100644 --- a/tests/test_msg_hive.py +++ b/tests/test_msg_hive.py @@ -353,7 +353,11 @@ def test_hive_sign_transfer(self): self.assertEqual((ref_num, ref_prefix, expiration), (12345, 67890, 1700000000)) self.assertEqual(r.string(), b"kktester") # from self.assertEqual(r.string(), b"kkrecipient") # to - self.assertEqual(r.asset(), (1000, 3, "HIVE")) + # The WIRE spelling, per _WIRE_SYMBOL above: hived writes "STEEM" for + # HIVE, and this reads the bytes the device actually signed. Asserting + # the display name here passed only while the firmware serialized a + # symbol the chain does not use. + self.assertEqual(r.asset(), (1000, 3, _WIRE_SYMBOL["HIVE"])) self.assertEqual(r.string(), b"kktest") # memo self.assertEqual(r.varint(), 0) # extensions r.assert_end() @@ -399,7 +403,7 @@ def test_hive_sign_account_create(self): r = _Reader(resp.serialized_tx) ref_num, ref_prefix, expiration = _parse_header(r, HIVE_OP_ACCOUNT_CREATE) self.assertEqual((ref_num, ref_prefix, expiration), (12345, 67890, 1700000000)) - self.assertEqual(r.asset(), (3000, 3, "HIVE")) # fee + self.assertEqual(r.asset(), (3000, 3, _WIRE_SYMBOL["HIVE"])) # fee self.assertEqual(r.string(), b"kksponsor") # creator self.assertEqual(r.string(), b"kktestacct") # new_account_name self.assertEqual(r.authority(), raw[ROLE_OWNER]) From 6a85668736d7d4ecbb5dddf9478be65074a31154 Mon Sep 17 00:00:00 2001 From: highlander Date: Sat, 12 Sep 2026 04:35:07 -0600 Subject: [PATCH 2/4] test(eth): refresh the frame hash for the corrected 1-bit serialiser kkemu_get_display() lit every nonzero shade while the DebugLink layout and the capture ring used ordered dithering (display_mono_pixel_is_lit), so the dylib transport this test reads produced a different frame than the device's other evidence paths for the same screen -- and this golden pinned the odd one out. The firmware side is aligned on the 7.15 line; this is the frame all three serialisers now agree on. --- tests/test_msg_ethereum_signtx_xfer.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_msg_ethereum_signtx_xfer.py b/tests/test_msg_ethereum_signtx_xfer.py index 627342e0..7d4fef1e 100644 --- a/tests/test_msg_ethereum_signtx_xfer.py +++ b/tests/test_msg_ethereum_signtx_xfer.py @@ -59,8 +59,14 @@ def test_native_pseudo_address_transfer_is_unknown_off_mainnet(self): data=erc20_data, chain_id=257, ) self.assertGreaterEqual(len(recorder.screens), 2) + # The 7.15 hash changed when the dylib's 1-bit serialiser stopped + # treating every nonzero shade as lit and adopted the ordered + # dithering the DebugLink layout and the capture ring already used + # (display_mono_pixel_is_lit). The frame this now hashes is the one + # the device's other evidence paths produce for the same screen; + # the old value came from the one serialiser that disagreed. expected_frame = ( - "3915d325da0a0e9842d7eb3eaa6e01ef0bbf7e010790af883ca1a7f30770ae8f" + "beb98f914a77d933b458b625085cef4ea92a2a243bf56bee37abf95294d42497" if self.firmware_at_least("7.15.0") else "b0a3026e7af1778ebd71a968ace25c03945cccf2d8abc951e5dd65abc04e914e" ) From 06b6de2a08909e4d6c3fd7ffb3677ec07e5d389f Mon Sep 17 00:00:00 2001 From: highlander Date: Mon, 14 Sep 2026 15:02:17 -0600 Subject: [PATCH 3/4] ci: exercise Python harness against audited firmware candidates --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15aba8b8..ecb16777 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -125,7 +125,7 @@ jobs: uses: actions/checkout@v4 with: repository: BitHighlander/keepkey-firmware - ref: d0a494a805533f02387f58d89dbb6f1fb09a621a + ref: d33f1711c3b2b205f64c5dc35fdec02926a6dc63 path: keepkey-firmware # NOT `submodules: recursive`. trezor-firmware carries a micropython @@ -362,7 +362,7 @@ jobs: uses: actions/checkout@v4 with: repository: BitHighlander/keepkey-firmware - ref: e6a6711e5e4164d3b3840356dc301aa873f1fbf7 + ref: 4125e1c7409b1cb7b08ba595bc408e3128fc24ca path: keepkey-firmware - name: Init the submodules the emulator build needs @@ -543,10 +543,10 @@ jobs: matrix: include: - release: "7.14.3" - firmware_ref: e6a6711e5e4164d3b3840356dc301aa873f1fbf7 + firmware_ref: 4125e1c7409b1cb7b08ba595bc408e3128fc24ca min_fw: "7.14.3" - release: "7.15" - firmware_ref: d0a494a805533f02387f58d89dbb6f1fb09a621a + firmware_ref: d33f1711c3b2b205f64c5dc35fdec02926a6dc63 min_fw: "7.15.0" # KK_BITCOIN_ONLY=ON is a second shipping product, not a build flavour: From 11b976157b09f526022b235002f327f36e9fe4a4 Mon Sep 17 00:00:00 2001 From: highlander Date: Mon, 14 Sep 2026 15:09:15 -0600 Subject: [PATCH 4/4] ci: run CircleCI against the same 7.15 audit head --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b445e9d0..aea3a1a1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,10 +38,10 @@ jobs: git remote add origin \ https://github.com/BitHighlander/keepkey-firmware.git git fetch --depth 1 origin \ - d0a494a805533f02387f58d89dbb6f1fb09a621a + d33f1711c3b2b205f64c5dc35fdec02926a6dc63 git checkout --detach FETCH_HEAD test "$(git rev-parse HEAD)" = \ - d0a494a805533f02387f58d89dbb6f1fb09a621a + d33f1711c3b2b205f64c5dc35fdec02926a6dc63 # Match firmware CI's build set. A recursive init reaches optional # trezor-firmware vendors that do not support shallow HTTPS clones.