upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/randomx_pow.cpp
AgeCommit message (Collapse)Author
2026-09-05Merge upstream/main into the forkbitflash-maintainer
Brings the nine commits that are actually the latest on our lineage: isolated testnet parameters and genesis, optional 2 MB large pages for RandomX, and five README changes. This is what "up to date" means here -- not the 1.2.2x tags, which carry higher version numbers but were cut 2026-07-30, three weeks before the line we ship, and which upstream/main does not contain. Three conflicts, all resolved toward upstream's structure while keeping what this fork knows: main.cpp -- upstream moved genesis construction into BuildGenesisBlock() so mainnet and the new testnet can share it. Verified byte-for-byte before taking it: MAINNET_GENESIS_TIMESTAMP, _TIME (1753315200), _NONCE (3141), _HASH, _MERKLE, the scriptPubKey, nBits and nVersion all equal what this tree built inline. The mainnet genesis hash is unchanged and the asserts still guard it. Kept our warning about never editing those inputs, and kept our note that 1753315200 is 2025-07-24, not 2026 -- upstream's comment on that constant states the wrong year. net.h -- DEFAULT_PORT = htons(8433) becomes MAINNET_PORT/TESTNET_PORT in host order. Nothing is lost: net.cpp's GetDefaultPort() applies htons() itself and is what every caller uses, so the value reaching a sockaddr is unchanged and mainnet stays on 8433. selftest.cpp -- the known-tests string had diverged in both directions. Took the union: upstream's network-params alongside our payout-ledger, rather than dropping either. Gates: 15/15 selftests (our 14 plus upstream's network-params), consensus constants unchanged against e4f898c except the pre-existing MAX_BLOCK_SIZE_GEN, mainnet genesis intact, compactblock's 17 checks still pass, money-log check ok, GNU_STACK RW.
2026-09-02net: a refused thread spawn drops one peer, not the nodebitflash-maintainer
std::thread throws std::system_error when pthread_create is refused (RLIMIT_NPROC, a container's pids cgroup, memory pressure), and nothing caught it, so the node died by std::terminate. Threads are spawned per peer connection, so the pressure that triggers this scales with peer count, which is attacker-influenced. Observed killing a healthy participant worker mid-mining. Every spawn site in the node build, and what a failure now does: - btftunnel.cpp: both tunnel pumps are guarded. The inbound pump starts first because it owns cleanup of the pump end and rendezvous socket; if the second spawn is refused, shutdown() wakes the first out of its read and it cleans up itself -- closing those descriptors from the failure path instead would race it onto reused descriptors. Both paths return INVALID_SOCKET, which every caller already treats as "this connection failed". - btfrv.cpp: the relay's accept loop drops the connection it cannot serve and stops accepting for a moment -- longer after consecutive failures, capped at 5s -- instead of dying at an arbitrary one. The per-pair second pump now runs on the handling thread itself, leaving exactly one spawn to guard and nothing running yet to race. - main.cpp: a participant that cannot spawn its hash workers stops the ones that did start, drops the pool connection, and returns to the reconnect loop, the same way an ordinary disconnect does. - randomx_pow.cpp: dataset init joins the workers it got, releases the dataset, and stays in light mode -- the same trade the allocation failure path above it already makes. - rpc.cpp, net.cpp: the remaining unchecked _beginthread calls (which report failure by value, they cannot throw) now say precisely what did not start. The pool's accept and payout threads failing silently left the pool running deaf -- nobody accepts, nobody gets paid, and nothing in the log says why. Left alone deliberately: the per-relay accept spawns (rpc.cpp) already check, log and retry on the next poll; startup-critical spawns in net.cpp keep failing hard; the selftest-only std::thread uses may abort a selftest run, which is acceptable where dying over one peer is not. Verified: full node rebuilds clean and links; pool-stratum selftest passes; a scratch harness under RLIMIT_NPROC=1 confirms _beginthread reports -1 and std::thread throws system_error, the premises of every path above.
2026-08-20randomx: make the large-pages fallback hint OS-specificbitflash
The reservation instruction printed when a large-page allocation falls back was Linux-only (sysctl vm.nr_hugepages). Route it through a small helper so a Windows build points at the "Lock pages in memory" privilege instead.
2026-08-20randomx: optional 2 MB large pages for the cache, dataset and scratchpadsmischief
RandomX reads its 256 MB cache, 2 GB dataset and per-VM scratchpads at random, so most accesses miss the TLB on 4 KB pages. Requesting 2 MB pages recovers roughly a tenth of the hash rate. Each allocation tries large pages first and falls back to normal pages when the pool is not reserved, so nothing regresses when hugepages are unavailable. -nolargepages opts out, and the diagnostics report which allocations got large pages.
2026-08-07randomx: serialize cache initialization (#4)Nsable-sh
2026-07-31randomx: allocate the dataset once, not once per miner thread (#68)Bitflash
Every miner thread calls RandomXInitDataset at startup. Its only guard is g_fFast, which is set at the very end -- after the ~2 GB dataset has been filled, which takes tens of seconds. So all of them sailed past the guard together and each allocated its own dataset. Measured in production on a 32-core machine running 31 miner threads: the log says "initializing ~2 GB dataset" 34 times, and the process holds 65,127 MB of private pages while its own startup line promises 2142 MB "(~2080 MB shared RandomX dataset + ~2 MB per thread)". The word shared was not true. A 4-core machine showed the same thing at its own scale: 4 allocations for 3 threads. The waste was the mild half. g_dataset is assigned the moment memory is allocated, before it holds anything, so the last thread to allocate swung the pointer out from under threads still filling their own. A miner could then hash against a dataset another thread had not finished writing, and proof of work computed that way is not reproducible by any other node -- the block would be found invalid by everyone, including this node's own verifier, which uses the cache rather than the dataset. This only became reachable with multi-threaded mining (#52); with one thread there was nobody to race. Holding the lock across the whole initialisation is deliberate: a thread arriving mid-init has nothing useful to do until the dataset exists, and blocking is how it waits for exactly that. Verified with three mining threads: one "initializing ~2 GB dataset", one "dataset ready", and 2362 MB of private memory against 2086 MB advertised -- the difference being the 256 MB cache. Before, three threads meant three datasets.
2026-07-24Bitflash: fair-launch releaseBitflash-sh
Satoshi's bitcoin-0.1.0 reborn with RandomX CPU proof of work, anonymous .btf addressing over Nostr with CGNAT rendezvous, automatic peer discovery, a headless Linux node, and Windows GUI wallet. Fair launch, no premine, 21M cap.