ASERT fractional polynomial diverges from BCH reference #20

Closed
opened 2026-08-24 16:18:50 +00:00 by getrigeos · 3 comments
getrigeos commented 2026-08-24 16:18:50 +00:00 (Migrated from github.com)

Problem

noid_chain/src/consensus/difficulty.rs describes its fractional exponent approximation as identical to BCH CalculateASERT, but the implemented terms are scaled differently:

  • the quadratic term is calculated as B * f * f / 65536 instead of B * f * f;
  • the cubic term uses (f / 65536), which is zero for every u16 fractional value.

The resulting factor increasingly understates 2^(frac/65536), reaching about 15.2% at the upper fractional boundary. For a six-block epoch that is one second ahead of its 120-second schedule, the reference target multiplier is about 0.994 while the current implementation produces about 0.845, introducing a large discontinuity around zero schedule error.

Protocol impact

This calculation is consensus-critical: correcting it changes expected difficulty targets and therefore block validity. It must be handled as a coordinated network upgrade or explicit activation, not silently deployed to only some nodes.

Proposed change

  • Restore the exact BCH integer polynomial using u128 intermediates.
  • Add exact fractional-factor vectors.
  • Add a regression vector for the one-second-fast boundary.
  • Target the v2 branch as required by CONTRIBUTING.md.

Reference: https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node/-/blob/master/src/pow.cpp#L230-238

## Problem `noid_chain/src/consensus/difficulty.rs` describes its fractional exponent approximation as identical to BCH `CalculateASERT`, but the implemented terms are scaled differently: - the quadratic term is calculated as `B * f * f / 65536` instead of `B * f * f`; - the cubic term uses `(f / 65536)`, which is zero for every `u16` fractional value. The resulting factor increasingly understates `2^(frac/65536)`, reaching about 15.2% at the upper fractional boundary. For a six-block epoch that is one second ahead of its 120-second schedule, the reference target multiplier is about 0.994 while the current implementation produces about 0.845, introducing a large discontinuity around zero schedule error. ## Protocol impact This calculation is consensus-critical: correcting it changes expected difficulty targets and therefore block validity. It must be handled as a coordinated network upgrade or explicit activation, not silently deployed to only some nodes. ## Proposed change - Restore the exact BCH integer polynomial using `u128` intermediates. - Add exact fractional-factor vectors. - Add a regression vector for the one-second-fast boundary. - Target the `v2` branch as required by `CONTRIBUTING.md`. Reference: https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node/-/blob/master/src/pow.cpp#L230-238
ignotusnemo commented 2026-08-24 18:39:48 +00:00 (Migrated from github.com)

Confirmed. I reproduced the divergence and verified the one-second-fast boundary against BCH CalculateASERT. Current mainnet nodes all use the same existing rule and remain in consensus.
I will integrate the corrected polynomial into v2 alongside the legacy rule, with activation disabled until the complete v2 consensus scope and activation height are finalized. The implementation and regression vectors are being handled in #21.

Confirmed. I reproduced the divergence and verified the one-second-fast boundary against BCH CalculateASERT. Current mainnet nodes all use the same existing rule and remain in consensus. I will integrate the corrected polynomial into v2 alongside the legacy rule, with activation disabled until the complete v2 consensus scope and activation height are finalized. The implementation and regression vectors are being handled in #21.
ignotusnemo commented 2026-08-24 18:54:46 +00:00 (Migrated from github.com)

Implemented in v2 by #21. The legacy and corrected BCH rules are now explicit and covered by exact regression vectors. Production activation remains disabled until the complete v2 consensus scope and activation height are finalized. Current mainnet behavior is unchanged.

Implemented in v2 by #21. The legacy and corrected BCH rules are now explicit and covered by exact regression vectors. Production activation remains disabled until the complete v2 consensus scope and activation height are finalized. Current mainnet behavior is unchanged.
ignotusnemo commented 2026-08-26 11:48:53 +00:00 (Migrated from github.com)

Although this report predates the Bug Hunt and was public before its rules existed, the finding was real and led to a correction prepared for v2. I am awarding it 500 NOID retroactively. @getrigeos, please reply here with your NOID payout address. I will only use an address posted from the account that opened this issue.

Although this report predates the Bug Hunt and was public before its rules existed, the finding was real and led to a correction prepared for v2. I am awarding it 500 NOID retroactively. @getrigeos, please reply here with your NOID payout address. I will only use an address posted from the account that opened this issue.
Sign in to join this conversation.
No description provided.