upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNsable-sh <nsable-sh@noreply.git.bitflash.network>2026-08-20 17:06:08 -0300
committerNsable-sh <nsable-sh@noreply.git.bitflash.network>2026-08-20 17:20:18 -0300
commit56be66dd66e64e6d21eadd80a808b4627921059f (patch)
tree123605546b7d0d8320b317df463a23d2ae8cbbe9
parent721a7e46fadba3251564e2308b7b7eefcb2e9d36 (diff)
chain: add isolated testnet genesis
-rw-r--r--README.md2
-rw-r--r--src/main.cpp103
-rw-r--r--src/main.h2
-rw-r--r--src/main_gui.cpp5
-rw-r--r--src/readme.txt2
-rw-r--r--src/selftest.cpp21
6 files changed, 105 insertions, 30 deletions
diff --git a/README.md b/README.md
index 4843f5c..77227fa 100644
--- a/README.md
+++ b/README.md
@@ -355,7 +355,7 @@ Other options worth knowing:
355 355
356```bash 356```bash
357-datadir=PATH # wallet and chain data elsewhere 357-datadir=PATH # wallet and chain data elsewhere
358-testnet # isolated test network datadir, port 18433, and message magic 358-testnet # isolated test network genesis, datadir, port 18433, and magic
359-port=N # P2P listen port, default 8433; testnet default 18433 359-port=N # P2P listen port, default 8433; testnet default 18433
360-socks=HOST:PORT # SOCKS5 for outbound Nostr, .btf relay, and onion peer dials 360-socks=HOST:PORT # SOCKS5 for outbound Nostr, .btf relay, and onion peer dials
361-tor[=HOST:PORT] # Tor mode; default local Tor SOCKS5 proxy is 127.0.0.1:9050 361-tor[=HOST:PORT] # Tor mode; default local Tor SOCKS5 proxy is 127.0.0.1:9050
diff --git a/src/main.cpp b/src/main.cpp
index 6fd8c82..5d266ff 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -41,12 +41,30 @@ unsigned int nTransactionsUpdated = 0;
41map<COutPoint, CInPoint> mapNextTx; 41map<COutPoint, CInPoint> mapNextTx;
42 42
43map<uint256, CBlockIndex*> mapBlockIndex; 43map<uint256, CBlockIndex*> mapBlockIndex;
44// Bitflash genesis -- mined under RandomX PoW on 2026-07-22 44// Bitflash mainnet genesis -- mined under RandomX PoW for the 2026 stable
45// (nTime 1753142400, nBits 0x1f0fffff, RandomX key "Bitflash/RandomX/v1/...") 45// relaunch. Testnet gets its own resettable genesis below so block indexes,
46// Bitflash 2026 stable relaunch genesis (2-min blocks, RandomX). Mined values. 46// headers, and wallet scans cannot be accidentally mixed across networks.
47unsigned int GENESIS_NONCE = 3141; 47static const unsigned int MAINNET_GENESIS_TIME = 1753315200; // 2026-07-24 00:00:00 UTC
48uint256 hashGenesisBlock("0x5bd7cb255d814e48cebcdfb72da4dc87b34bd774227f8ceb546c5640f4bdc169"); 48static const unsigned int MAINNET_GENESIS_NONCE = 3141;
49uint256 hashGenesisMerkleRoot("0x1a45b4482532abb29b10e234d3f13132230525a339ecea91658ffa675a5b1325"); 49static const char* MAINNET_GENESIS_TIMESTAMP =
50 "Bitflash 24/Jul/2026 Fair launch: one CPU one vote, no premine";
51static const char* MAINNET_GENESIS_HASH =
52 "0x5bd7cb255d814e48cebcdfb72da4dc87b34bd774227f8ceb546c5640f4bdc169";
53static const char* MAINNET_GENESIS_MERKLE =
54 "0x1a45b4482532abb29b10e234d3f13132230525a339ecea91658ffa675a5b1325";
55
56static const unsigned int TESTNET_GENESIS_TIME = 1787184000; // 2026-08-20 00:00:00 UTC
57static const unsigned int TESTNET_GENESIS_NONCE = 3199;
58static const char* TESTNET_GENESIS_TIMESTAMP =
59 "Bitflash testnet 20/Aug/2026: resettable public test chain";
60static const char* TESTNET_GENESIS_HASH =
61 "0xa9d11c6d697bcb7aea0653bc088b12dcf9f44e732df205162cf085fd9d9963eb";
62static const char* TESTNET_GENESIS_MERKLE =
63 "0x510b293105e3ff85b8d4c3920e357f85d1a86bf199eb4e7d11f04f380030ec5c";
64
65unsigned int GENESIS_NONCE = MAINNET_GENESIS_NONCE;
66uint256 hashGenesisBlock(MAINNET_GENESIS_HASH);
67uint256 hashGenesisMerkleRoot(MAINNET_GENESIS_MERKLE);
50CBlockIndex* pindexGenesisBlock = NULL; 68CBlockIndex* pindexGenesisBlock = NULL;
51int nBestHeight = -1; 69int nBestHeight = -1;
52uint256 hashBestChain = 0; 70uint256 hashBestChain = 0;
@@ -117,6 +135,63 @@ static std::atomic<uint64> gParticipantHashRateX1000{0};
117static std::mutex gParticipantStatusMutex; 135static std::mutex gParticipantStatusMutex;
118static std::string gParticipantStatus; 136static std::string gParticipantStatus;
119 137
138void SelectGenesisParams(bool fTestNetIn)
139{
140 static bool fGenesisParamsSelected = false;
141 static bool fGenesisParamsTestNet = false;
142 if (fGenesisParamsSelected && fGenesisParamsTestNet == fTestNetIn)
143 return;
144
145 fGenesisParamsSelected = true;
146 fGenesisParamsTestNet = fTestNetIn;
147
148 if (fTestNetIn)
149 {
150 GENESIS_NONCE = TESTNET_GENESIS_NONCE;
151 hashGenesisBlock = uint256(TESTNET_GENESIS_HASH);
152 hashGenesisMerkleRoot = uint256(TESTNET_GENESIS_MERKLE);
153 }
154 else
155 {
156 GENESIS_NONCE = MAINNET_GENESIS_NONCE;
157 hashGenesisBlock = uint256(MAINNET_GENESIS_HASH);
158 hashGenesisMerkleRoot = uint256(MAINNET_GENESIS_MERKLE);
159 }
160}
161
162void SelectChainParams(bool fTestNetIn)
163{
164 SelectNetworkParams(fTestNetIn);
165 SelectGenesisParams(fTestNetIn);
166}
167
168static CBlock BuildGenesisBlock()
169{
170 const char* pszTimestamp = IsTestNet() ?
171 TESTNET_GENESIS_TIMESTAMP : MAINNET_GENESIS_TIMESTAMP;
172
173 CTransaction txNew;
174 txNew.vin.resize(1);
175 txNew.vout.resize(1);
176 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) <<
177 vector<unsigned char>((unsigned char*)pszTimestamp,
178 (unsigned char*)pszTimestamp + strlen(pszTimestamp));
179 txNew.vout[0].nValue = 50 * COIN;
180 txNew.vout[0].scriptPubKey = CScript() <<
181 CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") <<
182 OP_CHECKSIG;
183
184 CBlock block;
185 block.vtx.push_back(txNew);
186 block.hashPrevBlock = 0;
187 block.hashMerkleRoot = block.BuildMerkleTree();
188 block.nVersion = 1;
189 block.nTime = IsTestNet() ? TESTNET_GENESIS_TIME : MAINNET_GENESIS_TIME;
190 block.nBits = 0x1f0fffff; // = bnProofOfWorkLimit (Bitflash RandomX floor)
191 block.nNonce = GENESIS_NONCE;
192 return block;
193}
194
120void SetParticipantMiningStatus(const std::string& status) 195void SetParticipantMiningStatus(const std::string& status)
121{ 196{
122 // Updates the GUI status string only. Logging is done at each call site 197 // Updates the GUI status string only. Logging is done at each call site
@@ -2664,21 +2739,7 @@ bool LoadBlockIndex(bool fAllowNew)
2664 // vMerkleTree: 4a5e1e 2739 // vMerkleTree: 4a5e1e
2665 2740
2666 // Bitflash genesis block -- own header (fair launch, 2026 stable relaunch) 2741 // Bitflash genesis block -- own header (fair launch, 2026 stable relaunch)
2667 char* pszTimestamp = "Bitflash 24/Jul/2026 Fair launch: one CPU one vote, no premine"; 2742 CBlock block = BuildGenesisBlock();
2668 CTransaction txNew;
2669 txNew.vin.resize(1);
2670 txNew.vout.resize(1);
2671 txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((unsigned char*)pszTimestamp, (unsigned char*)pszTimestamp + strlen(pszTimestamp));
2672 txNew.vout[0].nValue = 50 * COIN;
2673 txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
2674 CBlock block;
2675 block.vtx.push_back(txNew);
2676 block.hashPrevBlock = 0;
2677 block.hashMerkleRoot = block.BuildMerkleTree();
2678 block.nVersion = 1;
2679 block.nTime = 1753315200; // 2026-07-24 00:00:00 UTC (stable relaunch)
2680 block.nBits = 0x1f0fffff; // = bnProofOfWorkLimit (Bitflash RandomX floor)
2681 block.nNonce = GENESIS_NONCE;
2682 2743
2683 // If the nonce has not been found yet, mine the genesis once (RandomX) 2744 // If the nonce has not been found yet, mine the genesis once (RandomX)
2684 // and print the values to be hardcoded in the constants above. 2745 // and print the values to be hardcoded in the constants above.
diff --git a/src/main.h b/src/main.h
index dc5527e..793c4e8 100644
--- a/src/main.h
+++ b/src/main.h
@@ -59,6 +59,8 @@ extern map<uint256, CBlockIndex*> mapBlockIndex;
59extern uint256 hashGenesisBlock; 59extern uint256 hashGenesisBlock;
60extern uint256 hashGenesisMerkleRoot; 60extern uint256 hashGenesisMerkleRoot;
61extern unsigned int GENESIS_NONCE; 61extern unsigned int GENESIS_NONCE;
62void SelectGenesisParams(bool fTestNetIn);
63void SelectChainParams(bool fTestNetIn);
62extern CBlockIndex* pindexGenesisBlock; 64extern CBlockIndex* pindexGenesisBlock;
63extern int nBestHeight; 65extern int nBestHeight;
64extern uint256 hashBestChain; 66extern uint256 hashBestChain;
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 0a961bf..9f0fec0 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -143,7 +143,7 @@ static void PrintUsage()
143 printf(" /onionservice=HOST.onion:PORT (advertise this node's Tor hidden service)\n"); 143 printf(" /onionservice=HOST.onion:PORT (advertise this node's Tor hidden service)\n");
144 printf("\n"); 144 printf("\n");
145 printf("Network:\n"); 145 printf("Network:\n");
146 printf(" /testnet (isolated test network datadir, port, and magic)\n"); 146 printf(" /testnet (isolated test network genesis, datadir, port, and magic)\n");
147 printf(" /port=N (P2P listen port, default 8433; testnet 18433)\n"); 147 printf(" /port=N (P2P listen port, default 8433; testnet 18433)\n");
148 printf(" /socks=HOST:PORT (SOCKS5 proxy for Nostr, .btf relay, and onion dials)\n"); 148 printf(" /socks=HOST:PORT (SOCKS5 proxy for Nostr, .btf relay, and onion dials)\n");
149 printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n"); 149 printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n");
@@ -206,7 +206,8 @@ static void ParseStartupArguments(int argc, char* argv[])
206 if (arg(argc,argv,"/datadir") || arg(argc,argv,"-datadir")) 206 if (arg(argc,argv,"/datadir") || arg(argc,argv,"-datadir"))
207 strSetDataDir = argval2(argc, argv, "/datadir", "-datadir"); 207 strSetDataDir = argval2(argc, argv, "/datadir", "-datadir");
208 208
209 SelectNetworkParams(arg(argc, argv, "/testnet") || arg(argc, argv, "-testnet")); 209 bool fUseTestNet = arg(argc, argv, "/testnet") || arg(argc, argv, "-testnet");
210 SelectChainParams(fUseTestNet);
210 211
211 if (arg(argc,argv,"/debug") || arg(argc,argv,"-debug")) 212 if (arg(argc,argv,"/debug") || arg(argc,argv,"-debug"))
212 fDebug = true; 213 fDebug = true;
diff --git a/src/readme.txt b/src/readme.txt
index 5d62791..810e8b7 100644
--- a/src/readme.txt
+++ b/src/readme.txt
@@ -41,7 +41,7 @@ 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 /testnet use isolated test network datadir, port 18433, and message magic 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 /port=N listen on P2P port N (default 8433; testnet default 18433)
46 /socks=HOST:PORT 46 /socks=HOST:PORT
47 route outbound Nostr, .btf rendezvous, and direct onion peer 47 route outbound Nostr, .btf rendezvous, and direct onion peer
diff --git a/src/selftest.cpp b/src/selftest.cpp
index 30bd28e..1a72e3a 100644
--- a/src/selftest.cpp
+++ b/src/selftest.cpp
@@ -3085,7 +3085,7 @@ static int RunNetworkParamsSelfTest()
3085 std::string strOldDataDir = strSetDataDir; 3085 std::string strOldDataDir = strSetDataDir;
3086 try 3086 try
3087 { 3087 {
3088 SelectNetworkParams(false); 3088 SelectChainParams(false);
3089 nFail += Check(!IsTestNet(), "starts on mainnet after explicit selection") ? 0 : 1; 3089 nFail += Check(!IsTestNet(), "starts on mainnet after explicit selection") ? 0 : 1;
3090 nFail += Check(ntohs(GetDefaultPort()) == MAINNET_PORT, 3090 nFail += Check(ntohs(GetDefaultPort()) == MAINNET_PORT,
3091 "mainnet default P2P port is 8433") ? 0 : 1; 3091 "mainnet default P2P port is 8433") ? 0 : 1;
@@ -3095,8 +3095,11 @@ static int RunNetworkParamsSelfTest()
3095 CMessageHeader mainHeader("ping", 0); 3095 CMessageHeader mainHeader("ping", 0);
3096 char mainMagic[4]; 3096 char mainMagic[4];
3097 memcpy(mainMagic, mainHeader.pchMessageStart, sizeof(mainMagic)); 3097 memcpy(mainMagic, mainHeader.pchMessageStart, sizeof(mainMagic));
3098 uint256 mainGenesis = hashGenesisBlock;
3099 uint256 mainMerkle = hashGenesisMerkleRoot;
3100 unsigned int mainNonce = GENESIS_NONCE;
3098 3101
3099 SelectNetworkParams(true); 3102 SelectChainParams(true);
3100 nFail += Check(IsTestNet(), "testnet selection is sticky") ? 0 : 1; 3103 nFail += Check(IsTestNet(), "testnet selection is sticky") ? 0 : 1;
3101 nFail += Check(ntohs(GetDefaultPort()) == TESTNET_PORT, 3104 nFail += Check(ntohs(GetDefaultPort()) == TESTNET_PORT,
3102 "testnet default P2P port is 18433") ? 0 : 1; 3105 "testnet default P2P port is 18433") ? 0 : 1;
@@ -3106,6 +3109,14 @@ static int RunNetworkParamsSelfTest()
3106 CMessageHeader testHeader("ping", 0); 3109 CMessageHeader testHeader("ping", 0);
3107 nFail += Check(memcmp(mainMagic, testHeader.pchMessageStart, sizeof(mainMagic)) != 0, 3110 nFail += Check(memcmp(mainMagic, testHeader.pchMessageStart, sizeof(mainMagic)) != 0,
3108 "testnet message magic differs from mainnet") ? 0 : 1; 3111 "testnet message magic differs from mainnet") ? 0 : 1;
3112 nFail += Check(hashGenesisBlock != mainGenesis &&
3113 hashGenesisMerkleRoot != mainMerkle &&
3114 GENESIS_NONCE != mainNonce,
3115 "testnet genesis constants differ from mainnet") ? 0 : 1;
3116 nFail += Check(hashGenesisBlock == uint256("0xa9d11c6d697bcb7aea0653bc088b12dcf9f44e732df205162cf085fd9d9963eb") &&
3117 hashGenesisMerkleRoot == uint256("0x510b293105e3ff85b8d4c3920e357f85d1a86bf199eb4e7d11f04f380030ec5c") &&
3118 GENESIS_NONCE == 3199,
3119 "testnet genesis constants are pinned") ? 0 : 1;
3109 3120
3110 std::string tmp; 3121 std::string tmp;
3111 if (!MakeTempDir(tmp)) 3122 if (!MakeTempDir(tmp))
@@ -3115,9 +3126,9 @@ static int RunNetworkParamsSelfTest()
3115 else 3126 else
3116 { 3127 {
3117 strSetDataDir = tmp; 3128 strSetDataDir = tmp;
3118 SelectNetworkParams(false); 3129 SelectChainParams(false);
3119 std::string mainDir = GetAppDir(); 3130 std::string mainDir = GetAppDir();
3120 SelectNetworkParams(true); 3131 SelectChainParams(true);
3121 std::string testDir = GetAppDir(); 3132 std::string testDir = GetAppDir();
3122 nFail += Check(mainDir == tmp, 3133 nFail += Check(mainDir == tmp,
3123 "mainnet uses the selected data directory") ? 0 : 1; 3134 "mainnet uses the selected data directory") ? 0 : 1;
@@ -3138,7 +3149,7 @@ static int RunNetworkParamsSelfTest()
3138 } 3149 }
3139 3150
3140 strSetDataDir = strOldDataDir; 3151 strSetDataDir = strOldDataDir;
3141 SelectNetworkParams(false); 3152 SelectChainParams(false);
3142 3153
3143 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", 3154 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
3144 nFail, nFail == 1 ? "" : "s"); 3155 nFail, nFail == 1 ? "" : "s");