Skip to content

btc: couple AutoRatchet mint gate to the work-weighted accept gate - #290

Merged
frstrtr merged 2 commits into
masterfrom
btc/ratchet-mint-accept-coupling
Jun 21, 2026
Merged

btc: couple AutoRatchet mint gate to the work-weighted accept gate#290
frstrtr merged 2 commits into
masterfrom
btc/ratchet-mint-accept-coupling

Conversation

@frstrtr

@frstrtr frstrtr commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Mirrors the LTC AutoRatchet mint<->accept coupling fix (ltc-doge/ratchet-mint-accept-coupling @865fdd78) onto the BTC SHA256d lane. Per-coin isolation: touches only src/impl/btc/.

Root cause (shared latent wedge): AutoRatchet activated on a 95%-by-flat-COUNT desired-version tally, but the consensus accept gate admits a V36 boundary share only at 60% by WORK over [9/10*CL, CL] (canonical get_desired_version_counts is work-weighted despite the name). Under heterogeneous hashrate the flat count outran the work-weighted accept gate -> minted boundary shares every peer rejects -> frozen crossing. btc/auto_ratchet.hpp carried the byte-identical flat-count guard.

Change:

  • btc/auto_ratchet.hpp — tail guard swapped from get_desired_version_counts to a work-weighted tally over the same window/threshold the accept gate enforces; activation now strictly implies the accept rule.
  • btc/share_tracker.hpp — ports get_desired_version_weights (BTC tracker previously had only the counts variant), work-weighted via get_index()->work, mirroring the ltc/dgb tracker shape.

v36-native standardization: consensus version-signaling — bucket 2 (standardize cross-coin toward the v37 shape).

HOLD MERGE. Gated on BTC crossing re-soak (green) before any cutover. Consensus-version-signaling merge stays operator-tap-gated; integrator surfaces post-soak.

frstrtr added 2 commits June 21, 2026 05:26
Mirror of the LTC mint<->accept coupling fix onto the BTC lane. The
v35->v36 crossing soak (#97) wedged on LTC: AutoRatchet activated on a
95%-by-flat-COUNT desired-version tally, but the consensus accept gate
(share_check step 2 / p2pool check() data.py:1399) admits a V36 boundary
share only when desired-version reaches 60% by WORK over the
[9/10*CL, CL] window -- canonical get_desired_version_counts
(data.py:2651) weights each share by target_to_average_attempts(target).
Under heterogeneous hashrate a small miner set can carry the COUNT past
95% while the work-weighted tail sits below 60%, so the activated node
mints a V36 boundary share that every peer rejects, freezing the crossing.

btc/auto_ratchet.hpp carried the byte-identical flat-count tail guard, so
the same latent wedge existed on this SHA256d sharechain. Switch the tail
guard from get_desired_version_counts to a work-weighted tally over the
same [9/10*CL, CL] window at the same 60% threshold the accept gate
enforces, so activation strictly implies the accept rule and a minted
boundary share can never be rejected.

BTC tracker had only get_desired_version_counts, so this also ports
get_desired_version_weights onto btc/share_tracker.hpp (work-weighted via
get_index()->work, mirroring the ltc/dgb tracker shape). Per-coin lane,
btc/ tree only; v36-native consensus-version-signaling standardization.
Merge held pending BTC crossing re-soak.
…60%-work switch rule

Completes the mint<->accept coupling. The prior commit (27a4463) made the
AutoRatchet MINT guard work-weighted, but BTC share_check step 2 still
admitted a version BOUNDARY via the non-canonical 95%-flat-COUNT
should_punish_version path -- the inverse of the #97 LTC wedge: a
work-weighted mint guard in front of a flat-count accept gate.

Port the canonical accept rule from ltc/share_check.hpp ~1715-1762
(p2pool data.py check() 1396-1414): a boundary share (share.version !=
parent.version) is valid only when, in the window [CHAIN_LENGTH*9/10,
CHAIN_LENGTH] behind the PARENT, the new version holds >= 60% of the
PPLNS-WORK-WEIGHTED desired-version tally (get_desired_version_weights).
same-version always valid; -1 downgrade valid (AutoRatchet V35-after-V36);
any other jump throws "invalid version jump". Removes the
should_punish_version call from the accept path entirely (F10/(b): the 60%
switch rule is now the ONLY version gate, matching ltc/dgb).

Per-coin lane, src/impl/btc/ only. Semantics byte-mirror LTC. Merge held
pending full gh CI rollup CLEAN + BTC crossing re-soak; no self-merge.
@frstrtr
frstrtr marked this pull request as ready for review June 21, 2026 08:36
@frstrtr
frstrtr merged commit 5905f74 into master Jun 21, 2026
20 checks passed
frstrtr added a commit that referenced this pull request Jun 23, 2026
)

* btc: couple AutoRatchet mint gate to the work-weighted accept gate

Mirror of the LTC mint<->accept coupling fix onto the BTC lane. The
v35->v36 crossing soak (#97) wedged on LTC: AutoRatchet activated on a
95%-by-flat-COUNT desired-version tally, but the consensus accept gate
(share_check step 2 / p2pool check() data.py:1399) admits a V36 boundary
share only when desired-version reaches 60% by WORK over the
[9/10*CL, CL] window -- canonical get_desired_version_counts
(data.py:2651) weights each share by target_to_average_attempts(target).
Under heterogeneous hashrate a small miner set can carry the COUNT past
95% while the work-weighted tail sits below 60%, so the activated node
mints a V36 boundary share that every peer rejects, freezing the crossing.

btc/auto_ratchet.hpp carried the byte-identical flat-count tail guard, so
the same latent wedge existed on this SHA256d sharechain. Switch the tail
guard from get_desired_version_counts to a work-weighted tally over the
same [9/10*CL, CL] window at the same 60% threshold the accept gate
enforces, so activation strictly implies the accept rule and a minted
boundary share can never be rejected.

BTC tracker had only get_desired_version_counts, so this also ports
get_desired_version_weights onto btc/share_tracker.hpp (work-weighted via
get_index()->work, mirroring the ltc/dgb tracker shape). Per-coin lane,
btc/ tree only; v36-native consensus-version-signaling standardization.
Merge held pending BTC crossing re-soak.

* btc(#290): replace 95%-flat should_punish accept gate with canonical 60%-work switch rule

Completes the mint<->accept coupling. The prior commit (27a4463) made the
AutoRatchet MINT guard work-weighted, but BTC share_check step 2 still
admitted a version BOUNDARY via the non-canonical 95%-flat-COUNT
should_punish_version path -- the inverse of the #97 LTC wedge: a
work-weighted mint guard in front of a flat-count accept gate.

Port the canonical accept rule from ltc/share_check.hpp ~1715-1762
(p2pool data.py check() 1396-1414): a boundary share (share.version !=
parent.version) is valid only when, in the window [CHAIN_LENGTH*9/10,
CHAIN_LENGTH] behind the PARENT, the new version holds >= 60% of the
PPLNS-WORK-WEIGHTED desired-version tally (get_desired_version_weights).
same-version always valid; -1 downgrade valid (AutoRatchet V35-after-V36);
any other jump throws "invalid version jump". Removes the
should_punish_version call from the accept path entirely (F10/(b): the 60%
switch rule is now the ONLY version gate, matching ltc/dgb).

Per-coin lane, src/impl/btc/ only. Semantics byte-mirror LTC. Merge held
pending full gh CI rollup CLEAN + BTC crossing re-soak; no self-merge.

---------

Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
frstrtr added a commit that referenced this pull request Jun 27, 2026
…577)

Fenced, additive, rig-free known-answer test for the BCH G2 staged 1-by-1
miner-migration gate. Pins the canonical 60%-by-WORK version-switch ACCEPT
gate that bch::check_share enforces inline (src/impl/bch/share_check.hpp:1774):

    if (new_ver_weight * 100 < total_weight * 60)
        throw "switch without enough hash power upgraded";

via a verbatim replica of the live tail-guard (same non-circular localisation
btc/DGB use; guard stays inline, no lifted SSOT). Arms the staged-migration
rows without a SHA256d bitaxe rig.

Properties pinned (15 asserts, all green):
  - 60%-by-WORK boundary at the exact crossing (59 hold / 60-100 pass / 0 hold)
  - mint-cannot-outrun-accept (#288): 95%-by-COUNT under heterogeneous hashrate
    can NOT outrun the 60%-by-work gate -> a minted V36 boundary share its peers
    would reject is prevented
  - work-weighted NOT flat-count (#290/#326 regression guard): gate diverges
    from a head-count in both directions; #326 dropped the 95%-flat-count punish
  - monotonic staged migration: 5 equal-work miners, tally advances monotone,
    accept gate crosses at stage 3/5 (60%) and stays on
  - downgrade asymmetry: V35-after-V36 (AutoRatchet deactivation) is un-gated

Test-only, bch-tree-local: pure int main()+assert over <core/pack_types.hpp>
uint288, no consensus / shared-base / CMake-shared surface. Registered in the
bch test CMakeLists foreach and BOTH build.yml COIN_BCH --target allowlists.

Co-authored-by: frstrtr <frstrtr@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant