Skip to content

Commit 2035cb7

Browse files
committed
docs: Keep only what Core's tutorial lacks
The guide's offline-signing section repeated Bitcoin Core's tutorial with QR transport added. Moving public wallet data by QR is Bails's job, not this library's, so the section goes back to what the tutorial lacks: restore offline_wallet with ms32 wallet, then follow the tutorial, now linked on master. Say the signer goes offline before it is restored and stays offline, so it need not have been offline its whole life. Drop the "QR tools below" sentence and the QR troubleshooting section, which no step uses. Refs #92 Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
1 parent 6f6c86f commit 2035cb7

1 file changed

Lines changed: 12 additions & 139 deletions

File tree

‎docs/user/guide.md‎

Lines changed: 12 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ port.
8181

8282
Use a computer you believe is malware-free and whose other software you trust.
8383
Only codex32 and Bitcoin Core should perform recovery, derivation, wallet
84-
initialization, or signing. The QR tools below transport only public
85-
descriptors, PSBTs, and signed transactions.
84+
initialization, or signing.
8685

8786
Bitcoin Core wallet encryption is strongly recommended. Bitcoin Core owns the
8887
passphrase and its prompts; codex32 never asks for, reads, or forwards it.
@@ -192,133 +191,16 @@ worth the extra steps.
192191

193192
## More protection: watch-only wallet and offline signer
194193

195-
This setup follows Bitcoin Core v32's
196-
[offline-signing tutorial](https://github.com/bitcoin/bitcoin/blob/v32.0rc1/doc/offline-signing-tutorial.md)
197-
and its two wallets: `offline_wallet` holds the signing keys on a computer that
198-
never connects to a network, and `watch_only_wallet` runs on an ordinary online
199-
node. Where the tutorial carries a file between the computers, this guide shows
200-
the same public data as a QR on one screen and scans it with the other
201-
computer's camera.
194+
On the offline signer, create an empty encrypted descriptor wallet with private
195+
keys enabled and run `ms32 wallet`. Take that computer and its USB stick offline
196+
before you restore the signer, and keep them offline for good.
202197

203-
Before disconnecting the offline computer for good, install Bitcoin Core and
204-
codex32. Both computers also use `python3`, `gzip`, `qr`, and ZBar's
205-
`zbarcam`, which Tails already includes. Disable Ethernet, internet, Tor, Wi-Fi,
206-
Bluetooth, cellular, and every other network path on the offline computer.
207-
208-
### 1. Restore the offline signer
209-
210-
On the offline computer, create an empty encrypted descriptor wallet named
211-
`offline_wallet` with private keys enabled and run `ms32 wallet`. Keep that
212-
computer disconnected from every network while recovery text or signing keys
213-
are present.
214-
215-
### 2. Create the online watch-only wallet
216-
217-
The tutorial moves a watch-only wallet file made by `exportwatchonlywallet`.
218-
That file does not fit in a QR even compressed, so send the public descriptors
219-
instead, compressed with `gzip`. On the offline computer:
220-
221-
```bash
222-
bitcoin-cli -rpcwallet=offline_wallet listdescriptors |
223-
python3 -c 'import json, sys; print(json.dumps(json.load(sys.stdin)["descriptors"]), end="")' |
224-
gzip -9 | qr
225-
```
226-
227-
The compressed descriptors take about 640 bytes; see
228-
[QR troubleshooting](#qr-troubleshooting) if the QR does not fit. Public
229-
descriptors cannot spend, but they reveal wallet activity. Do not use a
230-
website, cloud scanner, chat service, or synced clipboard.
231-
232-
On the online computer, create a blank watch-only wallet, then scan and
233-
decompress the QR into it:
234-
235-
```bash
236-
bitcoin-cli -named createwallet wallet_name=watch_only_wallet disable_private_keys=true blank=true
237-
zbarcam --raw --oneshot -Sdisable -Sqrcode.enable -Sbinary | gunzip |
238-
bitcoin-cli -rpcwallet=watch_only_wallet -stdin importdescriptors
239-
```
240-
241-
Every result must say `"success": true`. Core's descriptor export keeps the
242-
stored timestamps, so the online node rescans from the same point. Run
243-
`getnewaddress` in each wallet and compare the two addresses on the two
244-
screens. Do not receive funds if they differ.
245-
246-
### 3. Receive to a checked address
247-
248-
Get receiving addresses and set labels in `watch_only_wallet`, as the tutorial
249-
does, so one wallet tracks which addresses are used. Malware on the online
250-
computer could show an address it controls, so check every address on the
251-
offline computer before giving it out. On the online computer:
252-
253-
```bash
254-
bitcoin-cli -rpcwallet=watch_only_wallet getnewaddress "LABEL" | qr
255-
```
256-
257-
On the offline computer, scan it and look it up in the signing wallet:
258-
259-
```bash
260-
address=$(zbarcam --raw --oneshot -Sdisable -Sqrcode.enable)
261-
bitcoin-cli -rpcwallet=offline_wallet getaddressinfo "$address"
262-
```
263-
264-
Give out the address only if the result shows `"ismine": true`. This works
265-
while `offline_wallet` is locked. The offline wallet recognizes its first 1,000
266-
addresses of each type; past that, a real address shows `"ismine": false` until
267-
you unlock `offline_wallet` and run `keypoolrefill` with a larger number.
268-
269-
When you pay yourself from a phone wallet, or the payer is with you, show the
270-
checked address as a QR on the offline screen and scan it there; nothing needs
271-
comparing:
272-
273-
```bash
274-
printf %s "$address" | qr
275-
```
276-
277-
For an exchange withdrawal or a payer over the internet, the address must pass
278-
through a networked computer or phone, where malware could swap it after the
279-
check. Paste it there, then compare the address on the last screen before you
280-
submit or send, such as the exchange's confirmation page or your sent message,
281-
character by character with the `"address"` shown offline.
282-
283-
### 4. Spend with a PSBT
284-
285-
On the online computer, create the unsigned PSBT with your destination and
286-
amount, and show it as a QR:
287-
288-
```bash
289-
bitcoin-cli -rpcwallet=watch_only_wallet send '{"DESTINATION_ADDRESS": AMOUNT}' |
290-
python3 -c 'import json, sys; print(json.load(sys.stdin)["psbt"], end="")' > funded_psbt.txt &&
291-
qr < funded_psbt.txt
292-
```
293-
294-
On the offline computer, scan it, then check every destination, amount, and
295-
fee before signing:
296-
297-
```bash
298-
zbarcam --raw --oneshot -Sdisable -Sqrcode.enable > funded_psbt.txt
299-
bitcoin-cli decodepsbt "$(cat funded_psbt.txt)"
300-
bitcoin-cli analyzepsbt "$(cat funded_psbt.txt)"
301-
```
302-
303-
Unlock `offline_wallet` as the tutorial shows, then sign and show the signed
304-
transaction as a QR:
305-
306-
```bash
307-
bitcoin-cli -rpcwallet=offline_wallet walletprocesspsbt "$(cat funded_psbt.txt)" |
308-
python3 -c 'import json, sys; r = json.load(sys.stdin); print(r["hex"] if r["complete"] else sys.exit("The PSBT is not fully signed."), end="")' > final_psbt.txt &&
309-
qr < final_psbt.txt
310-
```
311-
312-
On the online computer, scan it and broadcast:
313-
314-
```bash
315-
zbarcam --raw --oneshot -Sdisable -Sqrcode.enable > final_psbt.txt
316-
bitcoin-cli sendrawtransaction "$(cat final_psbt.txt)"
317-
```
318-
319-
If a PSBT is too large for a reliable QR, use a dedicated removable drive. The
320-
drive crosses the security boundary: keep it for this purpose, treat every file
321-
on it as untrusted, and still verify the transaction on the offline screen.
198+
After the signer is restored, follow Bitcoin Core's maintained
199+
[offline-signing tutorial](https://github.com/bitcoin/bitcoin/blob/master/doc/offline-signing-tutorial.md).
200+
That workflow owns the watch-only export/import and PSBT transport steps. In
201+
Bitcoin Core v32, `exportwatchonlywallet` creates the watch-only wallet file and
202+
`restorewallet` loads it on the online node. Do not improvise a codex32-specific
203+
descriptor-transfer procedure in place of that maintained workflow.
322204

323205
## Recover an existing or inherited wallet
324206

@@ -348,8 +230,8 @@ its public wallet data with the separate wallet record.
348230
It gives Core the master private key, asks Core to create the standard
349231
account-0 descriptors, scans history, and relocks an encrypted wallet.
350232
6. If you need an online watch-only counterpart, keep the restored signer
351-
offline and follow Bitcoin Core v32's
352-
[offline-signing tutorial](https://github.com/bitcoin/bitcoin/blob/v32.0rc1/doc/offline-signing-tutorial.md)
233+
offline and follow Bitcoin Core's
234+
[offline-signing tutorial](https://github.com/bitcoin/bitcoin/blob/master/doc/offline-signing-tutorial.md)
353235
to export and restore the watch-only wallet. Let the online node synchronize,
354236
then compare the recovered fingerprint, account, policy, addresses, balance,
355237
and transaction history with the wallet record.
@@ -410,15 +292,6 @@ Keep the matching application worksheet and original wallet instructions with
410292
the inheritance plan. Published BIP-93 still defines the `ms` application; the
411293
arbitrary-HRP format direction is not yet merged into that specification.
412294

413-
### QR troubleshooting
414-
415-
Maximize the terminal and reduce its font size if a QR does not fit. Keep `qr`
416-
connected to the terminal; redirecting its output creates an image file.
417-
Reading the compressed descriptors needs ZBar 0.23.1 or newer for `-Sbinary`;
418-
without it, ZBar rewrites the bytes as text and `gunzip` fails. Only public
419-
descriptors, xpubs, PSBTs, and signed transactions may cross the offline
420-
boundary by QR.
421-
422295
## Technical references
423296

424297
Automation, low-level private exports, parser behavior, correction mathematics,

0 commit comments

Comments
 (0)