Uh oh!
There was an error while loading. Please reload this page.
Clear-sign classic transactions on Ledger - #2584
Conversation
Claude finished @fnando's task in 4m 8s —— View job PR Review — Clear-sign classic transactions on LedgerNice, focused change. The core flip (route classic envelopes through FindingsInline comments posted on:
Things I checked and did NOT find issues with
Todo
Overall: ship-ready after the visibility / exhaustive-match nits. The fee-bump label, redundant SHA-256, and click-count coupling are polish items that can land in a follow-up if you prefer to keep this PR tight. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Routes Ledger signing for classic Stellar transactions through the Ledger app’s clear-sign APDU (SIGN_TX, INS=0x04) so users can review operation details on-device, while keeping Soroban-related transactions on hash-signing (SIGN_TX_HASH, INS=0x08) and surfacing the hash in the CLI prompt.
Changes:
- Refactors
Signerto produce a signature via a single path, and routes Ledger signing throughsign_tx_env(clear-sign vs hash-sign based on envelope content). - Adds fee-bump clear-sign support to the
stellar-ledgercrate (sign_fee_bump_transaction) and wires it into CLI Ledger signing. - Updates Speculos integration test to exercise classic clear-signing end-to-end (Payment + memo) using the correct approval click-flow.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| cmd/soroban-cli/src/signer/mod.rs | Refactors signature production and adds local helper(s) for envelope hashing + signing messages. |
| cmd/soroban-cli/src/signer/ledger.rs | Adds Soroban-envelope detection and implements Ledger sign_tx_env (clear-sign for classic; hash-sign for Soroban ops). |
| cmd/crates/stellar-ledger/src/lib.rs | Adds sign_fee_bump_transaction and factors signing into a shared tagged-transaction helper. |
| cmd/crates/soroban-test/tests/it/emulator.rs | Updates Speculos integration test to validate clear-sign classic transaction flow with Ledger identity. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Claude finished @fnando's task in 3m 16s —— View job PR Review — Clear-sign classic transactions on Ledger (re-review after fixes)Re-reviewed against the five follow-up commits since the initial review. Most prior items were addressed cleanly; a couple of polish items are still open. What was addressed
Still open from the prior review
New things I checked in this round
VerdictShip-ready. The two remaining items are minor polish — the fee-bump label inconsistency is the only one I'd nudge on since it's a now-visible divergence after the helper was extracted. Everything else can live in a follow-up. Todo
|
Uh oh!
There was an error while loading. Please reload this page.
5cd96c0 to
cc73055CompareClaude finished @fnando's task in 2m 28s —— View job PR Re-Review — Clear-sign classic transactions on Ledger (round 3)Re-reviewed against the current branch tip ( What I checked this round
Findings
Items previously raised and resolved by author decision (not re-flagging)
VerdictLGTM after addressing the stale comment (optional — cosmetic). The two unit-test + polling improvements in this round materially reduce maintenance risk; Todo
|
| // Sign a classic Payment envelope with a Ledger identity end-to-end. After the | ||
| // blind-signing fix the CLI sends the full `TransactionSignaturePayload` to the | ||
| // device via APDU `INS=0x04` (SIGN_TX), so the user approves the parsed | ||
| // operation — not a hex hash. The Speculos approval flow used here | ||
| // (`approve_tx_signature`) and the transaction shape mirror stellar-ledger's | ||
| // `test_sign_tx`, whose Speculos click counts are calibrated for this exact | ||
| // Payment + memo layout. |
There was a problem hiding this comment.
Stale comment after the polling refactor. This block still says the Speculos click counts are "calibrated for this exact Payment + memo layout", but commit cc73055 replaced the per-device-model click counts in approve_tx_signature with advance_to_approve_and_confirm, which polls until the on-screen text reads "Approve" (capped at 50 right-clicks). The fixture shape no longer drives click counts, so the rationale here misleads readers.
| // Sign a classic Payment envelope with a Ledger identity end-to-end. After the | |
| // blind-signing fix the CLI sends the full `TransactionSignaturePayload` to the | |
| // device via APDU `INS=0x04` (SIGN_TX), so the user approves the parsed | |
| // operation — not a hex hash. The Speculos approval flow used here | |
| // (`approve_tx_signature`) and the transaction shape mirror stellar-ledger's | |
| // `test_sign_tx`, whose Speculos click counts are calibrated for this exact | |
| // Payment + memo layout. | |
| // Sign a classic Payment envelope with a Ledger identity end-to-end. After the | |
| // blind-signing fix the CLI sends the full `TransactionSignaturePayload` to the | |
| // device via APDU `INS=0x04` (SIGN_TX), so the user approves the parsed | |
| // operation — not a hex hash. The Speculos approval flow used here | |
| // (`approve_tx_signature`) polls until the on-screen text reads "Approve", | |
| // so it tolerates changes in the device review screen flow. |
What
Route every classic
TransactionEnvelope::TxandTransactionEnvelope::TxFeeBumpsigned by a Ledger identity through the clear-sign APDUSIGN_TX(INS=0x04) instead ofSIGN_TX_HASH(INS=0x08). The fullTransactionSignaturePayloadXDR is sent to the device so the Ledger Stellar app parses and displays each operation — destination, amount, asset, fee, memo, source account, sequence — for the user to verify before approving.Smart contract transactions (
InvokeHostFunction,ExtendFootprintTtl,RestoreFootprint) continue to useSIGN_TX_HASHbecause the Ledger app cannot pretty-print these ops yet. The CLI now prints the transaction hash alongside the approval prompt so users can compare it against what the device shows. Smart contract authorization-entry preimage signing (sign_payload) is unchanged.Why
Classic transactions. Today, signing with a Ledger identity in
stellar-clishows only a hex hash on the device. Users have to enableHash Signing(meant for advanced/experimental flows) and trust the host. After this change, the everyday flow walks them through each operation on the trusted device screen — the experience hardware-wallet users expect.Smart contract transactions. The Ledger app cannot render these ops yet, so they still need
Hash Signing. Surfacing the host-computed hash in the CLI prompt gives users something concrete to compare against the device screen.The clear-sign primitive
LedgerSigner::sign_transaction(INS=0x04) was already implemented and tested against Speculos but had no production callers — this PR wires it up and adds a siblingsign_fee_bump_transactionso fee-bumps go through the same path.Known limitations
Smart contract transactions still require
Hash Signingto be enabled on the device and only show a hex hash on the screen. This is a device-side gap that will close when the Ledger Stellar app gains smart contract pretty-printing. Smart contract authorization-entry preimages signed viasign_payloadare inherently 32-byte hashes, so they remain on the blind-sign APDU.