Skip to content

feat(relay): Minimum-difficulty handling in retarget (testnet-style blocks)#944

Open
lionakhnazarov wants to merge 2 commits intothreshold-network:mainfrom
lionakhnazarov:feat/testnet4-relay-min-difficulty
Open

feat(relay): Minimum-difficulty handling in retarget (testnet-style blocks)#944
lionakhnazarov wants to merge 2 commits intothreshold-network:mainfrom
lionakhnazarov:feat/testnet4-relay-min-difficulty

Conversation

@lionakhnazarov
Copy link
Copy Markdown

@lionakhnazarov lionakhnazarov commented Mar 30, 2026

Problem
During retarget, after the first header of the new epoch sets minedTarget, the contract required every following header in the post-retarget half of the bundle to use exactly that same target. On Bitcoin testnet4, a minimum-difficulty block (bits like 0x1d00ffff) can appear in that window with a different expanded target than the retargeted blocks, which triggered Unexpected target change after retarget.

Introduces a dedicated minimum difficulty target constant aligned with Bitcoin’s difficulty-1 target (BTCUtils.DIFF1_TARGET / compact 0x1d00ffff), to model minimum-difficulty blocks that can appear on Bitcoin testnets (e.g. testnet4) when block spacing is high, while other blocks in the same post-retarget window use the new epoch difficulty after a retarget.

Smart contract (LightRelay.sol)
New constant MIN_DIFFICULTY_TARGET — same 256-bit value as DIFF1_TARGET, documented as the on-chain representation of minimum-difficulty headers in those scenarios.
retarget logic — after the first post-retarget header establishes minedTarget, remaining headers in the post-retarget proof must either:
match minedTarget, or
match MIN_DIFFICULTY_TARGET
so the relay accepts mixed post-retarget windows (normal retargeted difficulty + occasional minimum-difficulty blocks) instead of reverting with "Unexpected target change after retarget".
PoW and chain validation still run first via validateHeader; the minimum-difficulty exception only applies after minedTarget is fixed and only where the contract explicitly allows it.

Tests (LightRelay.test.ts)
Cover post-retarget behavior when nbits is forced to the minimum-difficulty encoding vs an unrelated easy target, including:
revert on Invalid work when DIFF1 nbits is applied without a matching PoW (shows the exception does not skip work checks);
revert on Unexpected target change after retarget when a header uses a different easy target than minedTarget / MIN_DIFFICULTY_TARGET.
Helpers to parse compact bits and patch nbits on fixture headers for these scenarios.

…rget logic

Added a new constant  to handle minimum difficulty blocks in Bitcoin testnet scenarios. Updated the retarget logic to accommodate this new target, ensuring that the relay can correctly validate post-retarget conditions. Enhanced test coverage to verify behavior with the new difficulty target in various scenarios.
Copy link
Copy Markdown
Member

@lrsaturnino lrsaturnino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, nice work on the testnet4 min-difficulty handling — the constant is correct and the post-retarget tests are well-designed. A few things worth discussing before merge.

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.

2 participants