Verifiable Bun worker node runtime for the Consensus network.
This package is intentionally separate from instance/, which remains as a reference
implementation while this runtime is built from scratch.
bun install
bun run startDefault local API:
http://localhost:9090State defaults to:
~/.consensus/nodeOverride with:
CONSENSUS_STATE_DIR=/path/to/state bun run startRecommended interactive setup:
bun install
bun run setupThe setup wizard explains the network commitment, installs the server-approved runtime release, detects IPv4/optional IPv6, classifies region through the Consensus server, runs encrypted eval, verifies contact email, and registers the node. Email verification happens after eval so failed nodes do not spend an email API call.
Node evaluation checks route integrity, system capacity, SHA-256 CPU throughput, ChaCha20-Poly1305 throughput, and memory pressure before registration continues. Registration consumes the encrypted eval authorization; it does not require port forwarding or a public benchmark endpoint.
First run encrypted eval against the public server tunnel. A passing eval writes
join-auth.json into the node state directory.
CONSENSUS_STATE_DIR=~/.consensus/node \
CONSENSUS_SERVER_URL=https://consensus.canister.software \
bun run evalThen register the node with the join authorization:
CONSENSUS_SERVER_URL=https://consensus.canister.software \
CONSENSUS_NODE_IPV6=... \
CONSENSUS_NODE_IPV4=... \
CONSENSUS_NODE_PORT=9090 \
[email protected] \
CONSENSUS_EMAIL_VERIFICATION_TOKEN=... \
CONSENSUS_EVM_ADDRESS=0x... \
CONSENSUS_SOLANA_ADDRESS=... \
CONSENSUS_ICP_ADDRESS=... \
bun run registerAfter registration, keep the outbound control tunnel open:
CONSENSUS_SERVER_URL=https://consensus.canister.software \
bun run controlVerify the registered node code and manifest:
CONSENSUS_SERVER_URL=https://consensus.canister.software \
bun run verifyThe verification payload signs the node release manifest with the node Ed25519 identity. The server checks that signature against the registered node key and, when an admin-required manifest is set, compares version, platform, commit, routes hash, and tarball SHA.
Check whether this node matches the required server release:
CONSENSUS_SERVER_URL=https://consensus.canister.software \
bun run updateIf the server requires a newer release and the manifest includes a verified artifact URL, download it into the node state directory:
CONSENSUS_SERVER_URL=https://consensus.canister.software \
bun run update -- --downloadVersion bumps are explicit commits. Normal commits do not publish releases.
bun run version:bump -- patch
git add package.json
git commit -m "Bump node version"Build a node artifact and matching server admin manifest payload:
bun run release -- \
--version 0.1.0-alpha.0 \
--commit "$(git rev-parse HEAD)" \
--platform darwin-arm64 \
--download-url https://consensus.canister.software/releases/consensus-node-0.1.0-alpha.0-darwin-arm64.tgzThe command writes the tarball, manifest, and /admin/manifest payload into
dist/. Upload the tarball to the download_url, then post the admin payload
to the Pi server with x-admin-key.
GitHub releases are manual. Run the Release workflow from GitHub Actions when
you want to publish a real node artifact. If no version is provided in the
workflow form, it uses the committed package.json version. The workflow does
not run on ordinary commits.
The Consensus server decides when a node should update. It sends
update_prepare over the encrypted control tunnel; the node downloads and
verifies the release artifact, then replies update_ready. The server drains the
node from routing and sends update_apply only when the router sees the node as
idle.
On apply, the node acknowledges, runs the installer, closes its control tunnel
with WebSocket code 1012, and exits cleanly with code 0. In production, run
the node through PM2 with ecosystem.config.cjs; PM2 supervises
scripts/run-control.sh and restarts from the new current symlink. The wrapper
still handles legacy exit code 75 for older releases during migration. If
CONSENSUS_NODE_UPDATE_COMMAND is set, the node runs it before exiting with:
CONSENSUS_NODE_UPDATE_ID
CONSENSUS_NODE_ARTIFACT_PATH
CONSENSUS_NODE_TARGET_VERSIONThat command should install the verified artifact. If the command is not set,
the runtime falls back to scripts/install-release.sh from the current release.
The default installer contract is:
export CONSENSUS_NODE_INSTALL_DIR="$HOME/.consensus/node-runtime"
export CONSENSUS_NODE_UPDATE_COMMAND="$CONSENSUS_NODE_INSTALL_DIR/current/scripts/install-release.sh"scripts/install-release.sh unpacks the verified tarball into
$CONSENSUS_NODE_INSTALL_DIR/releases/, installs production dependencies with
the lockfile, and atomically moves the current symlink. scripts/run-control.sh
always starts bun run control from that current release.
Recommended PM2 start:
CONSENSUS_NODE_INSTALL_DIR="$HOME/.consensus/node-runtime" \
CONSENSUS_STATE_DIR="$HOME/.consensus/node" \
CONSENSUS_SERVER_URL=https://consensus.canister.software \
"$HOME/.consensus/node-runtime/current/scripts/start-pm2.sh"For reboot persistence, run pm2 startup, follow the command it prints, then run
pm2 save.
The installer prunes old release directories after each successful install. It
keeps the newest 3 releases by default; set CONSENSUS_NODE_RELEASE_RETENTION=1
to keep only the active release, except for the release currently finishing an
update process.
For the first install, download a release tarball and run:
CONSENSUS_NODE_ARTIFACT_PATH=/path/to/consensus-node.tgz \
CONSENSUS_NODE_TARGET_VERSION=0.1.0-alpha.0 \
scripts/install-release.shscripts/ensure-pm2.sh installs missing macOS dependencies in order:
Homebrew, Node.js/npm, then PM2. It also persists Homebrew shell setup in
~/.zprofile when Homebrew is installed or discovered outside PATH. The older
launchd/ and systemd/ templates are still available if you do not want PM2.