upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-09-05 05:08:30 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-05 05:08:30 +0000
commit66e0b9158d050c46b1ff2509faeee3f4573cac1c (patch)
tree7e9132aa871fdc01cb95268d2f5ea3bb11853ddf
parent36201d2795b7b49beb1a837b0252134096beb64d (diff)
parent17741d9cf4c762ea03dc83e8aae6a176e5f338b0 (diff)
Merge upstream/main into the fork
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.
-rw-r--r--README.md50
-rw-r--r--src/Makefile1
-rw-r--r--src/main.cpp163
-rw-r--r--src/main.h2
-rw-r--r--src/main_gui.cpp15
-rw-r--r--src/makefile.mingw1
-rw-r--r--src/net.cpp33
-rw-r--r--src/net.h25
-rw-r--r--src/randomx_pow.cpp117
-rw-r--r--src/randomx_pow.h7
-rw-r--r--src/readme.txt3
-rw-r--r--src/selftest.cpp85
12 files changed, 424 insertions, 78 deletions
diff --git a/README.md b/README.md
index 77a0ad8..4453529 100644
--- a/README.md
+++ b/README.md
@@ -8,9 +8,11 @@ CPU-only cryptocurrency. A revival of Bitcoin 0.1.0 with RandomX proof of work a
8 8
9![PoW](https://img.shields.io/badge/PoW-RandomX%20(CPU)-2ea44f?style=for-the-badge) 9![PoW](https://img.shields.io/badge/PoW-RandomX%20(CPU)-2ea44f?style=for-the-badge)
10![Privacy](https://img.shields.io/badge/addresses-.btf%20anonymous-2ea44f?style=for-the-badge) 10![Privacy](https://img.shields.io/badge/addresses-.btf%20anonymous-2ea44f?style=for-the-badge)
11![Tor](https://img.shields.io/badge/tor-onion%20service-7d4698?style=for-the-badge)
11![Fair Launch](https://img.shields.io/badge/premine-none-2ea44f?style=for-the-badge) 12![Fair Launch](https://img.shields.io/badge/premine-none-2ea44f?style=for-the-badge)
13[![Discord](https://img.shields.io/badge/discord-join-5865F2?style=for-the-badge)](https://discord.gg/n7B2Eamn3)
12 14
13**[Download](../../releases/latest)** 15**[Download](https://releases.bitflash.network/)** · **[Discord](https://discord.gg/n7B2Eamn3)**
14 16
15</div> 17</div>
16 18
@@ -46,14 +48,14 @@ For a plain SOCKS5 proxy without Tor-specific defaults, use
46 48
47## Quick start 49## Quick start
48 50
49Download the [latest release](../../releases/latest) and run. No install, no 51Download the [latest release](https://releases.bitflash.network/) and run. No
50configuration — it connects automatically and starts syncing. 52install, no configuration — it connects automatically and starts syncing.
51 53
52**Linux:** make the `.AppImage` executable and run it. 54**Linux:** make the `.AppImage` executable and run it.
53 55
54**Windows:** extract the `-windows.zip` and run `Bitflash.exe`. 56**Windows:** extract the `-windows-with-tor.zip` and run `Bitflash.exe`. Tor is
55If you want managed Tor without a separate Tor install, use the 57bundled and a managed Tor instance starts automatically, so onion transport
56`-windows-with-tor.zip` package and start Bitflash with `-managedtor`. 58works with no separate install. Pass `-nomanagedtor` to turn it off.
57 59
58Every release ships a `SHA256SUMS` covering the assets. Verifying takes a second 60Every release ships a `SHA256SUMS` covering the assets. Verifying takes a second
59and is worth doing: 61and is worth doing:
@@ -83,7 +85,7 @@ Public mirrors should make the latest checksum files available both under the
83versioned release directory and at the release root: 85versioned release directory and at the release root:
84 86
85```text 87```text
86https://releases.bitflash.network/v1.2.19/SHA256SUMS 88https://releases.bitflash.network/v1.2.20/SHA256SUMS
87https://releases.bitflash.network/SHA256SUMS # alias to latest 89https://releases.bitflash.network/SHA256SUMS # alias to latest
88``` 90```
89 91
@@ -166,6 +168,14 @@ words also cover the address the window shows you. **Both still matter** — the
166phrase and the file back up different things, and the difference is where people 168phrase and the file back up different things, and the difference is where people
167lose money. 169lose money.
168 170
171Since 1.2.20 the file is a single self-contained `wallet.sqlite` by default. A
172fresh data directory starts on it; an existing Berkeley DB `wallet.dat` keeps
173working and the desktop app converts it in one click on first run, never
174touching the original, which stays as a fallback. Choose a backend explicitly
175with `-walletbackend=sqlite` or `-walletbackend=bdb`, recorded in a
176`wallet-backend` marker in the data directory. See
177[wallet storage](docs/storage.md).
178
169The derivation is written down in [docs/derivation.md](docs/derivation.md), with 179The derivation is written down in [docs/derivation.md](docs/derivation.md), with
170test vectors and a script that reproduces them from scratch. It is there so the 180test vectors and a script that reproduces them from scratch. It is there so the
171twelve words keep working even if this software does not: paths, address format 181twelve words keep working even if this software does not: paths, address format
@@ -179,8 +189,11 @@ bitflash -newphrase # create it, show it once, exit
179bitflash -restorephrase="twelve words here" # rebuild a wallet from it 189bitflash -restorephrase="twelve words here" # rebuild a wallet from it
180``` 190```
181 191
182`-newphrase` installs a BIP32 seed, derives the wallet's key pool and default 192`-newphrase` installs a BIP39/BIP32 seed and derives the wallet as a BIP44 tree
183receiving address from it, and prints the words once. It refuses if a phrase 193along `m/44'/4346950'/0'/…` — coin type **4346950** is `0x425446`, the ASCII
194bytes `BTF`, registered in [SLIP-0044](https://github.com/satoshilabs/slips/blob/master/slip-0044.md).
195It builds the key pool and default receiving address from the seed, and prints
196the words once. It refuses if a phrase
184already exists: replacing one silently would strand every coin on addresses the 197already exists: replacing one silently would strand every coin on addresses the
185written-down words no longer describe. 198written-down words no longer describe.
186 199
@@ -207,6 +220,10 @@ matter.
207 220
208### The file 221### The file
209 222
223Under the SQLite default the wallet is one self-contained `wallet.sqlite`, and
224`-backupwallet` writes a matching `.sqlite` copy that opens on its own — no
225sidecar directory. The Berkeley DB notes below apply to a legacy `wallet.dat`.
226
210**Copying `wallet.dat` on its own is not a backup.** Berkeley DB ties the file 227**Copying `wallet.dat` on its own is not a backup.** Berkeley DB ties the file
211to the environment in the `database/` subdirectory beside it, so a lone 228to the environment in the `database/` subdirectory beside it, so a lone
212`wallet.dat` will not open elsewhere — the keys are all still in there, and the 229`wallet.dat` will not open elsewhere — the keys are all still in there, and the
@@ -244,7 +261,7 @@ as a verdict to somebody who has just lost a wallet.
244 261
245### When wallet.dat itself will not open 262### When wallet.dat itself will not open
246 263
247Everything above still runs through Berkeley DB. If the database is the thing 264A legacy `wallet.dat` runs on Berkeley DB. If that database is the thing
248that is broken — a build that will not read it, a file truncated by a bad copy, 265that is broken — a build that will not read it, a file truncated by a bad copy,
249an environment beyond recovery — the keys are usually still fine, and you can 266an environment beyond recovery — the keys are usually still fine, and you can
250take them out as text: 267take them out as text:
@@ -348,10 +365,12 @@ Other options worth knowing:
348 365
349```bash 366```bash
350-datadir=PATH # wallet and chain data elsewhere 367-datadir=PATH # wallet and chain data elsewhere
351-port=N # P2P listen port, default 8433 368-testnet # isolated test network genesis, datadir, port 18433, and magic
369-port=N # P2P listen port, default 8433; testnet default 18433
352-socks=HOST:PORT # SOCKS5 for outbound Nostr, .btf relay, and onion peer dials 370-socks=HOST:PORT # SOCKS5 for outbound Nostr, .btf relay, and onion peer dials
353-tor[=HOST:PORT] # Tor mode; default local Tor SOCKS5 proxy is 127.0.0.1:9050 371-tor[=HOST:PORT] # Tor mode; default local Tor SOCKS5 proxy is 127.0.0.1:9050
354-managedtor[=PATH] # start Tor, create a hidden service, advertise its onion 372-managedtor[=PATH] # start Tor, create a hidden service, advertise its onion
373-nomanagedtor # disable the automatic bundled-Tor startup
355-onionservice=HOST.onion:PORT # advertise this node's Tor hidden service 374-onionservice=HOST.onion:PORT # advertise this node's Tor hidden service
356-debug # verbose log; without it debug.log is nearly silent 375-debug # verbose log; without it debug.log is nearly silent
357-help # full list 376-help # full list
@@ -372,6 +391,10 @@ proxy. IPv6 proxy endpoints use brackets, for example `-socks=[::1]:9050`.
372and signed direct `.onion` peer dials through Tor, and keeps external-IP probes 391and signed direct `.onion` peer dials through Tor, and keeps external-IP probes
373disabled. Use `-tor=HOST:PORT` when Tor listens somewhere else. 392disabled. Use `-tor=HOST:PORT` when Tor listens somewhere else.
374 393
394The desktop app starts a managed Tor automatically when no other Tor option is
395set, so onion transport works out of the box; `-nomanagedtor` turns that off.
396For a headless node, ask for it explicitly:
397
375`-managedtor[=PATH]` starts a Tor process for this node, writes a local `torrc`, 398`-managedtor[=PATH]` starts a Tor process for this node, writes a local `torrc`,
376creates a v3 hidden service for port `8433`, routes outbound discovery through 399creates a v3 hidden service for port `8433`, routes outbound discovery through
377that Tor instance, and signs the generated `.onion:8433` endpoint into the 400that Tor instance, and signs the generated `.onion:8433` endpoint into the
@@ -496,7 +519,8 @@ windows-tor` to require the extra signature check.
496| Addressing | `.btf` rendezvous — see the caveats above | 519| Addressing | `.btf` rendezvous — see the caveats above |
497| Premine | None | 520| Premine | None |
498| Pool server | Built-in — `.btf` rendezvous only | 521| Pool server | Built-in — `.btf` rendezvous only |
499| Wallet recovery | Twelve-word phrase (BIP39 + BIP32), plus file backup | 522| Wallet recovery | Twelve-word phrase (BIP39 + BIP32 + BIP44, coin type 4346950), plus file backup |
523| Wallet storage | SQLite `wallet.sqlite` by default, or Berkeley DB `wallet.dat` |
500 524
501The halving interval is the number most people get wrong coming from Bitcoin. 525The halving interval is the number most people get wrong coming from Bitcoin.
502Same 210,000 blocks, but at two minutes instead of ten, so it arrives in about 526Same 210,000 blocks, but at two minutes instead of ten, so it arrives in about
@@ -504,6 +528,6 @@ ten months rather than four years.
504 528
505--- 529---
506 530
507Experimental software. Young network. Don't put in more than you are willing to lose. 531Young network. Keep your node current and don't put in more than you are willing to lose.
508 532
509MIT. Built on Bitcoin 0.1.0 (Satoshi Nakamoto, 2009). 533MIT. Built on Bitcoin 0.1.0 (Satoshi Nakamoto, 2009).
diff --git a/src/Makefile b/src/Makefile
index 888110f..c997ae3 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -225,6 +225,7 @@ tests: test_bip32 test_compactblock bitflash-node
225 ./bitflash-node -selftest=wallet-crypto 225 ./bitflash-node -selftest=wallet-crypto
226 ./bitflash-node -selftest=wallet-encrypt 226 ./bitflash-node -selftest=wallet-encrypt
227 ./bitflash-node -selftest=net-message 227 ./bitflash-node -selftest=net-message
228 ./bitflash-node -selftest=network-params
228 ./bitflash-node -selftest=consensus-limits 229 ./bitflash-node -selftest=consensus-limits
229 ./bitflash-node -selftest=pool-stratum 230 ./bitflash-node -selftest=pool-stratum
230 ./bitflash-node -selftest=payout-ledger 231 ./bitflash-node -selftest=payout-ledger
diff --git a/src/main.cpp b/src/main.cpp
index 7398064..0fa6b89 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -42,12 +42,30 @@ unsigned int nTransactionsUpdated = 0;
42map<COutPoint, CInPoint> mapNextTx; 42map<COutPoint, CInPoint> mapNextTx;
43 43
44map<uint256, CBlockIndex*> mapBlockIndex; 44map<uint256, CBlockIndex*> mapBlockIndex;
45// Bitflash genesis -- mined under RandomX PoW on 2026-07-22 45// Bitflash mainnet genesis -- mined under RandomX PoW for the 2026 stable
46// (nTime 1753142400, nBits 0x1f0fffff, RandomX key "Bitflash/RandomX/v1/...") 46// relaunch. Testnet gets its own resettable genesis below so block indexes,
47// Bitflash 2026 stable relaunch genesis (2-min blocks, RandomX). Mined values. 47// headers, and wallet scans cannot be accidentally mixed across networks.
48unsigned int GENESIS_NONCE = 3141; 48static const unsigned int MAINNET_GENESIS_TIME = 1753315200; // 2026-07-24 00:00:00 UTC
49uint256 hashGenesisBlock("0x5bd7cb255d814e48cebcdfb72da4dc87b34bd774227f8ceb546c5640f4bdc169"); 49static const unsigned int MAINNET_GENESIS_NONCE = 3141;
50uint256 hashGenesisMerkleRoot("0x1a45b4482532abb29b10e234d3f13132230525a339ecea91658ffa675a5b1325"); 50static const char* MAINNET_GENESIS_TIMESTAMP =
51 "Bitflash 24/Jul/2026 Fair launch: one CPU one vote, no premine";
52static const char* MAINNET_GENESIS_HASH =
53 "0x5bd7cb255d814e48cebcdfb72da4dc87b34bd774227f8ceb546c5640f4bdc169";
54static const char* MAINNET_GENESIS_MERKLE =
55 "0x1a45b4482532abb29b10e234d3f13132230525a339ecea91658ffa675a5b1325";
56
57static const unsigned int TESTNET_GENESIS_TIME = 1787184000; // 2026-08-20 00:00:00 UTC
58static const unsigned int TESTNET_GENESIS_NONCE = 3199;
59static const char* TESTNET_GENESIS_TIMESTAMP =
60 "Bitflash testnet 20/Aug/2026: resettable public test chain";
61static const char* TESTNET_GENESIS_HASH =
62 "0xa9d11c6d697bcb7aea0653bc088b12dcf9f44e732df205162cf085fd9d9963eb";
63static const char* TESTNET_GENESIS_MERKLE =
64 "0x510b293105e3ff85b8d4c3920e357f85d1a86bf199eb4e7d11f04f380030ec5c";
65
66unsigned int GENESIS_NONCE = MAINNET_GENESIS_NONCE;
67uint256 hashGenesisBlock(MAINNET_GENESIS_HASH);
68uint256 hashGenesisMerkleRoot(MAINNET_GENESIS_MERKLE);
51CBlockIndex* pindexGenesisBlock = NULL; 69CBlockIndex* pindexGenesisBlock = NULL;
52int nBestHeight = -1; 70int nBestHeight = -1;
53uint256 hashBestChain = 0; 71uint256 hashBestChain = 0;
@@ -254,6 +272,63 @@ static std::atomic<uint64> gParticipantHashRateX1000{0};
254static std::mutex gParticipantStatusMutex; 272static std::mutex gParticipantStatusMutex;
255static std::string gParticipantStatus; 273static std::string gParticipantStatus;
256 274
275void SelectGenesisParams(bool fTestNetIn)
276{
277 static bool fGenesisParamsSelected = false;
278 static bool fGenesisParamsTestNet = false;
279 if (fGenesisParamsSelected && fGenesisParamsTestNet == fTestNetIn)
280 return;
281
282 fGenesisParamsSelected = true;
283 fGenesisParamsTestNet = fTestNetIn;
284
285 if (fTestNetIn)
286 {
287 GENESIS_NONCE = TESTNET_GENESIS_NONCE;
288 hashGenesisBlock = uint256(TESTNET_GENESIS_HASH);
289 hashGenesisMerkleRoot = uint256(TESTNET_GENESIS_MERKLE);
290 }
291 else
292 {
293 GENESIS_NONCE = MAINNET_GENESIS_NONCE;
294 hashGenesisBlock = uint256(MAINNET_GENESIS_HASH);
295 hashGenesisMerkleRoot = uint256(MAINNET_GENESIS_MERKLE);
296 }
297}
298
299void SelectChainParams(bool fTestNetIn)
300{
301 SelectNetworkParams(fTestNetIn);
302 SelectGenesisParams(fTestNetIn);
303}
304
305static CBlock BuildGenesisBlock()
306{
307 const char* pszTimestamp = IsTestNet() ?
308 TESTNET_GENESIS_TIMESTAMP : MAINNET_GENESIS_TIMESTAMP;
309
310 CTransaction txNew;
311 txNew.vin.resize(1);
312 txNew.vout.resize(1);
313 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) <<
314 vector<unsigned char>((unsigned char*)pszTimestamp,
315 (unsigned char*)pszTimestamp + strlen(pszTimestamp));
316 txNew.vout[0].nValue = 50 * COIN;
317 txNew.vout[0].scriptPubKey = CScript() <<
318 CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") <<
319 OP_CHECKSIG;
320
321 CBlock block;
322 block.vtx.push_back(txNew);
323 block.hashPrevBlock = 0;
324 block.hashMerkleRoot = block.BuildMerkleTree();
325 block.nVersion = 1;
326 block.nTime = IsTestNet() ? TESTNET_GENESIS_TIME : MAINNET_GENESIS_TIME;
327 block.nBits = 0x1f0fffff; // = bnProofOfWorkLimit (Bitflash RandomX floor)
328 block.nNonce = GENESIS_NONCE;
329 return block;
330}
331
257void SetParticipantMiningStatus(const std::string& status) 332void SetParticipantMiningStatus(const std::string& status)
258{ 333{
259 // Updates the GUI status string only. Logging is done at each call site 334 // Updates the GUI status string only. Logging is done at each call site
@@ -2654,11 +2729,21 @@ string GetAppDir()
2654 { 2729 {
2655 return "."; 2730 return ".";
2656 } 2731 }
2657 static bool fMkdirDone; 2732 static string strCreatedBaseDir;
2658 if (!fMkdirDone) 2733 if (strCreatedBaseDir != strDir)
2659 { 2734 {
2660 fMkdirDone = true;
2661 _mkdir(strDir.c_str()); 2735 _mkdir(strDir.c_str());
2736 strCreatedBaseDir = strDir;
2737 }
2738 if (IsTestNet())
2739 {
2740 strDir += "/testnet";
2741 static string strCreatedTestnetDir;
2742 if (strCreatedTestnetDir != strDir)
2743 {
2744 _mkdir(strDir.c_str());
2745 strCreatedTestnetDir = strDir;
2746 }
2662 } 2747 }
2663 return strDir; 2748 return strDir;
2664} 2749}
@@ -2812,38 +2897,34 @@ bool LoadBlockIndex(bool fAllowNew)
2812 2897
2813 // Bitflash genesis block -- own header (fair launch) 2898 // Bitflash genesis block -- own header (fair launch)
2814 // 2899 //
2815 // Do not change pszTimestamp, the scriptPubKey, nTime or nNonce. They 2900 // Upstream moved the construction into BuildGenesisBlock() so mainnet
2816 // are the inputs to the genesis hash, and the genesis hash is 2901 // and the isolated testnet can share it. The mainnet inputs it uses are
2817 // consensus. Changing one on its own trips the assert below, which is 2902 // byte-identical to what this block built inline before the merge --
2818 // loud and reverts cleanly; changing one and regenerating 2903 // timestamp string, nTime, nNonce, scriptPubKey, nBits and nVersion all
2819 // GENESIS_NONCE and hashGenesisBlock to match -- which is exactly what 2904 // verified equal against MAINNET_GENESIS_* -- so the mainnet genesis
2820 // the re-mining branch below prints out and invites -- gives a node 2905 // hash is unchanged. The warning below is why that was checked rather
2821 // that starts without complaint, builds its own chain from height 0, 2906 // than assumed, and it still applies to those constants:
2822 // and rejects every real peer as being on a different chain. That one 2907 //
2823 // fails silently, and the damage scales with how many people run the 2908 // Do not change MAINNET_GENESIS_TIMESTAMP, the scriptPubKey,
2824 // "fixed" build. 2909 // MAINNET_GENESIS_TIME or MAINNET_GENESIS_NONCE. They are the inputs to
2825 char* pszTimestamp = "Bitflash 24/Jul/2026 Fair launch: one CPU one vote, no premine"; 2910 // the genesis hash, and the genesis hash is consensus. Changing one on
2826 CTransaction txNew; 2911 // its own trips the assert below, which is loud and reverts cleanly;
2827 txNew.vin.resize(1); 2912 // changing one and regenerating GENESIS_NONCE and hashGenesisBlock to
2828 txNew.vout.resize(1); 2913 // match -- which is exactly what the re-mining branch below prints out
2829 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp)); 2914 // and invites -- gives a node that starts without complaint, builds its
2830 txNew.vout[0].nValue = 50 * COIN; 2915 // own chain from height 0, and rejects every real peer as being on a
2831 txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG; 2916 // different chain. That one fails silently, and the damage scales with
2832 CBlock block; 2917 // how many people run the "fixed" build.
2833 block.vtx.push_back(txNew); 2918 //
2834 block.hashPrevBlock = 0; 2919 // MAINNET_GENESIS_TIME is 1753315200, which is 2025-07-24T00:00:00Z,
2835 block.hashMerkleRoot = block.BuildMerkleTree(); 2920 // while the headline in MAINNET_GENESIS_TIMESTAMP reads 2026 -- as does
2836 block.nVersion = 1; 2921 // the comment upstream put on that constant, which is wrong about the
2837 // 1753315200 is 2025-07-24T00:00:00Z. The headline in pszTimestamp 2922 // year. This is a known discrepancy and not a typo in the value: it is
2838 // above reads 2026 and does not match it. This is a known discrepancy 2923 // only consensus-critical as an input to the genesis hash, the block
2839 // and not a typo in the constant: the value is only consensus-critical 2924 // hashes to hashGenesisBlock with it, and every node on the network
2840 // as an input to the genesis hash, the block hashes to 2925 // agrees. The mismatch is in the launched chain and cannot be corrected
2841 // hashGenesisBlock with it, and every node on the network agrees. The 2926 // -- see the warning above before deciding otherwise.
2842 // mismatch is in the launched chain and cannot be corrected -- see the 2927 CBlock block = BuildGenesisBlock();
2843 // warning above before deciding otherwise.
2844 block.nTime = 1753315200;
2845 block.nBits = 0x1f0fffff; // = bnProofOfWorkLimit (Bitflash RandomX floor)
2846 block.nNonce = GENESIS_NONCE;
2847 2928
2848 // If the nonce has not been found yet, mine the genesis once (RandomX) 2929 // If the nonce has not been found yet, mine the genesis once (RandomX)
2849 // and print the values to be hardcoded in the constants above. 2930 // and print the values to be hardcoded in the constants above.
diff --git a/src/main.h b/src/main.h
index e05b467..26b3b69 100644
--- a/src/main.h
+++ b/src/main.h
@@ -94,6 +94,8 @@ extern map<uint256, CBlockIndex*> mapBlockIndex;
94extern uint256 hashGenesisBlock; 94extern uint256 hashGenesisBlock;
95extern uint256 hashGenesisMerkleRoot; 95extern uint256 hashGenesisMerkleRoot;
96extern unsigned int GENESIS_NONCE; 96extern unsigned int GENESIS_NONCE;
97void SelectGenesisParams(bool fTestNetIn);
98void SelectChainParams(bool fTestNetIn);
97extern CBlockIndex* pindexGenesisBlock; 99extern CBlockIndex* pindexGenesisBlock;
98extern int nBestHeight; 100extern int nBestHeight;
99extern uint256 hashBestChain; 101extern uint256 hashBestChain;
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index dd001c8..2e4eb91 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -120,7 +120,7 @@ static void PrintUsage()
120 printf(" wallet-crypto, wallet-encrypt, wallet-portability,\n"); 120 printf(" wallet-crypto, wallet-encrypt, wallet-portability,\n");
121 printf(" net-message,\n"); 121 printf(" net-message,\n");
122 printf(" consensus-limits, pool-stratum,\n"); 122 printf(" consensus-limits, pool-stratum,\n");
123 printf(" parse-money, socks5-proxy, or managed-tor\n"); 123 printf(" parse-money, network-params, socks5-proxy, or managed-tor\n");
124 printf("\n"); 124 printf("\n");
125 printf("Mining mode:\n"); 125 printf("Mining mode:\n");
126 printf(" /operator\n"); 126 printf(" /operator\n");
@@ -132,6 +132,8 @@ static void PrintUsage()
132 printf(" /stratumbridgeport=N (default 3333; listen on 127.0.0.1)\n"); 132 printf(" /stratumbridgeport=N (default 3333; listen on 127.0.0.1)\n");
133 printf(" /solomine\n"); 133 printf(" /solomine\n");
134 printf(" /genproclimit=N (mining threads; 0 or absent = every core but one)\n"); 134 printf(" /genproclimit=N (mining threads; 0 or absent = every core but one)\n");
135 printf(" /nolargepages (do not ask for 2 MB pages for the RandomX\n");
136 printf(" cache, dataset and scratchpads)\n");
135 printf(" /checkblocks=N (blocks re-verified at startup, default 288, 0 = all)\n"); 137 printf(" /checkblocks=N (blocks re-verified at startup, default 288, 0 = all)\n");
136 printf("\n"); 138 printf("\n");
137 printf("Pool operator announcement:\n"); 139 printf("Pool operator announcement:\n");
@@ -148,7 +150,8 @@ static void PrintUsage()
148 printf(" /onionservice=HOST.onion:PORT (advertise this node's Tor hidden service)\n"); 150 printf(" /onionservice=HOST.onion:PORT (advertise this node's Tor hidden service)\n");
149 printf("\n"); 151 printf("\n");
150 printf("Network:\n"); 152 printf("Network:\n");
151 printf(" /port=N (P2P listen port, default 8433)\n"); 153 printf(" /testnet (isolated test network genesis, datadir, port, and magic)\n");
154 printf(" /port=N (P2P listen port, default 8433; testnet 18433)\n");
152 printf(" /socks=HOST:PORT (SOCKS5 proxy for Nostr, .btf relay, and onion dials)\n"); 155 printf(" /socks=HOST:PORT (SOCKS5 proxy for Nostr, .btf relay, and onion dials)\n");
153 printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n"); 156 printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n");
154 printf(" /managedtor[=PATH] (start Tor, create a hidden service, advertise its onion)\n"); 157 printf(" /managedtor[=PATH] (start Tor, create a hidden service, advertise its onion)\n");
@@ -214,6 +217,9 @@ static void ParseStartupArguments(int argc, char* argv[])
214 if (arg(argc,argv,"/datadir") || arg(argc,argv,"-datadir")) 217 if (arg(argc,argv,"/datadir") || arg(argc,argv,"-datadir"))
215 strSetDataDir = argval2(argc, argv, "/datadir", "-datadir"); 218 strSetDataDir = argval2(argc, argv, "/datadir", "-datadir");
216 219
220 bool fUseTestNet = arg(argc, argv, "/testnet") || arg(argc, argv, "-testnet");
221 SelectChainParams(fUseTestNet);
222
217 if (arg(argc,argv,"/debug") || arg(argc,argv,"-debug")) 223 if (arg(argc,argv,"/debug") || arg(argc,argv,"-debug"))
218 fDebug = true; 224 fDebug = true;
219 225
@@ -284,6 +290,11 @@ static void ParseStartupArguments(int argc, char* argv[])
284 if (!strCheckBlocks.empty()) 290 if (!strCheckBlocks.empty())
285 nCheckBlocksOnLoad = atoi(strCheckBlocks.c_str()); 291 nCheckBlocksOnLoad = atoi(strCheckBlocks.c_str());
286 292
293 // Must be read before LoadBlockIndex(), which is what first calls
294 // RandomXInit() and fixes how the cache is allocated.
295 if (arg(argc,argv,"/nolargepages") || arg(argc,argv,"-nolargepages"))
296 fRandomXLargePages = false;
297
287 // /genproclimit=N -- threads to hash with. 0 or absent means automatic, 298 // /genproclimit=N -- threads to hash with. 0 or absent means automatic,
288 // which is every core but one. Named after Bitcoin's own option so it reads 299 // which is every core but one. Named after Bitcoin's own option so it reads
289 // familiarly to anyone who has run one of these before. 300 // familiarly to anyone who has run one of these before.
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 740bba6..362794a 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -116,6 +116,7 @@ tests: test_bip32.exe bitflash.exe
116 ./bitflash.exe -selftest=wallet-backend-default 116 ./bitflash.exe -selftest=wallet-backend-default
117 ./bitflash.exe -selftest=wallet-convert 117 ./bitflash.exe -selftest=wallet-convert
118 ./bitflash.exe -selftest=net-message 118 ./bitflash.exe -selftest=net-message
119 ./bitflash.exe -selftest=network-params
119 ./bitflash.exe -selftest=consensus-limits 120 ./bitflash.exe -selftest=consensus-limits
120 ./bitflash.exe -selftest=pool-stratum 121 ./bitflash.exe -selftest=pool-stratum
121 ./bitflash.exe -selftest=socks5-proxy 122 ./bitflash.exe -selftest=socks5-proxy
diff --git a/src/net.cpp b/src/net.cpp
index bb05259..0576402 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -50,10 +50,14 @@ static int BtfPoll(BtfPollFd* pfd, unsigned int nfd, int nTimeoutMs)
50// 50//
51// Global state variables 51// Global state variables
52// 52//
53static const char pchMainnetMessageStart[4] = { 0xbf, 0x20, 0x5c, 0xfd };
54static const char pchTestnetMessageStart[4] = { (char)0xce, (char)0xe2, (char)0xc0, (char)0xff };
55static bool fTestNet = false;
56char pchMessageStart[4] = { 0xbf, 0x20, 0x5c, 0xfd };
53bool fClient = false; 57bool fClient = false;
54uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); 58uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
55CAddress addrLocalHost(0, DEFAULT_PORT, nLocalServices); 59CAddress addrLocalHost(0, GetDefaultPort(), nLocalServices);
56unsigned short nListenPort = DEFAULT_PORT; // local P2P port (tunable via /port) 60unsigned short nListenPort = GetDefaultPort(); // local P2P port (tunable via /port)
57CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices)); 61CNode nodeLocalHost(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
58CNode* pnodeLocalHost = &nodeLocalHost; 62CNode* pnodeLocalHost = &nodeLocalHost;
59bool fShutdown = false; 63bool fShutdown = false;
@@ -90,6 +94,29 @@ static int64 nBtfHandshakeSilent = 0;
90static string strBtfLastDialFail; 94static string strBtfLastDialFail;
91static string strBtfLastHandshakeTimeout; 95static string strBtfLastHandshakeTimeout;
92 96
97bool IsTestNet()
98{
99 return fTestNet;
100}
101
102unsigned short GetDefaultPort()
103{
104 return htons(fTestNet ? TESTNET_PORT : MAINNET_PORT);
105}
106
107void SelectNetworkParams(bool fTestNetIn)
108{
109 if (fTestNet == fTestNetIn)
110 return;
111
112 fTestNet = fTestNetIn;
113 memcpy(pchMessageStart,
114 fTestNet ? pchTestnetMessageStart : pchMainnetMessageStart,
115 sizeof(pchMessageStart));
116 nListenPort = GetDefaultPort();
117 addrLocalHost.port = nListenPort;
118}
119
93void BtfChurnNoteResolveAttempt() 120void BtfChurnNoteResolveAttempt()
94{ 121{
95 CRITICAL_BLOCK(cs_btfChurn) 122 CRITICAL_BLOCK(cs_btfChurn)
@@ -288,6 +315,7 @@ string GetDiagnosticsText()
288 int nMedian = GetPeerMedianHeight(); 315 int nMedian = GetPeerMedianHeight();
289 316
290 str += "Bitflash node diagnostics\n"; 317 str += "Bitflash node diagnostics\n";
318 str += strprintf(" network %s\n", IsTestNet() ? "testnet" : "mainnet");
291 str += strprintf(" uptime %s\n", 319 str += strprintf(" uptime %s\n",
292 FormatAge(nNodeStartTime ? nNow - nNodeStartTime : -1).c_str()); 320 FormatAge(nNodeStartTime ? nNow - nNodeStartTime : -1).c_str());
293 if (nMedian < 0) 321 if (nMedian < 0)
@@ -338,6 +366,7 @@ string GetDiagnosticsText()
338 nMining, 366 nMining,
339 (RandomXFastReady() ? 2080 : 256) + 2 * nMining).c_str() 367 (RandomXFastReady() ? 2080 : 256) + 2 * nMining).c_str()
340 : ", not mining"); 368 : ", not mining");
369 str += strprintf(" large pages %s\n", RandomXLargePagesStatus());
341 370
342 str += SockAccountingText(); 371 str += SockAccountingText();
343 372
diff --git a/src/net.h b/src/net.h
index 752b1fe..0988542 100644
--- a/src/net.h
+++ b/src/net.h
@@ -12,7 +12,13 @@ class CBlockIndex;
12 12
13 13
14 14
15static const unsigned short DEFAULT_PORT = htons(8433); 15// Held in host byte order, unlike the DEFAULT_PORT constant these replace,
16// which was htons(8433). Nothing is lost: net.cpp's GetDefaultPort() applies
17// htons() itself and is what every caller now uses, so the value that reaches
18// a sockaddr is byte-for-byte what it was. Mainnet stays on 8433.
19static const unsigned short MAINNET_PORT = 8433;
20static const unsigned short TESTNET_PORT = 18433;
21static const unsigned int PUBLISH_HOPS = 5;
16enum 22enum
17{ 23{
18 NODE_NETWORK = (1 << 0), 24 NODE_NETWORK = (1 << 0),
@@ -30,6 +36,9 @@ enum
30bool IsBlockFetchNearTip(); 36bool IsBlockFetchNearTip();
31 37
32bool GetMyExternalIP(unsigned int& ipRet); 38bool GetMyExternalIP(unsigned int& ipRet);
39bool IsTestNet();
40unsigned short GetDefaultPort();
41void SelectNetworkParams(bool fTestNetIn);
33CNode* ConnectNodeBtf(const string& strBtfAddr); 42CNode* ConnectNodeBtf(const string& strBtfAddr);
34CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, 43CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting,
35 const string& strOnion, const unsigned char enc_pub[32], 44 const string& strOnion, const unsigned char enc_pub[32],
@@ -266,15 +275,17 @@ void CheckForShutdown(int n);
266// The message start string is designed to be unlikely to occur in normal data. 275// The message start string is designed to be unlikely to occur in normal data.
267// The characters are rarely used upper ascii, not valid as UTF-8, and produce 276// The characters are rarely used upper ascii, not valid as UTF-8, and produce
268// a large 4-byte int at any alignment. 277// a large 4-byte int at any alignment.
269// Magic bytes unique to the Bitflash network (0xbf = "BF"). Second byte bumped 278// Magic bytes unique to the selected Bitflash network. Mainnet uses 0xbf =
270// to 0x20 for the 2026 stable relaunch so the old test chain can't interfere. 279// "BF"; testnet swaps the whole sequence so a test node cannot handshake with
271static const char pchMessageStart[4] = { 0xbf, 0x20, 0x5c, 0xfd }; 280// mainnet before consensus-level testnet activation exists.
281extern char pchMessageStart[4];
272 282
273class CMessageHeader 283class CMessageHeader
274{ 284{
275public: 285public:
276 enum { COMMAND_SIZE=12 }; 286 enum { COMMAND_SIZE=12 };
277 char pchMessageStart[sizeof(::pchMessageStart)]; 287 enum { MESSAGE_START_SIZE=4 };
288 char pchMessageStart[MESSAGE_START_SIZE];
278 char pchCommand[COMMAND_SIZE]; 289 char pchCommand[COMMAND_SIZE];
279 unsigned int nMessageSize; 290 unsigned int nMessageSize;
280 291
@@ -365,7 +376,7 @@ public:
365 nServices = 0; 376 nServices = 0;
366 memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 377 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
367 ip = 0; 378 ip = 0;
368 port = DEFAULT_PORT; 379 port = GetDefaultPort();
369 nTime = GetAdjustedTime(); 380 nTime = GetAdjustedTime();
370 nLastFailed = 0; 381 nLastFailed = 0;
371 } 382 }
@@ -395,7 +406,7 @@ public:
395 nServices = nServicesIn; 406 nServices = nServicesIn;
396 memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 407 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
397 ip = 0; 408 ip = 0;
398 port = DEFAULT_PORT; 409 port = GetDefaultPort();
399 nTime = GetAdjustedTime(); 410 nTime = GetAdjustedTime();
400 nLastFailed = 0; 411 nLastFailed = 0;
401 412
diff --git a/src/randomx_pow.cpp b/src/randomx_pow.cpp
index 9c59364..a509543 100644
--- a/src/randomx_pow.cpp
+++ b/src/randomx_pow.cpp
@@ -24,6 +24,50 @@ static std::mutex g_csInit;
24static bool g_fInit = false; 24static bool g_fInit = false;
25static bool g_fFast = false; 25static bool g_fFast = false;
26 26
27// RandomX reads a 256 MB cache, a 2 GB dataset and a 2 MB scratchpad per VM
28// at random, so most reads miss the TLB on 4 KB pages. 2 MB pages recover
29// roughly a tenth of the hash rate.
30//
31// The pool must be reserved first (vm.nr_hugepages), and RandomX returns NULL
32// instead of falling back, so each allocation below retries without the flag.
33bool fRandomXLargePages = true; // cleared by -nolargepages
34static bool g_fLargeCache = false;
35static bool g_fLargeDataset = false;
36static bool g_fLargeAny = false;
37
38// How to reserve the large-page pool, for the hint printed when a large-page
39// allocation falls back to normal pages. The mechanism is OS-specific.
40static const char* LargePagesHint()
41{
42#ifdef _WIN32
43 return "enable the \"Lock pages in memory\" privilege and run elevated";
44#else
45 return "reserve them with: sysctl vm.nr_hugepages=1280";
46#endif
47}
48
49static randomx_flags WithLargePages(randomx_flags f)
50{
51 return (randomx_flags)(f | RANDOMX_FLAG_LARGE_PAGES);
52}
53
54// Ask for a cache in large pages, then plain pages. Sets fLargeOut to say
55// which one answered.
56static randomx_cache* AllocCache(randomx_flags flags, bool& fLargeOut)
57{
58 fLargeOut = false;
59 if (fRandomXLargePages)
60 {
61 randomx_cache* c = randomx_alloc_cache(WithLargePages(flags));
62 if (c)
63 {
64 fLargeOut = true;
65 return c;
66 }
67 }
68 return randomx_alloc_cache(flags);
69}
70
27 71
28bool RandomXInit() 72bool RandomXInit()
29{ 73{
@@ -37,28 +81,56 @@ bool RandomXInit()
37 // Detect the best flags for this CPU (JIT, hardware AES, Argon2). 81 // Detect the best flags for this CPU (JIT, hardware AES, Argon2).
38 g_flags = randomx_get_flags(); 82 g_flags = randomx_get_flags();
39 83
40 g_cache = randomx_alloc_cache(g_flags); 84 g_cache = AllocCache(g_flags, g_fLargeCache);
41 if (!g_cache) 85 if (!g_cache)
42 { 86 {
43 // Try without JIT as a fallback 87 // Try without JIT as a fallback
44 g_flags = RANDOMX_FLAG_DEFAULT; 88 g_flags = RANDOMX_FLAG_DEFAULT;
45 g_cache = randomx_alloc_cache(g_flags); 89 g_cache = AllocCache(g_flags, g_fLargeCache);
46 if (!g_cache) 90 if (!g_cache)
47 return error("RandomX: failed to allocate cache (256 MB)"); 91 return error("RandomX: failed to allocate cache (256 MB)");
48 } 92 }
49 randomx_init_cache(g_cache, RANDOMX_KEY, strlen(RANDOMX_KEY)); 93 randomx_init_cache(g_cache, RANDOMX_KEY, strlen(RANDOMX_KEY));
50 94
51 // Verification VM in light mode (cache only) 95 // Verification VM in light mode (cache only). The scratchpad is only 2 MB
52 g_vmVerify = randomx_create_vm(g_flags, g_cache, NULL); 96 // and this VM is created once, but it hashes every block the node ever
97 // validates, so it gets the same treatment.
98 bool fLargeVerify = false;
99 if (fRandomXLargePages)
100 {
101 g_vmVerify = randomx_create_vm(WithLargePages(g_flags), g_cache, NULL);
102 fLargeVerify = (g_vmVerify != NULL);
103 }
104 if (!g_vmVerify)
105 g_vmVerify = randomx_create_vm(g_flags, g_cache, NULL);
53 if (!g_vmVerify) 106 if (!g_vmVerify)
54 return error("RandomX: failed to create verification VM"); 107 return error("RandomX: failed to create verification VM");
55 108
109 g_fLargeAny = g_fLargeCache || fLargeVerify;
56 g_fInit = true; 110 g_fInit = true;
57 printf("RandomX: initialized (cache 256 MB, flags=%d)\n", (int)g_flags); 111 printf("RandomX: initialized (cache 256 MB, flags=%d, large pages: %s)\n",
112 (int)g_flags, RandomXLargePagesStatus());
113 if (fRandomXLargePages && !g_fLargeCache)
114 printf("RandomX: large pages unavailable for the cache; %s "
115 "for about 10%% more hash rate\n", LargePagesHint());
58 return true; 116 return true;
59} 117}
60 118
61 119
120const char* RandomXLargePagesStatus()
121{
122 if (!fRandomXLargePages)
123 return "off (-nolargepages)";
124 if (g_fLargeCache && g_fLargeDataset)
125 return "cache + dataset";
126 if (g_fLargeCache)
127 return "cache only";
128 if (g_fLargeDataset)
129 return "dataset only";
130 return g_fLargeAny ? "scratchpad only" : "unavailable";
131}
132
133
62// One dataset, once, no matter how many miners ask for it. 134// One dataset, once, no matter how many miners ask for it.
63// 135//
64// Every miner thread calls this at startup. The g_fFast guard below is only 136// Every miner thread calls this at startup. The g_fFast guard below is only
@@ -88,8 +160,18 @@ bool RandomXInitDataset(int nThreads)
88 if (g_fFast) 160 if (g_fFast)
89 return true; 161 return true;
90 162
91 randomx_flags fastFlags = (randomx_flags)(g_flags | RANDOMX_FLAG_FULL_MEM); 163 // Only RANDOMX_FLAG_LARGE_PAGES means anything to randomx_alloc_dataset;
92 g_dataset = randomx_alloc_dataset(fastFlags); 164 // the rest of g_flags belongs to the VMs that read it.
165 if (fRandomXLargePages)
166 {
167 g_dataset = randomx_alloc_dataset(WithLargePages(RANDOMX_FLAG_DEFAULT));
168 g_fLargeDataset = (g_dataset != NULL);
169 if (!g_dataset)
170 printf("RandomX: large pages unavailable for the 2 GB dataset; %s "
171 "for about 10%% more hash rate\n", LargePagesHint());
172 }
173 if (!g_dataset)
174 g_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
93 if (!g_dataset) 175 if (!g_dataset)
94 { 176 {
95 printf("RandomX: not enough memory for the 2 GB dataset, staying in light mode\n"); 177 printf("RandomX: not enough memory for the 2 GB dataset, staying in light mode\n");
@@ -158,13 +240,26 @@ void* RandomXCreateMinerVM()
158{ 240{
159 if (!g_fInit && !RandomXInit()) 241 if (!g_fInit && !RandomXInit())
160 return NULL; 242 return NULL;
243
244 randomx_flags flags = g_flags;
245 randomx_cache* cache = g_cache;
246 randomx_dataset* dataset = NULL;
161 if (g_fFast && g_dataset) 247 if (g_fFast && g_dataset)
162 { 248 {
163 randomx_flags fastFlags = (randomx_flags)(g_flags | RANDOMX_FLAG_FULL_MEM); 249 flags = (randomx_flags)(g_flags | RANDOMX_FLAG_FULL_MEM);
164 return randomx_create_vm(fastFlags, NULL, g_dataset); 250 cache = NULL;
251 dataset = g_dataset;
252 }
253
254 // Each thread gets its own 2 MB scratchpad, so the large-page pool can run
255 // dry partway through a fleet of miners. Threads that miss out still run.
256 if (fRandomXLargePages)
257 {
258 randomx_vm* vm = randomx_create_vm(WithLargePages(flags), cache, dataset);
259 if (vm)
260 return vm;
165 } 261 }
166 // Light mode: own VM sharing the cache 262 return randomx_create_vm(flags, cache, dataset);
167 return randomx_create_vm(g_flags, g_cache, NULL);
168} 263}
169 264
170 265
diff --git a/src/randomx_pow.h b/src/randomx_pow.h
index 0027571..355b708 100644
--- a/src/randomx_pow.h
+++ b/src/randomx_pow.h
@@ -41,4 +41,11 @@ uint256 RandomXHashWithVM(void* vm, const void* pHeader, size_t nSize);
41// True when the 2 GB dataset is ready (fast mode active). 41// True when the 2 GB dataset is ready (fast mode active).
42bool RandomXFastReady(); 42bool RandomXFastReady();
43 43
44// Ask for large (2 MB) pages for the cache, dataset and scratchpads. Set false
45// by -nolargepages. Must be set before the first RandomXInit().
46extern bool fRandomXLargePages;
47
48// Which allocations actually got large pages, for the status display.
49const char* RandomXLargePagesStatus();
50
44#endif 51#endif
diff --git a/src/readme.txt b/src/readme.txt
index 7490a9a..455884c 100644
--- a/src/readme.txt
+++ b/src/readme.txt
@@ -41,7 +41,8 @@ The resulting executable is src/bitflash.exe.
41 41
42Command-line options (in addition to the original ones) 42Command-line options (in addition to the original ones)
43------------------------------------------------------- 43-------------------------------------------------------
44 /port=N listen on P2P port N (default 8433) 44 /testnet use isolated test network genesis, datadir, port 18433, and message magic
45 /port=N listen on P2P port N (default 8433; testnet default 18433)
45 /socks=HOST:PORT 46 /socks=HOST:PORT
46 route outbound Nostr, .btf rendezvous, and direct onion peer 47 route outbound Nostr, .btf rendezvous, and direct onion peer
47 dials through a SOCKS5 proxy, e.g. /socks=127.0.0.1:9050 for local Tor 48 dials through a SOCKS5 proxy, e.g. /socks=127.0.0.1:9050 for local Tor
diff --git a/src/selftest.cpp b/src/selftest.cpp
index 65f215b..357d532 100644
--- a/src/selftest.cpp
+++ b/src/selftest.cpp
@@ -3118,6 +3118,87 @@ static int RunNetMessageSelfTest()
3118 return nFail == 0 ? 0 : 1; 3118 return nFail == 0 ? 0 : 1;
3119} 3119}
3120 3120
3121static int RunNetworkParamsSelfTest()
3122{
3123 fflush(stdout);
3124 printf("network-params self-test\n");
3125
3126 int nFail = 0;
3127 std::string strOldDataDir = strSetDataDir;
3128 try
3129 {
3130 SelectChainParams(false);
3131 nFail += Check(!IsTestNet(), "starts on mainnet after explicit selection") ? 0 : 1;
3132 nFail += Check(ntohs(GetDefaultPort()) == MAINNET_PORT,
3133 "mainnet default P2P port is 8433") ? 0 : 1;
3134 CAddress mainAddr("127.0.0.1");
3135 nFail += Check(mainAddr.port == htons(MAINNET_PORT),
3136 "mainnet address parsing uses the mainnet default port") ? 0 : 1;
3137 CMessageHeader mainHeader("ping", 0);
3138 char mainMagic[4];
3139 memcpy(mainMagic, mainHeader.pchMessageStart, sizeof(mainMagic));
3140 uint256 mainGenesis = hashGenesisBlock;
3141 uint256 mainMerkle = hashGenesisMerkleRoot;
3142 unsigned int mainNonce = GENESIS_NONCE;
3143
3144 SelectChainParams(true);
3145 nFail += Check(IsTestNet(), "testnet selection is sticky") ? 0 : 1;
3146 nFail += Check(ntohs(GetDefaultPort()) == TESTNET_PORT,
3147 "testnet default P2P port is 18433") ? 0 : 1;
3148 CAddress testAddr("127.0.0.1");
3149 nFail += Check(testAddr.port == htons(TESTNET_PORT),
3150 "testnet address parsing uses the testnet default port") ? 0 : 1;
3151 CMessageHeader testHeader("ping", 0);
3152 nFail += Check(memcmp(mainMagic, testHeader.pchMessageStart, sizeof(mainMagic)) != 0,
3153 "testnet message magic differs from mainnet") ? 0 : 1;
3154 nFail += Check(hashGenesisBlock != mainGenesis &&
3155 hashGenesisMerkleRoot != mainMerkle &&
3156 GENESIS_NONCE != mainNonce,
3157 "testnet genesis constants differ from mainnet") ? 0 : 1;
3158 nFail += Check(hashGenesisBlock == uint256("0xa9d11c6d697bcb7aea0653bc088b12dcf9f44e732df205162cf085fd9d9963eb") &&
3159 hashGenesisMerkleRoot == uint256("0x510b293105e3ff85b8d4c3920e357f85d1a86bf199eb4e7d11f04f380030ec5c") &&
3160 GENESIS_NONCE == 3199,
3161 "testnet genesis constants are pinned") ? 0 : 1;
3162
3163 std::string tmp;
3164 if (!MakeTempDir(tmp))
3165 {
3166 nFail += Check(false, "creates a temporary data directory") ? 0 : 1;
3167 }
3168 else
3169 {
3170 strSetDataDir = tmp;
3171 SelectChainParams(false);
3172 std::string mainDir = GetAppDir();
3173 SelectChainParams(true);
3174 std::string testDir = GetAppDir();
3175 nFail += Check(mainDir == tmp,
3176 "mainnet uses the selected data directory") ? 0 : 1;
3177 nFail += Check(testDir == tmp + "/testnet",
3178 "testnet stores data below a testnet subdirectory") ? 0 : 1;
3179 RemoveTree(tmp);
3180 }
3181 }
3182 catch (const std::exception& e)
3183 {
3184 printf(" FAIL exception: %s\n", e.what());
3185 nFail++;
3186 }
3187 catch (...)
3188 {
3189 printf(" FAIL unknown exception\n");
3190 nFail++;
3191 }
3192
3193 strSetDataDir = strOldDataDir;
3194 SelectChainParams(false);
3195
3196 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
3197 nFail, nFail == 1 ? "" : "s");
3198 fflush(stdout);
3199 return nFail == 0 ? 0 : 1;
3200}
3201
3121static CBlock MakeSizedConsensusBlock(size_t nScriptBytes) 3202static CBlock MakeSizedConsensusBlock(size_t nScriptBytes)
3122{ 3203{
3123 CTransaction tx; 3204 CTransaction tx;
@@ -3716,6 +3797,8 @@ int RunSelfTest(const std::string& name)
3716 return RunWalletPortabilitySelfTest(); 3797 return RunWalletPortabilitySelfTest();
3717 if (name == "net-message") 3798 if (name == "net-message")
3718 return RunNetMessageSelfTest(); 3799 return RunNetMessageSelfTest();
3800 if (name == "network-params")
3801 return RunNetworkParamsSelfTest();
3719 if (name == "consensus-limits") 3802 if (name == "consensus-limits")
3720 return RunConsensusLimitsSelfTest(); 3803 return RunConsensusLimitsSelfTest();
3721 if (name == "pool-stratum") 3804 if (name == "pool-stratum")
@@ -3730,6 +3813,6 @@ int RunSelfTest(const std::string& name)
3730 return RunManagedTorSelfTest(); 3813 return RunManagedTorSelfTest();
3731 3814
3732 printf("Unknown self-test '%s'\n", name.c_str()); 3815 printf("Unknown self-test '%s'\n", name.c_str());
3733 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-sqlite-migration, wallet-crypto, wallet-encrypt, wallet-sqlite-encrypt, wallet-backend-default, wallet-convert, wallet-portability, net-message, consensus-limits, pool-stratum, payout-ledger, parse-money, socks5-proxy, managed-tor\n"); 3816 printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-sqlite-migration, wallet-crypto, wallet-encrypt, wallet-sqlite-encrypt, wallet-backend-default, wallet-convert, wallet-portability, net-message, network-params, consensus-limits, pool-stratum, payout-ledger, parse-money, socks5-proxy, managed-tor\n");
3734 return 1; 3817 return 1;
3735} 3818}