Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/impl/btc/auto_ratchet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,16 @@ class AutoRatchet
if (static_cast<int64_t>(ver) >= target_version_)
tail_target = tail_target + w;
}
// Canonical: counts.get(VERSION,0) < sum(counts)*60//100
bool tail_ok = !(tail_target * uint32_t(100) < tail_total * uint32_t(SWITCH_THRESHOLD));
// Canonical FLOOR (p2pool data.py share-acceptance):
// valid iff target >= floor(total * SWITCH_THRESHOLD / 100)
// i.e. counts.get(VERSION,0) >= sum(counts)*60//100.
// The prior cross-multiplied form (target*100 >= total*60) is the
// algebraic CEIL: at a non-integral boundary (total*60 % 100 != 0)
// it latched up to one work-unit LATER than the network oracle.
// Adopting FLOOR removes that c2pool-only late-latch divergence so
// our accept gate is byte-identical to every p2pool peer's.
bool tail_ok = !(tail_target <
(tail_total * uint32_t(SWITCH_THRESHOLD)) / uint32_t(100));

if (!tail_ok) {
static int tail_log = 0;
Expand Down
49 changes: 45 additions & 4 deletions src/impl/btc/test/auto_ratchet_sim_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ using btc::RatchetState;
namespace {

// Verbatim replica of the LIVE inline tail-guard in
// AutoRatchet::get_share_version: tail_ok = !(target*100 < total*SWITCH).
// AutoRatchet::get_share_version: tail_ok = !(target < total*SWITCH/100).
// Localises the 60%-by-WORK accept gate so C3 pins it WITHOUT driving the
// consensus path or importing a lifted SSOT.
// consensus path or importing a lifted SSOT. FLOOR form, tracking the SSOT
// step-2 adoption (was the algebraic CEIL target*100 < total*SWITCH).
bool inline_tail_ok(const uint288& target, const uint288& total,
int thr = AutoRatchet::SWITCH_THRESHOLD)
{
return !((target * static_cast<uint32_t>(100)) <
(total * static_cast<uint32_t>(thr)));
return !(target < (total * static_cast<uint32_t>(thr))
/ static_cast<uint32_t>(100));
}

// 95%-by-COUNT activation predicate (flat head-count), mirroring the VOTING ->
Expand Down Expand Up @@ -193,3 +194,43 @@ TEST(BTC_AutoRatchetSim, C4_StatePersistsAcrossRestart)
EXPECT_EQ(vote, 36);
std::remove(path.c_str());
}

// ---------------------------------------------------------------------------
// SSOT step-2 / #1 standardization target — ORACLE FLOOR vs INLINE CEIL.
//
// p2pool oracle (data.py share-acceptance) valid threshold is the FLOOR form:
// counts.get(VERSION,0) >= sum(counts)*60//100 # floor
// The BTC inline tail-guard (auto_ratchet.hpp, replicated as inline_tail_ok
// above) has ADOPTED that FLOOR form. Previously it was the algebraic CEIL
// target*100 >= total*60 <=> target >= ceil(total*60/100),
// which at a non-integral boundary (total*60 % 100 != 0) latched up to one
// share LATER than the oracle. This KAT now PINS the CONVERGED state: at the
// same non-integral boundary (total=101 => total*60 = 6060, 6060 % 100 != 0)
// floor(6060/100) = 60 (oracle : target=60 PASSES)
// inline (FLOOR) = 60 (adopted : target=60 PASSES) <-- seam CLOSED
// Pre-adoption this line read EXPECT_FALSE on the inline form (CEIL held until
// 61); the SSOT floor adoption (operator-tap gated) flips it to EXPECT_TRUE.
// The integral control (total=100) still shows both forms AGREE on the exact
// boundary, so the only behavioural change is the %100 remainder share, now
// accepted one unit earlier in lock-step with the network. Consensus surface
// equals the p2pool oracle EXACTLY.
// ---------------------------------------------------------------------------
TEST(BTC_AutoRatchetSim, SSOT2_OracleFloorVsInlineCeilBoundary)
{
// Oracle floor predicate: target >= floor(total*60/100).
auto oracle_floor_ok = [](const uint288& target, const uint288& total) {
return !(target < ((total * static_cast<uint32_t>(60))
/ static_cast<uint32_t>(100)));
};

// Integral-boundary control (total=100): floor==ceil==60, forms AGREE.
EXPECT_EQ(oracle_floor_ok(uint288(60), uint288(100)),
inline_tail_ok (uint288(60), uint288(100)));

const uint288 total(101); // 101*60 = 6060, %100 = 60
EXPECT_TRUE (oracle_floor_ok(uint288(60), total)); // oracle: latches at 60
EXPECT_TRUE (inline_tail_ok (uint288(60), total)); // inline FLOOR: latches at 60 too
// Forms are now identical at every point (boundary and beyond).
EXPECT_TRUE (oracle_floor_ok(uint288(61), total));
EXPECT_TRUE (inline_tail_ok (uint288(61), total));
}
Loading