Commit b5812f8
Dashboard Serving/Asset index rows, getnodestats RPC, FIX RPC actually listens (win.31)
Three features plus a discovery of a massive pre-existing bug.
FEATURES
- Part A: new "Serving:" dashboard row polls IPFS bitswap stats every 30s
(POST /api/v0/stats/bitswap) and displays BlocksSent total, rate per minute,
and DataSent as a human-readable byte count. Proves to the operator that
their node is actually serving content out to IPFS peers instead of just
pinning it. Wired through a new NodeStats singleton so the getnodestats
RPC method can report the same numbers without doing its own HTTP call.
- Part B: new "Asset index:" dashboard row cross-checks the local assets
table against mctrivia's /permanent/<page>.json list (every asset
mctrivia's permanent storage pool tracks). Reports local count + tracked
count + coverage percentage. A 100% result is strong evidence the chain
analyzer is not missing any issuances, because PSP-enrolled and
non-PSP-enrolled assets go through the same parse path. Missing assetIds
are logged at WARNING level so they're visible without flipping to DEBUG.
- Part C: new getnodestats RPC method returns a snapshot of buildVersion,
syncHeight, assetCount, bitswap stats, and permanent-list coverage as
JSON. Intended for two-node side-by-side comparison:
DigiAssetCore-cli.exe getnodestats
Run it on two nodes; if assetCount differs at the same syncHeight, one
chain analyzer has a bug.
- Expanded [H] info key: pressing H now prints a multi-section plain-English
explanation of every dashboard row, what the numbers mean, and what the
node is doing. Readable by a first-time operator with no DigiAsset
background.
FIX: RPC server actually listens now. The big one.
src/boost/asio.hpp in this fork was a hand-written NO-OP STUB that
silently emulated boost::asio's API with empty implementations:
class acceptor {
void open(int) {}
void set_option(const reuse_address&) {}
void bind(const endpoint&) {}
void listen() {}
void accept(socket&) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
};
Because <boost/asio.hpp> at src/ was shadowed by this stub (src/ is on
the include path), RPC::Server compiled against it. Every bind/listen/
accept call was a no-op. The "RPC Server listening on port 14024" log
line was logged after the no-op listen() returned. The "RPC call # received"
DEBUG lines we had been staring at for hours were the stub's accept() loop
spinning once per second, NOT real inbound connections. netstat never
showed port 14024 bound because no socket was ever created.
DigiAssetCore-cli.exe has never worked on this Windows fork for any RPC
command. Not version, not getblockcount, not listassets, nothing. It
always failed with a libcurl-like error because there was no server.
Upstream CMakeLists.txt explicitly hacked around this for WebServer.cpp
with a per-source COMPILE_FLAGS /I to the real boost path, acknowledging
that "WebServer.cpp needs real Boost Beast headers (not the stub in
src/boost/)" -- but nothing else got the fix.
The fix, minimal but enough:
- include_directories(BEFORE ...) in src/CMakeLists.txt puts the real
boost 1.82 at packages/boost.1.82.0/lib/native/include AT THE FRONT of
the include path, so <boost/asio.hpp> resolves to the real header for
every source file globally. The stub at src/boost/asio.hpp becomes dead.
- RPC/Server.h and RPC/Server.cpp switch from <boost/asio.hpp> to the
specific sub-headers <boost/asio/io_context.hpp>, <boost/asio/ip/tcp.hpp>,
<boost/asio/executor_work_guard.hpp>, <boost/asio/post.hpp>, and
<boost/asio/write.hpp>. Sub-headers aren't shadowed by the stub so this
also works independently.
- cli/main.cpp drops its unused #include "RPC/Server.h" so the cli build
doesn't need real boost headers at all.
With real boost in the build, two latent bugs in Server::Server surfaced
and needed fixing to compile:
- _workGuard must be a MEMBER of Server, not a local in the ctor body.
Previously it was `auto work = boost::asio::make_work_guard(_io);` which
went out of scope the moment the ctor returned, leaving _io with no
outstanding work and the 16 thread-pool threads exiting immediately.
(This was invisible against the stub because the stub's run() was a
no-op anyway; against real boost the thread pool would have been empty
for the entire lifetime of Server.) Now a member initialized in the
init list.
- _acceptor must be initialized with an executor in the init list. Real
boost::asio::basic_socket_acceptor has no default constructor.
Plus defensive improvements in case accept() ever does exit in the
future:
- Server::start() now logs CRITICAL and calls
AppMain::GetInstance()->setRpcServer(nullptr) when accept() returns,
so the dashboard's RPC probe reflects reality instead of a dangling
raw pointer from a destroyed Server object.
- DigiByteCore::makeConnection() optionally prints the RPC URL to stderr
when DGBCORE_DEBUG_URL=1 is set, for debugging cases where libcurl
reports "couldn't resolve host" but the URL is valid.
- ConsoleDashboard's spawn-race guard for the bitswap poll and the
coverage scan no longer ORs against _probed / _checked. The
_lastBitswapPoll / _lastCoverageCheck fields are epoch-initialized, so
the first render fires immediately because `elapsed > threshold` is
trivially true, and subsequent renders skip until the next interval
elapses. Previously the `|| !_bitswapProbed` fallback caused every
render during the first probe's in-flight window (~500ms) to spawn a
duplicate probe thread.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 7d2812d commit b5812f8
13 files changed
Lines changed: 704 additions & 24 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
| 43 | + | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
68 | 77 | | |
69 | 78 | | |
70 | 79 | | |
| |||
105 | 114 | | |
106 | 115 | | |
107 | 116 | | |
| 117 | + | |
108 | 118 | | |
109 | 119 | | |
110 | 120 | | |
| |||
148 | 158 | | |
149 | 159 | | |
150 | 160 | | |
| 161 | + | |
151 | 162 | | |
152 | 163 | | |
153 | 164 | | |
| |||
168 | 179 | | |
169 | 180 | | |
170 | 181 | | |
171 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
172 | 186 | | |
173 | | - | |
| 187 | + | |
174 | 188 | | |
175 | 189 | | |
176 | 190 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 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 | + | |
86 | 113 | | |
87 | 114 | | |
88 | 115 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
93 | | - | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
94 | 99 | | |
95 | 100 | | |
96 | 101 | | |
97 | | - | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
98 | 112 | | |
99 | 113 | | |
100 | 114 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
29 | 30 | | |
30 | 31 | | |
31 | 32 | | |
| |||
0 commit comments