1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
|
<div align="center">
<img src="docs/social.png" width="820" alt="Bitflash"/>
# Bitflash `BTF`
CPU-only cryptocurrency. A revival of Bitcoin 0.1.0 with RandomX proof of work and anonymous `.btf` addressing over Nostr.
-2ea44f?style=for-the-badge)



[](https://discord.gg/n7B2Eamn3)
**[Download](https://releases.bitflash.network/)** · **[Discord](https://discord.gg/n7B2Eamn3)**
</div>
---
## What it is
Bitflash keeps Satoshi's original consensus rules and replaces two things:
**RandomX proof of work.** Memory-hard algorithm used by Monero. A laptop competes equally with a server. ASICs and GPUs have no advantage.
**Anonymous addressing.** Every node has a `.btf` address derived from its public key, similar to a Tor `.onion`. Nodes reach each other through encrypted rendezvous tunnels by default, and can advertise a signed direct `.onion` endpoint for Tor peers.
No premine. No ICO. 50 BTF per block, halving on schedule, 21M cap, ~2 minute blocks.
### What `.btf` does and does not hide
Worth being precise, because the difference matters if you are relying on it.
**A peer you reach over `.btf` does not learn your IP.** Outbound peer discovery uses rendezvous tunnels by default. If both sides use Tor and the peer advertises a signed `.onion` endpoint, the node connects directly to that hidden service instead. In both cases the peer does not see your clearnet IP.
**The rendezvous relay sees your IP unless you use Tor.** It has to — it is the thing your TCP connection terminates on. With `-tor`, the relay sees Tor instead. With a signed direct `.onion` peer endpoint, the relay is not on that connection path at all.
**The node still listens on 8433.** Nothing dials by IP any more, but the listener is still there, so anyone who already knows your address and can reach that port may connect directly. If that matters to you, firewall it.
This is unlinkability between peers, not anonymity against a network observer.
For Tor routing and direct onion peer endpoints, start the node with `-tor`;
see [Tor mode](docs/tor.md).
For a plain SOCKS5 proxy without Tor-specific defaults, use
`-socks=HOST:PORT`.
---
## Quick start
Download the [latest release](https://releases.bitflash.network/) and run. No
install, no configuration — it connects automatically and starts syncing.
**Linux:** make the `.AppImage` executable and run it.
**Windows:** extract the `-windows-with-tor.zip` and run `Bitflash.exe`. Tor is
bundled and a managed Tor instance starts automatically, so onion transport
works with no separate install. Pass `-nomanagedtor` to turn it off.
Every release ships a `SHA256SUMS` covering the assets. Verifying takes a second
and is worth doing:
```bash
sha256sum -c SHA256SUMS
```
For newer signed releases, verify the checksum file itself first:
```bash
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum -c SHA256SUMS
```
The helper below downloads the release assets, verifies `SHA256SUMS.asc` when it
is present, then checks the hashes:
```bash
scripts/verify-release.sh latest
```
See [release verification](docs/release-verification.md) for the full release
audit flow and the maintainer signing step.
Public mirrors should make the latest checksum files available both under the
versioned release directory and at the release root:
```text
https://releases.bitflash.network/v1.2.20/SHA256SUMS
https://releases.bitflash.network/SHA256SUMS # alias to latest
```
Bitflash also ships a deterministic UTXO-set commitment tool:
```bash
python3 scripts/verify-utxo-set.py --out utxo-report.json --json
```
It reconstructs the best chain from local block files, computes the current
UTXO root and supply, and writes canonical JSON that independent auditors can
compare or timestamp externally with OpenTimestamps. See
[UTXO-set commitments](docs/utxo-commitment.md).
The same root can prove one unspent output without sharing the full UTXO set:
```bash
python3 scripts/prove-utxo.py TXID:VOUT --out utxo-proof.json --json
python3 scripts/verify-utxo-proof.py utxo-proof.json
```
See [UTXO inclusion proofs](docs/utxo-proofs.md).
Bitflash also ships a deterministic fair-launch verifier:
```bash
python3 scripts/verify-fair-launch.py --max-blocks 1000 --out bitflash-fair-launch-report.json --json
```
The report reads the local chain directly, checks the genesis launch baseline,
and produces canonical JSON whose hash can be compared by independent auditors
or timestamped externally with OpenTimestamps. See
[fair-launch verification](docs/fair-launch.md).
For a static local block explorer, generate HTML and JSON from either a data
directory or explicit block files:
```bash
python3 scripts/build-explorer.py --datadir ~/.bitflash ./explorer-out
python3 scripts/build-explorer.py ~/.bitflash/blk0001.dat ~/.bitflash/blk0002.dat ./explorer-out
```
The generated explorer is static and self-contained: `index.html`,
`style.css`, `explorer.js`, `blocks.json`, `block/*.json`, and `logo.png`. It is
safe to host behind a strict policy such as `default-src 'none'; img-src 'self';
style-src 'self'; script-src 'self'; connect-src 'self'; base-uri 'none';
form-action 'none'`.
**Keep your node current.** Consensus rules have changed since the first
releases — 1.2.1 fixed a bug that let anyone spend anyone's coins, and 1.2.2
added a per-block signature-operation cap. A node on an older build will accept
blocks that current nodes reject, which puts it on a different chain without any
warning.
Two more reasons, both measured rather than theorised:
- **Before 1.2.13** a node closed a disconnected peer's socket twice and left the
closed handle in its `select()` set, where it made `select()` fail on every
iteration. The node then spent its socket loop in an error path instead of
reading its peers — the deaf-node behaviour reported since 1.2.7. Two nodes
side by side on one machine, same network: the one without the fix held 11
peers and logged 741 spurious disconnections; the one with it held 21 and
logged none. On 1.2.13 in production, two mining nodes hold 13 and 18 peers
with zero.
- **Before 1.2.11** a long-running Windows node accumulated sockets it never
released — 1262 of them in 26 hours on one machine, each holding an ephemeral
port. Restarting returned them; upgrading stops them accumulating.
Your wallet and chain data live in `%APPDATA%\Bitflash` (Windows) or
`~/.bitflash` (Linux) and are shared by every version, so upgrading is just
replacing the binary. Never delete that directory to "fix" something without a
backup — it holds your keys.
---
## Your wallet: the phrase and the file
Since 1.2.12 a wallet can hold twelve words that rebuild it. Since 1.2.13 those
words also cover the address the window shows you. **Both still matter** — the
phrase and the file back up different things, and the difference is where people
lose money.
Since 1.2.20 the file is a single self-contained `wallet.sqlite` by default. A
fresh data directory starts on it; an existing Berkeley DB `wallet.dat` keeps
working and the desktop app converts it in one click on first run, never
touching the original, which stays as a fallback. Choose a backend explicitly
with `-walletbackend=sqlite` or `-walletbackend=bdb`, recorded in a
`wallet-backend` marker in the data directory. See
[wallet storage](docs/storage.md).
The derivation is written down in [docs/derivation.md](docs/derivation.md), with
test vectors and a script that reproduces them from scratch. It is there so the
twelve words keep working even if this software does not: paths, address format
and encoding, enough to recover the keys with ordinary tools and no Bitflash
code at all.
### The recovery phrase
```
bitflash -newphrase # create it, show it once, exit
bitflash -restorephrase="twelve words here" # rebuild a wallet from it
```
`-newphrase` installs a BIP39/BIP32 seed and derives the wallet as a BIP44 tree
along `m/44'/4346950'/0'/…` — coin type **4346950** is `0x425446`, the ASCII
bytes `BTF`, registered in [SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md).
It builds the key pool and default receiving address from the seed, and prints
the words once. It refuses if a phrase
already exists: replacing one silently would strand every coin on addresses the
written-down words no longer describe.
`-restorephrase` installs the seed and walks forward in batches of a hundred
addresses, rescanning the chain after each and stopping when a whole batch turns
up nothing. `-restoredepth=N` looks further. `-showderived=N` lists the addresses
a phrase produces, so you can check one before trusting it.
The same two operations are in the window, under **Wallet Safety**.
**The words are printed to the terminal and nowhere else** — never to
`debug.log`, which is the file people are routinely asked to attach to an issue.
**What the phrase does not cover.** Keys that existed *before* the seed was
installed are random. They are not derived from it and they do not come back
from the words. The wallet names such an address `Your Address (created before
the recovery phrase)` so you can tell them apart. This is why file backups still
matter.
> **If you created a phrase on 1.2.12, run `-restorephrase` with the same twelve
> words.** That release installed the seed but left the visible address and the
> key pool random, so the wallet went on handing out addresses the words cannot
> reproduce while the window said a phrase existed. Restoring repairs it.
### The file
Under the SQLite default the wallet is one self-contained `wallet.sqlite`, and
`-backupwallet` writes a matching `.sqlite` copy that opens on its own — no
sidecar directory. The Berkeley DB notes below apply to a legacy `wallet.dat`.
**Copying `wallet.dat` on its own is not a backup.** Berkeley DB ties the file
to the environment in the `database/` subdirectory beside it, so a lone
`wallet.dat` will not open elsewhere — the keys are all still in there, and the
file is refused anyway. Use the built-in command, which writes a copy that
stands on its own:
```
bitflash -backupwallet=/path/to/wallet-backup.dat
```
It loads the wallet, writes the copy, and exits without starting the node. If
you would rather copy by hand, shut the node down first and take the **whole**
data directory, not just `wallet.dat`.
A file backup covers what a phrase cannot: keys from before the seed, and any
key the wallet acquired by import. It also has a margin of its own — the wallet
keeps a pool of 100 pre-generated keys, so a backup covers the next 100 mining
rewards or receive addresses. Take a fresh one after mining for a while, after
creating many receive addresses, and before moving the wallet to another machine.
The GUI has a **Backup Wallet** button and a **Wallet Safety** view, which fills
the key pool before writing the backup.
### Finding coins the wallet never recorded
```
bitflash -rescan
```
Walks the chain for coins a key of yours owns but the wallet has no record of —
after importing keys, or after restoring a file from another machine.
`-importwallet` runs this automatically. A scan asked for with no chain data
loaded is refused rather than reported as "no transactions found", which reads
as a verdict to somebody who has just lost a wallet.
### When wallet.dat itself will not open
A legacy `wallet.dat` runs on Berkeley DB. If that database is the thing
that is broken — a build that will not read it, a file truncated by a bad copy,
an environment beyond recovery — the keys are usually still fine, and you can
take them out as text:
```
bitflash -dumpwallet=/path/to/keys.txt
bitflash -importwallet=/path/to/keys.txt # into any wallet, on any machine
```
One key per line with its address and label, no database and no environment.
Importing skips keys the wallet already holds, so running it twice is safe, and
an unreadable line is reported and stepped over rather than abandoning the rest.
Restart the node afterwards so it scans the chain for transactions belonging to
the new keys.
**The dump is your private keys in the clear.** Anyone who reads that file can
spend those coins. It is written owner-only on Linux and macOS; on Windows it
inherits whatever the containing folder allows, so choose the folder carefully.
Move it somewhere safe and delete the copy. `-dumpwallet` will not overwrite an
existing file.
---
## Mining
Open **Options** from the menu bar. Under Mining Mode:
**Solo** — mine directly to your wallet. Default.
**Operator** — run a pool. The pool server uses `.btf` rendezvous only. The window shows the pool's `.btf` address, discovered pools, and owed payouts.
Pool announcements are published on Nostr with live status fields, so external tools can query the latest pool state by `.btf` address.
Pool operators also write a local `pool_status.json` every ten seconds and a
`pool_rounds.json` proof ledger whenever they find blocks or pay miners. By
default both are created in the data directory; use `-poolstatusfile=PATH` and
`-poolroundsfile=PATH` to write them somewhere a dashboard or web sync can read.
The files are informational only: nodes still discover pools through Nostr and
`.btf`, not through any web domain.
See [public pool directory](docs/pool-directory.md) for the website/API shape.
**Participant** — mine to someone else's pool. Enter or select the pool's `.btf` address and enable Start Mining.
The built-in participant miner connects to operator pools through the `.btf`
path. Use it — **third-party RandomX miners such as XMRig and SRBMiner cannot
mine Bitflash pools**, and no amount of configuration changes that. In RandomX
mode they speak the Monero-style JSON-RPC protocol (`login`/`job`/`submit`) and
assume a Monero-style job: the nonce at byte 39 of the blob, and a 32-byte seed
hash given as 64 hex characters. Bitflash pools speak Bitcoin-style Stratum
(`mining.subscribe`/`mining.notify`/`mining.submit`) over an 80-byte header
whose nonce is at byte 76 — byte 39 falls inside the merkle root — and key
RandomX from a fixed 36-byte string that is not a hash at all.
`-stratumbridge` carries that same Bitcoin-style Stratum over the `.btf` path,
so a miner on this machine can reach a pool it otherwise could not address. It
is a byte relay, not a protocol translator, so it helps only a miner that
already speaks the pool's dialect, and it does not make the miners above work:
```bash
./bitflash -nogui -stratumbridge=POOL_BTF_ADDRESS -stratumbridgeport=3333
```
Estimate rewards and electricity cost locally:
```bash
python3 scripts/bitflash-mining-calculator.py \
--hashrate 21 --hashrate-unit kh/s \
--network-hashrate 1.56 --network-hashrate-unit mh/s \
--watts 140 --kwh-cost 0.10 \
--price 0.001 --pool-fee 1
```
See [mining calculator](docs/mining-calculator.md). Price is manual until
Bitflash has a reliable public market.
---
## Headless / server mode
```bash
./bitflash -nogui # node only
./bitflash -nogui -gen # node + solo mining
./bitflash -nogui -gen -operator # pool operator
./bitflash -nogui -gen -operator \
-poolstatusfile=/var/www/pool_status.json \
-poolroundsfile=/var/www/pool_rounds.json
./bitflash -nogui -gen -participant=POOL_BTF_ADDRESS # mine to pool
./bitflash -nogui -stratumbridge=POOL_BTF_ADDRESS # Stratum over .btf (see Mining)
```
Every option takes `-` or `/`. **Under MSYS2 use the `-` form** — the shell
rewrites a leading slash into a path before the node ever sees it.
**The mining mode is remembered between restarts** since 1.2.11, so a node that
was mining comes back mining. A `-gen`, `-operator` or `-participant` flag always
wins over what was stored, and the log says on every start which of the two
decided. Passing the flag anyway is the safe habit: it survives a wallet that
came from an older build.
Other options worth knowing:
```bash
-datadir=PATH # wallet and chain data elsewhere
-testnet # isolated test network genesis, datadir, port 18433, and magic
-port=N # P2P listen port, default 8433; testnet default 18433
-socks=HOST:PORT # SOCKS5 for outbound Nostr, .btf relay, and onion peer dials
-tor[=HOST:PORT] # Tor mode; default local Tor SOCKS5 proxy is 127.0.0.1:9050
-managedtor[=PATH] # start Tor, create a hidden service, advertise its onion
-nomanagedtor # disable the automatic bundled-Tor startup
-onionservice=HOST.onion:PORT # advertise this node's Tor hidden service
-debug # verbose log; without it debug.log is nearly silent
-help # full list
```
`-port` plus `-datadir` is what lets two nodes share one machine. Both are
needed — the data directory takes an exclusive lock, so a second node pointed at
the same one will refuse to start.
`-socks=127.0.0.1:9050` routes outbound Nostr discovery, `.btf` rendezvous
dials, and direct `.onion` peer dials through a local SOCKS5 proxy such as Tor.
When it is set, the node skips
plain HTTP external-IP probes instead of leaking a direct request outside the
proxy. IPv6 proxy endpoints use brackets, for example `-socks=[::1]:9050`.
`-tor` is a privacy shorthand for the usual local Tor SOCKS5 listener at
`127.0.0.1:9050`. It routes outbound Nostr discovery, `.btf` rendezvous dials,
and signed direct `.onion` peer dials through Tor, and keeps external-IP probes
disabled. Use `-tor=HOST:PORT` when Tor listens somewhere else.
The desktop app starts a managed Tor automatically when no other Tor option is
set, so onion transport works out of the box; `-nomanagedtor` turns that off.
For a headless node, ask for it explicitly:
`-managedtor[=PATH]` starts a Tor process for this node, writes a local `torrc`,
creates a v3 hidden service for port `8433`, routes outbound discovery through
that Tor instance, and signs the generated `.onion:8433` endpoint into the
node's `.btf` descriptor. Without `PATH`, Bitflash looks for `tor/tor.exe`,
`tor.exe`, or `tor` beside the binary and then on `PATH`. The hidden-service key
is stored under the Bitflash data directory in `managed-tor/onion-service/`.
### When something looks wrong
**Menu > Diagnostics**, and the same report in `debug.log` every ten minutes:
peers held against peers the socket loop is actually watching, blocks received and how
many arrived without a parent, the proof-of-work mode with the live miner thread
count, sockets by the part of the program that opened them, and per peer how long
since the last message each way. There is a copy button — if you open an issue,
paste that.
It exists because every hard problem in this project so far was found from
*outside* the node: sockets read over WMI from another machine, memory compared
against a number in a README, a `grep` over somebody's log. In each case the node
knew and had no way to say so.
As a systemd service:
```ini
[Unit]
Description=Bitflash node
After=network.target
[Service]
ExecStart=/opt/bitflash/bitflash -nogui -gen -operator
Restart=always
User=bitcoin
WorkingDirectory=/opt/bitflash
[Install]
WantedBy=multi-user.target
```
---
## How nodes find each other
A node publishes a **self-certifying descriptor**: its `.btf` address, an
encryption key, and the rendezvous relay where it is currently reachable, signed
with the key the address decodes to. Nobody can publish a descriptor for an
address they do not own, so a hostile relay can withhold descriptors but cannot
forge one.
Discovery runs on four layers, so no single failure takes the network down:
| | |
|---|---|
| **Nostr relays** | where descriptors are published and looked up |
| **Rendezvous relays** | the tunnel itself, where two nodes are paired |
| **Peer cache** | peers that answered last time, saved to `btfpeers.json` and dialled on start before any relay is contacted |
| **Peer exchange** | connected nodes hand each other signed descriptors, so discovery keeps working while relays are down |
Peer exchange carries the same signed descriptors, verified the same way, so a
peer passing one on is trusted for nothing.
The cache is what makes a restart fast: on a clean install the first peer takes
about 36 seconds, and on the next start about 2.
---
## Running a relay
Relays are the meeting points that let nodes behind NAT connect to each other. More relays make the network more resilient.
```bash
sudo bash relay/install-bitflash-relay.sh 8434
./bitflash -nogui -announcerelay=YOUR_PUBLIC_IP:8434
```
Relays forward encrypted bytes and cannot read or modify traffic.
---
## Build from source
**Linux:**
```bash
make linux
```
Installs deps via apt, builds libsecp256k1 and RandomX, produces `Bitflash-*.AppImage`.
**Windows (MSYS2 UCRT64):**
```bash
make windows
```
Installs deps via pacman, produces `Bitflash-*-windows.zip`.
To build the Windows package that also carries the Tor Expert Bundle:
```bash
make windows-tor
```
That produces `Bitflash-*-windows-with-tor.zip`. The release script downloads
the Tor Expert Bundle from the official Tor archive, verifies its pinned SHA256,
optionally verifies the Tor Project GPG signature when `gpg` is available, and
places `tor/tor.exe` beside `Bitflash.exe` so `-managedtor` works without a
separate Tor install. For release builds, use `TOR_VERIFY_GPG=required make
windows-tor` to require the extra signature check.
---
## At a glance
| | |
|---|---|
| Ticker | BTF |
| Proof of work | RandomX (CPU, memory-hard) |
| Block time | ~2 minutes |
| Difficulty retarget | every 30 blocks (~1 hour) |
| Block reward | 50 BTF, halving every 210,000 blocks |
| Halving interval | **~292 days** at target block time |
| Max supply | 21,000,000 BTF |
| Coinbase maturity | 100 blocks (~3.3 hours) before mined coins can be spent |
| Max signature ops | 20,000 per block |
| P2P port | 8433 |
| Addressing | `.btf` rendezvous — see the caveats above |
| Premine | None |
| Pool server | Built-in — `.btf` rendezvous only |
| Wallet recovery | Twelve-word phrase (BIP39 + BIP32 + BIP44, coin type 4346950), plus file backup |
| Wallet storage | SQLite `wallet.sqlite` by default, or Berkeley DB `wallet.dat` |
The halving interval is the number most people get wrong coming from Bitcoin.
Same 210,000 blocks, but at two minutes instead of ten, so it arrives in about
ten months rather than four years.
---
Young network. Keep your node current and don't put in more than you are willing to lose.
MIT. Built on Bitcoin 0.1.0 (Satoshi Nakamoto, 2009).
|