upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/Makefile
AgeCommit message (Collapse)Author
2026-08-23build: pin the dependencies that decide consensus, and check what we runbitflash-maintainer
The two dependency clones were `git clone --depth 1 <url>` with no revision, which resolves to whatever the default branch points at the moment the build happens to run. For RandomX that is the proof of work. Its master is not frozen -- v2.0 changed the algorithm in March -- so two builds of the same Bitflash commit, made weeks apart, can hash the same header differently. That is not a supply-chain worry, it is a chain split delivered as a build artifact, with no version recorded anywhere to explain it afterwards. For libsecp256k1 it is signature verification, the rule deciding who may spend. Both now fetch a full commit id, which is the only form here that verifies what it got, since git resolves the object by its own hash. The RandomX pin is the commit this tree has been building and syncing against, so today's behaviour is unchanged; secp256k1 is pinned to the v0.8.0 release commit. appimagetool came from the "continuous" tag, which upstream moves in place on every push, fetched over the network and executed unverified. Pinned to a numbered release and checked by digest before it is allowed to run. It also ran from /tmp on a fixed name, guarded by `[ ! -x /tmp/appimagetool ]` -- an executable already sitting there is taken as the tool, so any local account could leave one and have it run as whoever built. The AppDir had the same shape one step later, through symlinks on the rm -rf. Both moved under the build tree, which the build already owns, and cleaned by `make clean`. (cherry picked from commit 664aebca08d17a9dbae12c25f21cd8ef2abe7aa6)
2026-08-04Add release verification tooling (#108)mtg0001
Co-authored-by: Gilcimar Duarte <ti@gpm.infra>
2026-08-03Bump to 1.2.15 (#120)Bitflash
2026-08-02Bump to 1.2.14 (#116)Bitflash
A block had no size limit, spending could move coins onto a key your recovery phrase cannot reproduce, and one peer could hold up the whole node with a message it never finished sending. All three are fixed here, and all three were found by auditing the tree rather than by anyone hitting them. ## Blocks now have a size limit — and this one is consensus `CheckBlock()` measured a block against `MAX_SIZE`, the serializer's generic 32 MB guard. There was no `MAX_BLOCK_SIZE` anywhere in the tree: Bitcoin's 1 MB cap arrived in 0.3.x, after the 0.1.0 this project came from, so the inheritance was simply missing. A miner could produce a 32 MB block and every node would download, verify and store it. The cap is now **1 MB**, chosen against the chain rather than tradition. Reading all 5709 blocks out of `blk0001.dat`: | | | |---|---| | largest block ever mined | 34,290 bytes | | median | 216 bytes | | p99 | 14,451 bytes | 1 MB leaves **29× of headroom** over the largest block this chain has ever carried, so nothing existing is rejected. A node built with the rule then synced genesis → 5706 on the live network with zero rejections, which is the same test that once caught BIP30 rejecting a real block at height 859. **Because it is consensus, it matters that you upgrade.** Until most nodes have it, a block above 1 MB would be accepted by old nodes and rejected by new ones — which is how a chain splits. Nobody is mining such blocks today; the gap is worth closing before somebody does. ## Spending could put your change on a key the phrase cannot recover When a wallet spends, the leftover goes back to you as *change*. This tree sent change to **the same key as one of the coins being spent** — 0.1.0 behaviour, and a privacy problem long tracked as #23. With recovery phrases it became a way to lose money. If the coin being spent sat on a key created *before* the seed — the wallet's original default address, an imported key, anything older than `-newphrase` — then the change went back to that same pre-seed key. So spending quietly moved your balance onto a key the twelve words do not reproduce, in a wallet you believed the words covered. Change now comes from a newly derived, phrase-backed key. **If that derivation fails, the transaction is refused rather than created**, because a failed send is recoverable and unrecoverable change is not. Wallets with no seed keep the old behaviour exactly. Restore also now scans past the pre-generated key-pool window before accepting an empty batch as the end, so a restore cannot stop short while used addresses sit just beyond it. ## One peer could hold up the whole node `ProcessMessages` runs in a single thread that serves every peer. When a message header announced more bytes than had arrived, the old code consumed the header, inserted it back at the *front* of the receive buffer — an O(n) memmove on a buffer that could hold 256 MB — and then slept 100 ms **inside that shared thread**. A peer that announced a large message and dripped bytes could make every pass pay both costs, forever, while looking perfectly active to the inactivity reaper. The parser now reads the header from a copy without consuming it, never sleeps in the shared thread, and disconnects a peer that sits on an incomplete message for two minutes. The wire cap drops from 256 MB to `MAX_SIZE`. ## The rendezvous holds more than one registration A node's registration at a rendezvous relay was consumed by the first caller, and registering again *replaced* the previous one — so a node was reachable to exactly one peer at a time and unreachable for the whole gap between being paired and registering again. Measured on a live node: descriptors resolved 53 times out of 54, its own registrations paired 11 out of 12, and **half of every outbound dial failed**. All three relays now keep a queue per node and pair with the oldest registration still alive. **This is already deployed** — you get it without upgrading. The matching node-side change, which parks spare registrations, is deliberately **not** in this release: it measured worse in the field than the code it replaced and will not ship until that is explained. ## Restoring from a phrase now looks far enough Found by proving the change fix above with real coin, and caused by it. Restoring derived forward in batches of a hundred and stopped at the first batch that turned up nothing. The wallet digs a wider gap than that by itself: a restore leaves the derivation counter at the depth it scanned, the key pool derives a hundred more, and change takes the index after those. So the address used *after* a restore can sit two hundred indices past the last one used before it, with nothing in between. On a real wallet: receive, restore, spend once — the outputs land at indices 201 and 302. Restoring again reported ``` Restored: 1 transaction(s) across 201 derived addresses ``` and the spend was invisible, both the payment and the change. The money was derived and covered by the phrase; the search stopped short of it. Three quiet batches instead of one, and the same wallet reports `2 transaction(s) across 601 derived addresses`. Change returning to an input's key used to hide this, because that key sat at a low index the scan had already passed. Fixing recoverability moved change out to where the search stopped looking, so the two had to be fixed together. The gap is self-inflicted and grows with each restore, so a long enough history can still outrun a fixed number of quiet batches. `-restoredepth=N` looks as far as you ask. The structural fix is tracked separately. ## A headless node can finally spend `SendMoney()` has been in this tree since 0.1.0 and only the window ever called it, so a node without a screen could be paid and could never pay — it could hold a balance with no way to move it. Found while trying to prove the change fix, which needs a spend. ``` bitflash -sendto=ADDRESS,AMOUNT ``` Refuses an address that does not decode, an amount that is zero, negative or not a number, and a wallet whose chain is not loaded — all before touching the wallet. A transaction created while the node is stopped is not broadcast until the node starts. ## Also - `-help` printed nothing at all on Windows. This tree remaps `printf` to the debug-log writer, and a `-mwindows` binary has no console, so the one command whose job is to tell you something returned 0 in silence. - The README described a program from several releases ago — deterministic restore listed as an open issue, mining mode described as forgotten between restarts, and every flag written in the slash form that MSYS2 rewrites into a path. - Diagnostics now report why a socket close failed, per error code and per site, and flag a handle handed back while some part of the program still claims it. ## Downloads | File | Platform | Notes | |------|----------|-------| | `Bitflash-1.2.14-windows.zip` | Windows x86_64 | Extract and run | | `Bitflash-1.2.14-x86_64.AppImage` | Linux x86_64 | Desktop/GUI — `chmod +x` and run | | `bitflash-node-1.2.14-x86_64` | Linux x86_64 | Headless server node, no libGL or FUSE | Verify with `sha256sum -c SHA256SUMS`. Everything in [v1.2.13](https://github.com/Bitflash-sh/bitflash/releases/tag/v1.2.13) is included.
2026-08-01Bump to 1.2.13 (#105)Bitflash
Two things a node could do wrong without ever saying so: close a peer's socket twice, and hand out addresses a recovery phrase cannot reproduce. ## If you created a recovery phrase on 1.2.12, do this first Run, with the same twelve words: ``` Bitflash.exe -restorephrase="your twelve words here" ``` 1.2.12 installed the seed but left the wallet's visible address as the old random key, and left the old random key pool in place. The window said a recovery phrase existed while the next address the wallet handed out — a mining payout included — could be one the words cannot reproduce. Restoring with the same phrase repairs it: the pool is cleared, and the default address becomes a derived one. Coins already sitting on pre-phrase addresses stay where they are. They are still yours, still spendable, and still **not** covered by the words — which is why `wallet.dat` backups keep mattering. The wallet now names that address `Your Address (created before the recovery phrase)` instead of leaving two entries both called `Your Address` with only one of them recoverable. Thanks to **@mtg0001**, who found this within hours of 1.2.12 shipping (#102). ## A peer's socket was closed twice, and the second close hit whoever had the number `CNode::Disconnect()` closed the socket and left the handle number in the object; the destructor then closed that same number again. There is no assignment of `INVALID_SOCKET` to that field anywhere in the tree, so the guard meant to prevent this never fired. A double close is not a harmless no-op. This node opens hundreds of sockets a minute, and Windows reissues a handle number as soon as its last close lands — so the second close takes down a connection that now belongs to something else entirely. The same omission left a closed handle in the `select()` set, where it makes `select()` fail on every iteration for as long as that node is in the list. The node then spends its socket loop in an error path instead of reading its peers. **That is the deaf-node behaviour this project has been chasing since 1.2.7**, and the `dropping node: its socket is no longer valid` line in the log is the recovery path, not the disease. Measured, two nodes on the same machine and the same network, stopped at matched socket volume: | | sockets opened | failed closes | `no longer valid` | peers held | |---|---|---|---|---| | without the fix | 552 | 4 | **741** | 11 | | **with the fix** | 547 | **0** | **0** | **21** | Half the peers, on the same machine, at the same minute. All 741 drops were the same peer, over and over — one dead handle in the set is enough. ## The socket leak was already fixed, and the way it was being measured was wrong Earlier notes, including 1.2.12's, said sockets were still leaking. They were not. Windows lists a wildcard-bound socket **twice** in `Get-NetTCPConnection` — once for the binding (`0.0.0.0:port`, state `Bound`) and once for the connection — and 35 of one node's 38 `Bound` rows shared a local port with one of its own established connections. Counting those rows makes the number climb whenever the node talks to more peers, which is why the fix that worked looked like it had done nothing. Counting **orphans** instead — a `Bound` row whose port appears nowhere else in that process — measured on three machines the same evening: | node | version | uptime | orphans | |---|---|---|---| | 32-core miner | 1.2.10 | 26 h | **1262**, still taking on 30–90 an hour | | second miner | 1.2.11 | 4h40m | 3 | | test bench | 1.2.12 | 2 min | 3 | The leak was real and **1.2.11 ended it**. If you are still on 1.2.10 or earlier, that alone is worth the upgrade. ## Also in this release - The diagnostics report now says why a close failed, per error code and per site, totals what the node believes it is holding, and counts a handle handed out while some part of the program still claims it (#98, #100, #101). - Every header is listed in both makefiles (#99). `sockcount.h` was missing, so editing it rebuilt some objects and not others and left two layouts of the same shared struct in one binary — a warning in the middle of a build log and nothing else. ## Downloads | File | Platform | Notes | |------|----------|-------| | `Bitflash-1.2.13-windows.zip` | Windows x86_64 | Extract and run | | `Bitflash-1.2.13-x86_64.AppImage` | Linux x86_64 | Desktop/GUI — `chmod +x` and run | | `bitflash-node-1.2.13-x86_64` | Linux x86_64 | Headless server node, no libGL or FUSE | Verify with `sha256sum -c SHA256SUMS`. Everything in [v1.2.12](https://github.com/Bitflash-sh/bitflash/releases/tag/v1.2.12) is included.
2026-08-01Bump to 1.2.12 (#97)Bitflash
Version bump for the 1.2.12 release. One line of Makefile; the release notes live here. ## The reason this release is not optional **#87 — a node that was mining before 1.2.11 can come back as a relay and never say so.** The 1.2.11 mining rework left `fGenerateBitcoins` readable on its own: a wallet carrying that flag from an older build, with no mining mode stored beside it, loads as "not mining" and the window shows nothing wrong. It happened here, on a real node, and it was found only because somebody looked at the hashrate. Anyone running 1.2.11 who mined on an earlier build should assume they are affected. ## Recovery phrase (#93, #96) Twelve words that bring a wallet back. Proved end to end before merging: a live wallet was paid on a derived address, `wallet.dat` was deleted, and the coin came back from the phrase alone. - `-newphrase` creates a phrase, installs the seed, fills the key pool from it and shows the words once. It refuses when a seed already exists. - `-restorephrase="WORDS"` installs the seed and walks forward in batches of 100, rescanning after each and stopping when a batch turns up nothing. `-restoredepth=N` to look further. - `-newaddress` prints the next receiving address; `-showderived=N` lists what a phrase produces. - The same two operations are reachable from the window. **What the phrase does not cover, stated plainly:** keys that existed before the seed was installed — including the wallet's original default address — are not derived from it and do not come back from the words. The commands say this at the point of use. Keep the `wallet.dat` backup as well; the phrase is a second line, not a replacement. The words are printed to the terminal only, never to `debug.log`. ## Wallet safety - **#88** — `ScanForWalletTransactions` plus `-rescan`: the node can now walk the chain for coins a key owns but the wallet never saw. `-importwallet` scans too. Without this, restoring from a phrase would have derived the right keys and found nothing. - **#89, #90** — a backup panel in the window, with the default backup written outside the directory it protects. - **#95** — a scan with no chain data loaded is refused instead of reporting "no transactions found", which read as a verdict to somebody who had just lost a wallet. ## Tests and diagnostics **#91** wallet key pool self-test, **#92** self-test output where the person running it can see it, **#94** MSYS2 argument conversion (use `-selftest=...`, not `/selftest=...`, under MSYS2). `make tests` runs the BIP32/BIP39 vectors and both wallet self-tests on Linux and Windows. ## Still not fixed The socket accounting shipped in 1.2.11 is instrumentation, not a fix — sockets still leak. The three obvious causes have been measured and eliminated; the next step is reading a real node's diagnostic report, not another guess.
2026-08-01diag: let the node say what is wrong with it (#81)Bitflash
* Bump to 1.2.11 One change, and it is the reason a node on Windows kept collecting peers it could not hear. FD_SETSIZE was never defined in this tree, so it defaulted to 64 and select() could watch the listen socket plus 63 peers -- everything past that stayed connected and was never read again. Windows FD_SET stops adding once its array is full and says nothing, so there was no error to notice. Because new connections go on the end of vNodes, it was always the newest connection that starved, including the ones dialed to fix connectivity. Measured on two nodes: 277 and 90 CNode objects against 93 and 90 live sockets, 316 and 355 sockets in a bound-but-never-connected state, and a status bar reporting hundreds of peers for a node really talking to thirty. 1.2.11 raises FD_SETSIZE to 1024 on Windows, caps connections at 125, drops a node stuck undeliverable after 60 seconds instead of holding it forever, stops answering a failed select() with POSIX code that has no meaning on Windows, and warns when there are more peers than select can watch. * diag: let the node say what is wrong with it Every hard problem in this project so far was found from outside the node -- sockets read over WMI, committed memory compared against a README, a grep over somebody debug.log. In each case the node knew and had no way to say so. One report, rendered identically for the GUI panel and the log: peers held vs peers actually watched by select(), blocks received and how many arrived without a parent, proof-of-work mode with the live miner thread count, and per peer the age of the last message in each direction plus anything stuck unsent.
2026-08-01Add BIP39 and BIP32 foundation tests (#83)mtg0001
Co-authored-by: Gilcimar Duarte <ti@gpm.infra>
2026-07-31Bump to 1.2.10 (#77)Bitflash
1.2.9 shipped before the last seven merges landed, and one of them is holding two live nodes hostage. Measured on a 32-core node running 1.2.9 today: 65,134 MB committed, which is 30 RandomX datasets at 2,142 MB each -- one per miner thread, for a node that advertises 2 GB. A 4-core node on the same build sits at 6,568 MB, three datasets. #68 allocates the dataset once and closes the window where a thread could mine against one that was not finished being filled. The rest of the release: - #67 orphans no longer stack above earned blocks in the GUI list - #69 no submitting a solution for a parent that is no longer the tip - #70 a ceiling on orphan blocks, and getblocks stops repeating itself - #71 Berkeley DB cursors get closed instead of left to the handle - #73 bounds on what a peer can make the node allocate - #74 the recipient no longer collects the fee when a transaction retries
2026-07-31Bump to 1.2.9 (#66)Bitflash
relay.nostr.band went down and stayed down. Every node running 1.2.8 or earlier spends ten seconds of every discovery pass waiting for it and writes an error line each time -- the seed logged 2029 of them. #64 replaces it with a relay that answers and backs off from any relay that stops answering, so the next one to go down costs nothing.
2026-07-31Bump to 1.2.8 (#63)Bitflash
Six changes since 1.2.7, and the reason not to sit on this is #58: coinbase transactions were not unique, two of them overwrote older ones on the main chain, and 100 BTF stopped being reachable. Nothing in how they were built had changed since, so it could happen again at any time. The height now goes into the coinbase on both paths that build one (#59, #60), which makes a repeat impossible without any coordination. Also in: a node now notices a peer it can no longer hear and stays audible to peers that check the same way (#55); it announces its height in the handshake and says out loud when it falls behind the network (#56); script evaluation has ceilings on operation count and stack depth (#57); the tail of the chain is verified at startup and a bad tip is backed out of instead of being mined on (#61); and the wallet now believes the chain about what it has already spent, which is what a restored backup gets wrong (#62).
2026-07-30Bump to 1.2.7 (#53)Bitflash
Rendezvous no longer waits forever for a dial (#51), keys can be exported and imported as text (#49), and mining uses every core instead of one (#52). #51 is the reason not to sit on this: without it a node goes silently deaf after a while and only a restart brings it back.
2026-07-30Bump to 1.2.6 (#48)Bitflash
Wallet backup and clean shutdown (#46). Two reasons not to sit on this: every Linux node aborts on the way out instead of releasing wallet.dat, and until a node has shut down cleanly once, the wallet it wrote cannot be moved anywhere else.
2026-07-30Bump to 1.2.5 (#45)Bitflash
Headless mining fix (#42), ARM64 build (#41), format-string checking (#44), gitignore for key material (#43). #42 is the reason this release exists: -gen has mined nothing on headless nodes since v1.2.0.
2026-07-29Bump to 1.2.4 (#39)Bitflash
Seeds (#36), headless node (#37), README (#35), wallet crash fix (#38).
2026-07-29build: headless Linux node that does not need libGL (#37)Bitflash
The GUI build requires libGL at load time even when started with -nogui. The dynamic loader resolves every dependency before main() runs, so the flag arrives far too late -- on a clean server the binary dies with error while loading shared libraries: libGL.so.1: cannot open shared object file and nothing suggests it would otherwise have worked. A server is where a node most naturally lives, so this is the deployment that mattered most and the one that failed. The AppImage additionally needs FUSE, which minimal servers lack. Bundling libGL into the AppImage would be the wrong fix: GL has to come from the host's driver stack, and shipping our own breaks machines that have a real GPU. So: a second binary, built from the same node objects without ImGui, GLFW or OpenGL. `make linux-node` produces bitflash-node-<version>-x86_64, 2.5 MB stripped, with no graphics or FUSE dependency at all. `make linux` now builds it alongside the AppImage. Anyone wanting a window keeps using the AppImage. Two small moves were needed. MainFrameRepaint is called from main.cpp and net.cpp but defined in gui.cpp, so headless.cpp provides an empty one rather than putting ifdefs at six call sites. DateTimeStr also lived in gui.cpp while main.cpp logs block times with it -- nothing about formatting a date is GUI work, so it moved to util.cpp and both builds share one definition. Verified on Debian 13: ldd bitflash-node | grep -iE 'libGL|glfw|X11' -> nothing ldd bitflash | grep -iE 'libGL|glfw' -> libglfw.so.3, libGL.so.1, libGLdispatch.so.0 and at runtime, from an empty datadir: btfseed: reached ygffz37...btf via 90.156.222.107:8434 rendezvous: registered at 90.156.222.107:8434, waiting for a dial self-resolve OK (meeting_node=90.156.222.107:8434) btfpeers: kept 15 of 15 descriptor(s) first block at ~30s, 3182 blocks accepted, synced to the tip The GUI builds on Linux and Windows were rebuilt and are unaffected.
2026-07-29Bump to 1.2.3 for the connectivity release (#33)Bitflash
Everything since 1.2.2 is about nodes being able to find and reach each other, which is the problem this project actually had: #30 rendezvous registration and waiting split apart. Registering used to block until somebody dialled, so a node could not advertise a meeting node until it had already been reached at one. This is the root cause of the flaky connectivity, not dead relays or stale descriptors. #26 a node no longer advertises a rendezvous it is not registered at #25 .btf peers that answered are remembered and dialled first (36.3s -> 2.1s) #32 peers exchange signed descriptors, so discovery survives a relay outage #29 debug.log stopped dropping lines under concurrency #28 /port, so two nodes can share a machine
2026-07-28Bump to 1.2.2 for the hardening release (#24)Bitflash
2026-07-28Bump to 1.2.1 for the consensus security release (#14)Bitflash
2026-07-28Release plumbing: bump to 1.2.0, add python3-pil to Linux deps (#10)Bitflash
The AppImage step converts src/rc/bitcoin.ico with PIL, but python3-pil was never in deps-apt, so 'make linux' failed at packaging on a clean Debian install -- the AppImage the README points Linux users at could not actually be produced by following the documented steps. Version bump only renames the produced artefacts; no rebuild needed.
2026-07-27Add Linux GUI installer via Wine (#3)Victorio Nascimento
* Add Linux GUI installer via Wine * Fix launcher creation and add BTF_RELAY env var support * Pool server, Linux GUI, unified binary, README update * Root Makefile: make linux / make windows, cleaner README * Remove headless.cpp * Fix XPM color count mismatch causing toolbar image errors on Linux * XPM icons: same code on Windows and Linux, no ifdefs around image loading * Fix GTK icon crash and Linux printf format * btfrv: 10s socket timeout on relay connects * Faster peer discovery: more dials per pass, shorter backoff and sleep * Parallel btf peer connections * Fix GetMyExternalIP - was disabled, now uses modern IP echo services * Fix tunnel disconnect on idle and restore external IP detection * Filter stale Nostr descriptors * Sort peers by freshness, fresh first * Pool: add .btf Stratum listener — miners connect via rendezvous, no port forwarding needed * btf pool: self-replacing listeners, one per relay, no queuing between miners * Mining modes: solo/operator/participant — pool server on-demand, participant Stratum client * Status bar: show external IP and .btf address * README: clean rewrite, concept-first, minimal * make linux produces AppImage * make linux produces AppImage * Pool dashboard: connect instructions, tabs, share bars * Perf fixes: GetMyExternalIP threaded, btf listener counted * Perf fixes: GetMyExternalIP threaded, btf listener counted * Fix pool payouts: defer until coinbase maturity * Pool: clean mode switching, IP warning * Pool: clean mode switching * Fix gPoolRunning: remove static * AppImage: use real icon from bitcoin.ico * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Windows build: use mingw32-make * Windows build: simpler make invocation * Add deps-windows target * Windows build fixes * Windows build fixes * Windows makefile: fix obj dir * Windows: output to repo root * Windows: bundle DLLs into zip * Replace wxWidgets with ImGui+GLFW: same build on Linux and Windows * Fix %I64d that slipped back through rebase (main.h, net.h) * MinGW: add _mkdir shim for non-MSVC Windows; fix %I64d * Fix gPoolRunning extern outside ifndef _WIN32 * Remove -lboost_system: boost is header-only in this codebase * Status bar: copy buttons for IP and .btf address * Windows: add app icon via windres, strip wx stuff from rc file * Clean GUI: single Options menu item, bigger font, better spacing, cleaner options dialog; update README * GUI: embed Roboto font at 16px for clear readability on all platforms * Windows: windres depends on obj dir target * Fix balance hidden off-screen: put on own line below address bar * Windows: inline mkdir in every rule, remove dir target that confused make * Windows: move all target to top so it's the default rule * Fix pool server not starting: always start when operator selected, re-sync dialog state on open * Write debug.log to data directory (AppData/Roaming/Bitflash on Windows) * Participant miner: use wallet address as username so payouts go to wallet * Add .gitattributes to lock LF line endings, prevent CRLF drift * Refactor pool mining to btf-only transport * Persist pool settings and startup wiring * Prune stale peers and expose pool queries * Fix build regressions and add CLI mode/arg parity * Fix rpc miner stats declaration order * Centralize pool runtime extern declarations * Separate operator/participant dashboards and restore peer stats * Add live telemetry strip and clearer per-mode runtime metrics * Reduce mining dashboard clutter and remove manual pool entry * Count only authorized pool miners * Seed initial pool job on startup * Use a real share target for pool work * Switch pool accounting to round-based shares * Fix nostr pool announcer stats call sites * Fix pool stats definition order * Improve pool worker status display * Add mutex include for participant status * Replace ImClamp in dashboard layout * Clarify participant work status * Log participant status transitions * Reduce peer discovery log noise * Add participant status badge * Track participant auth acknowledgements * Log and validate pool job delivery --------- Co-authored-by: Bitflash Pool Dev <pool@bitflash>