1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
// Copyright (c) 2026 Bitflash developers
// Distributed under the MIT/X11 software license.
//
// Headless entry point for the Linux node/miner `bitflash-node`. Replaces the
// wxWidgets GUI (ui.cpp) with a command-line daemon: it loads the chain and
// wallet, starts the P2P/Nostr node (which auto-discovers .btf peers through
// the rendezvous relay), and optionally mines with RandomX. No GUI, no wx.
//
// ./bitflash-node -gen mine with the CPU, auto-connect peers
// ./bitflash-node -gen -datadir=/path use a specific data directory
// ./bitflash-node -rvrelay=host:port use a specific rendezvous relay
// ./bitflash-node -connectbtf=<addr>.btf pin a specific peer
// ./bitflash-node -solomine -gen mine without waiting for a peer (test)
#include "headers.h"
#include <csignal>
// ---- UI hooks the core references, provided here as headless equivalents ----
// The core asks the GUI to repaint on new blocks/transactions; nothing to do.
void MainFrameRepaint() {}
// Wallet address book -- defined in ui.cpp on Windows; the core (db.cpp) reads
// and writes it, so the headless build must provide the definition.
map<string, string> mapAddressBook;
// Format a unix timestamp for transaction listings (ui.cpp used wxDateTime).
string DateTimeStr(int64 nTime)
{
time_t t = (time_t)nTime;
struct tm* ptm = localtime(&t);
if (!ptm)
return "";
char buf[64];
strftime(buf, sizeof(buf), "%m/%d/%y %H:%M", ptm);
return string(buf);
}
// ---- argument parsing (mirrors ui.cpp's ParseParameters) ----
static map<string, string> ParseParameters(int argc, char* argv[])
{
map<string, string> mapArgs;
for (int i = 0; i < argc; i++)
{
string s = argv[i];
string val;
size_t eq = s.find('=');
if (eq != string::npos)
{
val = s.substr(eq + 1);
s = s.substr(0, eq);
}
for (size_t j = 0; j < s.size(); j++)
s[j] = (char)tolower((unsigned char)s[j]);
if (!s.empty() && s[0] == '-')
s[0] = '/';
mapArgs[s] = val;
}
return mapArgs;
}
static void HandleSignal(int)
{
fShutdown = true;
}
int main(int argc, char* argv[])
{
map<string, string> mapArgs = ParseParameters(argc, argv);
if (mapArgs.count("/?") || mapArgs.count("/help") || mapArgs.count("/h"))
{
fprintf(stderr,
"Bitflash headless node\n"
"Usage: %s [options]\n"
" -gen generate coins (mine with RandomX)\n"
" -datadir=<dir> data directory (default ~/.bitflash)\n"
" -port=<n> P2P listen port (default 8433)\n"
" -rvrelay=host:port rendezvous meeting relay (has a seed default)\n"
" -connectbtf=<a>.btf keep a connection to a specific .btf peer\n"
" -solomine mine without waiting for a peer (testing)\n"
" -debug verbose logging\n",
argv[0]);
return 0;
}
// Parameters (same set the Windows UI honors)
if (mapArgs.count("/datadir"))
strSetDataDir = mapArgs["/datadir"];
if (mapArgs.count("/port"))
nListenPort = htons(atoi(mapArgs["/port"].c_str()));
if (mapArgs.count("/proxy"))
addrProxy = CAddress(mapArgs["/proxy"].c_str());
if (mapArgs.count("/rvrelay"))
strBtfMeetingRelay = mapArgs["/rvrelay"];
if (mapArgs.count("/connectbtf"))
strBtfConnect = mapArgs["/connectbtf"];
if (mapArgs.count("/debug"))
fDebug = true;
if (mapArgs.count("/solomine"))
fSoloMineTest = true;
if (mapArgs.count("/gen"))
fGenerateBitcoins = mapArgs["/gen"].empty() ? true : atoi(mapArgs["/gen"].c_str());
printf("\nBitflash headless node starting\n");
//
// Load data files (mirror of the Windows OnInit2 startup)
//
printf("Loading addresses...\n");
if (!LoadAddresses())
printf("Error loading addr.dat\n");
printf("Loading block index...\n");
if (!LoadBlockIndex())
{
printf("Error loading blkindex.dat\n");
return 1;
}
printf("Loading wallet...\n");
if (!LoadWallet())
{
printf("Error loading wallet.dat\n");
return 1;
}
printf("Done loading. nBestHeight=%d, wallet keys=%d\n",
nBestHeight, (int)mapKeys.size());
// Rebroadcast any wallet transactions not yet in a block
ReacceptWalletTransactions();
//
// Start the node (P2P + Nostr discovery + .btf rendezvous)
//
string strErrors;
if (!StartNode(strErrors))
{
printf("StartNode failed: %s\n", strErrors.c_str());
return 1;
}
//
// Start mining if requested
//
if (fGenerateBitcoins)
{
if (_beginthread(ThreadBitcoinMiner, 0, NULL) == (uintptr_t)-1)
printf("Error: _beginthread(ThreadBitcoinMiner) failed\n");
else
printf("Mining enabled (RandomX, CPU)\n");
}
else
{
printf("Mining disabled (pass -gen to mine)\n");
}
//
// Run until interrupted
//
signal(SIGINT, HandleSignal);
signal(SIGTERM, HandleSignal);
printf("Bitflash node running. Press Ctrl-C to stop.\n");
while (!fShutdown)
Sleep(500);
printf("Shutting down...\n");
StopNode();
Sleep(500);
printf("Bitflash node stopped.\n");
return 0;
}
|