Skip to content

Commit f7e0e1f

Browse files
authored
Merge pull request #608 from frstrtr/dashboard/v36-status-desired-version-tally
core(web): re-source /v36_status crossing counter from desired-version tally (not format flag)
2 parents 2cedd38 + 5863cf9 commit f7e0e1f

2 files changed

Lines changed: 63 additions & 2 deletions

File tree

src/core/web_server.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6158,9 +6158,22 @@ nlohmann::json MiningInterface::rest_v36_status()
61586158
};
61596159

61606160
int sample_size = vs.value("overall_total", 0);
6161-
int v36_shares = vs.value("overall_v36_shares", 0);
6161+
// Crossing counter must reflect the DESIRED-version tally the AutoRatchet
6162+
// keys on (get_desired_version_weights), NOT the per-share FORMAT flag.
6163+
// p2p-received shares relayed from the V35 seed carry format V35 even while
6164+
// their miners are voting V36, so overall_v36_shares (a format-flag count)
6165+
// stays 0 straight through a real crossing -- the founding-charter class of
6166+
// lie, here in the very fields the operator curls to watch the ratchet.
6167+
// Re-source from the desired-version data (the same swap #288 made for the
6168+
// ratchet mint gate): the headline percentage is the work-weighted sampling
6169+
// signal -- the exact "N% old version" figure the journal logs and the
6170+
// integrator reads to fire the crossing-event ping -- and the counts are the
6171+
// flat desired-version vote counts over the chain. Both climb with the cross;
6172+
// neither is the format-flag stub. (overall_v36_shares stays available on the
6173+
// parent version_signaling object for anyone who wants the format breakdown.)
6174+
int v36_shares = vs.value("overall_v36_votes", 0);
61626175
int v35_shares = std::max(0, sample_size - v36_shares);
6163-
double v36_pct = vs.value("overall_v36_share_pct", 0.0);
6176+
double v36_pct = vs.value("sampling_signaling", 0.0);
61646177

61656178
int height = 0;
61666179
if (m_sharechain_stats_fn) {

test/test_web_honesty_regression.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,54 @@ TEST(WebHonestyRegression, V36StatusActiveLatchTracksLiveShareVersion) {
317317
<< "v36_active must latch true once the live ratchet reaches V36";
318318
}
319319

320+
// (c) v36_status.share_chain.{v35_shares,v36_shares,v36_percentage} must reflect
321+
// the DESIRED-version tally the AutoRatchet keys on (get_desired_version_weights),
322+
// NOT the per-share FORMAT flag. During the graded g2 ratchet the .157 seed relays
323+
// V35-FORMAT shares over p2p even while their miners vote V36, so a format-flag
324+
// count reads 0 v36 straight through a real crossing -- the founding 0-stub class
325+
// of lie, in the exact fields the operator curls to watch the vote climb. This pins
326+
// the #288-style swap: build a sharechain-stats snapshot whose FORMAT is 100% V35
327+
// yet whose DESIRED-version tally is ~33% V36 (one rig flipped), and assert the
328+
// crossing counter tracks the vote, never the frozen format zero.
329+
TEST(WebHonestyRegression, V36StatusShareChainTracksDesiredVersionNotFormatFlag) {
330+
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::LITECOIN);
331+
332+
// Snapshot mirroring rig #1 (.37) flipped to V36 while .38/.39 stay V35 and the
333+
// seed relays V35-format shares: FORMAT all V35, DESIRED-version ~1/3 V36, and a
334+
// work-weighted sampling signal of ~33.33%.
335+
mi.set_sharechain_stats_fn([]() {
336+
nlohmann::json sc = nlohmann::json::object();
337+
sc["total_shares"] = 400;
338+
sc["chain_height"] = 400;
339+
sc["chain_length"] = 400;
340+
sc["shares_by_version"] = {{"35", 400}}; // FORMAT: 100% V35
341+
sc["shares_by_desired_version"] = {{"35", 268}, {"36", 132}}; // VOTE: 132/400 = 33%
342+
sc["sampling_desired_version"] = {{"35", 2.0}, {"36", 1.0}}; // work-weighted: 33.33%
343+
return sc;
344+
});
345+
346+
nlohmann::json v = mi.rest_v36_status();
347+
ASSERT_TRUE(v.contains("share_chain"));
348+
const auto& scj = v["share_chain"];
349+
350+
// The format-flag count IS zero here -- that is the pre-fix stub value the
351+
// crossing counter used to echo. Pin it on the parent version_signaling object
352+
// (its true source) so a refactor that reverts share_chain to the format tally
353+
// is caught: the bug is real precisely because format says 0 while vote says 33.
354+
nlohmann::json sig = mi.rest_version_signaling();
355+
EXPECT_EQ(sig.value("overall_v36_shares", -1), 0)
356+
<< "guard: this snapshot is the crossing where FORMAT is still 100% V35";
357+
358+
EXPECT_EQ(scj["v36_shares"].get<int>(), 132)
359+
<< "v36_shares must be the desired-version vote count (132), not the "
360+
"format-flag count (0) that lies through the crossing";
361+
EXPECT_EQ(scj["v35_shares"].get<int>(), 268)
362+
<< "v35_shares is the desired-version remainder (400-132), not 400";
363+
EXPECT_NEAR(scj["v36_percentage"].get<double>(), 33.33, 0.01)
364+
<< "v36_percentage must be the work-weighted sampling signal (the journal "
365+
"N% old version complement the integrator reads), never 0";
366+
}
367+
320368
// --- charter #3: crossing-banner coin coverage (de-allowlist, #496) ----------
321369
// The V35->V36 crossing banner must surface on EVERY v36-ratcheting coin, not
322370
// just LTC/DOGE. Before #496 a hardcoded {LITECOIN,DOGECOIN} allowlist gated

0 commit comments

Comments
 (0)