feat(relay): Minimum-difficulty handling in retarget (testnet-style blocks)#944
Open
lionakhnazarov wants to merge 2 commits intothreshold-network:mainfrom
Open
Conversation
…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.
lrsaturnino
reviewed
Mar 31, 2026
Member
lrsaturnino
left a comment
There was a problem hiding this comment.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.