Metro Vault

com.gorunjinian.metrovault
by Zapstore _@zapstore.dev

Republished from GitHub / F-Droid by the Zapstore main account.

First release: Aug 4, 2026, 2 total releases.

Most recent release: Sep 4, 2026.

Website Repo

Appears in 0 app stacks.

0 sats / 0 zaps received in the past year.

Sats Received

Underlying data available via MCP: app_zaps, app_releases.

Zap Count

Underlying data available via MCP: app_zaps, app_releases.

Releases

  • Sep 4, 2026 3.9.5
    # MetroVault v3.9.5 - Release Notes ## Taproot Signing Hardening - **Master fingerprint fix**: Taproot BIP-32 derivation fingerprints are now parsed as unsigned 32-bit values, so wallets whose fingerprint has the high bit set resolve their keys correctly instead of being skipped - **BIP-86 output-key verification**: key-path signing checks that the input's scriptPubKey commits to the tweaked output key (not the raw internal key) before signing, so every produced signature actually satisfies the spent output - **Strict sighash policy**: undefined or ambiguous hashtypes are rejected for both Taproot and ECDSA inputs (`SigHash.isValidTaproot` / `isValidEcdsa`); silent-payment spends enforce the same Taproot policy - **BIP-341 signature encoding**: `SIGHASH_DEFAULT` yields 64-byte signatures; every other hashtype appends the sighash byte - **x-only key matching**: Taproot inputs resolve even when the PSBT only carries x-only keys
    More…
    --- ## Partial-Signing Transparency - **Refusals are explained**: a new `InputSigningRefusal` hierarchy records *why* a matched input was declined (script-tree commitment, script-path key, unsupported sighash type) - **Warning cards in the UI**: the PSBT scan screen and the signed-PSBT export show exactly which inputs were left unsigned and why, instead of silently returning a partially signed transaction --- ## Coordinator Export (Nunchuk, Sparrow, Coldcard) - **Public-only export to coordinators** (#13): new "Export to wallet coordinator" flow exporting the active account as a Nunchuk signer-record QR or a Coldcard "Generic JSON" QR that Sparrow's Coldcard importer consumes, plus a JSON file export through the Storage Access Framework; the export never contains private material and rejects private extended-key prefixes - **Multi-account and combined exports** (#15): pick any account number, or export a combined JSON that bundles all supported single-sig and multisig (BIP-48) sections into one payload - **Animated QR playback**: large exports use BBQr or BC-UR with pause, manual frame stepping and a frame counter; frames are recycled when leaving the screen - **Live verification details**: fingerprint, derivation path and first receive address update for the selected account and format - **Standardized address display**: new `AddressFormatter` groups addresses in 5-character blocks and bolds the first/last segments for easier checking --- ## UI and Usability - **Show/hide password toggle** (#14) on every secure password field (setup, unlock, sensitive-operation verification, biometric and decoy setup, password changes); hidden by default, independent per field, resets when cleared or recreated - **Sensitive clipboard auto-clear**: clipboard handling is centralized in `SecurityUtils`; private keys, BIP-85 secrets and other sensitive values are wiped from the clipboard after 20 seconds --- ## Smaller APK ### Compact secp256k1 tables The bundled secp256k1 cryptography library is now built with compact precomputed multiplication tables, cutting roughly **4 MB from the APK** (and about twice that from on-device install size, since the native libraries are extracted at install): - **~1.1 MB → ~2.5 KB per ABI**: the precomputed tables (`ECMULT_WINDOW_SIZE=4`, `ECMULT_GEN_KB=2`) made up over 80% of each native library (the stock 0.24.0 `.so` is 1.28–1.48 MB per ABI); they are now sized like a dedicated hardware signer's build instead of a full node's - **No functional change**: table size is a pure speed/size trade in the reference bitcoin-core/secp256k1 library — signatures are byte-identical (deterministic nonces per RFC 6979 / BIP-340) and signing remains constant-time - **Applied identically on both sides**: the release CI (`.github/reproducible-build.sh`) and the F-Droid recipe patch the same two flags into the from-source build, so the published APK still reproduces byte-for-byte ### Leaner dependencies - **R8 and dependency cleanup**: `MainActivity` moved from `AppCompatActivity` to `FragmentActivity`, Material Components and `material-icons-extended` were dropped in favor of local vector assets, and broad keep rules were replaced by targeted ones for ZXing and the secp256k1 JNI (letting R8 prune unused Tink/Protobuf code) - **Assets and packaging**: logo and profile images converted to WebP; redundant `META-INF` entries, Kotlin metadata and coroutine debug probes excluded from the release APK --- ## secp256k1 0.24.0 - **Library update**: ACINQ secp256k1-kmp 0.23.0 → 0.24.0, bundling bitcoin-core/secp256k1 0.8.0 - **Hardened JNI bindings**: invalid arguments (including MuSig2 inputs without a parse step) now surface as a `Secp256k1Exception` instead of the library's default `abort()` callback; context initialization fails early if it cannot complete --- ## Tests - **Signing**: `TaprootPsbtSigningTest`, `TaprootSighashPolicyTest`, `SegwitV0SighashTest`; `SilentPaymentReceiveSignerTest` extended for the sighash policy - **Serialization codecs**: `MultisigConfigJsonTest`, `WalletKeysJsonTest`, `WalletMetadataJsonTest` (including the v1.x passphrase-setting migration) and `QuickShortcutStorageTest` - **Coordinator export**: `CoordinatorExportServiceTest` covers the Nunchuk record, Coldcard/Sparrow JSON and combined exports --- ## Technical Details ### Key Files Modified Paths below are relative to `app/src/main/java/com/gorunjinian/metrovault/` unless noted. **Signing** - `lib/bitcoin/Psbt.kt`, `lib/bitcoin/PsbtTypes.kt` - BIP-341 signature encoding, Taproot fingerprint parsing - `lib/bitcoin/SigHash.kt` - `isValidTaproot` / `isValidEcdsa` sighash policy - `lib/bitcoin/Bip371Fields.kt` - `PSBT_IN_TAP_MERKLE_ROOT` - `domain/service/psbt/PsbtSigner.kt`, `domain/service/psbt/PsbtKeyResolver.kt` - BIP-86 output-key verification, x-only matching, refusal reporting - `domain/service/bitcoin/WalletSigningService.kt` - signing-refusal plumbing - `data/model/PsbtModels.kt` - `InputSigningRefusal` - `feature/transaction/ScanPSBTScreen.kt`, `feature/transaction/components/SignedPSBTDisplay.kt` - partial-signing warning cards **Coordinator export** - `domain/service/bitcoin/CoordinatorExportService.kt`, `data/model/CoordinatorExport.kt` - Nunchuk / Coldcard-Sparrow JSON / combined exports - `feature/wallet/details/CoordinatorExportScreen.kt`, `feature/wallet/details/components/AccountExportComponents.kt` - unified export screen, account selector - `core/qr/AnimatedQREncoder.kt`, `core/qr/CoordinatorQREncoder.kt`, `core/ui/components/AnimatedQrDisplay.kt` - animated QR encoding and playback - `core/ui/util/AddressFormatter.kt` - styled address display **Build and size** (repo-relative) - `app/build.gradle.kts`, `app/proguard-rules.pro` - version 3.9.5 (8), packaging exclusions, targeted keep rules - `gradle/libs.versions.toml` - secp256k1-kmp 0.24.0; AGP 9.3.2, Navigation 2.10.0, Gradle 9.7.1 - `.github/reproducible-build.sh` - builds the v0.24.0 tag from source with the compact-table flags (mirrored in the fdroiddata recipe) - `docs/FDROID_BUILD.md` - updated pins (tag `e9d5c95`, submodule `6e2c8bc` = upstream v0.8.0) and the recipe's new `prebuild` step - `docs/SECURITY.md` - secp256k1 build configuration documented under Cryptographic Standards - `fastlane/metadata/android/en-US/changelogs/8.txt` - F-Droid changelog - `app/src/main/java/com/gorunjinian/metrovault/feature/settings/LibUsedScreen.kt` - library versions ## More Info * Add password visibility controls by @charbelgereige in https://github.com/gorunjinian/MetroVault/pull/14 * Add Nunchuk and Sparrow coordinator exports by @charbelgereige in https://github.com/gorunjinian/MetroVault/pull/13 * Refactor export flows for multi-account support and QR enhancements by @gorunjinian in https://github.com/gorunjinian/MetroVault/pull/15 ## New Contributors * @charbelgereige made their first contribution in https://github.com/gorunjinian/MetroVault/pull/14 **Full Changelog**: https://github.com/gorunjinian/MetroVault/compare/v3.9.0...v3.9.5
  • Aug 4, 2026 3.9.0
    # MetroVault v3.9.0 - Release Notes ## Multisig Setup File Import Import multisig wallets directly from vendor setup files via QR: - **Broad Vendor Support**: Parses multisig setup files (`Name:` / `Policy:` / `Derivation:` format) from Passport, Jade, Sparrow and ColdCard - **SLIP-132 Normalization**: Ypub/Zpub extended keys (and testnet variants) are automatically converted to standard xpubs - **Smart Name Pre-Fill**: Wallet names are pre-filled from setup file headers or QR transport metadata - **Improved BC-UR Decoding**: `UR:BYTES` payload support and wallet name extraction from `UR:OUTPUT-DESCRIPTOR` envelopes
    More…
    - **Unified Format Detection**: One import path now auto-detects setup files, BSMS records, and plain descriptors --- ## Security Hardening Upgrades to the credential and key-derivation architecture: - **Stronger Password KDF**: PBKDF2 iterations raised to 600,000 for newly created vaults - **Verifier-Only Storage**: Passwords are checked against domain-separated HKDF verifiers — the derived encryption key is never persisted to disk - **Dual-Clock Rate Limiting**: Login lockouts track both wall-clock and monotonic time, preventing lockout bypass via system clock manipulation - **Stricter Biometrics**: `BIOMETRIC_STRONG` (Class 3) enforced on Android 11+; biometric unlock is automatically disabled when it becomes stale after a password change - **Hardened Schnorr Signing**: BIP-340 signing now always mixes in 32 bytes of fresh `SecureRandom` auxiliary data, hardening nonces against side-channel attacks - **Safer Defaults**: "Save passphrase locally" is now OFF by default when creating a wallet - **Memory Safety**: Improved thread safety and atomicity in `SecureByteArray`, `SecureSeedCache`, and the password change flow --- ## Architecture Improvements Large-scale refactor of screens into MVVM with shared components: - **Session Orchestration**: New `AppSessionViewModel` handles session expiry, auto-open logic, and wallet key unloading — moved out of the navigation composable - **Dedicated ViewModels**: Stateless import and message signing flows migrated to `ImportStatelessViewModel` and `SignMessageViewModel` - **Unified Password Dialog**: New `VerifyPasswordDialog` replaces per-screen password checking across account details, settings, and export screens — verification always runs off the main thread - **Single-Pass Password Classification**: `SecureStorage.classifyPassword` identifies main vs. decoy vault passwords in one PBKDF2 pass instead of two - **Shared Wizard Steps**: Wallet configuration and BIP39 passphrase steps deduplicated across the Create, Import, and Stateless flows - **Centralized QR Export**: New `TapToCopyQRCard` component and `DescriptorQREncoder` utility standardize QR display and descriptor encoding across all export screens --- ## Additional Improvements ### UX - **Entropy Info Dialog**: Wallet creation now explains seed generation and system entropy usage - **Responsive Multisig Export**: Descriptor generation runs on a background thread with a progress indicator instead of blocking the UI - **Smoother Home Pager**: Removed custom fling/spring behavior in favor of default, more predictable paging - **Silent Payments**: Quick-action label corrected to singular "Address" for Silent Payment wallets ### Build & Dependencies - **Toolchain**: Gradle 9.6.1, Android Gradle Plugin 9.3.1, Kotlin 2.4.10 - **Libraries**: Compose BOM 2026.06.01, AndroidX Biometric 1.4.0-alpha07, Lifecycle 2.11.0, Core-KTX 1.19.0 ### Testing - **New Test Suites**: Vendor setup file parsing with cross-format address equivalence, descriptor format detection, QR transport unwrapping, pinned AES-GCM/HKDF-SHA256 compatibility vectors, and password hash verification --- ## Technical Details ### Key Files Modified **Multisig Setup File Import** - `ColdCardSetupFile.kt` - New parser for vendor setup files with SLIP-132 normalization - `MultisigDescriptorParser.kt` - Refactored into a format-detection router - `DescriptorQRScanner.kt` - `UR:BYTES` support and transport-embedded name extraction - `ImportMultisigViewModel.kt` - Wallet name pre-fill from setup file metadata **Security** - `KeyDerivation.kt` - New shared crypto utility (PBKDF2 → HKDF, AES-GCM) - `SecureStorage.kt` - Domain-separated HKDF verifiers, `classifyPassword` single-pass lookup - `LoginAttemptManager.kt` - Dual-clock (wall + monotonic) rate limiting - `BiometricAuthManager.kt` / `BiometricPasswordManager.kt` - STRONG biometric enforcement, stale credential invalidation - `Crypto.kt` - BIP-340 auxiliary randomness in Schnorr signing **Architecture** - `AppSessionViewModel.kt` - Session expiry, auto-open, and wallet loading orchestration - `ImportStatelessViewModel.kt` / `SignMessageViewModel.kt` - New ViewModels for stateless import and message signing - `WalletWizardSteps.kt` - Shared wallet configuration and passphrase wizard steps - `TapToCopyQRCard.kt` / `DescriptorQREncoder.kt` - Shared QR display component and centralized descriptor QR encoding - `VerifyPasswordDialog` (`SecurityDialogs.kt`) - Unified off-main-thread password verification **Full Changelog**: https://github.com/gorunjinian/MetroVault/compare/v3.8.7...v3.9.0