DocsManual
Bitflash BTF
CPU-only cryptocurrency. A revival of Bitcoin 0.1.0 with RandomX proof of work and anonymous .btf addressing over Tor onion services.
-2ea44f?style=for-the-badge) 
Download · Testnet faucet · Discord
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 only through Tor hidden services: a peer is dialled at the .onion its own signed descriptor names, and the address it decodes to is what authenticates it. There is no clearnet transport to fall back to.
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. Every dial goes out through Tor to the peer's hidden service, and every inbound connection arrives through your own. Neither side sees the other's clearnet address, and there is no third party in the middle: the relays that used to pair nodes are gone from the code.
Nothing terminates your connection but the peer. Earlier versions routed through a rendezvous relay, which by construction saw your IP unless you also used Tor. That transport was removed, not merely discouraged.
Your listener no longer gives you away. It used to bind every interface, so anything that could reach the plain port completed a handshake and was handed your signed descriptor — onion included. Under managed Tor it binds loopback only, which is all the hidden service needs. If your Tor runs on another machine and has to reach this one over the network, -bindaddr=IP says so explicitly.
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. For a plain SOCKS5 proxy without Tor-specific defaults, use -socks=HOST:PORT.
Quick start
Download the latest release 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:
sha256sum -c SHA256SUMS
For newer signed releases, verify the checksum file itself first:
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:
scripts/verify-release.sh latest
See release verification 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:
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:
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.
The same root can prove one unspent output without sharing the full UTXO set:
python3 scripts/prove-utxo.py TXID:VOUT --out utxo-proof.json --json
python3 scripts/verify-utxo-proof.py utxo-proof.json
Bitflash also ships a deterministic fair-launch verifier:
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.
For a static local block explorer, generate HTML and JSON from either a data directory or explicit block files:
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 madeselect()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.
The derivation is written down in 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. 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
-restorephrasewith 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 listens on a second port on the same hidden service, so workers reach it over Tor like any other peer. The window shows the pool's .btf address, discovered pools, and owed payouts. A worker announces which chain it is mining when it subscribes, and a pool on the other network refuses it rather than handing out work whose shares could never be paid.
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 for the website/API shape.
Participant — mine to someone else's pool. Enter or select the pool's .btf address and enable Start Mining.
Mining with ordinary software
From PoW v2 — mainnet at block time 1789992000 (2026-09-21 12:00 UTC), testnet at 1789419600 (2026-09-14 21:00 UTC) — you do not need Bitflash installed to mine it. Download Bitflash Miner from the releases page (Bitflash-Miner-*-windows.zip or -linux.tar.gz): it is the official XMRig build plus a Tor client and a launcher.
mine.cmd YOUR_BTF_ADDRESS Windows
./mine.sh YOUR_BTF_ADDRESS Linux
It starts a private Tor and runs XMRig through it to the pool's onion; Ctrl+C stops both. Double-clicked, it asks for the address. Antivirus products flag XMRig everywhere — the binary is unchanged, and its hash matches the one on XMRig's release page.
Or bring your own XMRig, which has spoken Tor on its own since 5.7.0: run Tor (the Tor Browser, open, is enough — its SOCKS port is 9150; a tor daemon listens on 9050) and point the miner at the pool's onion through it:
xmrig -a rx/0 -x 127.0.0.1:9150 -o mddjuyuctouv62eqdaofvwf4timxxmp72d2ghmc6qp5mdey6f5au56id.onion:8436 -u YOUR_BTF_ADDRESS -p x
The pool lives behind a Tor hidden service like every node on this network, and nothing in either path touches the clear net; there is no public IP anywhere in it to switch off. YOUR_BTF_ADDRESS is a Bitflash payment address, the kind -newaddress prints — not a .btf node address. The pool pays out to it. Fee 1%. To try PoW v2 before mainnet switches, the testnet pool is vocwzaqll3vzuvs4nkva5fxh6q5odlokkqvfc2uvhcjtmjlygae5l4id.onion:18438 (testnet as the launcher's second word) and pays a testnet address.
Before the switch the pool refuses these miners with a message that names the activation time. Until then, and for anyone who prefers the node's own miner, Bitflash mines to the same pool over its own Tor:
./bitflash -participant=ygnbd2zwq5wllaafopxa7ccnvnwuen75qt6rqco3x4bx3mfiorbaxei.btf
Why a switch was needed, and what a pool has to send, is in docs/pow-v2.md. The 1.2.23 release and earlier could not be mined by XMRig at all — the README of that release said otherwise, and it was wrong.
The same switch brings the consensus rules Bitcoin adopted after 0.1.0 — strict DER and low-S signatures, the height in every coinbase, the retarget window that measures what it divides by — see docs/rules-v2.md.
A node can also act as a local stratum bridge for a pool, for miners that cannot be given a proxy:
./bitflash -nogui -stratumbridge=POOL_BTF_ADDRESS -stratumbridgeport=3333
xmrig -a rx/0 -o 127.0.0.1:3333 -u YOUR_BTF_ADDRESS -p x
-stratumbridgebind=0.0.0.0 opens it to the network; it stays on loopback unless asked. Bitflash itself runs no public bridge.
Estimate rewards and electricity cost locally:
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. Price is manual until Bitflash has a reliable public market.
Headless / server mode
./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 # local bridge for XMRig/SRBMiner
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:
-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 and onion peer dials
-bindaddr=IP # listen here instead of loopback (only for Tor on another machine)
-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 and .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 and signed .onion peer dials through Tor, and keeps external-IP probes disabled. Use -tor=HOST:PORT when Tor listens somewhere else.
Bridges are for networks that block Tor itself: -torbridges uses the built-in Snowflake set, -torbridge=LINE adds an obfs4 or snowflake bridge of your own. If you ask for bridges and the pluggable-transport binary is missing, the node refuses to start rather than quietly reaching Tor directly — that fallback would be the exact thing you were avoiding.
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:
[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 .onion 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 whoever passes one on is trusted for nothing — forging an entry would need somebody else's secret key.
Discovery runs on three layers, and none of them is required for the others to work:
| Baked seed | a pinned .onion compiled into the binary, dialled directly, so a cold start needs no relay to answer |
| Peer cache | peers that answered before, kept in btfpeers.json |
| Peer exchange | connected nodes hand each other signed descriptors, so the network grows and heals on its own |
Nostr is used to look up a descriptor when nothing else has one, and that is all it is used for. Tor frequently has no exit to reach the Nostr relays, so nothing load-bearing may depend on it.
A single connection scheduler works through all three, re-reading the cache each round — which is what puts peer exchange to use — with exponential backoff and jitter per address. A dead peer costs one dial and then goes quiet; a peer that was merely unreachable for a moment gets tried again. Seeds are retried whenever the peer count is on the floor, not only on the first run.
Running a bootstrap seed
Relays are gone. A node behind NAT needs nothing forwarded, because its hidden service is its address. What still helps a stranger is somebody answering the very first dial, and any node with a stable onion can be that:
./bitflash-node -nogui -managedtor -port=8433
Publish the .btf address it prints and people can pass it with -btfseed=. A seed holds no balance, does not mine, and is trusted for nothing: it serves the same signed descriptors any peer does.
Testnet
There is a test network with its own genesis, magic bytes, port and data directory, so a testnet node and a mainnet node cannot see or corrupt each other. It is where to try a wallet change, a pool, or a patch before it touches coins that matter.
./bitflash-node -nogui -testnet -datadir=<a folder of its own>
Pass -datadir explicitly. Without it both networks land in the same application directory and fight over the same hidden service, which fails in ways that look like a network problem.
Coins are free from the faucet at <https://faucet.bitflash.network>, 10 BTF at a time, one per address and per IP every six hours. Get an address to give it with -newaddress. You can also just mine: the difficulty floor makes the first blocks trivial, so -testnet -gen fills a wallet quickly.
Testnet and mainnet addresses are indistinguishable — same version byte — so nothing can tell them apart for you. Coins sent to a mainnet address on testnet land on an output nobody can ever spend on mainnet.
Build from source
Linux:
make linux
Installs deps via apt, builds libsecp256k1 and RandomX, produces Bitflash-*.AppImage.
Windows (MSYS2 UCRT64):
make windows
Installs deps via pacman, produces Bitflash-*-windows.zip.
To build the Windows package that also carries the Tor Expert Bundle:
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 | 120 blocks (~4 hours) before mined coins can be spent |
| Max signature ops | 20,000 per block |
| P2P port | 8433 (testnet 18433) |
| Addressing | .btf over Tor onion services — see the caveats above |
| Premine | None |
| Pool server | Built-in — second port on the node's own onion |
| 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).
Rendered from README.md in the repository. Read the source.