Skip to content

Commit e392b46

Browse files
authored
test(web): pin charter-#3 ratchet honesty in regression KAT (SAFE-ADDITIVE) (#518)
currency_info.share_version must track the LIVE ratchet (m_cached_share_version), never a static 36 (#491): a VOTING LTC node on V35 reporting 36 makes the sharechain-explorer misclassify live V35 cells as V36. Dash stays static v16 (LTC AutoRatchet cache must not bleed into a Dash dashboard). v36_status.auto_ratchet.v36_active must derive from the live latch (m_cached_share_version >= 36), not a frozen stub (#499), so a transient sampling dip cannot misreport the V35->V36 crossing state. Test-only, no runtime change. 13/13 green. Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
1 parent 21f4c82 commit e392b46

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

test/test_web_honesty_regression.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,75 @@ TEST(WebHonestyRegression, StratumSecuritySignalsNotInstrumentedNotFakeGreen) {
244244
EXPECT_FALSE(r.contains("blacklisted_ips"));
245245
EXPECT_FALSE(r.contains("threat_level"));
246246
}
247+
248+
// --- charter #3: ratchet / crossing-state honesty ----------------------------
249+
// The dashboard must tell the truth about the V35->V36 cross. Two founding-class
250+
// lies are pinned here:
251+
// (a) currency_info.share_version was hardcoded 36 -- a node still VOTING
252+
// (producing V35 shares) would report 36, making the bundled sharechain-
253+
// explorer misclassify live V35 share cells as V36 (#491).
254+
// (b) v36_status.auto_ratchet.v36_active was a frozen stub -- it must derive
255+
// from the LIVE ratchet latch (m_cached_share_version) so a node that has
256+
// latched to V36 cannot be shown as still "voting", nor vice-versa (#499).
257+
// Both are the same class of lie as the founding 0-stubs: the dashboard claiming
258+
// one thing while the node is actually doing another, during the very crossing
259+
// the operator is coordinating live on LTC prod.
260+
261+
// (a) currency_info.share_version reflects the LIVE ratchet output, never a
262+
// static 36: a VOTING LTC node still mining V35 must report 35.
263+
TEST(WebHonestyRegression, CurrencyInfoShareVersionIsLiveRatchetNotStatic36) {
264+
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::LITECOIN);
265+
266+
mi.set_cached_share_version(35); // node still VOTING -- producing V35 shares
267+
json r = mi.rest_web_currency_info();
268+
EXPECT_EQ(r["share_version"].get<int64_t>(), 35)
269+
<< "share_version must track m_cached_share_version (live ratchet), never "
270+
"a hardcoded 36 -- reporting 36 while VOTING lies about the cross";
271+
}
272+
273+
// currency_info.share_version follows the latch forward once the node crosses.
274+
TEST(WebHonestyRegression, CurrencyInfoShareVersionFollowsLatchToV36) {
275+
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::LITECOIN);
276+
277+
mi.set_cached_share_version(36); // node has latched to V36
278+
json r = mi.rest_web_currency_info();
279+
EXPECT_EQ(r["share_version"].get<int64_t>(), 36)
280+
<< "share_version must follow the live latch to 36 once crossed";
281+
}
282+
283+
// DASH is non-ratcheting on the LTC AutoRatchet path: its share_version stays
284+
// the static protocol v16 even if the cached ratchet value is something else --
285+
// the LTC ratchet cache must never bleed into a Dash dashboard.
286+
TEST(WebHonestyRegression, CurrencyInfoDashShareVersionStaysStatic16) {
287+
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::DASH);
288+
289+
mi.set_cached_share_version(35); // would be a lie to surface on Dash
290+
json r = mi.rest_web_currency_info();
291+
EXPECT_EQ(r["share_version"].get<int64_t>(), 16)
292+
<< "Dash share_version is the static protocol v16, not the LTC ratchet cache";
293+
}
294+
295+
// (b) v36_status.auto_ratchet.v36_active is derived from the LIVE latch
296+
// (m_cached_share_version >= 36), not a frozen stub. With no sharechain stats
297+
// wired, version_signaling returns {} and the chain-derived branch is skipped --
298+
// isolating the latch derivation, which is exactly what #499 surfaces as ground
299+
// truth so a transient sampling dip cannot misreport the crossing state.
300+
TEST(WebHonestyRegression, V36StatusActiveLatchTracksLiveShareVersion) {
301+
MiningInterface mi(/*testnet=*/true, /*node=*/nullptr, Blockchain::LITECOIN);
302+
303+
// Pre-cross: still on V35.
304+
mi.set_cached_share_version(35);
305+
json voting = mi.rest_v36_status();
306+
ASSERT_TRUE(voting.contains("auto_ratchet"));
307+
EXPECT_EQ(voting["auto_ratchet"]["live_share_version"].get<int64_t>(), 35);
308+
EXPECT_FALSE(voting["auto_ratchet"]["v36_active"].get<bool>())
309+
<< "v36_active must be false while the live latch is still V35";
310+
311+
// Post-cross: latched to V36.
312+
mi.set_cached_share_version(36);
313+
json active = mi.rest_v36_status();
314+
ASSERT_TRUE(active.contains("auto_ratchet"));
315+
EXPECT_EQ(active["auto_ratchet"]["live_share_version"].get<int64_t>(), 36);
316+
EXPECT_TRUE(active["auto_ratchet"]["v36_active"].get<bool>())
317+
<< "v36_active must latch true once the live ratchet reaches V36";
318+
}

0 commit comments

Comments
 (0)