diff options
| author | Bitflash <btf01@proton.me> | 2026-08-01 22:19:34 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-01 22:19:34 -0300 |
| commit | e9b3c1734aa274f801b4ffe7cfbc54d4c455f8e5 (patch) | |
| tree | 6ca4184e417affe0e1f8a4dcec30fc4f13f63eb6 | |
| parent | a45ed6918bc69c938e86e7107a038fd830a1cfde (diff) | |
docs: bring the README up to the wallet that exists, and make -help print (#106)
The README still said deterministic restore was an open issue, told people the mining mode was not remembered between restarts, and wrote every flag in the slash form that MSYS2 turns into a path before the node sees it. Rewritten around the phrase and the file as two backups covering different keys, the -restorephrase note for anyone who made a phrase on 1.2.12, -rescan, the diagnostics report, and the two upgrade reasons measured this week.
Also: -help printed nothing at all. This tree remaps printf to OutputDebugStringF, so the usage page went into debug.log, and a -mwindows binary has no console to write to either way -- the one command whose job is to tell you something returned 0 and said nothing. It now takes the real printf and attaches the terminal. The help text was missing -restoredepth, -showderived and the wallet-hd self-test.
| -rw-r--r-- | README.md | 131 | ||||
| -rw-r--r-- | src/main_gui.cpp | 19 |
2 files changed, 121 insertions, 29 deletions
| @@ -62,6 +62,17 @@ added a per-block signature-operation cap. A node on an older build will accept | |||
| 62 | blocks that current nodes reject, which puts it on a different chain without any | 62 | blocks that current nodes reject, which puts it on a different chain without any |
| 63 | warning. | 63 | warning. |
| 64 | 64 | ||
| 65 | Two more reasons, both measured rather than theorised: | ||
| 66 | |||
| 67 | - **Before 1.2.13** a node closed a disconnected peer's socket twice and left the | ||
| 68 | closed handle in its `select()` set, where it made `select()` fail on every | ||
| 69 | iteration. The node then spent its socket loop in an error path instead of | ||
| 70 | reading its peers. Two nodes side by side on the same machine, same network: | ||
| 71 | the one without the fix held 11 peers, the one with it held 21. | ||
| 72 | - **Before 1.2.11** a long-running Windows node accumulated sockets it never | ||
| 73 | released — 1262 of them in 26 hours on one machine, each holding an ephemeral | ||
| 74 | port. | ||
| 75 | |||
| 65 | Your wallet and chain data live in `%APPDATA%\Bitflash` (Windows) or | 76 | Your wallet and chain data live in `%APPDATA%\Bitflash` (Windows) or |
| 66 | `~/.bitflash` (Linux) and are shared by every version, so upgrading is just | 77 | `~/.bitflash` (Linux) and are shared by every version, so upgrading is just |
| 67 | replacing the binary. Never delete that directory to "fix" something without a | 78 | replacing the binary. Never delete that directory to "fix" something without a |
| @@ -69,10 +80,47 @@ backup — it holds your keys. | |||
| 69 | 80 | ||
| 70 | --- | 81 | --- |
| 71 | 82 | ||
| 72 | ## Backing up your wallet | 83 | ## Your wallet: the phrase and the file |
| 84 | |||
| 85 | Since 1.2.12 a wallet can hold twelve words that rebuild it. Since 1.2.13 those | ||
| 86 | words also cover the address the window shows you. **Both still matter** — the | ||
| 87 | phrase and the file back up different things, and the difference is where people | ||
| 88 | lose money. | ||
| 89 | |||
| 90 | ### The recovery phrase | ||
| 91 | |||
| 92 | ``` | ||
| 93 | bitflash -newphrase # create it, show it once, exit | ||
| 94 | bitflash -restorephrase="twelve words here" # rebuild a wallet from it | ||
| 95 | ``` | ||
| 96 | |||
| 97 | `-newphrase` installs a BIP32 seed, derives the wallet's key pool and default | ||
| 98 | receiving address from it, and prints the words once. It refuses if a phrase | ||
| 99 | already exists: replacing one silently would strand every coin on addresses the | ||
| 100 | written-down words no longer describe. | ||
| 101 | |||
| 102 | `-restorephrase` installs the seed and walks forward in batches of a hundred | ||
| 103 | addresses, rescanning the chain after each and stopping when a whole batch turns | ||
| 104 | up nothing. `-restoredepth=N` looks further. `-showderived=N` lists the addresses | ||
| 105 | a phrase produces, so you can check one before trusting it. | ||
| 106 | |||
| 107 | The same two operations are in the window, under **Wallet Safety**. | ||
| 108 | |||
| 109 | **The words are printed to the terminal and nowhere else** — never to | ||
| 110 | `debug.log`, which is the file people are routinely asked to attach to an issue. | ||
| 73 | 111 | ||
| 74 | Two things about this wallet will cost you money if you do not know them. Both | 112 | **What the phrase does not cover.** Keys that existed *before* the seed was |
| 75 | are consequences of the 0.1.0 wallet format, and neither is obvious. | 113 | installed are random. They are not derived from it and they do not come back |
| 114 | from the words. The wallet names such an address `Your Address (created before | ||
| 115 | the recovery phrase)` so you can tell them apart. This is why file backups still | ||
| 116 | matter. | ||
| 117 | |||
| 118 | > **If you created a phrase on 1.2.12, run `-restorephrase` with the same twelve | ||
| 119 | > words.** That release installed the seed but left the visible address and the | ||
| 120 | > key pool random, so the wallet went on handing out addresses the words cannot | ||
| 121 | > reproduce while the window said a phrase existed. Restoring repairs it. | ||
| 122 | |||
| 123 | ### The file | ||
| 76 | 124 | ||
| 77 | **Copying `wallet.dat` on its own is not a backup.** Berkeley DB ties the file | 125 | **Copying `wallet.dat` on its own is not a backup.** Berkeley DB ties the file |
| 78 | to the environment in the `database/` subdirectory beside it, so a lone | 126 | to the environment in the `database/` subdirectory beside it, so a lone |
| @@ -88,20 +136,26 @@ It loads the wallet, writes the copy, and exits without starting the node. If | |||
| 88 | you would rather copy by hand, shut the node down first and take the **whole** | 136 | you would rather copy by hand, shut the node down first and take the **whole** |
| 89 | data directory, not just `wallet.dat`. | 137 | data directory, not just `wallet.dat`. |
| 90 | 138 | ||
| 91 | **Every backup is still a snapshot, but it now has a safety margin.** The wallet | 139 | A file backup covers what a phrase cannot: keys from before the seed, and any |
| 92 | keeps a pool of 100 pre-generated keys. A backup contains those keys, so it | 140 | key the wallet acquired by import. It also has a margin of its own — the wallet |
| 93 | covers the next 100 mining rewards or receive addresses the node hands out after | 141 | keeps a pool of 100 pre-generated keys, so a backup covers the next 100 mining |
| 94 | the backup. That makes a normal backup much safer than the original 0.1.0 | 142 | rewards or receive addresses. Take a fresh one after mining for a while, after |
| 95 | wallet, where the very next block could land on a key the backup did not have. | 143 | creating many receive addresses, and before moving the wallet to another machine. |
| 144 | |||
| 145 | The GUI has a **Backup Wallet** button and a **Wallet Safety** view, which fills | ||
| 146 | the key pool before writing the backup. | ||
| 96 | 147 | ||
| 97 | It is not a seed phrase. Heavy use can drain the key pool, and deterministic | 148 | ### Finding coins the wallet never recorded |
| 98 | wallet restore is still tracked in [#47](https://github.com/Bitflash-sh/bitflash/issues/47). | 149 | |
| 99 | Back up again after mining for a while, after creating many receive addresses, | 150 | ``` |
| 100 | and before moving the wallet to another machine. | 151 | bitflash -rescan |
| 152 | ``` | ||
| 101 | 153 | ||
| 102 | The GUI has a **Backup Wallet** button and a **Wallet Safety** view. Use that if | 154 | Walks the chain for coins a key of yours owns but the wallet has no record of — |
| 103 | you do not want to run the command by hand; it fills the key pool before writing | 155 | after importing keys, or after restoring a file from another machine. |
| 104 | the backup. | 156 | `-importwallet` runs this automatically. A scan asked for with no chain data |
| 157 | loaded is refused rather than reported as "no transactions found", which reads | ||
| 158 | as a verdict to somebody who has just lost a wallet. | ||
| 105 | 159 | ||
| 106 | ### When wallet.dat itself will not open | 160 | ### When wallet.dat itself will not open |
| 107 | 161 | ||
| @@ -153,28 +207,48 @@ xmrig -a rx/0 -o POOL_BTF_ADDRESS -u YOUR_BTF_ADDRESS -p x | |||
| 153 | ## Headless / server mode | 207 | ## Headless / server mode |
| 154 | 208 | ||
| 155 | ```bash | 209 | ```bash |
| 156 | ./bitflash /nogui # node only | 210 | ./bitflash -nogui # node only |
| 157 | ./bitflash /nogui /gen # node + solo mining | 211 | ./bitflash -nogui -gen # node + solo mining |
| 158 | ./bitflash /nogui /gen /operator # pool operator | 212 | ./bitflash -nogui -gen -operator # pool operator |
| 159 | ./bitflash /nogui /gen /participant=POOL_BTF_ADDRESS # mine to pool | 213 | ./bitflash -nogui -gen -participant=POOL_BTF_ADDRESS # mine to pool |
| 160 | ``` | 214 | ``` |
| 161 | 215 | ||
| 162 | Mining is off unless you pass `/gen` — it is not remembered between restarts, so | 216 | Every option takes `-` or `/`. **Under MSYS2 use the `-` form** — the shell |
| 163 | put the flag in whatever starts the node rather than enabling it in the window. | 217 | rewrites a leading slash into a path before the node ever sees it. |
| 218 | |||
| 219 | **The mining mode is remembered between restarts** since 1.2.11, so a node that | ||
| 220 | was mining comes back mining. A `-gen`, `-operator` or `-participant` flag always | ||
| 221 | wins over what was stored, and the log says on every start which of the two | ||
| 222 | decided. Passing the flag anyway is the safe habit: it survives a wallet that | ||
| 223 | came from an older build. | ||
| 164 | 224 | ||
| 165 | Other options worth knowing: | 225 | Other options worth knowing: |
| 166 | 226 | ||
| 167 | ```bash | 227 | ```bash |
| 168 | /datadir=PATH # wallet and chain data elsewhere | 228 | -datadir=PATH # wallet and chain data elsewhere |
| 169 | /port=N # P2P listen port, default 8433 | 229 | -port=N # P2P listen port, default 8433 |
| 170 | /debug # verbose log; without it debug.log is nearly silent | 230 | -debug # verbose log; without it debug.log is nearly silent |
| 171 | /help # full list | 231 | -help # full list |
| 172 | ``` | 232 | ``` |
| 173 | 233 | ||
| 174 | `/port` plus `/datadir` is what lets two nodes share one machine. Both are | 234 | `-port` plus `-datadir` is what lets two nodes share one machine. Both are |
| 175 | needed — the data directory takes an exclusive lock, so a second node pointed at | 235 | needed — the data directory takes an exclusive lock, so a second node pointed at |
| 176 | the same one will refuse to start. | 236 | the same one will refuse to start. |
| 177 | 237 | ||
| 238 | ### When something looks wrong | ||
| 239 | |||
| 240 | **Menu > Diagnostics**, and the same report in `debug.log` every ten minutes: | ||
| 241 | peers held against peers `select()` is actually watching, blocks received and how | ||
| 242 | many arrived without a parent, the proof-of-work mode with the live miner thread | ||
| 243 | count, sockets by the part of the program that opened them, and per peer how long | ||
| 244 | since the last message each way. There is a copy button — if you open an issue, | ||
| 245 | paste that. | ||
| 246 | |||
| 247 | It exists because every hard problem in this project so far was found from | ||
| 248 | *outside* the node: sockets read over WMI from another machine, memory compared | ||
| 249 | against a number in a README, a `grep` over somebody's log. In each case the node | ||
| 250 | knew and had no way to say so. | ||
| 251 | |||
| 178 | As a systemd service: | 252 | As a systemd service: |
| 179 | 253 | ||
| 180 | ```ini | 254 | ```ini |
| @@ -183,7 +257,7 @@ Description=Bitflash node | |||
| 183 | After=network.target | 257 | After=network.target |
| 184 | 258 | ||
| 185 | [Service] | 259 | [Service] |
| 186 | ExecStart=/opt/bitflash/bitflash /nogui /gen /operator | 260 | ExecStart=/opt/bitflash/bitflash -nogui -gen -operator |
| 187 | Restart=always | 261 | Restart=always |
| 188 | User=bitcoin | 262 | User=bitcoin |
| 189 | WorkingDirectory=/opt/bitflash | 263 | WorkingDirectory=/opt/bitflash |
| @@ -225,7 +299,7 @@ Relays are the meeting points that let nodes behind NAT connect to each other. M | |||
| 225 | 299 | ||
| 226 | ```bash | 300 | ```bash |
| 227 | sudo bash relay/install-bitflash-relay.sh 8434 | 301 | sudo bash relay/install-bitflash-relay.sh 8434 |
| 228 | ./bitflash /nogui /announcerelay=YOUR_PUBLIC_IP:8434 | 302 | ./bitflash -nogui -announcerelay=YOUR_PUBLIC_IP:8434 |
| 229 | ``` | 303 | ``` |
| 230 | 304 | ||
| 231 | Relays forward encrypted bytes and cannot read or modify traffic. | 305 | Relays forward encrypted bytes and cannot read or modify traffic. |
| @@ -265,6 +339,7 @@ Installs deps via pacman, produces `Bitflash-*-windows.zip`. | |||
| 265 | | Addressing | `.btf` rendezvous — see the caveats above | | 339 | | Addressing | `.btf` rendezvous — see the caveats above | |
| 266 | | Premine | None | | 340 | | Premine | None | |
| 267 | | Pool server | Built-in — `.btf` rendezvous only | | 341 | | Pool server | Built-in — `.btf` rendezvous only | |
| 342 | | Wallet recovery | Twelve-word phrase (BIP39 + BIP32), plus file backup | | ||
| 268 | 343 | ||
| 269 | The halving interval is the number most people get wrong coming from Bitcoin. | 344 | The halving interval is the number most people get wrong coming from Bitcoin. |
| 270 | Same 210,000 blocks, but at two minutes instead of ten, so it arrives in about | 345 | Same 210,000 blocks, but at two minutes instead of ten, so it arrives in about |
diff --git a/src/main_gui.cpp b/src/main_gui.cpp index c9e7dee..32fcdef 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp | |||
| @@ -40,6 +40,12 @@ static string argval2(int argc, char* argv[], const char* keySlash, const char* | |||
| 40 | return argval(argc, argv, keyDash); | 40 | return argval(argc, argv, keyDash); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | // The real printf, not the one util.h remaps to OutputDebugStringF. Help that | ||
| 44 | // goes to debug.log is help nobody asked for: `-help` printed a full page into | ||
| 45 | // the data directory and returned 0 with an empty terminal, which reads as a | ||
| 46 | // command that does nothing. Same reason walletcmd.cpp undefines it. | ||
| 47 | #undef printf | ||
| 48 | |||
| 43 | static void PrintUsage() | 49 | static void PrintUsage() |
| 44 | { | 50 | { |
| 45 | printf("Bitflash command-line options\n"); | 51 | printf("Bitflash command-line options\n"); |
| @@ -50,7 +56,7 @@ static void PrintUsage() | |||
| 50 | printf(" /debug\n"); | 56 | printf(" /debug\n"); |
| 51 | printf(" /gen\n"); | 57 | printf(" /gen\n"); |
| 52 | printf(" /nogui or /daemon\n"); | 58 | printf(" /nogui or /daemon\n"); |
| 53 | printf(" /selftest=wallet-keypool\n"); | 59 | printf(" /selftest=wallet-keypool or /selftest=wallet-hd\n"); |
| 54 | printf("\n"); | 60 | printf("\n"); |
| 55 | printf("Mining mode:\n"); | 61 | printf("Mining mode:\n"); |
| 56 | printf(" /operator\n"); | 62 | printf(" /operator\n"); |
| @@ -84,12 +90,18 @@ static void PrintUsage() | |||
| 84 | printf(" wallet that has none, show it once, exit)\n"); | 90 | printf(" wallet that has none, show it once, exit)\n"); |
| 85 | printf(" /restorephrase=\"WORDS\" (rebuild this wallet from a phrase and scan\n"); | 91 | printf(" /restorephrase=\"WORDS\" (rebuild this wallet from a phrase and scan\n"); |
| 86 | printf(" the chain for its coins, then exit)\n"); | 92 | printf(" the chain for its coins, then exit)\n"); |
| 93 | printf(" /restoredepth=N (with /restorephrase: derive at least N\n"); | ||
| 94 | printf(" addresses before giving up)\n"); | ||
| 95 | printf(" /showderived=N (list the first N addresses a phrase\n"); | ||
| 96 | printf(" produces, without installing it)\n"); | ||
| 87 | printf(" /rescan (walk the chain for coins this wallet owns\n"); | 97 | printf(" /rescan (walk the chain for coins this wallet owns\n"); |
| 88 | printf(" but never recorded, then exit)\n"); | 98 | printf(" but never recorded, then exit)\n"); |
| 89 | printf("\n"); | 99 | printf("\n"); |
| 90 | printf("Each option also accepts '-' instead of '/'.\n"); | 100 | printf("Each option also accepts '-' instead of '/'.\n"); |
| 91 | } | 101 | } |
| 92 | 102 | ||
| 103 | #define printf OutputDebugStringF | ||
| 104 | |||
| 93 | static void ParseStartupArguments(int argc, char* argv[]) | 105 | static void ParseStartupArguments(int argc, char* argv[]) |
| 94 | { | 106 | { |
| 95 | if (arg(argc,argv,"/datadir") || arg(argc,argv,"-datadir")) | 107 | if (arg(argc,argv,"/datadir") || arg(argc,argv,"-datadir")) |
| @@ -221,6 +233,11 @@ int main(int argc, char* argv[]) | |||
| 221 | if (arg(argc,argv,"/help") || arg(argc,argv,"-help") || | 233 | if (arg(argc,argv,"/help") || arg(argc,argv,"-help") || |
| 222 | arg(argc,argv,"--help") || arg(argc,argv,"/?")) | 234 | arg(argc,argv,"--help") || arg(argc,argv,"/?")) |
| 223 | { | 235 | { |
| 236 | // Without this the help prints into nothing. A -mwindows binary starts | ||
| 237 | // with no console, so every one of those printfs went nowhere and the | ||
| 238 | // one command whose entire job is to tell you something told you | ||
| 239 | // nothing at all -- exit code 0, not a byte of output. | ||
| 240 | AttachTerminal(); | ||
| 224 | PrintUsage(); | 241 | PrintUsage(); |
| 225 | return 0; | 242 | return 0; |
| 226 | } | 243 | } |