test(hardware-wallet): exercise hardware-wallet builds and mocks in CI - #759
test(hardware-wallet): exercise hardware-wallet builds and mocks in CI#759TheWeirdDee wants to merge 2 commits into
Conversation
…/rejection/disconnect/unsupported envelopes The hardware-wallet Cargo feature (hidapi + trezor-client) was never built or tested in CI, so its code paths silently bit-rotted. Add a dedicated CI job that builds and tests it, extract and unit-test the Ledger APDU status-word classification (approval / rejection / unsupported envelope), reorder Trezor sign_transaction to validate its input and report "not supported" before touching the device (so that path is deterministically testable without hardware), and add feature-gated tests exercising the real hidapi/trezor-client backends' disconnect (no-device) behavior. Document compatibility, security, and system-dependency notes for the feature.
Building with --features hardware-wallet surfaced pre-existing, unrelated breakage on master that also blocks the default build: - database.rs used thiserror::Error/#[error(...)] without thiserror being a declared dependency, and passed &mut Transaction where the Migration trait expects &mut Connection (Transaction has no DerefMut). Added the dependency and switched the trait/impls to &Connection, which is all any Migration actually needs. - commands/mod.rs and utils/mod.rs were missing `pub mod ai_doc_qa;` from the ai-documentation-Q&A merge, so main.rs referenced modules that didn't exist. None of this is hardware-wallet specific; it was simply never caught because nothing built the crate with every feature/target combination CI now exercises.
|
@TheWeirdDee Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
|
Pushed a follow-up commit that fixes the build-breaking bugs this PR's CI job surfaced (unrelated to hardware wallets, but they block the whole crate from compiling):
Confirmed locally: |
Closes #666.
Objective
hardware-walletis an optional Cargo feature (hidapifor Ledger,trezor-clientfor Trezor) that was never actually built or tested in CI —build-and-testonly rancargo build/cargo testwith default features, and whileclippydid pass--all-features,cargo clippyalone doesn't run the code, only type-check it. As a result the feature's code paths could (and did) silently break without anyone noticing.Root cause found while fixing this
Compiling with
--features hardware-walletfor the first time surfaced thatTrezorTransport::sign_transactioncalled protobuf setters (set_network,set_transaction) that don't exist on the pinnedtrezor-client = 0.1.5— Trezor's Stellar protocol has no "raw envelope" field; it requires the transaction to be decomposed into structured per-operation messages, which was never implemented. This is exactly the kind of regression issue #666 asks CI to catch. (Someone had already partially patched the compile error onmastersince I started; I kept their fix and improved it further — see below.)What changed
CI (
.github/workflows/ci.yml)hardware-walletjob: installslibudev-dev(hidapi's Linux HID backend) andlibusb-1.0-0-dev(trezor-client'srusbtransport), then runscargo build --locked --features hardware-walletandcargo test --locked --features hardware-wallet -- --test-threads=1.-- --test-threads=1matches the existingbuild-and-testjob's own precedent, and I confirmed locally it matters here too: running the new hidapi + trezor-client tests in parallel intermittently crashed the test binary (Windows-side hidapi/libusb concurrency issue); serial execution was reliably clean.libusb-1.0-0-devto theclippyjob's deps, since it already lints with--all-featuresand needs the same headers to linktrezor-client.src/utils/hardware_wallet.rsLedgerTransport::exchangeinto standaloneclassify_status_word/check_apdu_statusfunctions, with unit tests for: approval (0x9000), rejection (0x6985/0x6982— user declined on-device), unsupported envelope (0x6D00/0x6E00/0x6A81— outdated app / wrong envelope), an unrecognized status code, and a truncated response.TrezorTransport::sign_transactionto validate the HD path and report "not supported" before opening a device session — previously it calledconnect()first, so in any environment without a physical Trezor (i.e. CI) the "not supported" message was unreachable; you'd always get "No Trezor device detected" instead, masking the real limitation. This also means the unsupported-envelope path can now be tested deterministically without hardware.map_signing_errorguidance for the unsupported-envelope case.connect/device_statusfor both Ledger and Trezor return a clear disconnect error rather than hanging or panicking.tests/hardware_wallet_integration.rswallet connect ledger --timeout 1s,wallet hw-status trezor, andwallet import ... --hardware ledgerall fail cleanly (non-zero exit, clear message) with no device attached.Docs
API_REFERENCE.md: new "Hardware wallets (Ledger / Trezor)" section coveringconnect/hw-status/hw-address/import --hardware, plus security notes (every signing op needs on-device approval, no headless signing path) and the current Trezor-signing limitation.BUILD_TROUBLESHOOTING.md: per-OS system dependencies for the feature, and added the feature-enabled build/test commands to the "simulates CI" checklist.CONTRIBUTING.md: new "Run Optional-Feature Tests" section pointing contributors at the feature before they touch this file.Out of scope (flagged, not fixed here)
stellar-xdr, which is a substantial, security-sensitive feature on its own.wallet sign --hardware trezor/tx send --hardware trezornow fail with a clear "not supported" error instead of a compile error or a misleading device error.master. While validating this change I foundcargo test --lockedcurrently fails to compile onmasterfor reasons that have nothing to do with hardware wallets — at the time I branched, 34 errors acrosstemplates.rs,database.rs,ai.rs,compliance.rs,template_analytics.rs, andtemplate_recommender.rs(missing struct fields,Option<Vec<_>>vsVec<_>mismatches, immutable-borrow errors, etc.). I did not touch any of those files — that's a separate, pre-existing issue and well outside this PR's scope. Practically, this meansbuild-and-test/clippy/smokemay show red on this PR through no fault of this change; I validatedhardware_wallet.rsin isolation (a standalone scratch crate with the same pinnedhidapi/trezor-client/clap/stellar-strkeyversions) to confirm this PR's own code is correct independent of that.Testing performed
cargo fmt --checkon every file touched by this PR (clean).hardware_wallet.rsagainst the exact pinned dependency versions (clap = 4.4.18,stellar-strkey = 0.0.9,hidapi = 2.6.5,trezor-client = 0.1.5): 22 tests pass with default features, 28 pass / 1 ignored with--features hardware-wallet(the ignored one requires a physical Ledger, as before).--test-threads=1resolves it.