Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
6447ace
feat(transport): add DylibTransport for in-process libkkemu testing
BitHighlander Apr 26, 2026
2add091
test(dylib): screenshot regression for ringbuf capacity + canvas sema…
BitHighlander Apr 27, 2026
d4eda86
fix(dylib): address PR #14 review — strip-? consistency, narrow KK_TR…
BitHighlander Apr 27, 2026
e88ff15
feat(zcash): seed_fingerprint client + tests
BitHighlander Apr 29, 2026
69d28d6
test(zcash): split helper tests + cover client wrappers
BitHighlander Apr 29, 2026
1688716
Merge pull request #15 from BitHighlander/feat/zcash-seed-fingerprint
BitHighlander Apr 29, 2026
3335e6f
chore: defer planning test gates
BitHighlander Apr 30, 2026
a39dad4
test(eth): regression for EIP-1559 chunked-data signing bug (firmware…
BitHighlander Apr 28, 2026
7ecc099
test(eth): drop requires_message gate that probe-skips this test
BitHighlander Apr 28, 2026
cc0f4ae
test(ci): install pycryptodome so eth-utils.keccak has a backend
BitHighlander Apr 28, 2026
61ea6ab
test(eth): drop msg arg from assertEqual (custom 2-arg overload)
BitHighlander Apr 28, 2026
43e3b54
test(eth): gate EIP-1559 chunked-data regression on firmware 7.14.1+
BitHighlander Apr 29, 2026
fcdf6bf
release: python-keepkey 7.14.1
BitHighlander Apr 30, 2026
38b57f7
feat: add message-signing protocol bindings
BitHighlander Apr 30, 2026
297cba3
feat(7.14.2): XRP THORChain memo support + EVM depositWithExpiry reco…
BitHighlander May 15, 2026
bf870e6
Merge pull request #18 from BitHighlander/release/7.14.2-python-keepkey
BitHighlander May 15, 2026
eee4804
feat(hive): add Hive blockchain support (#19)
BitHighlander May 24, 2026
04119f3
fix(hive): regenerate messages_hive_pb2.py with old-style descriptor …
BitHighlander May 24, 2026
e338df0
fix(tests): port alpha CI test fixes to feature/hive baseline
BitHighlander May 24, 2026
4e7034e
test: skip legacy sighash test — firmware requires full tx digests
BitHighlander May 24, 2026
e717f10
test: skip all legacy sighash PCZT tests — firmware requires full tx …
BitHighlander May 24, 2026
e3fb2ff
test(hive): vendored SLIP-0048 multi-key + account-op device tests
BitHighlander Jun 26, 2026
e9e4a2e
test(hive): parse serialized_tx and bind every field by position
BitHighlander Jun 26, 2026
7388ae2
Merge pull request #21 from BitHighlander/feat/hive-tests
BitHighlander Jun 26, 2026
8ac46ac
test(hive): drop unsupported msg arg from assertEqual calls
BitHighlander Jun 27, 2026
ae1d39c
Merge pull request #22 from BitHighlander/fix/hive-tests-assertequal
BitHighlander Jun 27, 2026
bdfb2d1
test(insight): EVM clear-signing metadata vectors + tx-hash binding t…
BitHighlander Jun 29, 2026
2acc77f
test(insight): activate clear-signing tests on 7.15.0 + expand report…
BitHighlander Jun 29, 2026
ce4bdca
Merge pull request #24 from BitHighlander/feat/insight-clearsign-tests
BitHighlander Jun 29, 2026
206114d
test(eth): signing-guard regression tests (EIP-1559 consistency + con…
BitHighlander Jun 29, 2026
027146f
test(0x): enable AdvancedMode for transformERC20 blind-sign
BitHighlander Jun 29, 2026
a79ce7b
Merge pull request #26 from BitHighlander/fix/0x-transformerc20-advan…
BitHighlander Jun 29, 2026
531756a
test(eth): transformERC20 needs AdvancedMode at 7.15 (calldata > init…
BitHighlander Jun 29, 2026
79ff6b1
test(eth): transformERC20 clear-signs without AdvancedMode (revert 7.…
BitHighlander Jun 29, 2026
3a72308
Merge pull request #25 from BitHighlander/test/eth-signing-guards-master
BitHighlander Jun 29, 2026
5a08e0c
Merge remote-tracking branch 'upstream/master' into HEAD
BitHighlander Jun 30, 2026
452ca98
test(thor): point eth swap/add-liquidity vectors at the firmware-pinn…
BitHighlander Jun 29, 2026
88da246
feat(clearsign): LoadClearsignSigner trust path + release-protocol pr…
BitHighlander Jul 2, 2026
c346561
test/report: fix stale zcash tests + report generator for the 7.15 PDF
BitHighlander Jul 2, 2026
b46a8b0
test: skip emulator-only uniswap approve; alias injection cases; repo…
BitHighlander Jul 2, 2026
8e8ee81
test: requires_message probe no longer false-skips required-field mes…
BitHighlander Jul 2, 2026
e152271
feat(clearsign): human-readable who/what/why — STRING + TOKEN_AMOUNT …
BitHighlander Jul 2, 2026
0ab2bea
test(clearsign): full hex-free flow suite — all 7 real-world payloads
BitHighlander Jul 2, 2026
6680f8f
feat(clearsign): CLEARSIGN_FLOWS catalog — python-keepkey as the comp…
BitHighlander Jul 2, 2026
683e247
fix(test): batch assert — KeepKeyTest.assertEqual has no msg param
BitHighlander Jul 2, 2026
2b924bf
feat(clearsign): 51-flow reference catalog — 50+ real tx types, hex-free
BitHighlander Jul 2, 2026
1545299
fix(report): Decode line renders real values (scaled amounts, 0x.. ad…
BitHighlander Jul 2, 2026
e728e31
fix(bip85): gate tests on 7.15.0, not 7.14.0 — BIP-85 landed in 7.15
BitHighlander Jul 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "device-protocol"]
path = device-protocol
url = https://github.com/keepkey/device-protocol.git
url = https://github.com/BitHighlander/device-protocol.git
branch = master
[submodule "keepkeylib/eth/ethereum-lists"]
path = keepkeylib/eth/ethereum-lists
Expand Down
2 changes: 1 addition & 1 deletion build_pb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ CURDIR=$(pwd)
cd "device-protocol"

echo "Building with protoc version: $(protoc --version)"
for i in messages messages-ethereum messages-eos messages-nano messages-cosmos messages-ripple messages-binance messages-tendermint messages-thorchain messages-osmosis messages-mayachain messages-solana messages-tron messages-ton messages-zcash types ; do
for i in messages messages-ethereum messages-eos messages-nano messages-cosmos messages-ripple messages-binance messages-hive messages-tendermint messages-thorchain messages-osmosis messages-mayachain messages-solana messages-tron messages-ton messages-zcash types ; do
protoc --python_out=$CURDIR/keepkeylib/ -I/usr/include -I. $i.proto
i=${i/-/_}
sed -i -Ee 's/^import ([^.]+_pb2)/from . import \1/' $CURDIR/keepkeylib/"$i"_pb2.py
Expand Down
81 changes: 81 additions & 0 deletions keepkeylib/clearsign_abi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""
Minimal, deterministic Solidity ABI encoder for STATIC types only.

Used to build REAL calldata for the clear-sign flow catalog from a function
signature + argument values, instead of hand-typing hex (which is how bugs
get shipped in a signing test suite). Selectors are always derived from
keccak256(signature) here — never trusted from an external source — so a
wrong/hallucinated selector fails loudly instead of silently producing a
plausible-looking but wrong test vector.

Deliberately does NOT support dynamic types (string, bytes, T[], tuples with
dynamic members) — those need offset/length ABI encoding that's easy to get
subtly wrong by hand. Calls with dynamic types are hand-built at the call
site (see clearsign_catalog.py's multicall/handleOps entries) using the
primitives here (_word/_addr_word) plus an explicit comment that the layout
is a representative simplification, not a literal captured mainnet tx.
"""

from .signed_metadata import keccak256


def parse_signature(signature):
"""'supply(address,uint256,address,uint16)' -> ('supply', ['address', 'uint256', 'address', 'uint16'])"""
name, rest = signature.split('(', 1)
rest = rest.rsplit(')', 1)[0]
types = [t.strip() for t in rest.split(',')] if rest.strip() else []
return name, types


def selector(signature):
"""4-byte function selector, always computed — never trusted as input."""
return keccak256(signature.encode('ascii'))[:4]


def _word(value):
if isinstance(value, str) and value.startswith('0x'):
value = int(value, 16)
return int(value).to_bytes(32, 'big')


def _addr_word(address):
if isinstance(address, str):
address = bytes.fromhex(address[2:] if address.startswith('0x') else address)
assert len(address) == 20, 'address must be 20 bytes, got %d' % len(address)
return b'\x00' * 12 + address


def encode_static_args(types, values):
"""ABI-encode STATIC Solidity types into concatenated 32-byte words.
Raises on any dynamic type (string/bytes/arrays) — build those by hand."""
assert len(types) == len(values), (
'arg count mismatch: %d types, %d values' % (len(types), len(values)))
out = bytearray()
for typ, val in zip(types, values):
if typ == 'address':
out += _addr_word(val)
elif typ.startswith('uint') or typ.startswith('int'):
digits = typ[4:] if typ.startswith('uint') else typ[3:]
bits = int(digits) if digits else 256
n = int(val)
assert 0 <= n < (1 << bits), 'value %r out of range for %s' % (val, typ)
out += n.to_bytes(32, 'big')
elif typ == 'bool':
out += (1 if val else 0).to_bytes(32, 'big')
elif typ.startswith('bytes') and typ != 'bytes' and not typ.endswith('[]'):
n = int(typ[5:])
b = val if isinstance(val, (bytes, bytearray)) else bytes.fromhex(
val[2:] if val.startswith('0x') else val)
assert len(b) == n, 'bytes%d value has wrong length' % n
out += b.ljust(32, b'\x00') # bytesN is left-aligned per ABI spec
else:
raise ValueError(
'dynamic/unsupported type %r — build this call by hand '
'(see module docstring)' % typ)
return bytes(out)


def build_calldata(signature, values):
"""selector(signature) + ABI-encoded static args, in one call."""
_, types = parse_signature(signature)
return selector(signature) + encode_static_args(types, values)
Loading
Loading