winnow

The wallet on your phone

Your phone matches payments locally, keeps its keys in the device keychain, and connects to Bitcoin peers, directly or through your own Tor and I2P gateways, while the app is open and in short background checks iOS allows.

What this means for you

Unexpected payments may appear on the next sync. Fees are estimates, and a backup restores signing only when it holds this phone’s words, which the iCloud copy always does; see what a backup cannot restore. Direct connections expose your IP address to peers; your own Tor or I2P gateways can carry peer connections instead. The read guide, payment guide and recovery guide explain these tradeoffs.

2. What a phone actually is

Constraints that are load-bearing, not stylistic:

Bandwidth and battery are real but secondary. Steady-state compact filters are a few megabytes a day (approx.; see read-side §2.5). The worse mobile cost is policy: an always-on mempool subscription, a historical back-scan, or a server that answers getbalance. Those are refused even when the radio would allow them.


3. The four jobs, and two more

Job Default on this phone Paper
What’s mine? BIP157/158 filters, matched on-device, from creation height forward read-side
Where’s the tip? 80-byte headers, PoW + chainwork read-side
What fee? User override, else median of our confirmed spends, else presets; raised to the BIP133 feefilter floor most peer seats report, with an automatic increase capped at 120 sat/vB write-side
Did my tx get out? inv → getdata → tx to the peer pool, rebroadcast until a filter match, echo-watch while Send is open write-side
Who holds the keys? This-device Keychain; Taproot key-path for the everyday wallet this paper, write-side
Shared custody? Raw k-of-n sortedmulti_a script-path accounts in Advanced mode, coordinated by PSBT, no server; a Ledger can sign over Bluetooth; no MuSig2 multisig accounts
Moving a wallet in? A history bundle. There is no back-scan. import

One user-controlled escape hatch crosses several rows: a selected external explorer website. Opening an exact address or transaction requires a warning; its response never becomes wallet state.


4. What the device forces onto the wallet

4.1 Fresh, and forward-only

A new wallet and its recovery phrase are created immediately, offline. Header synchronization and automatic backup continue after onboarding; the wallet starts scanning from the last already-validated height so the interval cannot be missed. Recovering an old wallet privately from the chain would mean gigabytes of historical filters on a radio the user pays for. The product does not do that. Import requires the previous wallet’s answers to come along — descriptor, UTXOs, history, a last-known height — and the phone verifies them by scanning forward from that height. The argument and the bundle format are import.

This is the constraint that makes the rest cheap. It is not a v1 shortcut.

4.2 Taproot only

Receiving is BIP86 P2TR. There is no legacy / nested-segwit / P2WPKH path, and no ECDSA signing path. One output type means one watch-list shape, one sighash, one witness size for fee math (66 bytes for a key-path spend), and no “which address type did this contact use?” branch in the UI. The proposed P2WSH Safe is a deliberately scoped exception: an opt-in wsh(pk(KEY)) store with its own hardened keys, its own watch list and an ECDSA/BIP143 signing path, added beside the Taproot account rather than in place of it. Nothing about the account described here changes; see the Safe’s design and release criteria.

The phone can pay standard P2PKH, P2SH, P2WPKH, P2WSH and P2TR addresses. Recovery supports descriptor-derived coins; wallet files requiring unsupported signing data are refused. Keep the original wallet and backup for any unsupported coin types. See import and recovery.

4.3 Multisig accounts, same read path

A multisig account is another descriptor and another watch list, scanned with the same filters. The phone does not run a coordinator, a coinjoin server, or a notification service for co-signers. The PSBT is the coordinator, and anything that carries text carries it. A paired Ledger is reached over Bluetooth instead: it registers the account, shows addresses and payments on its own screen, and returns a signature the phone verifies before keeping it. Each signer adds an ordinary script-path signature, in any order. A backup that carries a MuSig2 account from the older Swift app is refused rather than restored without those funds. Multisig accounts.

4.4 Mainnet by default, signet for testing

The app opens on mainnet by default; signet is available in Advanced settings with its own wallet state. CI’s UI journeys and their video use a disposable regtest node. The numbers in screenshots/timings.json are historical signet measurements.


5. Trust on a phone

What the user is asked to trust, stated as mechanisms rather than intentions:

What the user is not asked to trust: an indexer operator’s retention policy or a push-notification vendor. Automatic iCloud backup adds trust in the Apple Account and iCloud Keychain recovery path. The app asks for device authentication and keeps the backup preference. Wallet, protocol and crypto code is the Winnow library under Lean/, which does not depend on the app; what only iOS can do goes through the shell’s declared capabilities. The Objective-C shell and iOS are trusted, not proven.


6. Deliberate absences

These are product decisions, not missing tickets:

The focused guides explain the consequences: delayed payment discovery, coarser fees, a required history backup, and transaction disclosure to relay peers.


7. How the implementation is checked

The validation appendix of the read side covers the stack. CI runs on every pull request and push to main. It builds the Lean once, checking every proof, then runs the Lean test executables, a regtest stage (io-test, backend-test and a differential check of multisig accounts against Bitcoin Core) and the Objective-C UI journeys in an iPhone simulator against a disposable regtest node: create, receive, send and confirm; pair a simulated Ledger, verify an address and spend; a 2-of-3 with two Bitcoin Core wallets, then its recovery path; the shipped census list; a silent payment. Each Debug, Release and device build is checked for Swift. Guide illustrations and screenshots/timings.json retain their historical provenance; they are not current-run evidence.

The journeys record a video and screenshots, which this site takes from the newest successful run on main; the recording keeps its source and run.


8. Status

The app defaults to mainnet and also supports signet. Current signing choices are ordinary Taproot and script-path k-of-n accounts. Silent payments can be sent, not received. Planned features remain on the roadmap.