Release v0.16.0 - xchain-node - #39
Merged
Merged
Conversation
…indexer and hub containers
…to the latest release A no-ref `update` on a release node resolves the latest published release and pins every service to it, the same way a no-ref `install` does; a branch node stays on its branch and says so. Before this the no-ref path re-read each module's git branch, and a pinned checkout is detached, so every release node failed its own documented upgrade command with "branch 'HEAD' not found". - The node records what it is on (data/install-target.json) at every install and update; a node with no record is classified from its checkouts. - `update all` includes the hub and the sync client, hub first; absent services skip and report on one line; an absent coin node is not installed; a coin node already at the pinned daemon version is left running. - The CLI moves itself first: fetch tags, verify the target tag against the shipped release key, checkout, npm install (rolled back on failure), then re-execute the command in the explicit pinned form. A dirty tracked tree is refused with the files named; XCHAIN_NODE_NO_SELF_UPDATE=1 updates the services only. - Every command except `update` prints a one-line notice when a newer release exists, cached for an hour, silent on failure. - On a validator the additive `validator init` repair runs before the hub rebuild. - preCheck stages the hub from the release manifest: a no-ref install pins it to the latest release instead of cloning master, and `install v0.15.1 xchain-hub` works on a train in which the hub did not move. - `update` no longer requires a service argument. Driven in a docker-in-docker sandbox: a hub-only stack at the v0.15.1 pin moved to hub 0.15.2 with a bare `update all`; a 0.15.1 carrier self-updated, re-ran the pinned update and rebuilt the hub.
…gate can see it The two reads of the self-update re-execution marker in the CLI used a computed key, which the documentation coverage scanner cannot match. Read by name; the variable and the opt-out are documented in the companion documentation change.
feat(update): `update all` moves the CLI and every installed service to the latest release
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
…honours a clear A decoder carrying a durable REORG_HALT marker keeps parsing with a green healthcheck, so `ps` showed a clean "running" for a service that will stop at its next reorg, and the only recovery anywhere was a full resync. `clear-reorg-halt <chain> <network> --reason <text> [--force] [--dry-run]` runs the decoder's own audited clear inside its container (the decoder checks the database is intact and records the reason as an events row). `ps` probes running decoders' health surface, marks a live halt as "running REORG_HALT" and prints a note under the table with the reason, the date and both recoveries. The bootstrap health gate counts only halts newer than the newest clear, so a cleared database can be published again.
Nothing ever passed --memory, so every tracker's memoryBudget read the whole host (its cgroup branch never bound) and N trackers on one box oversubscribed it: three trackers on a 16 GB host intended 13.7 GB before the chain daemons and MariaDB, and the mainnet one reached 5.9 GB RSS (operator report 2026-09-07). The orchestrator is the one thing that knows how many trackers share a host, so it hands each one its share: half the host RAM divided by the installed tracker count (registry rows plus the one being created), floor 1024 MB, ceiling 16384 MB, --memory-swap equal to --memory. Only the tracker is capped by default; it is the one service that sizes itself to the cgroup limit, and a cap on a service that does not turns a spike into an OOM restart loop. Any module takes an explicit XCHAIN_NODE_MODULE_MEMORY_MB_<SERVICE>; 0 disables the derived cap. The limit is fixed at create time, so adding a chain needs a tracker recreate to re-size the others; the deployment guide says so.
Both run a complete singleton installModule and take 1.2-1.5s on a CI runner (measured at two consecutive commits), which only fits the 2s default while the runner is idle; three concurrent gate runs pushed them over and blocked an unrelated push. The describe blocks now carry a 10s budget.
full_node is a possession-proof tier, not an opt-in capability, and it ships inert on every network (reward share zero, no verifier set) until its activation flag day. The capabilities line never listed it, so an operator whose stake cleared its floor went looking for how to earn it (operator report 2026-09-07). Status now says so in one line.
…e restoring
A fresh mainnet install restored the published decoder bootstrap next to a
coin node still syncing from zero; the released decoder read the node's lower
tip as a reorg and wrote a durable halt. Both numbers exist at restore time
and nothing compared them.
The publisher now writes bootstrap.json {format, module, coin, network,
height, created} as the FIRST member of the wrapper (decoder/indexer height
from MAX(block_index) after the dump, tracker height from its status before
the stop), and a streaming reader pulls it off the leading tar entry without a
pass over the archive. Between download and restore the install reads the
coin node's getblockchaininfo through its container CLI and decides: at or
past the archive, restore; below it and the service waits out a catching-up
node (its status carries node_catching_up, or its version is 0.16.0+), restore
and report WAITING FOR NODE; below it and the image would halt, refuse, leave
the store untouched and say how to take the restore later. The indexer follows
the decoder and always passes. XCHAIN_NODE_SKIP_NODE_TIP_GUARD=1 skips it
loudly.
`ps` probes decoder and tracker health and marks a service waiting out its
node as WAITING FOR NODE, with both heights under the table.
Pin the nine moved components at their v0.16.0 tags (hub 8ba9b3b, indexer dc864aef, sync 6032d2c, decoder c3b2e8c, encoder c621917, utxo-tracker 1e5ac07, explorer e916639, sdk 7d1634f, e2e-test 685c346); vm, contracts and regtest-miner stay at v0.15.0 (sparse lockstep).
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.
XChain Platform v0.16.0 release train: this repository's frozen
release/v0.16.0branch, carrying every develop commit since its last tag plus the version bump, CHANGELOG block and README refresh.A minor train. Two consensus rails arm on Bitcoin testnet by height, both ahead of the chain at cut time: zero-confirmation ATTEST service from block 151800 and ROLLCALL v1 consensus gates from block 152208. Mainnet is unratified and byte for byte unchanged. Testnet indexers roll before hubs, the whole fleet inside one roll-call epoch.
Merge order per the release runbook (section 6, 5b): hub, then decoder/sync/encoder/utxo-tracker, then indexer, then explorer, e2e-test and sdk, node last with the pinned manifest. Merge commit, never squash: the train tag is cut on the merge commit.