Skip to content

XChain Platform v0.17.0

Choose a tag to compare

@jdogresorg jdogresorg released this 11 Sep 01:58
· 220 commits to master since this release
v0.17.0
be5ce31

XChain Platform v0.17.0.

A minor train, and a full one: all thirteen code components plus xchain-documentation
move to 0.17.0. It exists to roll the five testnet validator hubs. The mainnet hub stays
at v0.16.2 under the standing write hold, so nothing here reaches a mainnet writer until
that hold lifts. src/release-manifest.json at this tag pins the resolved set; the signed
artifact set and SHA256SUMS.asc are attached.

Activation

Nothing in this train changes what any node derives from history it has already
processed. Six rules take a new or newly armed activation, and two of them arm mainnet
gates that have been inert since genesis:

Rule Mainnet Testnet Regtest
ATTEST leader-rotation silent-slot skip (ATTEST_LEADER_SILENCE_SKIP_ACTIVATION) unratified BTC 152400 genesis
Oracle clamp-reference realignment (ORACLE_CLAMP_REFERENCE_ACTIVATION) unratified BTC 152400 genesis
Rest-pattern metering and banned-rest deploys (REST_PATTERN_METER) 2027-01-01 00:00:00Z genesis genesis
Contract identity required at deploy (CONTRACT_META_REQUIRED) genesis 2026-09-13 00:00:00Z genesis
Archive invalid-height key repair (ARCHIVE_INVALID_HEIGHT_KEY_ACTIVATION) genesis BTC 155000, LTC 4896000, DOGE 67915000 genesis
Archive rollback author scope (ARCHIVE_ROLLBACK_AUTHOR_SCOPE_ACTIVATION) genesis DOGE 67915000 inert

The two testnet heights at BTC 152400 are the same boundary on purpose. The leader-silence
skip is keyed on the request's own block index and the clamp-reference realignment on the
round's BTC block height, so a fleet that crosses one crosses the other, and a hub cannot
be on the new rule for one and the old rule for the other.

The mainnet genesis arms discharge the identity ruling of 2026-09-09: 26 activation maps
and six mainnet time constants that had been held at unarmed sentinels are set to 0. That
is safe only because it is identity on the history the mainnet chains actually carry, and
it was not assumed. It was driven: a from-genesis OLD-versus-ON replay witness reproduced
byte-identical state on Bitcoin and Dogecoin mainnet, and Litecoin mainnet carries no
qualifying history to replay.

The two testnet archive heights are sized to sit above the tips measured on 2026-09-09,
roughly 22 to 23 days out, so every testnet process runs this release before the earliest
chain crosses. Deploy order is not free on the archive pair: xchain-sync carries the
same repaired key on the replication side and must be live before the indexer half, or a
follower is asked to hash a parent row it was never sent.

CONTRACT_META_REQUIRED is the tightest deadline in the train. Testnet arms it at
1789257600 (2026-09-13 00:00:00Z), which is 00:00:00Z of the second day after the latest
plausible landing of this roll, and testnet resolves protocol time from median-time-past
rather than the block's own stamp. Every testnet indexer must be running this release
before that instant, or an indexer left behind accepts a nameless deploy the armed fleet
rejects. If the roll slips past 2026-09-11 the instant is re-pinned forward before the
release notes are published; an activation already in the past is not a flag day.

Attestation liveness on the testnet validators

This is the cargo the train was cut for. A judge_model round could not finalize on the
live testnet fleet for three separate reasons, and all three are fixed here.

Leader rotation advanced one slot per window and stopped without ever wrapping, so from
request+9 the leader slot was frozen for the rest of the request's life. It now steps over
a slot it has proven silent. Because two hubs on different builds would then elect
different leaders for the same request, and a round whose members disagree about the
leader has no proposal to take its canonical effective_time from, the skip is gated on
the request's own block index rather than shipped bare.

A judge_model leader also chose the round's effective_time at proposal time and then
spent the whole collection and judge window before broadcasting, so the stamp had aged
past the follower propagation floor by the time anyone window-checked it and every PREPARE
was refused. The leader now stamps when the winner is established.

The attestation batch publisher retries a head wire the encoder refused before it was
sent, instead of treating an unsent wire as broadcast, and retractattestbatch clears a
batch link the chain has un-landed. On the indexer side a -32602 rejection from the hub is
a terminal push rather than a retry, and a reorg that un-lands an ATTEST v5 or v6 batch
retracts the link instead of leaving it pointing at a transaction the chain no longer
carries.

Oracle publishing and the price clamp

The oracle clamp reference is now a function of the round being judged rather than of each
hub's own refresh timer. Two hubs could previously judge the same PROPOSE against
references from different rounds and co-sign differently; measured, a reference one round
stale clamps an identical submission set to half the median an aligned hub emits. This
changes what a hub clamps to. Roll the hub fleet in a single pass rather than a rolling
one.
It carries its own activation height so the change lands as a flag day rather than
on whichever hub restarted first.

The publisher also restores its last-published markers from the durable table at startup
instead of re-publishing windows the chain already carries, drains a buffered window
backlog through a rotating catch-up cursor with attempt-plus-age retirement, and says
which kind of non-publisher it is so a silent oracle reads as configured rather than
broken.

A standalone hub gets two feeds it was missing. With no oracle consensus of its own it now
derives all four consensus capabilities from its own Bitcoin view, not only price, so a
chain-only node stops refusing every ATTEST and storing every archive head unverified. In
weighted mode it reads the federation's stake snapshot from the pinned staking bundle, so
it persists the validators' oracle frames instead of skipping every sender it has no
registration for. It also honours HUB_NETWORK, so its ingest gates resolve on the
network it declares rather than on a default.

Contract identity and the rest-pattern meter

Every deployable contract now names itself. A contract exports meta with a name and a
description, the chain requires it at deploy above the CONTRACT_META_REQUIRED flag day,
the indexer stores it in four searchable columns behind a full-text index, and the explorer
shows and searches it everywhere a contract appears. The SDK refuses a nameless deploy with
the chain's own verdict string before any fee is composed, and every contract template and
generated policy guard exports its own meta block.

Separately, the VM's allocator meter dispatched only on expression nodes, so a
destructuring rest (var [...c] = bigArr) performed an unbounded native copy for a flat
one gas. Rest sources are now size-metered, and the four rest positions with no addressable
source (rest parameters, nested rest, catch-clause rest, for-of and for-in heads) are
refused at deploy under a new banned-rest rule. That moves the VM consensus epoch to 4,
which the indexer goldens and the explorer's vm-query pin move with. It takes its own
future mainnet instant rather than riding the past contract-era flag day, because re-pricing
destructures that have already executed would make a from-genesis replay disagree with a
long-running node.

Also in this train

  • The archive election key binds the wrapper checkpoint only and a stale batch sequence
    converges upward, so hubs whose tables differ stop electing different leaders; a
    truncated capability snapshot is refused in count mode as well as weighted mode.
  • The wider validator_rewards and capability_snapshots unique keys are built before the
    old narrow ones are dropped, so a failed widen can no longer leave the table with no
    unique key at all.
  • A hub-mirror stream watermark that froze under healthy heartbeats is bounded, and the
    hub-db-sync bootstrap clears capability_snapshots rows the current hub does not serve.
  • xchain-node stops a service with a per-service SIGTERM budget instead of docker kill,
    marks a decoder or tracker whose coin node is not answering as NODE UNREACHABLE, creates
    the coin node before the services that poll it, and no longer lets a crash-looping hub
    block the precheck of the command that would repair it.
  • The explorer moves its market chart renderers into the main bundle, so the market page
    raises no CSP violation; it acknowledges a client unsubscribe per channel, queues a
    snapshot fan-out that arrives mid fan-out, and links ATTEST expiries back to their
    request and injected callback.
  • The decoder and utxo-tracker exit cleanly on SIGTERM under a SHUTDOWN_TIMEOUT_MS bound
    and report coin-node reachability on every health surface.
  • xchain-sync strict-checks SHOW WARNINGS on a from-zero lookup repair, fails closed on a
    ServerPoller cursor read so a source-database outage is not read as an idle chain, and
    carries the ATTEST batch-head verdict flip on the forward channel.
  • The encoder reports its written compression bytes and gains release_inputs, and the SDK
    carries both through so a confirm string matches the PSBT; @dankest-llc/xchain-sdk and
    xchain-mcp publish at 0.17.0.
  • The e2e suite gains the AT5 oracle barrier drill, a degraded ARCHIVE attestation round
    across two validators, and contract-meta fixtures for the flag day.

Verifying this release

gpg --verify SHA256SUMS.asc SHA256SUMS
shasum -a 256 -c SHA256SUMS

The signing key is published at xchain-documentation/operations/release-signing.md and in
tools/release/ in every train repo. Any other key is not an official release.

Installing this exact set

xchain-node install v0.17.0 <service> <coin> <network>

What is in this train

Component Version
xchain-node 0.17.0
xchain-hub 0.17.0
xchain-indexer 0.17.0
xchain-sync 0.17.0
xchain-explorer 0.17.0
xchain-decoder 0.17.0
xchain-encoder 0.17.0
xchain-utxo-tracker 0.17.0
xchain-sdk 0.17.0
xchain-e2e-test 0.17.0
xchain-vm 0.17.0
xchain-contracts 0.17.0
xchain-regtest-miner 0.17.0
xchain-documentation 0.17.0