ZooBC wiki
Running a node

Releases and updates

ZooBC changes its software without changing its chain. New versions are announced on the chain itself, each node installs them through an updater that its owner controls, and new consensus rules switch on only once two thirds of the producers already run them. Nobody can push software onto a node, and a new version never needs a new chain.

The release registry

The release authority, one key named in the chain's genesis, registers each release with RegisterRelease (type 32): a version string, a 32-byte manifest hash (the fingerprint of the release's files) and a release address. A release is registered per architecture and per chain, and its version string names both. A version string can be registered only once, so a fix needs a new version, and a revoked version can never return. The authority may also revoke a release (type 35) and hand its role to another key, which takes two steps: propose (type 33) and accept (type 34).

The registered seats hold a check on that key:

  • Veto. When two thirds of the registered seats attest "veto" for a version, it is revoked exactly as if the authority had revoked it: self-updating nodes skip it and the installer refuses it. Suspended seats are left out of the count, so with 11 active seats the veto needs 8. Each vote is a fee-free attestation signed with the node key, and operators cast it themselves; nothing votes automatically.
  • Replacement. A vote naming a new release authority is counted only once its oldest vote is a week (40,320 blocks) old, so the current holder sees it coming. At two thirds, the role passes to the address voted for.

A registration or a revocation is advisory. It guides the nodes whose owners chose to self-update; an operator who runs a binary of their own choice is not moved by it. Anyone can check a downloaded release against the registry (checking a downloaded file).

The updater

The ZooBC installer adds a small updater that runs beside the node, not inside it. It first runs 15 minutes after the machine boots, then about every 10 minutes (give or take 2). Each time it asks the local node for /api/v1/release/list and looks for the newest registered, unrevoked release for its chain and its machine type (amd64 or arm64) that is newer than the running one.

The updater installs that release only when it is due: at the release's registration height, plus the update delay, plus this node's own slot. Then it downloads the release, checks its signature and its manifest hash against the chain, installs it beside the running version, restarts the node and runs a health check. If the check fails it rolls back to the old version, and it retries a failed update after 12 hours.

The release registry on the chain, the updater waiting for the delay and its own slot, the signature and hash check, installation beside the old version and roll-back on failure, and the owner's on, off or chain switch
The release registry on the chain, the updater waiting for the delay and its own slot, the signature and hash check, installation beside the old version and roll-back on failure, and the owner's on, off or chain switch
  • The delay is 2 days (11,520 blocks) by default on mainnet. Each node sets its own, and the release authority cannot shorten it. It leaves time to revoke a bad release before it spreads.
  • The slots order the nodes by key and spread their start times so that, by default, at most 2 nodes start an update in any one block. The chain never loses many producers at once.
  • The owner's switch, auto_update, is on (the default), off, or chain. With chain, the updater follows a setting the owner signs on the chain from the wallet, so the owner can switch updates on or off without logging in to the server.

Every operator is told when a newer release exists: the updater, even when switched off, names it with the state of its readiness gate, the node writes a daily warning in its log, the node's /node/info route reports it, the web wallet shows a banner, and the explorer shows each node's version.

The readiness gate

New consensus rules ship in a release as a bundle, with a bundle id above 0. Every block carries its producer's software version, and the readiness gate reads it. The bundle's rules switch on, on every node at once, at the first height that meets all of these:

  • it is at or after the bundle's scheduled height, and at least 5,760 blocks (one day) after the release's registration;
  • at least two thirds of the registered seats (rounded up, suspended seats left out) have each made a block with a version at or above the bundle id within the signalling window, which is the larger of 720 blocks and 5 blocks per node;
  • the release has not been revoked; a revocation stops a pending bundle.

From that height on, blocks with an older version are refused. A node that did not update gets no grace: it misses its turns, earns nothing and loses score from its first refused turn (missed turns, suspension and expulsion). That is why operators are warned of every new release.

Because producers are counted, not blocks, a minority cut off from the rest cannot reach two thirds by itself. No key can force the switch either: the release authority signs no activation message, and a height alone never decides while the producers have not moved. The gate has known limits: it has no deadline, so just over a third of the seats can hold an upgrade back, and it does not catch a faulty release, which is what the delay and the veto are for.

A gauge of producers on the new version reaching two thirds of the seats, at least one day after the release's registration, opening the gate; a node still on the old version has its blocks refused
A gauge of producers on the new version reaching two thirds of the seats, at least one day after the release's registration, opening the gate; a node still on the old version has its blocks refused

Chains launched with version 0.5.8 have all 121 of their consensus rules on from block 0, and no rule is bundled, so the gate first matters for a later release. A node also refuses to start if its binary places a rule's activation differently from the chain's record, and a release can ship a release pin that ties it to a known spine block.

See also