INTcoin Core v1.0.6.1 — IIP-0120 wiring fix

INTcoin Core v1.0.6.1 — IIP-0120 wiring fix

Hotfix release for v1.0.6’s missing IIP-0120 activation wiring. Same rule body as v1.0.6 (declared Final there); only the call sites in BlockAssembler, validation, and the standalone P2P miner now thread nextBlockTime through, so the emergency-min-difficulty branch can fire as designed when nTime > parent + 20×T.

Downloads

Direct download links (verified 200 OK, unauthenticated — bookmarkable):

Release page (also corrected): https://gitlab.com/INT-devs/intcoin/-/releases/v1.0.6.1-stable

Note (2026-05-05 post-incident): the original release-page asset buttons returned 404 for the first ~5 hours after announcement because the auto-generated URLs pointed at the release:publish CI job which carries no artifacts. Binaries actually live on release:linux-x86_64 (job 14210985393) and release:windows-x64 (job 14210985394). Fixed via GitLab API; CI YAML fix queued for v1.0.7.

What was wrong with v1.0.6

v1.0.6 shipped IIP-0120 declared Final, regtest-locked, and announced — but the activation wiring was missing in BlockAssembler and validation. The inner function mining::GetNextWorkRequired accepts a nextBlockTime parameter (default 0) that all callers omitted, so the IIP-0120 branch was permanently dead code on the network. The mainnet chain remained stuck at h=8615 after the v1.0.6 fleet rollout because getblocktemplate returned the regular LWMA-computed difficulty (unchanged from the burst-miner-induced ramp) instead of the powLimit fallback the rule was supposed to provide.

What changed in v1.0.6.1

The rule body in pow/difficulty.cpp is byte-for-byte identical between v1.0.6 and v1.0.6.1. Only the call sites differ:

  • src/mining/block_template.cppBlockAssembler::InitializeHeader now computes the candidate timestamp before calling GetNextWorkRequired, threads it through, and reuses it for the block’s nTime. mining::UpdateTime similarly threads nNewTime through, and the recalc is no longer gated on fPowAllowMinDifficultyBlocks (mainnet must also recalc when IIP-0120 fires).
  • src/mining/p2p_client.cpp — the standalone P2P miner passes wall-clock time as nextBlockTime.
  • src/consensus/validation.cpp — added a 3-arg GetNextWorkRequired(pindexPrev, params, nextBlockTime) overload; ContextualCheckBlock now calls it with block.nTime. The 2-arg form is preserved for “what’s the next expected difficulty?” query callers (RPCs, status displays) where there is no candidate block in hand.
  • src/rpc/mining.cppgetblocktemplate, generatetoaddress, generateblock all pass candidate time too.
  • src/sync/headerchain.cppCheckDifficultyTransition passes the incoming header’s nTime.
  • src/version.h.inPROTOCOL_VERSION 70004 → 70005; MIN_PEER_PROTO_VERSION 70004 → 70005; user-agent renders the full 4-component 1.0.6.1 so peers can distinguish on the wire.

Folded in: IIP-0118’s mainnet+testnet nLWMAWindow 60 → 144 alignment. v1.0.6’s IIP-0118 change updated params.h’s default but left the explicit setters in MainnetParams() / TestnetParams() on 60. v1.0.6.1 fixes that so mainnet actually runs the IIP-0118 widened window.

Test discipline change

The v1.0.6 regtest case (lwma_emergency_min_diff_after_40_minutes) tested the inner function with nextBlockTime passed explicitly. It was green. It missed the bug because no test exercised the full validation/template path that the daemon actually uses.

v1.0.6.1 adds two new tests at the public-API level — validation::GetNextWorkRequired, the path the daemon really calls — that would have failed against v1.0.6:

  • iip_0120_validation_3arg_fires_emergency_min_diff
  • iip_0120_validation_within_window_no_trigger

Going forward: any consensus rule whose behaviour depends on a per-block input must have at least one test that exercises the rule through the public-API path the daemon uses, not just the inner deterministic function. That’s now a documented review-gate rule.

Why the protocol bump

v1.0.6 and v1.0.6.1 disagree on whether a block with nBits = powLimit and nTime > parent + 20×T is valid (v1.0.6 rejects, v1.0.6.1 accepts). Without a PROTOCOL_VERSION bump, v1.0.6 nodes would silently ban-score v1.0.6.1 peers when they relay IIP-0120 blocks. The bump makes the rejection explicit at handshake — operators see a clear “version mismatch, please upgrade” rather than a mysterious “chain not moving.”

The bump is operator-experience cleanup, not a “we added new rules” change. The rule itself was already declared Final in v1.0.6.

Live public chain dashboard

Unchanged URL — bookmark it:

https://intcoin.grafana.net/public-dashboards/30d0e9a455c447359a0f74d7ba3eece3

Block height, network hashrate, peer count, difficulty, mempool — refreshed every 30 seconds, 24h history. The chain has resumed normal block production: was stuck at h=8614 for 7+ hours pre-v1.0.6.1, now well past h=8700.

Migration

  • On v1.0.6 → download v1.0.6.1, swap binary, restart. No datadir migration. v1.0.6 nodes will be cut off at handshake.
  • On v1.0.5 or earlier → upgrade directly to v1.0.6.1; skip v1.0.6.

Acknowledgements

Sorry for the second tick in 24 hours, plus the 5-hour broken-download window after the announcement. Owning all of it directly. The lessons — that consensus tests must exercise the public-API path, that release-page asset URLs need an unauthenticated curl test before announcement — are now codified and will outlive this incident.

— INT-devs