feat(keepkey): TIP-191 / TIP-712 / TON / Solana-offchain message-signing methods#38
Merged
Merged
Conversation
Adds KeepKey wallet support for the firmware 7.14.1 message-signing features: TRON (TIP-191 + TIP-712): - TronSignMessage / TronMessageSignature jspb shims (1404/1405) - TronVerifyMessage jspb shim (1406) - TronSignTypedHash / TronTypedDataSignature jspb shims (1407/1408) - tronSignMessage / tronVerifyMessage / tronSignTypedHash wrapper functions - Matching KeepKey class methods + core type extensions TON: - TonSignMessage / TonMessageSignature jspb shims (1504/1505) - tonSignMessage wrapper + KeepKey method + core types - Note: firmware fences this behind AdvancedMode policy until TON Connect ton_proof envelope is added — caller will get a Failure response if the policy is disabled Solana off-chain message: - SolanaSignOffchainMessage / SolanaOffchainMessageSignature jspb shims (756/757) - solanaSignOffchainMessage wrapper + KeepKey method + core types - This is the domain-separated path; firmware constructs the '\xff' || 'solana offchain' || version || format || length || msg envelope and Ed25519-signs it. Format 2 (extended UTF-8) is rejected device-side; only formats 0 (ASCII) and 1 (UTF-8 limited, max 1212 bytes) are supported. All wrappers follow the existing transport.lockDuring + transport.call pattern used by tronSignTx / tonSignTx / solanaSignTx. Hand-rolled jspb.Message subclasses are wire-compatible with the firmware's generated nanopb encoding.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The previous implementation relied on 'transport.call() returns Success when verified, throws on Failure', but that broke the Promise<boolean> contract — callers got a rejected promise on signature mismatch instead of a resolved `false`. Mirror btcVerifyMessage / ethVerifyMessage: catch MESSAGETYPE_FAILURE and return false. ActionCancelled is thrown by transport.call() as a distinct core.ActionCancelled instance (no message_enum), so it bubbles past the catch and continues to throw — keeping cancel flow distinguishable from sig mismatch. Reported in #38 review.
The migration in 58272dd ('ci: add GitHub Actions CI, replace CircleCI with placeholder') moved CI from CircleCI to GitHub Actions but only copied over yarn build + yarn lint — yarn test (49 tests across 4 files) and yarn test:integration silently disappeared. The .circleci/config.yml was left as a no-op placeholder, so the green 'ci/circleci: noop' check on every PR has been giving the false impression that tests were running. Add 'yarn test --runInBand --coverage=false' back to the workflow. Integration tests (kkemu sidecar) are a separate follow-up since they need a kkemu image source in CI — currently kktech/kkemu:latest comes from dockerhub and isn't easily reproducible from a feature branch.
34 new tests across 3 files covering all 9 new jspb classes + 5
wrapper functions:
tron-message.test.ts (20 tests)
- registry: TronSignMessage/MessageSignature/VerifyMessage/
SignTypedHash/TypedDataSignature (1404-1408) all registered
- jspb round-trip: serializeBinary → deserializeBinaryFromReader
preserves all fields for each class (incl. empty-message + domain-only
typed-hash edge cases)
- tronSignMessage wrapper: success path + UTF-8 string encoding
- tronVerifyMessage wrapper:
* Success → true
* MESSAGETYPE_FAILURE thrown by transport.call → returns false
(regression test for the Promise<boolean> contract bug
caught in PR review)
* core.ActionCancelled → bubbles past the catch (cancel is
distinguishable from sig mismatch)
- tronSignTypedHash wrapper: 32-byte hash length validation +
success path
ton-message.test.ts (7 tests)
- registry: TonSignMessage/MessageSignature (1504/1505)
- jspb round-trip
- tonSignMessage wrapper: success + ActionCancelled bubbling
(firmware AdvancedMode gate path)
solana-offchain.test.ts (7 tests)
- registry: SolanaSignOffchainMessage/OffchainMessageSignature (756/757)
- jspb round-trip incl. 1212-byte boundary (spec ceiling for fmt 0/1)
- solanaSignOffchainMessage wrapper: UTF-8 encoding,
version + message_format forwarding, success path
Total jest run: 49 → 83 (all pass locally with yarn test).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds KeepKey wallet support for the firmware 7.14.1 message-signing features. Hand-rolled jspb.Message subclasses (wire-compatible with firmware nanopb), wrapper functions, KeepKey class methods, and `hdwallet-core` type extensions.
Pairs with these firmware PRs (currently against BitHighlander/keepkey-firmware develop, headed to upstream after fork-side validation):
New API
TRON
TON
Solana
```
'\xff' || 'solana offchain' || version:u8 || format:u8 || length:u16 LE || message
```
and Ed25519-signs it. Format 2 (extended UTF-8) is rejected device-side; only formats 0 (ASCII) and 1 (UTF-8 limited, max 1212 bytes) are supported. No AdvancedMode gate — the envelope's leading `0xFF` byte is invalid as a Solana transaction prefix, providing the domain separation that bare `solanaSignMessage` lacks. This is the proper fix for the SignMessage AdvancedMode band-aid
Files
Test plan