Skip to content

feat: add Solana support (GetAddress, SignTx, SignMessage)#386

Draft
BitHighlander wants to merge 5 commits intodevelopfrom
feat/solana-support
Draft

feat: add Solana support (GetAddress, SignTx, SignMessage)#386
BitHighlander wants to merge 5 commits intodevelopfrom
feat/solana-support

Conversation

@BitHighlander
Copy link
Collaborator

Motivation

Solana is the #5 cryptocurrency by market cap with a large KeepKey user overlap. Users currently cannot manage SOL on their KeepKey device, forcing them to use software wallets or competing hardware wallets. Adding Solana support addresses the most-requested chain addition.

Changes

Address derivation (solana.c):

  • Ed25519 key derivation at BIP-44 path m/44'/501'/account'/change'
  • Address is the Base58-encoded 32-byte Ed25519 public key (Solana's native format)
  • Path validation enforces 44'/501' prefix

Transaction signing (solana_tx.c, solana_msg.c):

  • Accept raw serialized Solana transaction bytes from host
  • Parse transaction to extract and display: recipient address, amount (lamports), program ID
  • Ed25519 sign the transaction message bytes
  • Return 64-byte signature

Message signing:

  • Sign arbitrary messages with Ed25519 at the user's Solana key
  • Return signature + public key for off-chain verification

Wire protocol:

  • SolanaGetAddress (750) → SolanaAddress (751)
  • SolanaSignTx (752) → SolanaSignedTx (753)
  • SolanaSignMessage (754) → SolanaMessageSignature (755)

Code review fixes applied:

  • Bounds checks on transaction parsing (C1, C3, C4)
  • Input validation for address_n path (H1, H3, H4)
  • Buffer size guards for raw_tx (L1, L4, L5)
  • Display formatting for lamport amounts (M6)
  • Additional fsm_msg_solana.h review hardening

Risk assessment

Isolated from existing chains — new source files, new message handlers, no modifications to Bitcoin/Ethereum signing paths. Uses the existing Ed25519 implementation from trezor-crypto (same curve as Nano, already battle-tested on-device).

The raw transaction signing model means the host is responsible for transaction construction. The device validates and displays what it can parse but ultimately signs the host-provided bytes. This matches the Trezor Model T approach for Solana.

Testing

  • Python integration tests: 3 test cases (address format, different accounts, deterministic)
  • Tests skip on firmware < 7.14.0
  • ARM and emulator builds clean

- Point device-protocol and python-keepkey submodules to upstream master
  (includes BIP-85, Solana, Tron, TON wire IDs and proto definitions)
- Add nanopb .options files for Solana, Tron, TON (field size constraints)
- Add Bip85Mnemonic.mnemonic max_size:241 to messages.options
- Update lib/transport/CMakeLists.txt with new proto sources, options,
  headers, and protoc compilation commands
- Fix CI: use pre-installed clang-format instead of apt-get install
  (eliminates 3-minute timeout on GitHub runners)
- Update Zcash transparent branch ID from Sapling to NU6
@BitHighlander BitHighlander force-pushed the feat/solana-support branch 2 times, most recently from 3447a61 to 39c3bba Compare March 17, 2026 03:16
BitHighlander and others added 3 commits March 16, 2026 21:24
Add Ed25519-based Solana chain support using existing trezor-crypto
primitives (ed25519, base58).

- SolanaGetAddress: derive Ed25519 key, Base58-encode pubkey
- SolanaSignTx: parse transaction, confirm on device, Ed25519 sign
- SolanaSignMessage: off-chain message signing with device confirm
- Transaction parser: System Transfer, SPL Token, Stake instructions
…,M6)

- Fix compact-u16 decode: use correct LE varint (bit 7 continuation), not big-endian ranges
- Remove duplicate compact-u16 in solana.c, share via read_compact_u16() in solana_tx.h
- Change solana_signTx from void to bool, propagate errors to FSM handler
- Default show_display to true when field not set (hardware wallet must confirm)
- Fix token transfer: check TransferChecked (len>=10) with instruction type, parse amount for both
- Reduce stack: account_keys 64→16, instructions 32→8 (saves ~3KB)
- Zero public_key after use in solana.c and solana_msg.c
- Remove dead read_u64_le function
- Fix formatLamports buffer guard: 20→30 bytes
- Guard MIN macro with #ifndef
- Add const to SolanaSignTx and SolanaSignMessage FSM params
- Fix NULL pointer dereference: remove fsm_getCoin("Solana") call (not in coin table),
  use bip32_path_to_string() directly for address display
- Add BIP44 path validation (m/44'/501'/...) to all 3 handlers
- Zero public_key stack variables on all exit paths
@BitHighlander BitHighlander marked this pull request as draft March 18, 2026 00:57
@BitHighlander
Copy link
Collaborator Author

Closing — superseded by more complete Solana implementation in BitHighlander/keepkey-firmware (merged to develop, includes native tx parser).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant